use of org.opendaylight.yangtools.yang.data.api.schema.stream.ForwardingNormalizedNodeStreamWriter in project netconf by opendaylight.
the class RestconfDocumentedExceptionMapper method toJsonResponseBody.
private static Object toJsonResponseBody(final NormalizedNodeContext errorsNode, final DataNodeContainer errorsSchemaNode) {
final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
NormalizedNode data = errorsNode.getData();
final InstanceIdentifierContext<?> context = errorsNode.getInstanceIdentifierContext();
final DataSchemaNode schema = (DataSchemaNode) context.getSchemaNode();
final OutputStreamWriter outputWriter = new OutputStreamWriter(outStream, StandardCharsets.UTF_8);
if (data == null) {
throw new RestconfDocumentedException(Response.Status.NOT_FOUND);
}
boolean isDataRoot = false;
XMLNamespace initialNs = null;
SchemaPath path;
if (context.getSchemaNode() instanceof SchemaContext) {
isDataRoot = true;
path = SchemaPath.ROOT;
} else {
final List<QName> qNames = context.getInstanceIdentifier().getPathArguments().stream().filter(arg -> !(arg instanceof NodeIdentifierWithPredicates)).filter(arg -> !(arg instanceof AugmentationIdentifier)).map(PathArgument::getNodeType).collect(Collectors.toList());
path = SchemaPath.of(Absolute.of(qNames)).getParent();
}
if (!schema.isAugmenting() && !(schema instanceof SchemaContext)) {
initialNs = schema.getQName().getNamespace();
}
final JsonWriter jsonWriter = JsonWriterFactory.createJsonWriter(outputWriter);
final NormalizedNodeStreamWriter jsonStreamWriter = JSONNormalizedNodeStreamWriter.createExclusiveWriter(JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02.getShared(context.getSchemaContext()), path, initialNs, jsonWriter);
// We create a delegating writer to special-case error-info as error-info is defined as an empty
// container in the restconf yang schema but we create a leaf node so we can output it. The delegate
// stream writer validates the node type against the schema and thus will expect a LeafSchemaNode but
// the schema has a ContainerSchemaNode so, to avoid an error, we override the leafNode behavior
// for error-info.
final NormalizedNodeStreamWriter streamWriter = new ForwardingNormalizedNodeStreamWriter() {
private boolean inOurLeaf;
@Override
protected NormalizedNodeStreamWriter delegate() {
return jsonStreamWriter;
}
@Override
public void startLeafNode(final NodeIdentifier name) throws IOException {
if (name.getNodeType().equals(RestConfModule.ERROR_INFO_QNAME)) {
inOurLeaf = true;
jsonWriter.name(RestConfModule.ERROR_INFO_QNAME.getLocalName());
} else {
super.startLeafNode(name);
}
}
@Override
public void scalarValue(final Object value) throws IOException {
if (inOurLeaf) {
jsonWriter.value(value.toString());
} else {
super.scalarValue(value);
}
}
@Override
public void endNode() throws IOException {
if (inOurLeaf) {
inOurLeaf = false;
} else {
super.endNode();
}
}
};
final NormalizedNodeWriter nnWriter = NormalizedNodeWriter.forStreamWriter(streamWriter);
try {
if (isDataRoot) {
writeDataRoot(outputWriter, nnWriter, (ContainerNode) data);
} else {
if (data instanceof MapEntryNode) {
data = ImmutableNodes.mapNodeBuilder(data.getIdentifier().getNodeType()).withChild((MapEntryNode) data).build();
}
nnWriter.write(data);
}
nnWriter.flush();
outputWriter.flush();
} catch (final IOException e) {
LOG.warn("Error writing error response body", e);
}
try {
streamWriter.close();
} catch (IOException e) {
LOG.warn("Failed to close stream writer", e);
}
return outStream.toString(StandardCharsets.UTF_8);
}
use of org.opendaylight.yangtools.yang.data.api.schema.stream.ForwardingNormalizedNodeStreamWriter in project yangtools by opendaylight.
the class ImmutableMountPointNormalizedNodeStreamWriter method startMountPoint.
@Override
public final NormalizedNodeStreamWriter startMountPoint(final MountPointIdentifier mountId, final MountPointContext mountCtx) {
final NormalizedNodeResult mountResult = new NormalizedNodeResult();
final NormalizedNodeStreamWriter mountDelegate = ImmutableNormalizedNodeStreamWriter.from(mountResult);
return new ForwardingNormalizedNodeStreamWriter() {
@Override
protected NormalizedNodeStreamWriter delegate() {
return mountDelegate;
}
@Override
public void close() throws IOException {
super.close();
final NormalizedNode data = mountResult.getResult();
if (!(data instanceof ContainerNode)) {
throw new IOException("Unhandled mount data " + data);
}
writeChild(ImmutableMountPointNode.of(mountId, mountCtx, (ContainerNode) data));
}
};
}
use of org.opendaylight.yangtools.yang.data.api.schema.stream.ForwardingNormalizedNodeStreamWriter in project netconf by opendaylight.
the class RestconfDocumentedExceptionMapper method toXMLResponseBody.
private static Object toXMLResponseBody(final NormalizedNodeContext errorsNode, final DataNodeContainer errorsSchemaNode) {
final InstanceIdentifierContext<?> pathContext = errorsNode.getInstanceIdentifierContext();
final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
final XMLStreamWriter xmlWriter;
try {
xmlWriter = XML_FACTORY.createXMLStreamWriter(outStream, StandardCharsets.UTF_8.name());
} catch (final XMLStreamException | FactoryConfigurationError e) {
throw new IllegalStateException(e);
}
NormalizedNode data = errorsNode.getData();
SchemaPath schemaPath;
boolean isDataRoot = false;
if (pathContext.getSchemaNode() instanceof SchemaContext) {
isDataRoot = true;
schemaPath = SchemaPath.ROOT;
} else {
final List<QName> qNames = pathContext.getInstanceIdentifier().getPathArguments().stream().filter(arg -> !(arg instanceof NodeIdentifierWithPredicates)).filter(arg -> !(arg instanceof AugmentationIdentifier)).map(PathArgument::getNodeType).collect(Collectors.toList());
schemaPath = SchemaPath.of(Absolute.of(qNames)).getParent();
}
final NormalizedNodeStreamWriter xmlStreamWriter = XMLStreamNormalizedNodeStreamWriter.create(xmlWriter, pathContext.getSchemaContext(), schemaPath);
// We create a delegating writer to special-case error-info as error-info is defined as an empty
// container in the restconf yang schema but we create a leaf node so we can output it. The delegate
// stream writer validates the node type against the schema and thus will expect a LeafSchemaNode but
// the schema has a ContainerSchemaNode so, to avoid an error, we override the leafNode behavior
// for error-info.
final NormalizedNodeStreamWriter streamWriter = new ForwardingNormalizedNodeStreamWriter() {
private boolean inOurLeaf;
@Override
protected NormalizedNodeStreamWriter delegate() {
return xmlStreamWriter;
}
@Override
public void startLeafNode(final NodeIdentifier name) throws IOException {
if (name.getNodeType().equals(RestConfModule.ERROR_INFO_QNAME)) {
String ns = RestConfModule.ERROR_INFO_QNAME.getNamespace().toString();
try {
xmlWriter.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX, RestConfModule.ERROR_INFO_QNAME.getLocalName(), ns);
} catch (XMLStreamException e) {
throw new IOException("Error writing error-info", e);
}
inOurLeaf = true;
} else {
super.startLeafNode(name);
}
}
@Override
public void scalarValue(final Object value) throws IOException {
if (inOurLeaf) {
try {
xmlWriter.writeCharacters(value.toString());
} catch (XMLStreamException e) {
throw new IOException("Error writing error-info", e);
}
} else {
super.scalarValue(value);
}
}
@Override
public void endNode() throws IOException {
if (inOurLeaf) {
try {
xmlWriter.writeEndElement();
} catch (XMLStreamException e) {
throw new IOException("Error writing error-info", e);
}
inOurLeaf = false;
} else {
super.endNode();
}
}
};
final NormalizedNodeWriter nnWriter = NormalizedNodeWriter.forStreamWriter(streamWriter);
try {
if (isDataRoot) {
writeRootElement(xmlWriter, nnWriter, (ContainerNode) data);
} else {
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.getIdentifier().getNodeType()).addChild((MapEntryNode) data).build();
}
nnWriter.write(data);
nnWriter.flush();
}
} catch (final IOException e) {
LOG.warn("Error writing error response body.", e);
}
return outStream.toString(StandardCharsets.UTF_8);
}
Aggregations