2 * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.mdsal.binding.api;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.annotations.Beta;
13 import com.google.common.base.MoreObjects;
14 import java.util.Objects;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.opendaylight.yangtools.concepts.Immutable;
17 import org.opendaylight.yangtools.concepts.Mutable;
18 import org.opendaylight.yangtools.yang.binding.Action;
19 import org.opendaylight.yangtools.yang.binding.Augmentation;
20 import org.opendaylight.yangtools.yang.binding.ChildOf;
21 import org.opendaylight.yangtools.yang.binding.ChoiceIn;
22 import org.opendaylight.yangtools.yang.binding.DataObject;
23 import org.opendaylight.yangtools.yang.binding.DataRoot;
24 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 * A combination of an {@link Action} class and its corresponding instantiation wildcard, expressed as
28 * an {@link InstanceIdentifier}. This means that {@code list}s are treated exactly as @{code container}s are, e.g.
29 * without a key value specification.
32 * This glue is required because action interfaces are generated at the place of their
33 * definition, most importantly in {@code grouping} and we actually need to bind to a particular instantiation (e.g. a
34 * place where {@code uses} references that grouping).
36 * @param <A> Generated Action interface type
37 * @param <P> Action parent type
40 public final class ActionSpec<A extends Action<? extends InstanceIdentifier<P>, ?, ?>, P extends DataObject>
41 implements Immutable {
42 private final @NonNull InstanceIdentifier<P> path;
43 private final @NonNull Class<A> type;
45 private ActionSpec(final Class<A> type, final InstanceIdentifier<P> path) {
46 this.type = requireNonNull(type);
47 this.path = requireNonNull(path);
50 public static <P extends ChildOf<? extends DataRoot>> @NonNull Builder<P> builder(final Class<P> container) {
51 return new Builder<>(InstanceIdentifier.builder(container));
54 public static <C extends ChoiceIn<? extends DataRoot> & DataObject, P extends ChildOf<? super C>>
55 @NonNull Builder<P> builder(final Class<C> caze, final Class<P> container) {
56 return new Builder<>(InstanceIdentifier.builder(caze, container));
59 public @NonNull InstanceIdentifier<P> path() {
63 public @NonNull Class<A> type() {
68 public int hashCode() {
69 return Objects.hash(type, path);
73 public boolean equals(final Object obj) {
74 return obj == this || obj instanceof ActionSpec<?, ?> other
75 && type.equals(other.type) && path.equals(other.path);
79 public String toString() {
80 return MoreObjects.toStringHelper(this).add("action", type).add("path", path).toString();
84 public static final class Builder<P extends DataObject> implements Mutable {
85 private final InstanceIdentifier.Builder<P> pathBuilder;
87 Builder(final InstanceIdentifier.Builder<P> pathBuilder) {
88 this.pathBuilder = requireNonNull(pathBuilder);
91 public <N extends ChildOf<? super P>> @NonNull Builder<N> withPathChild(final Class<N> container) {
92 pathBuilder.child(container);
96 public <C extends ChoiceIn<? super P> & DataObject, N extends ChildOf<? super C>>
97 @NonNull Builder<N> withPathChild(final Class<C> caze, final Class<N> container) {
98 pathBuilder.child(caze, container);
102 public <N extends DataObject & Augmentation<? super P>> @NonNull Builder<N> withPathAugmentation(
103 final Class<N> container) {
104 pathBuilder.augmentation(container);
108 public <A extends Action<? extends InstanceIdentifier<P>, ?, ?>> @NonNull ActionSpec<A, P> build(
109 final Class<A> type) {
110 return new ActionSpec<>(type, pathBuilder.build());
113 @SuppressWarnings("unchecked")
114 private <N extends DataObject> @NonNull Builder<N> castThis() {
115 return (Builder<N>) this;