BUG 2412 - restconf @POST invokeRpc for notification subscription 48/15948/13
authorVaclav Demcak <vdemcak@cisco.com>
Mon, 9 Mar 2015 13:32:32 +0000 (14:32 +0100)
committerVaclav Demcak <vdemcak@cisco.com>
Mon, 9 Mar 2015 14:41:57 +0000 (15:41 +0100)
* modified notification subscription to work on new api
* added conversion to normalized instance identifier in notification
subscription path
* removed mixin nodes from data change event path
* modified returned paths to skip augmentation identifiers in change
event path
* modified returned location header entry on get stream to use "ws"
protocol

Change-Id: If7f5e92eedbebe0daeb149a38d429a1dcb47c1c9
Signed-off-by: Vaclav Demcak <vdemcak@cisco.com>
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/listeners/ListenerAdapter.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/websockets/WebSocketServerHandler.java

index 5566f01674a3112e2f0dd09c8287b17a9e0752b4..a0b05150a84344a8c0cff9ca08472ac3067f2498 100644 (file)
@@ -31,6 +31,7 @@ import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
 import javax.ws.rs.core.Response.Status;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
@@ -955,6 +956,26 @@ public class ControllerContext implements SchemaContextListener {
         }
     }
 
+    public YangInstanceIdentifier toXpathRepresentation(final YangInstanceIdentifier instanceIdentifier) {
+        try {
+            return dataNormalizer.toLegacy(instanceIdentifier);
+        } catch (NullPointerException e) {
+            throw new RestconfDocumentedException("Data normalizer isn't set. Normalization isn't possible", e);
+        } catch (DataNormalizationException e) {
+            throw new RestconfDocumentedException("Data normalizer failed. Normalization isn't possible", e);
+        }
+    }
+
+    public boolean isNodeMixin(YangInstanceIdentifier path) {
+        final DataNormalizationOperation<?> operation;
+        try {
+            operation = dataNormalizer.getOperation(path);
+        } catch (DataNormalizationException e) {
+            throw new RestconfDocumentedException("Data normalizer failed. Normalization isn't possible", e);
+        }
+        return operation.isMixin();
+    }
+
     public DataNormalizationOperation<?> getRootOperation() {
         return dataNormalizer.getRootOperation();
     }
index 20e27c8a143e41e3630fc3943278405d7c8becc9..82ac862843b78db99d1707dce5ac701b139185e8 100644 (file)
@@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
 import java.math.BigInteger;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -50,6 +51,7 @@ import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 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;
+import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
 import org.opendaylight.controller.sal.rest.api.Draft02;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
 import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
@@ -65,7 +67,6 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -74,6 +75,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdent
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
@@ -83,9 +85,11 @@ import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.parser.Cn
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
@@ -469,7 +473,7 @@ public class RestconfImpl implements RestconfService {
         instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
                 ((DataNodeContainer) streamSchemaNode), "events");
         final DataSchemaNode eventsSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
-        streamNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(eventsSchemaNode.getQName(), null, ""));
+        streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(eventsSchemaNode.getQName(), null, ""));
 
         return NodeFactory.createImmutableCompositeNode(streamSchemaNode.getQName(), null, streamNodeValues);
     }
