Narrow Notification.implementedInterface() return type 75/97975/9
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 19 Oct 2021 11:59:00 +0000 (13:59 +0200)
committerRobert Varga <nite@hq.sk>
Mon, 15 Nov 2021 05:44:02 +0000 (05:44 +0000)
All Notification interfaces should provide their own identity here,
make sure there is no confusion about that.

Change-Id: I9fb7f82fcee7acd38aa05b38a2721ef62f8a1750
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
13 files changed:
binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/NotificationPublishService.java
binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/NotificationService.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/BindingDOMNotificationServiceAdapter.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/SingleBindingDOMNotificationAdapter.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/OSGiNotificationService.java
binding/mdsal-binding-dom-codec-api/src/main/java/org/opendaylight/mdsal/binding/dom/codec/api/BindingNormalizedNodeSerializer.java
binding/mdsal-binding-dom-codec-api/src/main/java/org/opendaylight/mdsal/binding/dom/codec/api/BindingNormalizedNodeWriterFactory.java
binding/mdsal-binding-dom-codec-spi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/spi/ForwardingBindingDOMCodecServices.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/NotificationGenerator.java
binding/mdsal-binding-model-ri/src/main/java/org/opendaylight/mdsal/binding/model/ri/BindingTypes.java
binding/mdsal-binding-model-ri/src/test/java/org/opendaylight/mdsal/binding/model/ri/BindingTypesTest.java
binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Notification.java

