From: Tony Tkacik Date: Tue, 17 Mar 2015 11:12:09 +0000 (+0100) Subject: Bug 2841: Fixed missing output element in Restconf RPCs X-Git-Tag: release/lithium~388^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=b634faa25065fd6774102530c7a66392dbe79631 Bug 2841: Fixed missing output element in Restconf RPCs JAXRS Body Writers reused root data container writeout for RPC outputs, which differed and writed "data" container instead of rpc "output", refactored writeTo method, to do this special handling. Change-Id: Ia6acf671b760c9aa578a02ce803c99a389030260 Signed-off-by: Tony Tkacik --- diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/NormalizedNodeJsonBodyWriter.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/NormalizedNodeJsonBodyWriter.java index 4944d96b54..5c17f2a14a 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/NormalizedNodeJsonBodyWriter.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/NormalizedNodeJsonBodyWriter.java @@ -66,36 +66,54 @@ public class NormalizedNodeJsonBodyWriter implements MessageBodyWriter context = (InstanceIdentifierContext) t.getInstanceIdentifierContext(); SchemaPath path = context.getSchemaNode().getPath(); - boolean isDataRoot = false; + final JsonWriter jsonWriter = createJsonWriter(entityStream); + jsonWriter.beginObject(); + writeNormalizedNode(jsonWriter,path,context,data); + jsonWriter.endObject(); + jsonWriter.flush(); + } + + private void writeNormalizedNode(JsonWriter jsonWriter, SchemaPath path, + InstanceIdentifierContext context, NormalizedNode data) throws IOException { + final NormalizedNodeWriter nnWriter; if (SchemaPath.ROOT.equals(path)) { - isDataRoot = true; + /* + * Creates writer without initialNs and we write children of root data container + * which is not visible in restconf + */ + nnWriter = createNormalizedNodeWriter(context,path,jsonWriter); + writeChildren(nnWriter,(ContainerNode) data); } else if (context.getSchemaNode() instanceof RpcDefinition) { - isDataRoot = true; + /* + * RpcDefinition is not supported as initial codec in JSONStreamWriter, + * so we need to emit initial output declaratation.. + */ path = ((RpcDefinition) context.getSchemaNode()).getOutput().getPath(); + nnWriter = createNormalizedNodeWriter(context,path,jsonWriter); + jsonWriter.name("output"); + jsonWriter.beginObject(); + writeChildren(nnWriter, (ContainerNode) data); + jsonWriter.endObject(); } else { path = path.getParent(); - // FIXME: Add proper handling of reading root. - } - final JsonWriter jsonWriter = createJsonWriter(entityStream); - final NormalizedNodeWriter nnWriter = createNormalizedNodeWriter(context,path,jsonWriter); - - jsonWriter.beginObject(); - if(isDataRoot) { - writeDataRoot(nnWriter,(ContainerNode) data); - } else { if(data instanceof MapEntryNode) { data = ImmutableNodes.mapNodeBuilder(data.getNodeType()).withChild(((MapEntryNode) data)).build(); } + nnWriter = createNormalizedNodeWriter(context,path,jsonWriter); nnWriter.write(data); } - nnWriter.flush(); - jsonWriter.endObject(); - jsonWriter.flush(); + } + + private void writeChildren(final NormalizedNodeWriter nnWriter, final ContainerNode data) throws IOException { + for(final DataContainerChild child : data.getValue()) { + nnWriter.write(child); + } } private NormalizedNodeWriter createNormalizedNodeWriter(final InstanceIdentifierContext context, @@ -104,9 +122,15 @@ public class NormalizedNodeJsonBodyWriter implements MessageBodyWriter context) { // TODO: Performance: Cache JSON Codec factory and schema context return JSONCodecFactory.create(context.getSchemaContext()); } - private void writeDataRoot(final NormalizedNodeWriter nnWriter, final ContainerNode data) throws IOException { - for(final DataContainerChild child : data.getValue()) { - nnWriter.write(child); - } - } - } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/NormalizedNodeXmlBodyWriter.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/NormalizedNodeXmlBodyWriter.java index f61ec4e1c0..f6b7027b34 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/NormalizedNodeXmlBodyWriter.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/NormalizedNodeXmlBodyWriter.java @@ -18,6 +18,7 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; +import javax.xml.XMLConstants; import javax.xml.stream.FactoryConfigurationError; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; @@ -27,9 +28,7 @@ import org.opendaylight.controller.sal.rest.api.RestconfService; import org.opendaylight.controller.sal.restconf.impl.InstanceIdentifierContext; import org.opendaylight.controller.sal.restconf.impl.NormalizedNodeContext; import org.opendaylight.yangtools.yang.common.QName; -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.MapEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; @@ -85,38 +84,45 @@ public class NormalizedNodeXmlBodyWriter implements MessageBodyWriter data = t.getData(); SchemaPath schemaPath = pathContext.getSchemaNode().getPath(); - boolean isDataRoot = false; + + + writeNormalizedNode(xmlWriter,schemaPath,pathContext,data); + } + + private void writeNormalizedNode(XMLStreamWriter xmlWriter, SchemaPath schemaPath,InstanceIdentifierContext pathContext, NormalizedNode data) throws IOException { + final NormalizedNodeWriter nnWriter; + final SchemaContext schemaCtx = pathContext.getSchemaContext(); if (SchemaPath.ROOT.equals(schemaPath)) { - isDataRoot = true; + nnWriter = createNormalizedNodeWriter(xmlWriter, schemaCtx, schemaPath); + writeElements(xmlWriter, nnWriter, (ContainerNode) data); } else if (pathContext.getSchemaNode() instanceof RpcDefinition) { - isDataRoot = true; - schemaPath = ((RpcDefinition) pathContext.getSchemaNode()).getOutput().getPath(); - } else { - schemaPath = schemaPath.getParent(); - } - - final NormalizedNodeStreamWriter jsonWriter = XMLStreamNormalizedNodeStreamWriter.create(xmlWriter, - pathContext.getSchemaContext(), schemaPath); - final NormalizedNodeWriter nnWriter = NormalizedNodeWriter.forStreamWriter(jsonWriter); - if (isDataRoot) { - writeRootElement(xmlWriter, nnWriter, (ContainerNode) data); + nnWriter = createNormalizedNodeWriter(xmlWriter, schemaCtx, ((RpcDefinition) pathContext.getSchemaNode()).getOutput().getPath()); + writeElements(xmlWriter, nnWriter, (ContainerNode) data); } else { + nnWriter = createNormalizedNodeWriter(xmlWriter, schemaCtx, schemaPath.getParent()); if (data instanceof MapEntryNode) { // Restconf allows returning one list item. We need to wrap it // in map node in order to serialize it properly data = ImmutableNodes.mapNodeBuilder(data.getNodeType()).addChild((MapEntryNode) data).build(); } nnWriter.write(data); - nnWriter.flush(); } + nnWriter.flush(); + } + + private NormalizedNodeWriter createNormalizedNodeWriter(XMLStreamWriter xmlWriter, + SchemaContext schemaContext, SchemaPath schemaPath) { + NormalizedNodeStreamWriter xmlStreamWriter = XMLStreamNormalizedNodeStreamWriter.create(xmlWriter, schemaContext, schemaPath); + return NormalizedNodeWriter.forStreamWriter(xmlStreamWriter); } - private void writeRootElement(final XMLStreamWriter xmlWriter, final NormalizedNodeWriter nnWriter, final ContainerNode data) + private void writeElements(final XMLStreamWriter xmlWriter, final NormalizedNodeWriter nnWriter, final ContainerNode data) throws IOException { try { - final QName name = SchemaContext.NAME; - xmlWriter.writeStartElement(name.getNamespace().toString(), name.getLocalName()); - for (final DataContainerChild child : data.getValue()) { + final QName name = data.getNodeType(); + xmlWriter.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX, name.getLocalName(), name.getNamespace().toString()); + xmlWriter.writeDefaultNamespace(name.getNamespace().toString()); + for(NormalizedNode child : data.getValue()) { nnWriter.write(child); } nnWriter.flush();