Rename InstanceIdentifierBuilder 90/104990/2
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 24 Mar 2023 10:02:30 +0000 (11:02 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 24 Mar 2023 12:47:46 +0000 (13:47 +0100)
Turn the intermediate interface into a sealed abstract class, which
lowers verbosity significantly. We now have three builder classes, only
two of which are exposed.

JIRA: MDSAL-798
Change-Id: I45e23643e196d9d06112053d60b2e2fbf1544311
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/ActionSpec.java
binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/InstanceNotificationSpec.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/DefaultDescendantQueryBuilder.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/query/DefaultMatchBuilderPath.java
binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/AbstractInstanceIdentifierBuilder.java [deleted file]
binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifier.java
binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyedInstanceIdentifier.java
binding/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifierTest.java

index 0c8e9d2a55d9ff72cffaaac7d3a10d306b3b2010..0e9826e5e1a32578f56d81b846edb87b354905c0 100644 (file)
@@ -22,7 +22,6 @@ import org.opendaylight.yangtools.yang.binding.ChoiceIn;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.DataRoot;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 
 /**
  * A combination of an {@link Action} class and its corresponding instantiation wildcard, expressed as
@@ -83,9 +82,9 @@ public final class ActionSpec<A extends Action<? extends InstanceIdentifier<P>,
 
     @Beta
     public static final class Builder<P extends DataObject> implements Mutable {
-        private final InstanceIdentifierBuilder<P> pathBuilder;
+        private final InstanceIdentifier.Builder<P> pathBuilder;
 
-        Builder(final InstanceIdentifierBuilder<P> pathBuilder) {
+        Builder(final InstanceIdentifier.Builder<P> pathBuilder) {
             this.pathBuilder = requireNonNull(pathBuilder);
         }
 
index 6a3107a889a0fe0ddd5ca4c84a94fb65e25a728c..11513f40e88681dd820c8a42aaa05f0e1cf2dddf 100644 (file)
@@ -21,7 +21,6 @@ import org.opendaylight.yangtools.yang.binding.ChoiceIn;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.DataRoot;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceNotification;
 
 /**
@@ -85,9 +84,9 @@ public final class InstanceNotificationSpec<N extends InstanceNotification<N, P>
 
     @Beta
     public static final class Builder<P extends DataObject> implements Mutable {
-        private final InstanceIdentifierBuilder<P> pathBuilder;
+        private final InstanceIdentifier.Builder<P> pathBuilder;
 
-        Builder(final InstanceIdentifierBuilder<P> pathBuilder) {
+        Builder(final InstanceIdentifier.Builder<P> pathBuilder) {
             this.pathBuilder = requireNonNull(pathBuilder);
         }
 
index a9d26f5336e2238ebe2ef81abcf19f455a82c6cc..59461ef04b4802902609507b86bf9dc43bb38fcb 100644 (file)
@@ -17,16 +17,15 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 
 final class DefaultDescendantQueryBuilder<R extends DataObject, T extends DataObject>
         implements DescendantQueryBuilder<T> {
-    private final InstanceIdentifierBuilder<T> childPath;
+    private final InstanceIdentifier.Builder<T> childPath;
     private final QueryBuilderState builder;
 
     DefaultDescendantQueryBuilder(final DefaultQueryFactory factory, final InstanceIdentifier<T> rootPath) {
-        this.builder = new QueryBuilderState(factory, rootPath);
-        this.childPath = rootPath.builder();
+        builder = new QueryBuilderState(factory, rootPath);
+        childPath = rootPath.builder();
     }
 
     @Override
index 23f23f17740c131ff583b8c40831ce584d2bbb83..6ebbe4cb8858540f9fc1acc383da908bc7f4dc99 100644 (file)
@@ -21,7 +21,6 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 import org.opendaylight.yangtools.yang.binding.TypeObject;
 import org.opendaylight.yangtools.yang.common.Decimal64;
 import org.opendaylight.yangtools.yang.common.Empty;
@@ -33,10 +32,10 @@ import org.opendaylight.yangtools.yang.common.Uint8;
 final class DefaultMatchBuilderPath<O extends DataObject, T extends DataObject> implements MatchBuilderPath<O, T> {
     private final QueryBuilderState builder;
     private final InstanceIdentifier<O> select;
-    private final InstanceIdentifierBuilder<T> target;
+    private final InstanceIdentifier.Builder<T> target;
 
     DefaultMatchBuilderPath(final QueryBuilderState builder, final InstanceIdentifier<O> select,
-            final InstanceIdentifierBuilder<T> target) {
+            final InstanceIdentifier.Builder<T> target) {
         this.builder = requireNonNull(builder);
         this.select = requireNonNull(select);
         this.target = requireNonNull(target);
diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/AbstractInstanceIdentifierBuilder.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/AbstractInstanceIdentifierBuilder.java
deleted file mode 100644 (file)
index 598ecc3..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * 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());
-    }
-}
index 0ea25e0f8d9b0c0c1d12b4301ee440949f45880e..6ebbba710cda0bd29a3398099833aa71e429bdeb 100644 (file)
@@ -56,7 +56,7 @@ import org.opendaylight.yangtools.util.HashCodeBuilder;
  *
  * <p>
  * You can create an instance identifier as follows to get to a node with id "openflow:1": {@code
- * InstanceIdentifierBuilder.builder(Nodes.class).child(Node.class, new NodeKey(new NodeId("openflow:1")).build();
+ * InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(new NodeId("openflow:1")).build();
  * }
  *
  * <p>
@@ -204,7 +204,7 @@ public class InstanceIdentifier<T extends DataObject>
      * <p>
      * For example let's say an instance identifier was built like so,
      * <pre>
-     *      identifier = InstanceIdentifierBuilder.builder(Nodes.class).child(Node.class,
+     *      identifier = InstanceIdentifier.builder(Nodes.class).child(Node.class,
      *                   new NodeKey(new NodeId("openflow:1")).build();
      * </pre>
      *
@@ -427,59 +427,58 @@ public class InstanceIdentifier<T extends DataObject>
      * @return A builder instance
      */
     // FIXME: rename this method to 'toBuilder()'
-    public @NonNull InstanceIdentifierBuilder<T> builder() {
-        return new AbstractInstanceIdentifierBuilder.Regular<>(this);
+    public @NonNull Builder<T> builder() {
+        return new RegularBuilder<>(this);
     }
 
     /**
-     * Create an InstanceIdentifierBuilder for a specific type of InstanceIdentifier as specified by container.
+     * Create a {@link Builder} for a specific type of InstanceIdentifier as specified by container.
      *
      * @param container Base container
      * @param <T> Type of the container
-     * @return A new {@link InstanceIdentifierBuilder}
+     * @return A new {@link Builder}
      * @throws NullPointerException if {@code container} is null
      */
-    public static <T extends ChildOf<? extends DataRoot>> @NonNull InstanceIdentifierBuilder<T> builder(
+    public static <T extends ChildOf<? extends DataRoot>> @NonNull Builder<T> builder(
             final Class<T> container) {
-        return new AbstractInstanceIdentifierBuilder.Regular<>(Item.of(container));
+        return new RegularBuilder<>(Item.of(container));
     }
 
     /**
-     * Create an InstanceIdentifierBuilder for a specific type of InstanceIdentifier as specified by container in
+     * Create a {@link Builder} for a specific type of InstanceIdentifier as specified by container in
      * a {@code grouping} used in the {@code case} statement.
      *
      * @param caze Choice case class
      * @param container Base container
      * @param <C> Case type
      * @param <T> Type of the container
-     * @return A new {@link InstanceIdentifierBuilder}
+     * @return A new {@link Builder}
      * @throws NullPointerException if any argument is null
      */
     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 AbstractInstanceIdentifierBuilder.Regular<>(Item.of(caze, container));
+            @NonNull Builder<T> builder(final Class<C> caze, final Class<T> container) {
+        return new RegularBuilder<>(Item.of(caze, container));
     }
 
     /**
-     * Create an InstanceIdentifierBuilder for a specific type of InstanceIdentifier which represents an
-     * {@link IdentifiableItem}.
+     * Create a {@link Builder} for a specific type of InstanceIdentifier which represents an {@link IdentifiableItem}.
      *
      * @param listItem list item class
      * @param listKey key value
      * @param <N> List type
      * @param <K> List key
-     * @return A new {@link InstanceIdentifierBuilder}
+     * @return A new {@link Builder}
      * @throws NullPointerException if any argument is null
      */
     public static <N extends Identifiable<K> & ChildOf<? extends DataRoot>,
             K extends Identifier<N>> @NonNull KeyedBuilder<N, K> builder(final Class<N> listItem,
                     final K listKey) {
-        return new AbstractInstanceIdentifierBuilder.Keyed<>(IdentifiableItem.of(listItem, listKey));
+        return new KeyedBuilder<>(IdentifiableItem.of(listItem, listKey));
     }
 
     /**
-     * Create an InstanceIdentifierBuilder for a specific type of InstanceIdentifier which represents an
-     * {@link IdentifiableItem} in a {@code grouping} used in the {@code case} statement.
+     * Create a {@link Builder} for a specific type of InstanceIdentifier which represents an {@link IdentifiableItem}
+     *  in a {@code grouping} used in the {@code case} statement.
      *
      * @param caze Choice case class
      * @param listItem list item class
@@ -487,28 +486,28 @@ public class InstanceIdentifier<T extends DataObject>
      * @param <C> Case type
      * @param <N> List type
      * @param <K> List key
-     * @return A new {@link InstanceIdentifierBuilder}
+     * @return A new {@link Builder}
      * @throws NullPointerException if any argument is null
      */
     public static <C extends ChoiceIn<? extends DataRoot> & DataObject,
             N extends Identifiable<K> & ChildOf<? super C>, K extends Identifier<N>>
             @NonNull KeyedBuilder<N, K> builder(final Class<C> caze, final Class<N> listItem,
                     final K listKey) {
-        return new AbstractInstanceIdentifierBuilder.Keyed<>(IdentifiableItem.of(caze, listItem, listKey));
+        return new KeyedBuilder<>(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) {
+            @NonNull Builder<T> builderOfInherited(final Class<R> root, final Class<T> container) {
         // FIXME: we are losing root identity, hence namespaces may not work correctly
-        return new AbstractInstanceIdentifierBuilder.Regular<>(Item.of(container));
+        return new RegularBuilder<>(Item.of(container));
     }
 
     public static <R extends DataRoot & DataObject, C extends ChoiceIn<? super R> & DataObject,
             T extends ChildOf<? super C>>
-            @NonNull InstanceIdentifierBuilder<T> builderOfInherited(final Class<R> root,
+            @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 AbstractInstanceIdentifierBuilder.Regular<>(Item.of(caze, container));
+        return new RegularBuilder<>(Item.of(caze, container));
     }
 
     public static <R extends DataRoot & DataObject, N extends Identifiable<K> & ChildOf<? super R>,
@@ -516,7 +515,7 @@ public class InstanceIdentifier<T extends DataObject>
             @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 AbstractInstanceIdentifierBuilder.Keyed<>(IdentifiableItem.of(listItem, listKey));
+        return new KeyedBuilder<>(IdentifiableItem.of(listItem, listKey));
     }
 
     public static <R extends DataRoot & DataObject, C extends ChoiceIn<? super R> & DataObject,
@@ -524,7 +523,7 @@ public class InstanceIdentifier<T extends DataObject>
             @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 AbstractInstanceIdentifierBuilder.Keyed<>(IdentifiableItem.of(caze, listItem, listKey));
+        return new KeyedBuilder<>(IdentifiableItem.of(caze, listItem, listKey));
     }
 
     /**
@@ -860,8 +859,60 @@ public class InstanceIdentifier<T extends DataObject>
         }
     }
 
-    // FIXME: rename to 'Builder'
-    public interface InstanceIdentifierBuilder<T extends DataObject> {
+    /**
+     * A builder of {@link InstanceIdentifier} objects.
+     *
+     * @param <T> Instance identifier target type
+     */
+    public abstract static sealed class Builder<T extends DataObject> {
+        private final ImmutableList.Builder<PathArgument> pathBuilder;
+        private final HashCodeBuilder<PathArgument> hashBuilder;
+        private final Iterable<? extends PathArgument> basePath;
+
+        private boolean wildcard;
+
+        Builder(final Builder<?> prev, final PathArgument item, final boolean isWildcard) {
+            pathBuilder = prev.pathBuilder;
+            hashBuilder = prev.hashBuilder;
+            basePath = prev.basePath;
+            wildcard = prev.wildcard;
+            appendItem(item, isWildcard);
+        }
+
+        Builder(final InstanceIdentifier<T> identifier) {
+            pathBuilder = ImmutableList.builder();
+            hashBuilder = new HashCodeBuilder<>(identifier.hashCode());
+            wildcard = identifier.isWildcarded();
+            basePath = identifier.pathArguments;
+        }
+
+        Builder(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;
+        }
+
+        /**
+         * 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
+         */
+        public final <N extends DataObject & Augmentation<? super T>> Builder<N> augmentation(
+                final Class<N> container) {
+            return append(Item.of(container), false);
+        }
+
         /**
          * 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
@@ -879,7 +930,9 @@ public class InstanceIdentifier<T extends DataObject>
          * @return this builder
          * @throws NullPointerException if {@code container} is null
          */
-        <N extends ChildOf<? super T>> @NonNull InstanceIdentifierBuilder<N> child(Class<N> container);
+        public final <N extends ChildOf<? super T>> Builder<N> child(final Class<N> container) {
+            return append(Item.of(container), Identifiable.class.isAssignableFrom(container));
+        }
 
         /**
          * Append the specified container as a child of the current InstanceIdentifier referenced by the builder. This
@@ -893,8 +946,10 @@ public class InstanceIdentifier<T extends DataObject>
          * @return this builder
          * @throws NullPointerException if {@code container} is null
          */
-        <C extends ChoiceIn<? super T> & DataObject, N extends ChildOf<? super C>>
-                @NonNull InstanceIdentifierBuilder<N> child(Class<C> caze, Class<N> container);
+        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(Item.of(caze, container), Identifiable.class.isAssignableFrom(container));
+        }
 
         /**
          * Append the specified listItem as a child of the current InstanceIdentifier referenced by the builder. This
@@ -908,8 +963,10 @@ public class InstanceIdentifier<T extends DataObject>
          * @return this builder
          * @throws NullPointerException if any argument is null
          */
-        <N extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<N>>
-                @NonNull KeyedBuilder<N, K> child(Class<@NonNull N> listItem, K listKey);
+        public final <N extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<N>> KeyedBuilder<N, K> child(
+                final Class<@NonNull N> listItem, final K listKey) {
+            return append(IdentifiableItem.of(listItem, listKey));
+        }
 
         /**
          * Append the specified listItem as a child of the current InstanceIdentifier referenced by the builder. This
@@ -925,38 +982,128 @@ public class InstanceIdentifier<T extends DataObject>
          * @return this builder
          * @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 KeyedBuilder<N, K> child(
-                        Class<C> caze, Class<N> listItem, K listKey);
-
-        /**
-         * 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
-         */
-        <N extends DataObject & Augmentation<? super T>> @NonNull InstanceIdentifierBuilder<N> augmentation(
-                Class<N> container);
+        public final <C extends ChoiceIn<? super T> & DataObject, K extends Identifier<N>,
+                N extends Identifiable<K> & ChildOf<? super C>> KeyedBuilder<N, K> child(final Class<C> caze,
+                    final Class<N> listItem, final K listKey) {
+            return append(IdentifiableItem.of(caze, listItem, listKey));
+        }
 
         /**
          * Build the instance identifier.
          *
-         * @return Resulting instance identifier.
+         * @return Resulting {@link InstanceIdentifier}.
          */
-        @NonNull InstanceIdentifier<T> build();
+        public abstract @NonNull InstanceIdentifier<T> build();
+
+        @Override
+        public final int hashCode() {
+            return hashBuilder.build();
+        }
+
+        @Override
+        public final boolean equals(final Object obj) {
+            return this == obj || obj instanceof Builder<?> other
+                && wildcard == other.wildcard && hashCode() == other.hashCode()
+                && Iterables.elementsEqual(pathArguments(), other.pathArguments());
+        }
+
+        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 RegularBuilder<X> append(Item<X> item, boolean isWildcard);
+
+        abstract <X extends DataObject & Identifiable<Y>, Y extends Identifier<X>>
+            @NonNull KeyedBuilder<X, Y> append(IdentifiableItem<X, Y> item);
     }
 
-    public interface KeyedBuilder<T extends DataObject & Identifiable<K>, K extends Identifier<T>>
-            extends InstanceIdentifierBuilder<T> {
+    public static final class KeyedBuilder<T extends DataObject & Identifiable<K>, K extends Identifier<T>>
+            extends Builder<T> {
+        private @NonNull IdentifiableItem<T, K> lastItem;
+
+        KeyedBuilder(final IdentifiableItem<T, K> item) {
+            super(item, false);
+            lastItem = requireNonNull(item);
+        }
+
+        KeyedBuilder(final KeyedInstanceIdentifier<T, K> identifier) {
+            super(identifier);
+            lastItem = IdentifiableItem.of(identifier.getTargetType(), identifier.getKey());
+        }
+
+        private KeyedBuilder(final RegularBuilder<?> prev, final IdentifiableItem<T, K> item) {
+            super(prev, item, false);
+            lastItem = requireNonNull(item);
+        }
+
         /**
          * Build the instance identifier.
          *
-         * @return Resulting instance identifier.
+         * @return Resulting {@link KeyedInstanceIdentifier}.
          */
         @Override
-        @NonNull KeyedInstanceIdentifier<T, K> build();
+        public @NonNull KeyedInstanceIdentifier<T, K> build() {
+            return new KeyedInstanceIdentifier<>(lastItem.getType(), pathArguments(), wildcard(), hashCode(),
+                lastItem.getKey());
+        }
+
+        @Override
+        <X extends DataObject> @NonNull RegularBuilder<X> append(final Item<X> item, final boolean isWildcard) {
+            return new RegularBuilder<>(this, item, isWildcard);
+        }
+
+        @Override
+        @SuppressWarnings({ "rawtypes", "unchecked" })
+        <X extends DataObject & Identifiable<Y>, Y extends Identifier<X>> KeyedBuilder<X, Y> append(
+                final IdentifiableItem<X, Y> item) {
+            appendItem(item, false);
+            lastItem = (IdentifiableItem) item;
+            return (KeyedBuilder<X, Y>) this;
+        }
+    }
+
+    private static final class RegularBuilder<T extends DataObject> extends Builder<T> {
+        private @NonNull Class<T> type;
+
+        RegularBuilder(final Item<T> item) {
+            super(item, Identifiable.class.isAssignableFrom(item.getType()));
+            type = item.getType();
+        }
+
+        RegularBuilder(final InstanceIdentifier<T> identifier) {
+            super(identifier);
+            type = identifier.getTargetType();
+        }
+
+        private RegularBuilder(final KeyedBuilder<?, ?> 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> RegularBuilder<X> append(final Item<X> item, final boolean isWildcard) {
+            appendItem(item, isWildcard);
+            type = (Class) item.getType();
+            return (RegularBuilder<X>) this;
+        }
+
+        @Override
+        <X extends DataObject & Identifiable<Y>, Y extends Identifier<X>> KeyedBuilder<X, Y> append(
+                final IdentifiableItem<X, Y> item) {
+            return new KeyedBuilder<>(this, item);
+        }
     }
 }
index fed0dacbfc8c4a0e98c0224cc28448744ca5fb8a..ae6038b103757b296cb0aeb61e06969024ede03b 100644 (file)
@@ -42,7 +42,7 @@ public class KeyedInstanceIdentifier<T extends Identifiable<K> & DataObject, K e
 
     @Override
     public final KeyedBuilder<T, K> builder() {
-        return new AbstractInstanceIdentifierBuilder.Keyed<>(this);
+        return new KeyedBuilder<>(this);
     }
 
     @Override
index de9e602070f6a0dcd6622b88f1614409acf3e843..2483db8855b7e1494bc5539f1b53aee7e3968a6e 100644 (file)
@@ -24,7 +24,6 @@ import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import org.junit.Test;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 import org.opendaylight.yangtools.yang.binding.test.mock.FooChild;
 import org.opendaylight.yangtools.yang.binding.test.mock.FooRoot;
 import org.opendaylight.yangtools.yang.binding.test.mock.InstantiatedFoo;
@@ -156,7 +155,7 @@ public class InstanceIdentifierTest {
         assertNotNull(instanceIdentifier1.hashCode());
         assertNotNull(instanceIdentifier1.toString());
 
-        final InstanceIdentifierBuilder instanceIdentifierBuilder = instanceIdentifier1.builder();
+        final InstanceIdentifier.Builder instanceIdentifierBuilder = instanceIdentifier1.builder();
         assertEquals(instanceIdentifier1.hashCode(), instanceIdentifierBuilder.hashCode());
         assertNotNull(instanceIdentifierBuilder.augmentation(InstantiatedFoo.class));
         assertNotNull(instanceIdentifierBuilder.build());
@@ -208,10 +207,10 @@ public class InstanceIdentifierTest {
 
     @Test
     public void equalsTest() {
-        final InstanceIdentifierBuilder<FooRoot> builder1 =  InstanceIdentifier.create(FooRoot.class).builder();
-        final InstanceIdentifierBuilder<FooRoot> builder2 =  InstanceIdentifier.create(FooRoot.class).builder();
-        final InstanceIdentifierBuilder<Nodes> builder3 =  InstanceIdentifier.create(Nodes.class).builder();
-        final InstanceIdentifierBuilder<Nodes> builder4 =  InstanceIdentifier.create(Nodes.class).builder();
+        final InstanceIdentifier.Builder<FooRoot> builder1 =  InstanceIdentifier.create(FooRoot.class).builder();
+        final InstanceIdentifier.Builder<FooRoot> builder2 =  InstanceIdentifier.create(FooRoot.class).builder();
+        final InstanceIdentifier.Builder<Nodes> builder3 =  InstanceIdentifier.create(Nodes.class).builder();
+        final InstanceIdentifier.Builder<Nodes> builder4 =  InstanceIdentifier.create(Nodes.class).builder();
         final Object obj = new Object();
 
         assertTrue(builder1.equals(builder2));
@@ -235,10 +234,10 @@ public class InstanceIdentifierTest {
 
     @Test
     public void hashCodeTest() {
-        final InstanceIdentifierBuilder<FooRoot> builder1 =  InstanceIdentifier.create(FooRoot.class).builder();
-        final InstanceIdentifierBuilder<FooRoot> builder2 =  InstanceIdentifier.create(FooRoot.class).builder();
-        final InstanceIdentifierBuilder<Nodes> builder3 =  InstanceIdentifier.create(Nodes.class).builder();
-        final InstanceIdentifierBuilder<Nodes> builder4 =  InstanceIdentifier.create(Nodes.class).builder();
+        final InstanceIdentifier.Builder<FooRoot> builder1 =  InstanceIdentifier.create(FooRoot.class).builder();
+        final InstanceIdentifier.Builder<FooRoot> builder2 =  InstanceIdentifier.create(FooRoot.class).builder();
+        final InstanceIdentifier.Builder<Nodes> builder3 =  InstanceIdentifier.create(Nodes.class).builder();
+        final InstanceIdentifier.Builder<Nodes> builder4 =  InstanceIdentifier.create(Nodes.class).builder();
         final Object obj = new Object();
 
         assertTrue(builder1.hashCode() == builder2.hashCode());