@@ -523,6 +527,7 @@ public class RestconfImpl implements RestconfService {
     @Override
     public NormalizedNodeContext invokeRpc(final String identifier, final NormalizedNodeContext payload, final UriInfo uriInfo) {
         final SchemaPath type = payload.getInstanceIdentifierContext().getSchemaNode().getPath();
+        final URI namespace = payload.getInstanceIdentifierContext().getSchemaNode().getQName().getNamespace();
         final CheckedFuture<DOMRpcResult, DOMRpcException> response;
         final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint();
         final SchemaContext schemaContext;
@@ -534,7 +539,11 @@ public class RestconfImpl implements RestconfService {
             schemaContext = mountPoint.getSchemaContext();
             response = mountRpcServices.get().invokeRpc(type, payload.getData());
         } else {
-            response = broker.invokeRpc(type, payload.getData());
+            if (namespace.toString().equals(SAL_REMOTE_NAMESPACE)) {
+                response = invokeSalRemoteRpcSubscribeRPC(payload);
+            } else {
+                response = broker.invokeRpc(type, payload.getData());
+            }
             schemaContext = controllerContext.getGlobalSchema();
         }
 
@@ -631,16 +640,12 @@ public class RestconfImpl implements RestconfService {
         // }
     }
 
-    /**
-     * @deprecated method wil be removed for Lithium release
-     */
-    @Deprecated
-    private StructuredData invokeSalRemoteRpcSubscribeRPC(final CompositeNode payload, final RpcDefinition rpc,
-            final boolean prettyPrint) {
-        final CompositeNode value = this.normalizeNode(payload, rpc.getInput(), null);
-        final SimpleNode<? extends Object> pathNode = value == null ? null : value.getFirstSimpleByName(QName.create(
-                rpc.getQName(), "path"));
-        final Object pathValue = pathNode == null ? null : pathNode.getValue();
+    private CheckedFuture<DOMRpcResult, DOMRpcException> invokeSalRemoteRpcSubscribeRPC(final NormalizedNodeContext payload) {
+        final ContainerNode value = (ContainerNode) payload.getData();
+        final QName rpcQName = payload.getInstanceIdentifierContext().getSchemaNode().getQName();
+        Optional<DataContainerChild<? extends PathArgument, ?>> path = value.getChild(new NodeIdentifier(
+                QName.create(payload.getInstanceIdentifierContext().getSchemaNode().getQName(), "path")));
+        final Object pathValue = path.isPresent() ? path.get().getValue() : null;
 
         if (!(pathValue instanceof YangInstanceIdentifier)) {
             throw new RestconfDocumentedException("Instance identifier was not normalized correctly.",
@@ -665,23 +670,24 @@ public class RestconfImpl implements RestconfService {
 
         if (Strings.isNullOrEmpty(streamName)) {
             throw new RestconfDocumentedException(
-                    "Path is empty or contains data node which is not Container or List build-in type.",
+                    "Path is empty or contains value node which is not Container or List build-in type.",
                     ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
         }
 
-        final SimpleNode<String> streamNameNode = NodeFactory.<String> createImmutableSimpleNode(
-                QName.create(rpc.getOutput().getQName(), "stream-name"), null, streamName);
-        final List<Node<?>> output = new ArrayList<Node<?>>();
-        output.add(streamNameNode);
+        QName outputQname = QName.create(rpcQName, "output");
+        QName streamNameQname = QName.create(rpcQName, "stream-name");
 
-        final MutableCompositeNode responseData = NodeFactory.createMutableCompositeNode(rpc.getOutput().getQName(),
-                null, output, null, null);
+        ContainerNode output = ImmutableContainerNodeBuilder.create().withNodeIdentifier(new NodeIdentifier(outputQname))
+                .withChild(ImmutableNodes.leafNode(streamNameQname, streamName)).build();
 
         if (!Notificator.existListenerFor(streamName)) {
-            Notificator.createListener(pathIdentifier, streamName);
+            YangInstanceIdentifier normalizedPathIdentifier = controllerContext.toNormalized(pathIdentifier);
+            Notificator.createListener(normalizedPathIdentifier, streamName);
         }
 
-        return new StructuredData(responseData, rpc.getOutput(), null, prettyPrint);
+        DOMRpcResult defaultDOMRpcResult = new DefaultDOMRpcResult(output);
+
+        return Futures.immediateCheckedFuture(defaultDOMRpcResult);
     }
 
     @Override
@@ -1341,8 +1347,8 @@ public class RestconfImpl implements RestconfService {
         } catch (final NullPointerException e) {
             WebSocketServer.createInstance(NOTIFICATION_PORT);
         }
-        final UriBuilder port = uriBuilder.port(notificationPort);
-        final URI uriToWebsocketServer = port.replacePath(streamName).build();
+        final UriBuilder uriToWebsocketServerBuilder = uriBuilder.port(notificationPort).scheme("ws");
+        final URI uriToWebsocketServer = uriToWebsocketServerBuilder.replacePath(streamName).build();
 
         return Response.status(Status.OK).location(uriToWebsocketServer).build();
     }
@@ -1354,15 +1360,16 @@ public class RestconfImpl implements RestconfService {
      *            contains value
      * @return enum object if its string value is equal to {@code paramName}. In other cases null.
      */
-    private <T> T parseEnumTypeParameter(final CompositeNode compNode, final Class<T> classDescriptor,
+    private <T> T parseEnumTypeParameter(final ContainerNode value, final Class<T> classDescriptor,
             final String paramName) {
         final QNameModule salRemoteAugment = QNameModule.create(NAMESPACE_EVENT_SUBSCRIPTION_AUGMENT,
                 EVENT_SUBSCRIPTION_AUGMENT_REVISION);
-        final SimpleNode<?> simpleNode = compNode.getFirstSimpleByName(QName.create(salRemoteAugment, paramName));
-        if (simpleNode == null) {
+        Optional<DataContainerChild<? extends PathArgument, ?>> enumNode = value.getChild(new NodeIdentifier(
+                QName.create(salRemoteAugment, paramName)));
+        if (!enumNode.isPresent()) {
             return null;
         }
-        final Object rawValue = simpleNode.getValue();
+        final Object rawValue = enumNode.get().getValue();
         if (!(rawValue instanceof String)) {
             return null;
         }
@@ -1517,7 +1524,7 @@ public class RestconfImpl implements RestconfService {
          * || MOUNT_POINT_MODULE_NAME .equals( namespace .
          * toString( ) )
          */)
-         && SchemaContext.NAME.getLocalName().equals(localName(data));
+                && SchemaContext.NAME.getLocalName().equals(localName(data));
     }
 
     private String addMountPointIdentifier(final String identifier) {
@@ -1960,8 +1967,47 @@ public class RestconfImpl implements RestconfService {
 
     protected MapEntryNode toModuleEntryNode(final Module module, final DataSchemaNode moduleSchemaNode) {
         Preconditions.checkArgument(moduleSchemaNode instanceof ListSchemaNode,
-                "moduleSchemaNode has to be of type ListSchemaNode");\r        final ListSchemaNode listModuleSchemaNode = (ListSchemaNode) moduleSchemaNode;\r        final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> moduleNodeValues = Builders\r                .mapEntryBuilder(listModuleSchemaNode);\r\r        List<DataSchemaNode> instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(\r                (listModuleSchemaNode), "name");\r        final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);\r        Preconditions.checkState(nameSchemaNode instanceof LeafSchemaNode);\r        moduleNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) nameSchemaNode).withValue(module.getName())\r                .build());\r\r        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(\r                (listModuleSchemaNode), "revision");\r        final DataSchemaNode revisionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);\r        Preconditions.checkState(revisionSchemaNode instanceof LeafSchemaNode);\r        final String revision = REVISION_FORMAT.format(module.getRevision());\r        moduleNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) revisionSchemaNode).withValue(revision)\r                .build());\r\r        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(\r                (listModuleSchemaNode), "namespace");\r        final DataSchemaNode namespaceSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);\r        Preconditions.checkState(namespaceSchemaNode instanceof LeafSchemaNode);\r        moduleNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) namespaceSchemaNode)\r                .withValue(module.getNamespace().toString()).build());\r\r        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(\r                (listModuleSchemaNode), "feature");\r        final DataSchemaNode featureSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);\r        Preconditions.checkState(featureSchemaNode instanceof LeafListSchemaNode);\r        final ListNodeBuilder<Object, LeafSetEntryNode<Object>> featuresBuilder = Builders\r                .leafSetBuilder((LeafListSchemaNode) featureSchemaNode);\r        for (final FeatureDefinition feature : module.getFeatures()) {\r            featuresBuilder.withChild(Builders.leafSetEntryBuilder(((LeafListSchemaNode) featureSchemaNode))\r                    .withValue(feature.getQName().getLocalName()).build());\r        }\r        moduleNodeValues.withChild(featuresBuilder.build());
-\r        return moduleNodeValues.build();\r    }
+                "moduleSchemaNode has to be of type ListSchemaNode");
+        final ListSchemaNode listModuleSchemaNode = (ListSchemaNode) moduleSchemaNode;
+        final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> moduleNodeValues = Builders
+                .mapEntryBuilder(listModuleSchemaNode);
+
+        List<DataSchemaNode> instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
+                (listModuleSchemaNode), "name");
+        final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+        Preconditions.checkState(nameSchemaNode instanceof LeafSchemaNode);
+        moduleNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) nameSchemaNode).withValue(module.getName())
+                .build());
+
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
+                (listModuleSchemaNode), "revision");
+        final DataSchemaNode revisionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+        Preconditions.checkState(revisionSchemaNode instanceof LeafSchemaNode);
+        final String revision = REVISION_FORMAT.format(module.getRevision());
+        moduleNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) revisionSchemaNode).withValue(revision)
+                .build());
+
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
+                (listModuleSchemaNode), "namespace");
+        final DataSchemaNode namespaceSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+        Preconditions.checkState(namespaceSchemaNode instanceof LeafSchemaNode);
+        moduleNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) namespaceSchemaNode)
+                .withValue(module.getNamespace().toString()).build());
+
+        instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
+                (listModuleSchemaNode), "feature");
+        final DataSchemaNode featureSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+        Preconditions.checkState(featureSchemaNode instanceof LeafListSchemaNode);
+        final ListNodeBuilder<Object, LeafSetEntryNode<Object>> featuresBuilder = Builders
+                .leafSetBuilder((LeafListSchemaNode) featureSchemaNode);
+        for (final FeatureDefinition feature : module.getFeatures()) {
+            featuresBuilder.withChild(Builders.leafSetEntryBuilder(((LeafListSchemaNode) featureSchemaNode))
+                    .withValue(feature.getQName().getLocalName()).build());
+        }
+        moduleNodeValues.withChild(featuresBuilder.build());
+
+        return moduleNodeValues.build();
+    }
 
     protected MapEntryNode toStreamEntryNode(final String streamName, final DataSchemaNode streamSchemaNode) {
         Preconditions.checkArgument(streamSchemaNode instanceof ListSchemaNode,
index 8481a9f0c8129f0a90f379dc5ca409d1bfc6b552..c5b831e28a9dad8c6a7b98dff7bd7a116b29033e 100644 (file)
@@ -23,12 +23,10 @@ import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Random;
 import java.util.Set;
 import java.util.concurrent.Executors;
 import java.util.regex.Pattern;
-import javax.activation.UnsupportedDataTypeException;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
@@ -44,13 +42,11 @@ import org.opendaylight.controller.sal.rest.impl.XmlMapper;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -174,7 +170,7 @@ public class ListenerAdapter implements DOMDataChangeListener {
         }
 
         /**
-         * Gets event data.
+         * Gets event String.
          *
          * @return String representation of event data.
          */
@@ -185,8 +181,7 @@ public class ListenerAdapter implements DOMDataChangeListener {
         /**
          * Sets event data.
          *
-         * @param String
-         *            data.
+         * @param data String.
          */
         public void setData(final String data) {
             this.data = data;
@@ -284,7 +279,7 @@ public class ListenerAdapter implements DOMDataChangeListener {
      * @param dataChangedNotificationEventElement
      *            {@link Element}
      * @param change
-     *            {@link DataChangeEvent}
+     *            {@link AsyncDataChangeEvent}
      */
     private void addValuesToDataChangedNotificationEventElement(final Document doc,
             final Element dataChangedNotificationEventElement,
@@ -308,8 +303,6 @@ public class ListenerAdapter implements DOMDataChangeListener {
      *            Set of {@link YangInstanceIdentifier}.
      * @param element
      *            {@link Element}
-     * @param store
-     *            {@link Store}
      * @param operation
      *            {@link Operation}
      */
@@ -319,35 +312,13 @@ public class ListenerAdapter implements DOMDataChangeListener {
             return;
         }
         for (final YangInstanceIdentifier path : data) {
-            final Node node = createDataChangeEventElement(doc, path, null, operation);
-            element.appendChild(node);
+            if (!ControllerContext.getInstance().isNodeMixin(path)) {
+                final Node node = createDataChangeEventElement(doc, path, operation);
+                element.appendChild(node);
+            }
         }
     }
 
-    /**
-     * Adds values from data to element.
-     *
-     * @param doc
-     *            {@link Document}
-     * @param data
-     *            Map of {@link YangInstanceIdentifier} and {@link CompositeNode}.
-     * @param element
-     *            {@link Element}
-     * @param store
-     *            {@link Store}
-     * @param operation
-     *            {@link Operation}
-     */
-    private void addValuesFromDataToElement(final Document doc, final Map<YangInstanceIdentifier, CompositeNode> data, final Element element,
-            final Operation operation) {
-        if (data == null || data.isEmpty()) {
-            return;
-        }
-        for (final Entry<YangInstanceIdentifier, CompositeNode> entry : data.entrySet()) {
-            final Node node = createDataChangeEventElement(doc, entry.getKey(), entry.getValue(), operation);
-            element.appendChild(node);
-        }
-    }
 
     /**
      * Creates changed event element from data.
@@ -356,65 +327,23 @@ public class ListenerAdapter implements DOMDataChangeListener {
      *            {@link Document}
      * @param path
      *            Path to data in data store.
-     * @param data
-     *            {@link CompositeNode}
-     * @param store
-     *            {@link Store}
      * @param operation
      *            {@link Operation}
      * @return {@link Node} node represented by changed event element.
      */
-    private Node createDataChangeEventElement(final Document doc, final YangInstanceIdentifier path, final CompositeNode data,
-            final Operation operation) {
+    private Node createDataChangeEventElement(final Document doc, final YangInstanceIdentifier path, final Operation operation) {
         final Element dataChangeEventElement = doc.createElement("data-change-event");
         final Element pathElement = doc.createElement("path");
         addPathAsValueToElement(path, pathElement);
         dataChangeEventElement.appendChild(pathElement);
 
-        // Element storeElement = doc.createElement("store");
-        // storeElement.setTextContent(store.value);
-        // dataChangeEventElement.appendChild(storeElement);
-
         final Element operationElement = doc.createElement("operation");
         operationElement.setTextContent(operation.value);
         dataChangeEventElement.appendChild(operationElement);
 
-        if (data != null) {
-            final Element dataElement = doc.createElement("data");
-            final Node dataAnyXml = translateToXml(path, data);
-            final Node adoptedNode = doc.adoptNode(dataAnyXml);
-            dataElement.appendChild(adoptedNode);
-            dataChangeEventElement.appendChild(dataElement);
-        }
-
         return dataChangeEventElement;
     }
 
-    /**
-     * Translates {@link CompositeNode} data to XML format.
-     *
-     * @param path
-     *            Path to data in data store.
-     * @param data
-     *            {@link CompositeNode}
-     * @return Data in XML format.
-     */
-    private Node translateToXml(final YangInstanceIdentifier path, final CompositeNode data) {
-        final DataNodeContainer schemaNode = ControllerContext.getInstance().getDataNodeContainerFor(path);
-        if (schemaNode == null) {
-            LOG.info(
-                    "Path '{}' contains node with unsupported type (supported type is Container or List) or some node was not found.",
-                    path);
-            return null;
-        }
-        try {
-            final Document xml = xmlMapper.write(data, schemaNode);
-            return xml.getFirstChild();
-        } catch (final UnsupportedDataTypeException e) {
-            LOG.error("Error occured during translation of notification to XML.", e);
-            return null;
-        }
-    }
 
     /**
      * Adds path as value to element.
@@ -427,11 +356,14 @@ public class ListenerAdapter implements DOMDataChangeListener {
     private void addPathAsValueToElement(final YangInstanceIdentifier path, final Element element) {
         // Map< key = namespace, value = prefix>
         final Map<String, String> prefixes = new HashMap<>();
-        final YangInstanceIdentifier instanceIdentifier = path;
+        final YangInstanceIdentifier normalizedPath = ControllerContext.getInstance().toXpathRepresentation(path);
         final StringBuilder textContent = new StringBuilder();
 
         // FIXME: BUG-1281: this is duplicated code from yangtools (BUG-1275)
-        for (final PathArgument pathArgument : instanceIdentifier.getPathArguments()) {
+        for (final PathArgument pathArgument : normalizedPath.getPathArguments()) {
+            if (pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+                continue;
+            }
             textContent.append("/");
             writeIdentifierWithNamespacePrefix(element, textContent, pathArgument.getNodeType(), prefixes);
             if (pathArgument instanceof NodeIdentifierWithPredicates) {
index ce12d34e083f2ca440c754ab736aed1834276e0f..5ce6b0ee012649483cb429c160c041e6d4910971 100644 (file)
@@ -162,7 +162,7 @@ public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object>
      * @return String representation of web socket location.
      */
     private static String getWebSocketLocation(final HttpRequest req) {
-        return "http://" + req.headers().get(HOST) + req.getUri();
+        return "ws://" + req.headers().get(HOST) + req.getUri();
     }
 
 }