Merge "BUG-3095 Add EventTime attribute to DOMNotification from netconf"
authorTony Tkacik <ttkacik@cisco.com>
Thu, 7 May 2015 10:26:05 +0000 (10:26 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 7 May 2015 10:26:06 +0000 (10:26 +0000)
15 files changed:
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMEvent.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/pom.xml
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/api/MessageTransformer.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/api/RemoteDeviceHandler.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NotificationHandler.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceNotificationService.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceSalFacade.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceSalProvider.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/schema/mapping/NetconfMessageTransformer.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTest.java
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfToNotificationTest.java
opendaylight/md-sal/sal-netconf-connector/src/test/resources/notification-payload.xml
opendaylight/netconf/netconf-cli/src/main/java/org/opendaylight/controller/netconf/cli/NetconfDeviceConnectionHandler.java

diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMEvent.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMEvent.java
new file mode 100644 (file)
index 0000000..1b8ec9b
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. 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.controller.md.sal.dom.api;
+
+import java.util.Date;
+
+/**
+ * Generic event interface
+ */
+public interface DOMEvent {
+
+    /**
+     * Get the time of the event occurrence
+     *
+     * @return the event time
+     */
+    Date getEventTime();
+}
index fd4d38a1111a871cbc33cc005d2ad2bd95528bdf..f407a4431cb293f9f5fea53bbed486c8dc08907a 100644 (file)
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>netconf-client</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>netconf-notifications-api</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>netty-config-api</artifactId>
index dc27cd6572c9dcaa8504c0c3b321db9092dd9474..861aaa43db362dc2c0f89caee51e4727434cbceb 100644 (file)
@@ -7,14 +7,14 @@
  */
 package org.opendaylight.controller.sal.connect.api;
 
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 
 public interface MessageTransformer<M> {
 
-    ContainerNode toNotification(M message);
+    DOMNotification toNotification(M message);
 
     M toRpcRequest(SchemaPath rpc, NormalizedNode<?, ?> node);
 
index 02f45e5bc33a288746954f077d13e32a7ee224b0..07c5fcb620464c62621ba93d6ec882e03edcc3e8 100644 (file)
@@ -7,8 +7,8 @@
  */
 package org.opendaylight.controller.sal.connect.api;
 
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 public interface RemoteDeviceHandler<PREF> extends AutoCloseable {
@@ -20,7 +20,7 @@ public interface RemoteDeviceHandler<PREF> extends AutoCloseable {
 
     void onDeviceFailed(Throwable throwable);
 
-    void onNotification(ContainerNode domNotification);
+    void onNotification(DOMNotification domNotification);
 
     void close();
 }
index c0b57de9a0d32ed26c60fa64e8dcfb551c62a354..a7ae9cb177a10ede9eebf2dab37812109996d00a 100644 (file)
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
@@ -47,7 +48,6 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.not
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.fields.unavailable.capabilities.UnavailableCapability;
 import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
 import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
@@ -182,18 +182,18 @@ public final class NetconfDevice implements RemoteDevice<NetconfSessionPreferenc
 
         final NotificationHandler.NotificationFilter filter = new NotificationHandler.NotificationFilter() {
             @Override
-            public Optional<NormalizedNode<?, ?>> filterNotification(final NormalizedNode<?, ?> notification) {
+            public Optional<DOMNotification> filterNotification(final DOMNotification notification) {
                 if (isCapabilityChanged(notification)) {
                     logger.info("{}: Schemas change detected, reconnecting", id);
                     // Only disconnect is enough, the reconnecting nature of the connector will take care of reconnecting
                     listener.disconnect();
                     return Optional.absent();
                 }
-                return Optional.<NormalizedNode<?, ?>>of(notification);
+                return Optional.of(notification);
             }
 
-            private boolean isCapabilityChanged(final NormalizedNode<?, ?> notification) {
-                return notification.getNodeType().equals(NetconfCapabilityChange.QNAME);
+            private boolean isCapabilityChanged(final DOMNotification notification) {
+                return notification.getBody().getNodeType().equals(NetconfCapabilityChange.QNAME);
             }
         };
 
index 481afa5c833e9e74719d4aa2593b9953b86b2083..2d47c6ae1bbe11f5863d66c97db5301208fa29ae 100644 (file)
@@ -11,13 +11,12 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import java.util.LinkedList;
 import java.util.List;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.controller.sal.connect.api.MessageTransformer;
 import org.opendaylight.controller.sal.connect.api.RemoteDeviceHandler;
 import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -65,8 +64,8 @@ final class NotificationHandler {
         queue.clear();
     }
 
-    private ContainerNode transformNotification(final NetconfMessage cachedNotification) {
-        final ContainerNode parsedNotification = messageTransformer.toNotification(cachedNotification);
+    private DOMNotification transformNotification(final NetconfMessage cachedNotification) {
+        final DOMNotification parsedNotification = messageTransformer.toNotification(cachedNotification);
         Preconditions.checkNotNull(parsedNotification, "%s: Unable to parse received notification: %s", id, cachedNotification);
         return parsedNotification;
     }
@@ -82,7 +81,7 @@ final class NotificationHandler {
         queue.add(notification);
     }
 
-    private synchronized void passNotification(final ContainerNode parsedNotification) {
+    private synchronized void passNotification(final DOMNotification parsedNotification) {
         logger.debug("{}: Forwarding notification {}", id, parsedNotification);
 
         if(filter == null || filter.filterNotification(parsedNotification).isPresent()) {
@@ -102,6 +101,6 @@ final class NotificationHandler {
 
     static interface NotificationFilter {
 
-        Optional<NormalizedNode<?, ?>> filterNotification(NormalizedNode<?, ?> notification);
+        Optional<DOMNotification> filterNotification(DOMNotification notification);
     }
 }
index bfcb4caddb9754c89b9ee1fa9f9bd13aa108dff4..b27430f5e3a5483ed02951787c33ddfeb2df42d7 100644 (file)
@@ -8,8 +8,6 @@
 
 package org.opendaylight.controller.sal.connect.netconf.sal;
 
-import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.toPath;
-
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Multimap;
@@ -19,7 +17,6 @@ import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
 import org.opendaylight.controller.md.sal.dom.api.DOMNotificationListener;
 import org.opendaylight.controller.md.sal.dom.api.DOMNotificationService;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 
 class NetconfDeviceNotificationService implements DOMNotificationService {
@@ -28,22 +25,9 @@ class NetconfDeviceNotificationService implements DOMNotificationService {
 
     // Notification publish is very simple and hijacks the thread of the caller
     // TODO shouldnt we reuse the implementation for notification router from sal-broker-impl ?
-    public synchronized void publishNotification(final ContainerNode notification) {
-        final SchemaPath schemaPath = toPath(notification.getNodeType());
-        for (final DOMNotificationListener domNotificationListener : listeners.get(schemaPath)) {
-            domNotificationListener.onNotification(new DOMNotification() {
-                @Nonnull
-                @Override
-                public SchemaPath getType() {
-                    return schemaPath;
-                }
-
-                @Nonnull
-                @Override
-                public ContainerNode getBody() {
-                    return notification;
-                }
-            });
+    public synchronized void publishNotification(final DOMNotification notification) {
+        for (final DOMNotificationListener domNotificationListener : listeners.get(notification.getType())) {
+            domNotificationListener.onNotification(notification);
         }
     }
 
index 11f82c02bfb9b9e8e65925cd0a7d0b802737267b..7ffeec3096934995dbc5dd73844ff49999d190c8 100644 (file)
@@ -11,6 +11,7 @@ import com.google.common.collect.Lists;
 import java.util.Collections;
 import java.util.List;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.connect.api.RemoteDeviceHandler;
@@ -19,7 +20,6 @@ import org.opendaylight.controller.sal.connect.netconf.listener.NetconfSessionPr
 import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
@@ -46,7 +46,7 @@ public final class NetconfDeviceSalFacade implements AutoCloseable, RemoteDevice
     }
 
     @Override
-    public synchronized void onNotification(final ContainerNode domNotification) {
+    public synchronized void onNotification(final DOMNotification domNotification) {
         salProvider.getMountInstance().publish(domNotification);
     }
 
index 2931468501a17d851f5629ef151f4d22bd992495..bf870bf36a07ccd421f86e9eeba1571ad73f0e5e 100644 (file)
@@ -14,6 +14,7 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
 import org.opendaylight.controller.md.sal.dom.api.DOMNotificationService;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
@@ -22,7 +23,6 @@ import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.controller.sal.core.api.Provider;
 import org.opendaylight.yangtools.concepts.ObjectRegistration;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -187,7 +187,7 @@ final class NetconfDeviceSalProvider implements AutoCloseable, Provider, Binding
             mountService = null;
         }
 
-        public synchronized void publish(final ContainerNode domNotification) {
+        public synchronized void publish(final DOMNotification domNotification) {
             Preconditions.checkNotNull(notificationService, "Device not set up yet, cannot handle notification {}", domNotification);
             notificationService.publishNotification(domNotification);
         }
index 819edce320d30f827f90f3c7358ed95ebefed0d4..5b579a0a8a3ecd936e6e5b6605b065dcc3f3fd6e 100644 (file)
@@ -7,30 +7,38 @@
  */
 package org.opendaylight.controller.sal.connect.netconf.schema.mapping;
 
+import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.EVENT_TIME;
 import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_RPC_QNAME;
 import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_URI;
+import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.toPath;
 
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Multimaps;
 import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.AbstractMap;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
-import java.util.NoSuchElementException;
 import java.util.Set;
+import javax.annotation.Nonnull;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
 import javax.xml.transform.dom.DOMResult;
+import org.opendaylight.controller.md.sal.dom.api.DOMEvent;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
 import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.notifications.NetconfNotification;
 import org.opendaylight.controller.netconf.util.OrderedNormalizedNodeWriter;
 import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
@@ -111,12 +119,12 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
     }
 
     @Override
-    public synchronized ContainerNode toNotification(final NetconfMessage message) {
-        final XmlElement stripped = stripNotification(message);
+    public synchronized DOMNotification toNotification(final NetconfMessage message) {
+        final Map.Entry<Date, XmlElement> stripped = stripNotification(message);
         final QName notificationNoRev;
         try {
             // How to construct QName with no revision ?
-            notificationNoRev = QName.cachedReference(QName.create(stripped.getNamespace(), "0000-00-00", stripped.getName()).withoutRevision());
+            notificationNoRev = QName.cachedReference(QName.create(stripped.getValue().getNamespace(), "0000-00-00", stripped.getValue().getName()).withoutRevision());
         } catch (final MissingNameSpaceException e) {
             throw new IllegalArgumentException("Unable to parse notification " + message + ", cannot find namespace", e);
         }
@@ -131,23 +139,43 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
 
         // We wrap the notification as a container node in order to reuse the parsers and builders for container node
         final ContainerSchemaNode notificationAsContainerSchemaNode = NetconfMessageTransformUtil.createSchemaForNotification(next);
-        return parserFactory.getContainerNodeParser().parse(Collections.singleton(stripped.getDomElement()), notificationAsContainerSchemaNode);
+        final ContainerNode content = parserFactory.getContainerNodeParser().parse(Collections.singleton(stripped.getValue().getDomElement()),
+                notificationAsContainerSchemaNode);
+        return new NetconfDeviceNotification(content, stripped.getKey());
     }
 
     // FIXME move somewhere to util
-    private static XmlElement stripNotification(final NetconfMessage message) {
+    private static Map.Entry<Date, XmlElement> stripNotification(final NetconfMessage message) {
         final XmlElement xmlElement = XmlElement.fromDomDocument(message.getDocument());
         final List<XmlElement> childElements = xmlElement.getChildElements();
         Preconditions.checkArgument(childElements.size() == 2, "Unable to parse notification %s, unexpected format", message);
+
+        final XmlElement eventTimeElement;
+        final XmlElement notificationElement;
+
+        if (childElements.get(0).getName().equals(EVENT_TIME)) {
+            eventTimeElement = childElements.get(0);
+            notificationElement = childElements.get(1);
+        }
+        else if(childElements.get(1).getName().equals(EVENT_TIME)) {
+            eventTimeElement = childElements.get(1);
+            notificationElement = childElements.get(0);
+        } else {
+            throw new IllegalArgumentException("Notification payload does not contain " + EVENT_TIME + " " + message);
+        }
+
         try {
-            return Iterables.find(childElements, new Predicate<XmlElement>() {
-                @Override
-                public boolean apply(final XmlElement xmlElement) {
-                    return !xmlElement.getName().equals("eventTime");
-                }
-            });
-        } catch (final NoSuchElementException e) {
-            throw new IllegalArgumentException("Unable to parse notification " + message + ", cannot strip notification metadata", e);
+            return new AbstractMap.SimpleEntry<>(parseEventTime(eventTimeElement.getTextContent()), notificationElement);
+        } catch (NetconfDocumentedException e) {
+            throw new IllegalArgumentException("Notification payload does not contain " + EVENT_TIME + " " + message);
+        }
+    }
+
+    private static Date parseEventTime(final String eventTime) {
+        try {
+            return new SimpleDateFormat(NetconfNotification.RFC3339_DATE_FORMAT_BLUEPRINT).parse(eventTime);
+        } catch (ParseException e) {
+            throw new IllegalArgumentException("Unable to parse event time from " + eventTime, e);
         }
     }
 
@@ -268,4 +296,33 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
         return new DefaultDOMRpcResult(normalizedNode);
     }
 
+    private static class NetconfDeviceNotification implements DOMNotification, DOMEvent {
+        private final ContainerNode content;
+        private final SchemaPath schemaPath;
+        private final Date eventTime;
+
+        NetconfDeviceNotification(final ContainerNode content, final Date eventTime) {
+            this.content = content;
+            this.eventTime = eventTime;
+            this.schemaPath = toPath(content.getNodeType());
+        }
+
+        @Nonnull
+        @Override
+        public SchemaPath getType() {
+            return schemaPath;
+
+        }
+
+        @Nonnull
+        @Override
+        public ContainerNode getBody() {
+            return content;
+        }
+
+        @Override
+        public Date getEventTime() {
+            return eventTime;
+        }
+    }
 }
index 1da39cf751cba27b999642c20da9d7659a45a728..ca1531b896b70eaa5bc050dcea76b307ccb766b6 100644 (file)
@@ -73,6 +73,7 @@ public class NetconfMessageTransformUtil {
 
     // Blank document used for creation of new DOM nodes
     private static final Document BLANK_DOCUMENT = XmlUtil.newDocument();
+    public static final String EVENT_TIME = "eventTime";
 
     private NetconfMessageTransformUtil() {}
 
index 93f4df83e44382b0f87b94a80c30b29ab98b4c4e..34972dffe2d4f09493e8b3bf5bba08557a00c552 100644 (file)
@@ -35,6 +35,7 @@ import org.junit.Test;
 import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
 import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
@@ -193,7 +194,7 @@ public class NetconfDeviceTest {
         device.onNotification(notification);
         device.onNotification(notification);
 
-        verify(facade, times(0)).onNotification(any(ContainerNode.class));
+        verify(facade, times(0)).onNotification(any(DOMNotification.class));
 
         final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
                 Lists.newArrayList(TEST_CAPABILITY));
@@ -202,10 +203,10 @@ public class NetconfDeviceTest {
 
         device.handleSalInitializationSuccess(NetconfToNotificationTest.getNotificationSchemaContext(getClass()), sessionCaps, deviceRpc);
 
-        verify(facade, timeout(10000).times(2)).onNotification(any(ContainerNode.class));
+        verify(facade, timeout(10000).times(2)).onNotification(any(DOMNotification.class));
 
         device.onNotification(notification);
-        verify(facade, timeout(10000).times(3)).onNotification(any(ContainerNode.class));
+        verify(facade, timeout(10000).times(3)).onNotification(any(DOMNotification.class));
     }
 
     @Test
@@ -253,7 +254,7 @@ public class NetconfDeviceTest {
         final RemoteDeviceHandler<NetconfSessionPreferences> remoteDeviceHandler = mockCloseableClass(RemoteDeviceHandler.class);
         doNothing().when(remoteDeviceHandler).onDeviceConnected(any(SchemaContext.class), any(NetconfSessionPreferences.class), any(NetconfDeviceRpc.class));
         doNothing().when(remoteDeviceHandler).onDeviceDisconnected();
-        doNothing().when(remoteDeviceHandler).onNotification(any(ContainerNode.class));
+        doNothing().when(remoteDeviceHandler).onNotification(any(DOMNotification.class));
         return remoteDeviceHandler;
     }
 
index 294efadc6f9506cb32bdaa7e8404b33c6a034e89..96c478f0977c2c963ef14c497bd3e64f9c9a0102 100644 (file)
@@ -6,13 +6,17 @@ import static org.junit.Assert.assertTrue;
 
 import com.google.common.collect.Iterables;
 import java.io.InputStream;
+import java.text.SimpleDateFormat;
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 import javax.xml.parsers.DocumentBuilderFactory;
 import org.junit.Before;
 import org.junit.Test;
+import org.opendaylight.controller.md.sal.dom.api.DOMEvent;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.notifications.NetconfNotification;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.controller.sal.connect.netconf.schema.mapping.NetconfMessageTransformer;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
@@ -60,9 +64,12 @@ public class NetconfToNotificationTest {
 
     @Test
     public void test() throws Exception {
-        final ContainerNode root = messageTransformer.toNotification(userNotification);
+        final DOMNotification domNotification = messageTransformer.toNotification(userNotification);
+        final ContainerNode root = domNotification.getBody();
         assertNotNull(root);
         assertEquals(6, Iterables.size(root.getValue()));
         assertEquals("user-visited-page", root.getNodeType().getLocalName());
+        assertEquals(new SimpleDateFormat(NetconfNotification.RFC3339_DATE_FORMAT_BLUEPRINT).parse("2007-07-08T00:01:00Z"),
+                ((DOMEvent) domNotification).getEventTime());
     }
 }
index 837fcc1a70a2c171d1b530d1449f8686d06ca64a..431787d34c929b84d56e98a675f4228010a64bed 100644 (file)
@@ -1,5 +1,5 @@
 <notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
-<eventTime>2014-07-08T11:20:48UTC</eventTime>
+<eventTime>2007-07-08T00:01:00Z</eventTime>
 <user-visited-page xmlns="org:opendaylight:notification:test:ns:yang:user-notification">
   <ui:incoming-user xmlns:ui="org:opendaylight:notification:test:ns:yang:user-notification">ui:public-user</ui:incoming-user>
   <ip-address>172.23.29.104</ip-address>
index 50c324313555fca9dbd6413bf2a51a747b818b77..aa9f4e8811ce7cd7d6aa889efef2a0e3947159e3 100644 (file)
@@ -10,13 +10,13 @@ package org.opendaylight.controller.netconf.cli;
 import com.google.common.base.Optional;
 import jline.console.completer.Completer;
 import jline.console.completer.NullCompleter;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
 import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
 import org.opendaylight.controller.netconf.cli.commands.CommandDispatcher;
 import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
 import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
 import org.opendaylight.controller.sal.connect.api.RemoteDeviceHandler;
 import org.opendaylight.controller.sal.connect.netconf.listener.NetconfSessionPreferences;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 /**
@@ -87,7 +87,7 @@ public class NetconfDeviceConnectionHandler implements RemoteDeviceHandler<Netco
     }
 
     @Override
-    public void onNotification(ContainerNode domNotification) {
+    public void onNotification(DOMNotification domNotification) {
 
     }