Bug 5708 - Schemaless mount point notifications 23/39123/4
authorJakub Morvay <jmorvay@cisco.com>
Thu, 19 May 2016 16:05:52 +0000 (18:05 +0200)
committerJakub Morvay <jmorvay@cisco.com>
Fri, 17 Jun 2016 14:11:51 +0000 (14:11 +0000)
Add support for notifications for schemaless mountpoints.
SchemalessMessageTransformer treats notification's payload as anyxml
node. To conform to API transformer wraps this payload in container node
with notification type as node identifier.

Change-Id: I4aceee416c8d630fe7689738b34fda3778d9f10f
Signed-off-by: Jakub Morvay <jmorvay@cisco.com>
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/SchemalessNetconfDevice.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/SchemalessNetconfDeviceRpc.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/schema/mapping/NetconfMessageTransformer.java
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/schema/mapping/SchemalessMessageTransformer.java
netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/SchemalessNetconfDeviceRpcTest.java

index 74e64354e10475d9710e81ff86c588e2c0cdad04..758c46c80df8a9d73a6160a7dd988fe26c145f25 100644 (file)
@@ -13,7 +13,10 @@ import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
 import org.opendaylight.netconf.sal.connect.netconf.sal.SchemalessNetconfDeviceRpc;
+import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseRpcSchemalessTransformer;
 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseSchema;
+import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.SchemalessMessageTransformer;
+import org.opendaylight.netconf.sal.connect.util.MessageCounter;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 
 public class SchemalessNetconfDevice implements
@@ -21,18 +24,22 @@ public class SchemalessNetconfDevice implements
 
     private RemoteDeviceId id;
     private RemoteDeviceHandler<NetconfSessionPreferences> salFacade;
+    private final SchemalessMessageTransformer messageTransformer;
+    private final BaseRpcSchemalessTransformer rpcTransformer;
 
     public SchemalessNetconfDevice(final RemoteDeviceId id,
                                    final RemoteDeviceHandler<NetconfSessionPreferences> salFacade) {
         this.id = id;
         this.salFacade = salFacade;
+        final MessageCounter counter = new MessageCounter();
+        rpcTransformer = new BaseRpcSchemalessTransformer(counter);
+        messageTransformer = new SchemalessMessageTransformer(counter);
     }
 
     @Override public void onRemoteSessionUp(final NetconfSessionPreferences remoteSessionCapabilities,
                                             final NetconfDeviceCommunicator netconfDeviceCommunicator) {
-
         final SchemalessNetconfDeviceRpc schemalessNetconfDeviceRpc = new SchemalessNetconfDeviceRpc(id,
-                netconfDeviceCommunicator);
+                netconfDeviceCommunicator, rpcTransformer, messageTransformer);
 
         salFacade.onDeviceConnected(BaseSchema.BASE_NETCONF_CTX.getSchemaContext(),
                 remoteSessionCapabilities, schemalessNetconfDeviceRpc);
@@ -48,6 +55,6 @@ public class SchemalessNetconfDevice implements
     }
 
     @Override public void onNotification(final NetconfMessage notification) {
-        // TODO support for notifications
+        salFacade.onNotification(messageTransformer.toNotification(notification));
     }
 }
