use of org.opendaylight.restconf.common.patch.PatchContext in project netconf by opendaylight.
the class JsonPatchBodyReader method readFrom.
private PatchContext readFrom(final InstanceIdentifierContext<?> path, final InputStream entityStream) throws IOException {
final JsonReader jsonReader = new JsonReader(new InputStreamReader(entityStream, StandardCharsets.UTF_8));
AtomicReference<String> patchId = new AtomicReference<>();
final List<PatchEntity> resultList = read(jsonReader, path, patchId);
jsonReader.close();
return new PatchContext(path, resultList, patchId.get());
}
use of org.opendaylight.restconf.common.patch.PatchContext in project netconf by opendaylight.
the class XmlToPatchBodyReader method readFrom.
@SuppressWarnings("checkstyle:IllegalCatch")
@Override
public PatchContext readFrom(final Class<PatchContext> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType, final MultivaluedMap<String, String> httpHeaders, final InputStream entityStream) throws WebApplicationException {
try {
final InstanceIdentifierContext<?> path = getInstanceIdentifierContext();
final Optional<InputStream> nonEmptyInputStreamOptional = RestUtil.isInputStreamEmpty(entityStream);
if (nonEmptyInputStreamOptional.isEmpty()) {
// represent empty nopayload input
return new PatchContext(path, null, null);
}
final Document doc = UntrustedXML.newDocumentBuilder().parse(nonEmptyInputStreamOptional.get());
return parse(path, doc);
} catch (final RestconfDocumentedException e) {
throw e;
} catch (final Exception e) {
LOG.debug("Error parsing xml input", e);
RestconfDocumentedException.throwIfYangError(e);
throw new RestconfDocumentedException("Error parsing input: " + e.getMessage(), ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE, e);
}
}
use of org.opendaylight.restconf.common.patch.PatchContext in project netconf by opendaylight.
the class XmlToPatchBodyReader method parse.
private static PatchContext parse(final InstanceIdentifierContext<?> pathContext, final Document doc) throws XMLStreamException, IOException, ParserConfigurationException, SAXException, URISyntaxException {
final List<PatchEntity> resultCollection = new ArrayList<>();
final String patchId = doc.getElementsByTagName("patch-id").item(0).getFirstChild().getNodeValue();
final NodeList editNodes = doc.getElementsByTagName("edit");
for (int i = 0; i < editNodes.getLength(); i++) {
DataSchemaNode schemaNode = (DataSchemaNode) pathContext.getSchemaNode();
final Element element = (Element) editNodes.item(i);
final String operation = element.getElementsByTagName("operation").item(0).getFirstChild().getNodeValue();
final PatchEditOperation oper = PatchEditOperation.valueOf(operation.toUpperCase(Locale.ROOT));
final String editId = element.getElementsByTagName("edit-id").item(0).getFirstChild().getNodeValue();
final String target = element.getElementsByTagName("target").item(0).getFirstChild().getNodeValue();
final List<Element> values = readValueNodes(element, oper);
final Element firstValueElement = values != null ? values.get(0) : null;
// get namespace according to schema node from path context or value
final String namespace = firstValueElement == null ? schemaNode.getQName().getNamespace().toString() : firstValueElement.getNamespaceURI();
// find module according to namespace
final Module module = pathContext.getSchemaContext().findModules(XMLNamespace.of(namespace)).iterator().next();
// initialize codec + set default prefix derived from module name
final StringModuleInstanceIdentifierCodec codec = new StringModuleInstanceIdentifierCodec(pathContext.getSchemaContext(), module.getName());
// find complete path to target and target schema node
// target can be also empty (only slash)
YangInstanceIdentifier targetII;
final SchemaNode targetNode;
final Inference inference;
if (target.equals("/")) {
targetII = pathContext.getInstanceIdentifier();
targetNode = pathContext.getSchemaContext();
inference = Inference.ofDataTreePath(pathContext.getSchemaContext(), schemaNode.getQName());
} else {
targetII = codec.deserialize(codec.serialize(pathContext.getInstanceIdentifier()).concat(prepareNonCondXpath(schemaNode, target.replaceFirst("/", ""), firstValueElement, namespace, module.getQNameModule().getRevision().map(Revision::toString).orElse(null))));
// move schema node
schemaNode = verifyNotNull(codec.getDataContextTree().findChild(targetII).orElseThrow().getDataSchemaNode());
final SchemaInferenceStack stack = SchemaInferenceStack.of(pathContext.getSchemaContext());
targetII.getPathArguments().stream().filter(arg -> !(arg instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates)).filter(arg -> !(arg instanceof YangInstanceIdentifier.AugmentationIdentifier)).forEach(p -> stack.enterSchemaTree(p.getNodeType()));
final EffectiveStatement<?, ?> parentStmt = stack.exit();
verify(parentStmt instanceof SchemaNode, "Unexpected parent %s", parentStmt);
targetNode = (SchemaNode) parentStmt;
inference = stack.toInference();
}
if (targetNode == null) {
LOG.debug("Target node {} not found in path {} ", target, pathContext.getSchemaNode());
throw new RestconfDocumentedException("Error parsing input", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
}
if (oper.isWithValue()) {
final NormalizedNode parsed;
if (schemaNode instanceof ContainerSchemaNode || schemaNode instanceof ListSchemaNode) {
final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
final XmlParserStream xmlParser = XmlParserStream.create(writer, inference);
xmlParser.traverse(new DOMSource(firstValueElement));
parsed = resultHolder.getResult();
} else {
parsed = null;
}
// for lists allow to manipulate with list items through their parent
if (targetII.getLastPathArgument() instanceof NodeIdentifierWithPredicates) {
targetII = targetII.getParent();
}
resultCollection.add(new PatchEntity(editId, oper, targetII, parsed));
} else {
resultCollection.add(new PatchEntity(editId, oper, targetII));
}
}
return new PatchContext(pathContext, ImmutableList.copyOf(resultCollection), patchId);
}
use of org.opendaylight.restconf.common.patch.PatchContext in project netconf by opendaylight.
the class JSONRestconfServiceImpl method patch.
@SuppressWarnings("checkstyle:IllegalCatch")
@Override
public Optional<String> patch(final String uriPath, final String payload) throws OperationFailedException {
String output = null;
requireNonNull(payload, "payload can't be null");
LOG.debug("patch: uriPath: {}, payload: {}", uriPath, payload);
final InputStream entityStream = new ByteArrayInputStream(payload.getBytes(StandardCharsets.UTF_8));
JsonToPatchBodyReader jsonToPatchBodyReader = new JsonToPatchBodyReader(controllerContext);
final PatchContext context = jsonToPatchBodyReader.readFrom(uriPath, entityStream);
LOG.debug("Parsed YangInstanceIdentifier: {}", context.getInstanceIdentifierContext().getInstanceIdentifier());
LOG.debug("Parsed NormalizedNode: {}", context.getData());
try {
PatchStatusContext patchStatusContext = restconfService.patchConfigurationData(context, new SimpleUriInfo(uriPath));
output = toJson(patchStatusContext);
} catch (final Exception e) {
propagateExceptionAs(uriPath, e, "PATCH");
}
return Optional.ofNullable(output);
}
use of org.opendaylight.restconf.common.patch.PatchContext in project netconf by opendaylight.
the class TestXmlPatchBodyReader method moduleDataAbsoluteTargetPathTest.
/**
* Test of Yang Patch with absolute target path.
*/
@Test
public void moduleDataAbsoluteTargetPathTest() throws Exception {
final String uri = "";
mockBodyReader(uri, xmlToPatchBodyReader, false);
final InputStream inputStream = TestXmlBodyReader.class.getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataAbsoluteTargetPath.xml");
final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream);
checkPatchContext(returnValue);
}
Aggregations