index d679c188192d3502bccc9637d0bc40d59f609131..69bf606014cb8b20348c007d28999412d27bd9d8 100644 (file)
@@ -50,7 +50,7 @@ public interface NotificationPublishService extends BindingService {
      * @throws InterruptedException if interrupted while waiting
      * @throws NullPointerException if the notification is null
      */
-    void putNotification(@NonNull Notification notification) throws InterruptedException;
+    void putNotification(@NonNull Notification<?> notification) throws InterruptedException;
 
     /**
      * Publishes a notification to subscribed listeners. This initiates the process of sending the
@@ -66,7 +66,7 @@ public interface NotificationPublishService extends BindingService {
      *         resource constraints prevent
      * @throws NullPointerException if the notification is null
      */
-    @NonNull ListenableFuture<? extends Object> offerNotification(@NonNull Notification notification);
+    @NonNull ListenableFuture<? extends Object> offerNotification(@NonNull Notification<?> notification);
 
     /**
      * Publishes a notification to subscribed listeners. This initiates the process of sending the
@@ -84,6 +84,6 @@ public interface NotificationPublishService extends BindingService {
      * @throws NullPointerException if the notification or unit is null
      * @throws IllegalArgumentException if timeout is negative.
      */
-    @NonNull ListenableFuture<? extends Object> offerNotification(@NonNull Notification notification,
+    @NonNull ListenableFuture<? extends Object> offerNotification(@NonNull Notification<?> notification,
             int timeout, @NonNull TimeUnit unit) throws InterruptedException;
 }
index 6ff74ca34159dd8a8d2b5ff8e8b9b2f28500b282..c2cc18eeabacec0e0ec35a2e68749fc4c1fd2642 100644 (file)
@@ -13,6 +13,7 @@ import java.util.concurrent.Executor;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.Notification;
 import org.opendaylight.yangtools.yang.binding.NotificationListener;
 
@@ -110,7 +111,7 @@ public interface NotificationService extends BindingService {
      * @return a {@link Registration} instance that should be used to unregister the listener by invoking the
      *        {@link Registration#close()} method when no longer needed
      */
-    <N extends Notification> @NonNull Registration registerListener(Class<N> type, Listener<N> listener,
+    <N extends Notification<N> & DataObject> @NonNull Registration registerListener(Class<N> type, Listener<N> listener,
         Executor executor);
 
     /**
@@ -126,7 +127,7 @@ public interface NotificationService extends BindingService {
      * @return a {@link Registration} instance that should be used to unregister the listener by invoking the
      *        {@link Registration#close()} method when no longer needed
      */
-    default <N extends Notification> @NonNull Registration registerListener(final Class<N> type,
+    default <N extends Notification<N> & DataObject> @NonNull Registration registerListener(final Class<N> type,
             final Listener<N> listener) {
         return registerListener(type, listener, MoreExecutors.directExecutor());
     }
@@ -139,7 +140,7 @@ public interface NotificationService extends BindingService {
      * @param N Notification type
      */
     @FunctionalInterface
-    interface Listener<N extends Notification> extends EventListener {
+    interface Listener<N extends Notification<N> & DataObject> extends EventListener {
         /**
          * Process a global notification.
          *
index ce26cbca98224edf2da4bae818bff06faff324e1..63a4f78c0cfbdc12e6b703da6a59a5f1f80da0c4 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.mdsal.dom.api.DOMService;
 import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.Notification;
 import org.opendaylight.yangtools.yang.binding.NotificationListener;
 
@@ -47,8 +48,8 @@ public class BindingDOMNotificationServiceAdapter implements NotificationService
     }
 
     @Override
-    public <N extends Notification> Registration registerListener(final Class<N> type, final Listener<N> listener,
-            final Executor executor) {
+    public <N extends Notification<N> & DataObject> Registration registerListener(final Class<N> type,
+            final Listener<N> listener, final Executor executor) {
         final var domListener = new SingleBindingDOMNotificationAdapter<>(adapterContext, type, listener, executor);
         return domNotifService.registerNotificationListener(domListener, domListener.getSupportedNotifications());
     }
index 0a7ead1061ebfa11474450472fc9f76e5f601b7e..9a7d002576d7499d4e1fda4da6f093f2c58d6d14 100644 (file)
@@ -13,10 +13,12 @@ import java.util.Set;
 import java.util.concurrent.Executor;
 import org.opendaylight.mdsal.binding.api.NotificationService.Listener;
 import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.Notification;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
 
-final class SingleBindingDOMNotificationAdapter<N extends Notification> extends AbstractDOMNotificationListenerAdapter {
+final class SingleBindingDOMNotificationAdapter<N extends Notification<N> & DataObject>
+        extends AbstractDOMNotificationListenerAdapter {
     private final Listener<N> delegate;
     private final Executor executor;
     private final Class<N> type;
index 0513f2efb2bc7a7f66963fb3f25c89dc22b0d37c..775c3187a4c0bbecfa1633765244e72b1c73fa08 100644 (file)
@@ -14,6 +14,7 @@ import org.opendaylight.mdsal.binding.api.NotificationService;
 import org.opendaylight.mdsal.binding.api.NotificationService.Listener;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.Notification;
 import org.opendaylight.yangtools.yang.binding.NotificationListener;
 import org.osgi.service.component.annotations.Activate;
@@ -37,8 +38,8 @@ public final class OSGiNotificationService extends AbstractAdaptedService<Notifi
     }
 
     @Override
-    public <N extends Notification> Registration registerListener(final Class<N> type, final Listener<N> listener,
-            final Executor executor) {
+    public <N extends Notification<N> & DataObject> Registration registerListener(final Class<N> type,
+            final Listener<N> listener, final Executor executor) {
         return delegate().registerListener(type, listener, executor);
     }
 
index 418a3a254aba7ccadb5e0c8619d229cfea8efcd0..2d3a0a458d5e1bb1700abe373da08ab2d8557235 100644 (file)
@@ -80,7 +80,7 @@ public interface BindingNormalizedNodeSerializer {
      * @param data NormalizedNode representing data
      * @return Binding representation of Notification
      */
-    @Nullable Notification fromNormalizedNodeNotification(@NonNull Absolute path, @NonNull ContainerNode data);
+    @Nullable Notification<?> fromNormalizedNodeNotification(@NonNull Absolute path, @NonNull ContainerNode data);
 
     /**
      * Translates supplied NormalizedNode Notification into Binding data, optionally taking an instant
@@ -92,7 +92,7 @@ public interface BindingNormalizedNodeSerializer {
      * @return Binding representation of Notification
      */
     @Beta
-    @Nullable Notification fromNormalizedNodeNotification(@NonNull Absolute path, @NonNull ContainerNode data,
+    @Nullable Notification<?> fromNormalizedNodeNotification(@NonNull Absolute path, @NonNull ContainerNode data,
             @Nullable Instant eventInstant);
 
     /**
@@ -134,7 +134,7 @@ public interface BindingNormalizedNodeSerializer {
      * @param data NormalizedNode representing notification data
      * @return NormalizedNode representation of notification
      */
-    @NonNull ContainerNode toNormalizedNodeNotification(@NonNull Notification data);
+    @NonNull ContainerNode toNormalizedNodeNotification(@NonNull Notification<?> data);
 
     /**
      * Translates supplied Binding RPC input or output into NormalizedNode data.
index da15c6be84db4792481558a86a4e0d469338de5d..917415c702c6c6b7ffbdc5535387d02873dd14e7 100644 (file)
@@ -89,7 +89,7 @@ public interface BindingNormalizedNodeWriterFactory {
      * @return {@link BindingStreamEventWriter} which will write to supplied
      *         {@link NormalizedNodeStreamWriter}.
      */
-    @NonNull BindingStreamEventWriter newNotificationWriter(@NonNull Class<? extends Notification> notification,
+    @NonNull BindingStreamEventWriter newNotificationWriter(@NonNull Class<? extends Notification<?>> notification,
             @NonNull NormalizedNodeStreamWriter domWriter);
 
     /**
index d1a18c27ed71c239120806263efd706ac9c4fb55..167e65fb0da4931248ceca60081cd7eb19d56cc8 100644 (file)
@@ -67,7 +67,7 @@ public abstract class ForwardingBindingDOMCodecServices extends ForwardingObject
     }
 
     @Override
-    public ContainerNode toNormalizedNodeNotification(final Notification data) {
+    public ContainerNode toNormalizedNodeNotification(final Notification<?> data) {
         return delegate().toNormalizedNodeNotification(data);
     }
 
@@ -95,12 +95,12 @@ public abstract class ForwardingBindingDOMCodecServices extends ForwardingObject
     }
 
     @Override
-    public Notification fromNormalizedNodeNotification(final Absolute path, final ContainerNode data) {
+    public Notification<?> fromNormalizedNodeNotification(final Absolute path, final ContainerNode data) {
         return delegate().fromNormalizedNodeNotification(path, data);
     }
 
     @Override
-    public Notification fromNormalizedNodeNotification(final Absolute path, final ContainerNode data,
+    public Notification<?> fromNormalizedNodeNotification(final Absolute path, final ContainerNode data,
             final Instant eventInstant) {
         return delegate().fromNormalizedNodeNotification(path, data, eventInstant);
     }
@@ -135,7 +135,7 @@ public abstract class ForwardingBindingDOMCodecServices extends ForwardingObject
     }
 
     @Override
-    public BindingStreamEventWriter newNotificationWriter(final Class<? extends Notification> notification,
+    public BindingStreamEventWriter newNotificationWriter(final Class<? extends Notification<?>> notification,
             final NormalizedNodeStreamWriter streamWriter) {
         return delegate().newNotificationWriter(notification, streamWriter);
     }
index 66f3e6d78424789624c23ea3751cd815e407c429..08bba8de6377b8938e404b2506595193d47df29c 100644 (file)
@@ -217,7 +217,7 @@ public final class BindingCodecContext extends AbstractBindingNormalizedNodeSeri
     }
 
     @Override
-    public BindingStreamEventWriter newNotificationWriter(final Class<? extends Notification> notification,
+    public BindingStreamEventWriter newNotificationWriter(final Class<? extends Notification<?>> notification,
             final NormalizedNodeStreamWriter domWriter) {
         return root.getNotification(notification).createWriter(domWriter);
     }
@@ -572,10 +572,11 @@ public final class BindingCodecContext extends AbstractBindingNormalizedNodeSeri
 
     @Override
     @SuppressFBWarnings("BC_UNCONFIRMED_CAST")
-    public ContainerNode toNormalizedNodeNotification(@NonNull final Notification data) {
+    public ContainerNode toNormalizedNodeNotification(@NonNull final Notification<?> data) {
         // FIXME: Should the cast to DataObject be necessary?
         return serializeDataObject((DataObject) data,
-            (ctx, iface, domWriter) -> ctx.newNotificationWriter(iface.asSubclass(Notification.class), domWriter));
+            (ctx, iface, domWriter) -> ctx.newNotificationWriter(
+                (Class<? extends Notification<?>>) iface.asSubclass(Notification.class), domWriter));
     }
 
     @Override
index 39d0a89c852533eb4591ee0f0d05b5a4709dd895..f59965a8cfadaeb5f394f7a0ef538d6ca583cf5c 100644 (file)
@@ -58,7 +58,7 @@ final class NotificationGenerator extends AbstractCompositeGenerator<Notificatio
     private Type notificationType(final GeneratedTypeBuilder builder, final TypeBuilderFactory builderFactory) {
         final AbstractCompositeGenerator<?> parent = getParent();
         if (parent instanceof ModuleGenerator) {
-            return BindingTypes.NOTIFICATION;
+            return BindingTypes.notification(builder);
         }
 
         final Type parentType = Type.of(parent.typeName());
index e1a3c5977c5a44d449328f084ad3e16fbda549c2..c4beb7b174144d2a046e2a00e67efafee327a20b 100644 (file)
@@ -51,7 +51,6 @@ public final class BindingTypes {
     public static final ConcreteType DATA_OBJECT = typeForClass(DataObject.class);
     public static final ConcreteType TYPE_OBJECT = typeForClass(TypeObject.class);
     public static final ConcreteType DATA_ROOT = typeForClass(DataRoot.class);
-    public static final ConcreteType NOTIFICATION = typeForClass(Notification.class);
     public static final ConcreteType NOTIFICATION_LISTENER = typeForClass(NotificationListener.class);
     public static final ConcreteType QNAME = typeForClass(QName.class);
     public static final ConcreteType RPC_INPUT = typeForClass(RpcInput.class);
@@ -79,6 +78,7 @@ public final class BindingTypes {
     private static final ConcreteType INSTANCE_NOTIFICATION = typeForClass(InstanceNotification.class);
     private static final ConcreteType KEYED_LIST_ACTION = typeForClass(KeyedListAction.class);
     private static final ConcreteType KEYED_LIST_NOTIFICATION = typeForClass(KeyedListNotification.class);
+    private static final ConcreteType NOTIFICATION = typeForClass(Notification.class);
     private static final ConcreteType OPAQUE_OBJECT = typeForClass(OpaqueObject.class);
     private static final ConcreteType RPC_RESULT = typeForClass(RpcResult.class);
 
@@ -114,11 +114,23 @@ public final class BindingTypes {
         return parameterizedTypeFor(KEYED_LIST_ACTION, keyType, parent, input, output);
     }
 
+    /**
+     * Type specializing {@link Notification} for a particular type.
+     *
+     * @param concreteType The concrete type of this notification
+     * @return A parameterized type corresponding to {@code Notification<ConcreteType>}
+     * @throws NullPointerException if any argument is is null
+     */
+    public static ParameterizedType notification(final Type concreteType) {
+        return parameterizedTypeFor(NOTIFICATION, concreteType);
+    }
+
     /**
      * Type specializing {@link InstanceNotification} for a particular type.
      *
+     * @param concreteType The concrete type of this notification
      * @param parent Type of parent defining the notification
-     * @return A parameterized type corresponding to {@code InstanceNotification<Parent>}
+     * @return A parameterized type corresponding to {@code InstanceNotification<ConcreteType, Parent>}
      * @throws NullPointerException if {@code parent} is is null
      */
     public static ParameterizedType instanceNotification(final Type concreteType, final Type parent) {
@@ -128,9 +140,10 @@ public final class BindingTypes {
     /**
      * Type specializing {@link InstanceNotification} for a particular type.
      *
+     * @param concreteType The concrete type of this notification
      * @param parent Type of parent defining the notification
      * @param keyType Type of parent's key
-     * @return A parameterized type corresponding to {@code KeyedInstanceNotification<ParentKey, Parent>}
+     * @return A parameterized type corresponding to {@code KeyedInstanceNotification<ConcreteType, ParentKey, Parent>}
      * @throws NullPointerException if any argument is is null
      */
     public static ParameterizedType keyedListNotification(final Type concreteType, final Type parent,
index 1588d001ce4ac7003c3edf2935ec286795e7d826..761861adbca00d88e42d4d8ca6d9fb5b9810ca7b 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.mdsal.binding.model.ri;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertThrows;
@@ -37,7 +38,6 @@ public class BindingTypesTest {
         assertEquals("IDENTIFIABLE", typeForClass(Identifiable.class), BindingTypes.IDENTIFIABLE);
         assertEquals("IDENTIFIER", typeForClass(Identifier.class), BindingTypes.IDENTIFIER);
         assertEquals("INSTANCE_IDENTIFIER", typeForClass(InstanceIdentifier.class), BindingTypes.INSTANCE_IDENTIFIER);
-        assertEquals("NOTIFICATION", typeForClass(Notification.class), BindingTypes.NOTIFICATION);
         assertEquals("NOTIFICATION_LISTENER", typeForClass(NotificationListener.class),
             BindingTypes.NOTIFICATION_LISTENER);
         assertEquals("RPC_SERVICE", typeForClass(RpcService.class), BindingTypes.RPC_SERVICE);
@@ -74,4 +74,16 @@ public class BindingTypesTest {
         final ParameterizedType augmentationType = BindingTypes.augmentation(Types.objectType());
         assertEquals("Augmentation", augmentationType.getName());
     }
+
+    @Test
+    public void testNotificationNull() {
+        assertThrows(NullPointerException.class, () -> BindingTypes.notification(null));
+    }
+
+    @Test
+    public void testNotification() {
+        final ParameterizedType notificationType = BindingTypes.notification(Types.objectType());
+        assertEquals(Types.typeForClass(Notification.class), notificationType.getRawType());
+        assertArrayEquals(new Object[] { Types.objectType() }, notificationType.getActualTypeArguments());
+    }
 }
\ No newline at end of file
index 2bb40f371eb53a9adf186f85653fad2f71008030..6acaa44d20c635149dd66a647bab4659cac84dee 100644 (file)
@@ -13,7 +13,7 @@ package org.opendaylight.yangtools.yang.binding;
  * interface. In case they do, {@link EventInstantAware#eventInstant()} returns the time when this notification was
  * generated.
  */
-// FIXME: 6.0.0: narrow implementedInterface()
-public interface Notification extends BaseNotification {
-
+public interface Notification<T extends Notification<T> & DataObject> extends BaseNotification {
+    @Override
+    Class<T> implementedInterface();
 }