From f55f03931ef55344b0fb71b75fb0cb577fa89d54 Mon Sep 17 00:00:00 2001 From: Vaclav Demcak Date: Mon, 9 Mar 2015 14:32:32 +0100 Subject: [PATCH] BUG 2412 - restconf @POST invokeRpc for notification subscription * 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 --- .../sal/restconf/impl/ControllerContext.java | 21 ++++ .../sal/restconf/impl/RestconfImpl.java | 108 +++++++++++++----- .../streams/listeners/ListenerAdapter.java | 94 +++------------ .../websockets/WebSocketServerHandler.java | 2 +- 4 files changed, 112 insertions(+), 113 deletions(-) diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java index 5566f01674..a0b05150a8 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java @@ -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(); } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java index 20e27c8a14..82ac862843 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java @@ -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. createImmutableSimpleNode(eventsSchemaNode.getQName(), null, "")); + streamNodeValues.add(NodeFactory.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 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 pathNode = value == null ? null : value.getFirstSimpleByName(QName.create( - rpc.getQName(), "path")); - final Object pathValue = pathNode == null ? null : pathNode.getValue(); + private CheckedFuture invokeSalRemoteRpcSubscribeRPC(final NormalizedNodeContext payload) { + final ContainerNode value = (ContainerNode) payload.getData(); + final QName rpcQName = payload.getInstanceIdentifierContext().getSchemaNode().getQName(); + Optional> 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 streamNameNode = NodeFactory. createImmutableSimpleNode( - QName.create(rpc.getOutput().getQName(), "stream-name"), null, streamName); - final List> output = new ArrayList>(); - 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 parseEnumTypeParameter(final CompositeNode compNode, final Class classDescriptor, + private T parseEnumTypeParameter(final ContainerNode value, final Class 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> 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"); final ListSchemaNode listModuleSchemaNode = (ListSchemaNode) moduleSchemaNode; final DataContainerNodeAttrBuilder moduleNodeValues = Builders .mapEntryBuilder(listModuleSchemaNode); List 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> 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(); } + "moduleSchemaNode has to be of type ListSchemaNode"); + final ListSchemaNode listModuleSchemaNode = (ListSchemaNode) moduleSchemaNode; + final DataContainerNodeAttrBuilder moduleNodeValues = Builders + .mapEntryBuilder(listModuleSchemaNode); + + List 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> 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, diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/listeners/ListenerAdapter.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/listeners/ListenerAdapter.java index 8481a9f0c8..c5b831e28a 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/listeners/ListenerAdapter.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/listeners/ListenerAdapter.java @@ -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 data, final Element element, - final Operation operation) { - if (data == null || data.isEmpty()) { - return; - } - for (final Entry 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 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) { diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/websockets/WebSocketServerHandler.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/websockets/WebSocketServerHandler.java index ce12d34e08..5ce6b0ee01 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/websockets/WebSocketServerHandler.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/websockets/WebSocketServerHandler.java @@ -162,7 +162,7 @@ public class WebSocketServerHandler extends SimpleChannelInboundHandler * @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(); } } -- 2.36.6