*/
package org.opendaylight.netconf.mdsal.connector.ops.get;
+import static com.google.common.base.Preconditions.checkArgument;
+
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Iterables;
import java.io.IOException;
import java.util.Optional;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.dom.DOMResult;
import org.opendaylight.netconf.api.DocumentedException;
-import org.opendaylight.netconf.api.DocumentedException.ErrorTag;
-import org.opendaylight.netconf.api.DocumentedException.ErrorType;
import org.opendaylight.netconf.api.xml.XmlElement;
import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
import org.opendaylight.netconf.mdsal.connector.CurrentSchemaContext;
import org.opendaylight.netconf.mdsal.connector.ops.Datastore;
-import org.opendaylight.netconf.util.mapping.AbstractSingletonNetconfOperation;
+import org.opendaylight.netconf.server.api.operations.AbstractSingletonNetconfOperation;
import org.opendaylight.yangtools.yang.common.ErrorSeverity;
+import org.opendaylight.yangtools.yang.common.ErrorTag;
+import org.opendaylight.yangtools.yang.common.ErrorType;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-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.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.YangInstanceIdentifierWriter;
import org.opendaylight.yangtools.yang.data.codec.xml.XMLStreamNormalizedNodeStreamWriter;
-import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
-public abstract class AbstractGet extends AbstractSingletonNetconfOperation {
+// FIXME: seal when we have JDK17+
+abstract class AbstractGet extends AbstractSingletonNetconfOperation {
private static final XMLOutputFactory XML_OUTPUT_FACTORY;
- private static final YangInstanceIdentifier ROOT = YangInstanceIdentifier.empty();
private static final String FILTER = "filter";
static {
XML_OUTPUT_FACTORY.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
}
- protected final CurrentSchemaContext schemaContext;
+ private final CurrentSchemaContext schemaContext;
private final FilterContentValidator validator;
- public AbstractGet(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext) {
+ AbstractGet(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext) {
super(netconfSessionIdForReporting);
this.schemaContext = schemaContext;
- this.validator = new FilterContentValidator(schemaContext);
+ validator = new FilterContentValidator(schemaContext);
}
- protected Node transformNormalizedNode(final Document document, final NormalizedNode data,
- final YangInstanceIdentifier dataRoot) {
-
+ // FIXME: throw a DocumentedException
+ private Node transformNormalizedNode(final Document document, final NormalizedNode data,
+ final YangInstanceIdentifier dataRoot) {
final DOMResult result = new DOMResult(document.createElement(XmlNetconfConstants.DATA_KEY));
-
final XMLStreamWriter xmlWriter = getXmlStreamWriter(result);
+ final EffectiveModelContext currentContext = schemaContext.getCurrentContext();
final NormalizedNodeStreamWriter nnStreamWriter = XMLStreamNormalizedNodeStreamWriter.create(xmlWriter,
- schemaContext.getCurrentContext(), getSchemaPath(dataRoot));
-
- final NormalizedNodeWriter nnWriter = NormalizedNodeWriter.forStreamWriter(nnStreamWriter, true);
+ currentContext);
- if (data instanceof ContainerNode) {
- writeRootElement(xmlWriter, nnWriter, (ContainerNode) data);
- } else if (data instanceof MapNode) {
- writeRootElement(xmlWriter, nnWriter, (MapNode) data);
- } else {
- throw new IllegalArgumentException("Unable to transform node of type: " + data.getClass().toString()
- + " offending node: " + data.toString());
+ try {
+ if (dataRoot.isEmpty()) {
+ writeRoot(nnStreamWriter, data);
+ } else {
+ write(nnStreamWriter, currentContext, dataRoot.coerceParent(), data);
+ }
+ } catch (IOException e) {
+ // FIXME: throw DocumentedException
+ throw new IllegalStateException(e);
}
return result.getNode();
}
- private static XMLStreamWriter getXmlStreamWriter(final DOMResult result) {
- try {
- return XML_OUTPUT_FACTORY.createXMLStreamWriter(result);
- } catch (final XMLStreamException e) {
- throw new RuntimeException(e);
+ private static void write(final NormalizedNodeStreamWriter nnStreamWriter,
+ final EffectiveModelContext currentContext, final YangInstanceIdentifier parent, final NormalizedNode data)
+ throws IOException {
+ try (var yiidWriter = YangInstanceIdentifierWriter.open(nnStreamWriter, currentContext, parent)) {
+ try (var nnWriter = NormalizedNodeWriter.forStreamWriter(nnStreamWriter, true)) {
+ nnWriter.write(data);
+ }
}
}
- private static SchemaPath getSchemaPath(final YangInstanceIdentifier dataRoot) {
- return SchemaPath.create(
- Iterables.transform(dataRoot.getPathArguments(), PathArgument::getNodeType), dataRoot.equals(ROOT));
- }
+ private static void writeRoot(final NormalizedNodeStreamWriter nnStreamWriter, final NormalizedNode data)
+ throws IOException {
+ checkArgument(data instanceof ContainerNode, "Unexpected root data %s", data);
- private static void writeRootElement(final XMLStreamWriter xmlWriter, final NormalizedNodeWriter nnWriter,
- final ContainerNode data) {
- try {
- if (data.getIdentifier().getNodeType().equals(SchemaContext.NAME)) {
- for (final DataContainerChild child : data.body()) {
- nnWriter.write(child);
- }
- } else {
- nnWriter.write(data);
+ try (var nnWriter = NormalizedNodeWriter.forStreamWriter(nnStreamWriter, true)) {
+ for (var child : ((ContainerNode) data).body()) {
+ nnWriter.write(child);
}
- nnWriter.flush();
- xmlWriter.flush();
- } catch (XMLStreamException | IOException e) {
- throw new RuntimeException(e);
}
}
- private static void writeRootElement(final XMLStreamWriter xmlWriter, final NormalizedNodeWriter nnWriter,
- final MapNode data) {
+ private static XMLStreamWriter getXmlStreamWriter(final DOMResult result) {
try {
- if (data.getIdentifier().getNodeType().equals(SchemaContext.NAME)) {
- for (final MapEntryNode child : data.body()) {
- nnWriter.write(child);
- }
- } else {
- nnWriter.write(data);
- }
- nnWriter.flush();
- xmlWriter.flush();
- } catch (XMLStreamException | IOException e) {
- throw new RuntimeException(e);
+ return XML_OUTPUT_FACTORY.createXMLStreamWriter(result);
+ } catch (final XMLStreamException e) {
+ // FIXME: throw DocumentedException
+ throw new IllegalStateException(e);
}
}
- protected Element serializeNodeWithParentStructure(final Document document, final YangInstanceIdentifier dataRoot,
- final NormalizedNode node) {
- if (!dataRoot.equals(ROOT)) {
- return (Element) transformNormalizedNode(document,
- ImmutableNodes.fromInstanceId(schemaContext.getCurrentContext(), dataRoot, node),
- ROOT);
- }
- return (Element) transformNormalizedNode(document, node, ROOT);
+ final Element serializeNodeWithParentStructure(final Document document, final YangInstanceIdentifier dataRoot,
+ final NormalizedNode node) {
+ return (Element) transformNormalizedNode(document, node, dataRoot);
}
/**
* container in the response. If filter is not present we want to read the entire datastore - return ROOT.
* @throws DocumentedException if not possible to get identifier from filter
*/
- protected Optional<YangInstanceIdentifier> getDataRootFromFilter(final XmlElement operationElement)
+ final Optional<YangInstanceIdentifier> getDataRootFromFilter(final XmlElement operationElement)
throws DocumentedException {
- final Optional<XmlElement> filterElement = operationElement.getOnlyChildElementOptionally(FILTER);
- if (filterElement.isPresent()) {
- if (filterElement.get().getChildElements().size() == 0) {
- return Optional.empty();
- }
- return Optional.of(getInstanceIdentifierFromFilter(filterElement.get()));
+ final var optFilterElement = operationElement.getOnlyChildElementOptionally(FILTER);
+ if (optFilterElement.isEmpty()) {
+ return Optional.of(YangInstanceIdentifier.empty());
}
- return Optional.of(ROOT);
+ final var filterElement = optFilterElement.orElseThrow();
+ if (filterElement.getChildElements().isEmpty()) {
+ return Optional.empty();
+ }
+ return Optional.of(getInstanceIdentifierFromFilter(filterElement));
}
@VisibleForTesting
- protected YangInstanceIdentifier getInstanceIdentifierFromFilter(final XmlElement filterElement)
+ protected final YangInstanceIdentifier getInstanceIdentifierFromFilter(final XmlElement filterElement)
throws DocumentedException {
if (filterElement.getChildElements().size() != 1) {
private static Optional<Datastore> parseSource(final XmlElement xml) throws DocumentedException {
final Optional<XmlElement> sourceElement = xml.getOnlyChildElementOptionally(XmlNetconfConstants.SOURCE_KEY,
- XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
- return sourceElement.isPresent()
- ? Optional.of(Datastore.valueOf(sourceElement.get().getOnlyChildElement().getName()))
- : Optional.empty();
+ XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+ return sourceElement.isEmpty() ? Optional.empty()
+ : Optional.of(Datastore.valueOf(sourceElement.orElseThrow().getOnlyChildElement().getName()));
}
private static void validateInputRpc(final XmlElement xml, final String operationName) throws