index d610904e6b76f2e34144d6c1a1f78a0c640e192b..68d20c7e42159b2a1b13d844f672c4f953c58bd7 100644 (file)
@@ -25,7 +25,6 @@ import org.opendaylight.netconf.sal.connect.api.RemoteDeviceCommunicator;
 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseRpcSchemalessTransformer;
 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.SchemalessMessageTransformer;
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
-import org.opendaylight.netconf.sal.connect.util.MessageCounter;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -45,13 +44,13 @@ public final class SchemalessNetconfDeviceRpc implements DOMRpcService {
     private final SchemalessMessageTransformer schemalessTransformer;
     private final RemoteDeviceId deviceId;
 
-    public SchemalessNetconfDeviceRpc(final RemoteDeviceId deviceId,
-                                      final RemoteDeviceCommunicator<NetconfMessage> listener) {
+    public SchemalessNetconfDeviceRpc(RemoteDeviceId deviceId, final RemoteDeviceCommunicator<NetconfMessage> listener,
+                                      final BaseRpcSchemalessTransformer baseRpcTransformer,
+                                      final SchemalessMessageTransformer messageTransformer) {
         this.deviceId = deviceId;
         this.listener = listener;
-        final MessageCounter counter = new MessageCounter();
-        baseRpcTransformer = new BaseRpcSchemalessTransformer(counter);
-        schemalessTransformer = new SchemalessMessageTransformer(counter);
+        this.baseRpcTransformer = baseRpcTransformer;
+        this.schemalessTransformer = messageTransformer;
     }
 
     @Nonnull
index bf8249fa8474b1cbe149b9401a2500e2358b7a2c..0abd74409709240a7b9ab13620e9b484b096b1b2 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.netconf.sal.connect.netconf.schema.mapping;
 
 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.IETF_NETCONF_NOTIFICATIONS;
 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_URI;
+import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.stripNotification;
 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toPath;
 
 import com.google.common.base.Function;
@@ -222,7 +223,7 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
         return new DefaultDOMRpcResult(normalizedNode);
     }
 
-    private static class NetconfDeviceNotification implements DOMNotification, DOMEvent {
+    static class NetconfDeviceNotification implements DOMNotification, DOMEvent {
         private final ContainerNode content;
         private final SchemaPath schemaPath;
         private final Date eventTime;
index 04c502399d1e7b58eec6c20864b7b3a396754a31..00fb9b4645d55a37b2e82132e2ae6b732a048d7f 100644 (file)
@@ -7,7 +7,11 @@
  */
 package org.opendaylight.netconf.sal.connect.netconf.schema.mapping;
 
+import java.util.Date;
+import java.util.Map;
 import javax.xml.transform.dom.DOMSource;
+import org.opendaylight.controller.config.util.xml.MissingNameSpaceException;
+import org.opendaylight.controller.config.util.xml.XmlElement;
 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;
@@ -15,8 +19,10 @@ import org.opendaylight.netconf.api.NetconfMessage;
 import org.opendaylight.netconf.sal.connect.api.MessageTransformer;
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
 import org.opendaylight.netconf.sal.connect.util.MessageCounter;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
@@ -30,6 +36,10 @@ public class SchemalessMessageTransformer implements MessageTransformer<NetconfM
 
     private static final YangInstanceIdentifier.NodeIdentifier REPLY_ID =
             new YangInstanceIdentifier.NodeIdentifier(NetconfMessageTransformUtil.NETCONF_RPC_REPLY_QNAME);
+    // TODO maybe we should move this somewhere else as this
+    // might be used in applications using schemaless mountpoints
+    public static final YangInstanceIdentifier.NodeIdentifier SCHEMALESS_NOTIFICATION_PAYLOAD =
+            new YangInstanceIdentifier.NodeIdentifier(QName.create("schemaless-notification-payload"));
 
     private final MessageCounter counter;
 
@@ -39,8 +49,26 @@ public class SchemalessMessageTransformer implements MessageTransformer<NetconfM
 
     @Override
     public DOMNotification toNotification(final NetconfMessage message) {
-        //TODO add support for notifications
-        throw new UnsupportedOperationException("Notifications not supported.");
+        final Map.Entry<Date, XmlElement> stripped = NetconfMessageTransformUtil.stripNotification(message);
+        final QName notificationNoRev;
+        try {
+            notificationNoRev =
+                    QName.create(stripped.getValue().getNamespace(), stripped.getValue().getName()).withoutRevision();
+        } catch (final MissingNameSpaceException e) {
+            throw new IllegalArgumentException("Unable to parse notification " + message + ", cannot find namespace", e);
+        }
+
+        final AnyXmlNode notificationPayload = Builders.anyXmlBuilder()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(notificationNoRev))
+                .withValue(new DOMSource(stripped.getValue().getDomElement()))
+                .build();
+
+        final ContainerNode notificationBody = Builders.containerBuilder()
+                .withNodeIdentifier(SCHEMALESS_NOTIFICATION_PAYLOAD)
+                .withChild(notificationPayload)
+                .build();
+
+        return new NetconfMessageTransformer.NetconfDeviceNotification(notificationBody, stripped.getKey());
     }
 
     @Override
index 575b7b96994d92307d8b8f9f9f309b9d13376a4b..237021930a9a28457315bee4f05dfe3ace3a2215 100644 (file)
@@ -16,6 +16,9 @@ import org.mockito.MockitoAnnotations;
 import org.opendaylight.controller.config.util.xml.XmlUtil;
 import org.opendaylight.netconf.api.NetconfMessage;
 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceCommunicator;
+import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseRpcSchemalessTransformer;
+import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.SchemalessMessageTransformer;
+import org.opendaylight.netconf.sal.connect.util.MessageCounter;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -37,7 +40,10 @@ public class SchemalessNetconfDeviceRpcTest {
         RpcResult<NetconfMessage> msg = null;
         ListenableFuture<RpcResult<NetconfMessage>> future = Futures.immediateFuture(msg);
         doReturn(future).when(listener).sendRequest(any(), any());
-        deviceRpc = new SchemalessNetconfDeviceRpc(new RemoteDeviceId("device1", InetSocketAddress.createUnresolved("0.0.0.0", 17830)), listener);
+        final MessageCounter counter = new MessageCounter();
+        deviceRpc = new SchemalessNetconfDeviceRpc(
+                new RemoteDeviceId("device1", InetSocketAddress.createUnresolved("0.0.0.0", 17830)), listener,
+                new BaseRpcSchemalessTransformer(counter), new SchemalessMessageTransformer(counter));
 
     }