Make LazySerializedDOMNotification a DOMEvent 79/81579/3
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 11 Apr 2019 20:10:16 +0000 (22:10 +0200)
committerRobert Varga <nite@hq.sk>
Wed, 17 Apr 2019 14:25:21 +0000 (14:25 +0000)
DOMEvent carries the information about when the event occurred,
make sure we propagate it when available and backfill it on
submission.

It also retrofits some @NonNull annotations to make it clear we
are not propagating nulls.

JIRA: MDSAL-282
Change-Id: I2153b007af2accbad41f5aea00dbced21030a67d
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/BindingDOMNotificationPublishServiceAdapter.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/LazySerializedDOMNotification.java
binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/LazySerializedDOMNotificationTest.java

index 1ac34bed3e37df061d2f64c76eab1db98584c9bf..3ce2684d01bae73cf8a8f13b1d224bce33848c69 100644 (file)
@@ -10,13 +10,16 @@ package org.opendaylight.mdsal.binding.dom.adapter;
 import com.google.common.collect.ClassToInstanceMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.ListenableFuture;
+import java.time.Instant;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
 import org.opendaylight.mdsal.binding.dom.adapter.BindingDOMAdapterBuilder.Factory;
 import org.opendaylight.mdsal.dom.api.DOMNotification;
 import org.opendaylight.mdsal.dom.api.DOMNotificationPublishService;
 import org.opendaylight.mdsal.dom.api.DOMService;
+import org.opendaylight.yangtools.yang.binding.EventInstantAware;
 import org.opendaylight.yangtools.yang.binding.Notification;
 
 public class BindingDOMNotificationPublishServiceAdapter extends AbstractBindingAdapter<DOMNotificationPublishService>
@@ -66,12 +69,13 @@ public class BindingDOMNotificationPublishServiceAdapter extends AbstractBinding
                 : offerResult;
     }
 
-    private DOMNotification toDomNotification(final Notification notification) {
-        return LazySerializedDOMNotification.create(getCodec(), notification);
+    private @NonNull DOMNotification toDomNotification(final Notification notification) {
+        final Instant instant = notification instanceof EventInstantAware
+                ? ((EventInstantAware) notification).eventInstant() : Instant.now();
+        return LazySerializedDOMNotification.create(getCodec(), notification, instant);
     }
 
     protected static class Builder extends BindingDOMAdapterBuilder<NotificationPublishService> {
-
         @Override
         public Set<Class<? extends DOMService>> getRequiredDelegates() {
             return ImmutableSet.of(DOMNotificationPublishService.class);
@@ -83,6 +87,5 @@ public class BindingDOMNotificationPublishServiceAdapter extends AbstractBinding
             final DOMNotificationPublishService domPublish = delegates.getInstance(DOMNotificationPublishService.class);
             return new BindingDOMNotificationPublishServiceAdapter(codec, domPublish);
         }
-
     }
 }
index 6fd7f13edebb3733edf42f0b0d955a8ff24bed2c..f117ca0d03a9a84c568d817ef369523c030e9a48 100644 (file)
@@ -7,8 +7,13 @@
  */
 package org.opendaylight.mdsal.binding.dom.adapter;
 
+import static java.util.Objects.requireNonNull;
+
+import java.time.Instant;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
 import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
+import org.opendaylight.mdsal.dom.api.DOMEvent;
 import org.opendaylight.mdsal.dom.api.DOMNotification;
 import org.opendaylight.yangtools.yang.binding.Notification;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
@@ -18,28 +23,32 @@ import org.opendaylight.yangtools.yang.model.api.SchemaPath;
  * Lazy serialized implementation of DOM Notification.
  *
  * <p>
- * This implementation performs serialization of data, only if receiver
- * of notification actually accessed data from notification.
- *
+ * This implementation performs serialization of data, only if receiver of notification actually accessed data from
+ * notification.
  */
-public final class LazySerializedDOMNotification implements DOMNotification {
-
-    private final BindingNormalizedNodeSerializer codec;
-    private final Notification data;
-    private final SchemaPath type;
+public final class LazySerializedDOMNotification implements DOMNotification, DOMEvent {
+    private final @NonNull BindingNormalizedNodeSerializer codec;
+    private final @NonNull Notification data;
+    private final @NonNull SchemaPath type;
+    private final @NonNull Instant eventInstant;
 
-    private ContainerNode domBody;
+    private volatile ContainerNode domBody;
 
-    private LazySerializedDOMNotification(final BindingNormalizedNodeSerializer codec,
-            final Notification data, final SchemaPath type) {
-        this.codec = codec;
-        this.data = data;
-        this.type = type;
+    LazySerializedDOMNotification(final BindingNormalizedNodeSerializer codec, final Notification data,
+            final SchemaPath type, final Instant eventInstant) {
+        this.codec = requireNonNull(codec);
+        this.data = requireNonNull(data);
+        this.type = requireNonNull(type);
+        this.eventInstant = requireNonNull(eventInstant);
     }
 
-    static DOMNotification create(final BindingNormalizedNodeSerializer codec, final Notification data) {
-        final SchemaPath type = SchemaPath.create(true, BindingReflections.findQName(data.implementedInterface()));
-        return new LazySerializedDOMNotification(codec, data, type);
+    static @NonNull DOMNotification create(final BindingNormalizedNodeSerializer codec, final Notification data,
+            final Instant eventInstant) {
+        // TODO: for nested (YANG 1.1) notifications we will need the SchemaPath where the notification is being invoked
+        //       and use that instead of ROOT. How Binding users will refer to it is TBD (but probably
+        //       InstanceIdentifier, which means we will need to do some lifting to find the SchemaPath)
+        final SchemaPath type = SchemaPath.ROOT.createChild(BindingReflections.findQName(data.implementedInterface()));
+        return new LazySerializedDOMNotification(codec, data, type, eventInstant);
     }
 
     @Override
@@ -49,13 +58,19 @@ public final class LazySerializedDOMNotification implements DOMNotification {
 
     @Override
     public ContainerNode getBody() {
-        if (domBody == null) {
-            domBody = codec.toNormalizedNodeNotification(data);
+        ContainerNode local = domBody;
+        if (local == null) {
+            domBody = local = codec.toNormalizedNodeNotification(data);
         }
-        return domBody;
+        return local;
+    }
+
+    @Override
+    public Instant getEventInstant() {
+        return eventInstant;
     }
 
-    public Notification getBindingData() {
+    public @NonNull Notification getBindingData() {
         return data;
     }
 }
index 0891c5d085b0538f39b88fce8d4933a46d191253..951f286dd75ff6a72c6d0d92f85dac919249a2d5 100644 (file)
@@ -12,6 +12,7 @@ import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
+import java.time.Instant;
 import org.junit.Test;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
 import org.opendaylight.mdsal.dom.api.DOMNotification;
@@ -24,7 +25,7 @@ public class LazySerializedDOMNotificationTest {
     public void basicTest() throws Exception {
         BindingNormalizedNodeSerializer codec = mock(BindingNormalizedNodeSerializer.class);
         final DOMNotification lazySerializedDOMNotification =
-                LazySerializedDOMNotification.create(codec, new TwoLevelListChangedBuilder().build());
+                LazySerializedDOMNotification.create(codec, new TwoLevelListChangedBuilder().build(), Instant.now());
         ContainerNode containerNode = mock(ContainerNode.class);
         doReturn(containerNode).when(codec).toNormalizedNodeNotification(any());
         assertEquals(containerNode, lazySerializedDOMNotification.getBody());