Add InstanceNotificationService
[mdsal.git] / binding / mdsal-binding-api / src / main / java / org / opendaylight / mdsal / binding / api / InstanceNotificationSpec.java
1 /*
2  * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.mdsal.binding.api;
9
10 import static java.util.Objects.requireNonNull;
11
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.Augmentation;
19 import org.opendaylight.yangtools.yang.binding.ChildOf;
20 import org.opendaylight.yangtools.yang.binding.ChoiceIn;
21 import org.opendaylight.yangtools.yang.binding.DataObject;
22 import org.opendaylight.yangtools.yang.binding.DataRoot;
23 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
24 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
25 import org.opendaylight.yangtools.yang.binding.InstanceNotification;
26
27 /**
28  * A combination of an {@link InstanceNotification} class and its corresponding instantiation wildcard, expressed as
29  * an {@link InstanceIdentifier}. This glue is required because instance notification interfaces are generated at the
30  * place of their definition, most importantly in {@code grouping} and we actually need to bind to a particular
31  * instantiation (e.g. a place where {@code uses} references that grouping).
32  *
33  * @param <N> Generated InstanceNotification interface type
34  * @param <P> Instance notification parent type
35  */
36 @Beta
37 public final class InstanceNotificationSpec<N extends InstanceNotification<N, P>, P extends DataObject>
38         implements Immutable {
39     private final @NonNull InstanceIdentifier<P> path;
40     private final @NonNull Class<N> type;
41
42     private InstanceNotificationSpec(final Class<N> type, final InstanceIdentifier<P> path) {
43         this.type = requireNonNull(type);
44         this.path = requireNonNull(path);
45     }
46
47     public static <P extends ChildOf<? extends DataRoot>> @NonNull Builder<P> builder(final Class<P> container) {
48         return new Builder<>(InstanceIdentifier.builder(container));
49     }
50
51     public static <C extends ChoiceIn<? extends DataRoot> & DataObject, P extends ChildOf<? super C>>
52             @NonNull Builder<P> builder(final Class<C> caze, final Class<P> container) {
53         return new Builder<>(InstanceIdentifier.builder(caze, container));
54     }
55
56     public @NonNull InstanceIdentifier<P> path() {
57         return path;
58     }
59
60     public @NonNull Class<N> type() {
61         return type;
62     }
63
64     @Override
65     public int hashCode() {
66         return Objects.hash(type, path);
67     }
68
69     @Override
70     public boolean equals(final Object obj) {
71         if (obj == this) {
72             return true;
73         }
74         if (!(obj instanceof InstanceNotificationSpec)) {
75             return false;
76         }
77         final var other = (InstanceNotificationSpec<?, ?>) obj;
78         return type.equals(other.type) && path.equals(other.path);
79     }
80
81     @Override
82     public String toString() {
83         return MoreObjects.toStringHelper(this).add("action", type).add("path", path).toString();
84     }
85
86     @Beta
87     public static final class Builder<P extends DataObject> implements Mutable {
88         private final InstanceIdentifierBuilder<P> pathBuilder;
89
90         Builder(final InstanceIdentifierBuilder<P> pathBuilder) {
91             this.pathBuilder = requireNonNull(pathBuilder);
92         }
93
94         public <N extends ChildOf<? super P>> @NonNull Builder<N> withPathChild(final Class<N> container) {
95             pathBuilder.child(container);
96             return castThis();
97         }
98
99         public <C extends ChoiceIn<? super P> & DataObject, N extends ChildOf<? super C>>
100                 @NonNull Builder<N> withPathChild(final Class<C> caze, final Class<N> container) {
101             pathBuilder.child(caze, container);
102             return castThis();
103         }
104
105         public <N extends DataObject & Augmentation<? super P>> @NonNull Builder<N> withPathAugmentation(
106                 final Class<N> container) {
107             pathBuilder.augmentation(container);
108             return castThis();
109         }
110
111         public <N extends InstanceNotification<N, P>> @NonNull InstanceNotificationSpec<N, P> build(
112                 final Class<N> type) {
113             return new InstanceNotificationSpec<>(type, pathBuilder.build());
114         }
115
116         @SuppressWarnings("unchecked")
117         private <N extends DataObject> @NonNull Builder<N> castThis() {
118             return (Builder<N>) this;
119         }
120     }
121 }