2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.netconf.mdsal.connector.ops.get;
11 import com.google.common.base.Function;
12 import com.google.common.base.Optional;
13 import com.google.common.base.Throwables;
14 import com.google.common.collect.Iterables;
15 import java.io.IOException;
16 import javax.xml.stream.XMLOutputFactory;
17 import javax.xml.stream.XMLStreamException;
18 import javax.xml.stream.XMLStreamWriter;
19 import javax.xml.transform.dom.DOMResult;
20 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
21 import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
22 import org.opendaylight.controller.netconf.mdsal.connector.CurrentSchemaContext;
23 import org.opendaylight.controller.netconf.mdsal.connector.ops.Datastore;
24 import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation;
25 import org.opendaylight.controller.netconf.util.xml.XmlElement;
26 import org.opendaylight.yangtools.yang.common.QName;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
29 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
31 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
32 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
33 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
34 import org.opendaylight.yangtools.yang.data.impl.codec.xml.XMLStreamNormalizedNodeStreamWriter;
35 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
36 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
37 import org.w3c.dom.Document;
38 import org.w3c.dom.Node;
40 public abstract class AbstractGet extends AbstractLastNetconfOperation {
42 protected static final YangInstanceIdentifier ROOT = YangInstanceIdentifier.builder().build();
44 protected final CurrentSchemaContext schemaContext;
47 public AbstractGet(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext) {
48 super(netconfSessionIdForReporting);
49 this.schemaContext = schemaContext;
52 private static final XMLOutputFactory XML_OUTPUT_FACTORY;
55 XML_OUTPUT_FACTORY = XMLOutputFactory.newFactory();
56 XML_OUTPUT_FACTORY.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
59 protected Node transformNormalizedNode(final Document document, final NormalizedNode<?, ?> data, final YangInstanceIdentifier dataRoot) {
60 // boolean isDataRoot = true;
62 final DOMResult result = new DOMResult(document.createElement(XmlNetconfConstants.DATA_KEY));
64 final XMLStreamWriter xmlWriter = getXmlStreamWriter(result);
66 final NormalizedNodeStreamWriter nnStreamWriter = XMLStreamNormalizedNodeStreamWriter.create(xmlWriter,
67 schemaContext.getCurrentContext(), getSchemaPath(dataRoot));
69 final NormalizedNodeWriter nnWriter = NormalizedNodeWriter.forStreamWriter(nnStreamWriter);
72 writeRootElement(xmlWriter, nnWriter, (ContainerNode) data);
74 // if (data instanceof MapEntryNode) {
75 // // Restconf allows returning one list item. We need to wrap it
76 // // in map node in order to serialize it properly
77 // data = ImmutableNodes.mapNodeBuilder(data.getNodeType()).addChild((MapEntryNode) data).build();
79 // nnWriter.write(data);
82 return result.getNode();
85 private XMLStreamWriter getXmlStreamWriter(final DOMResult result) {
87 return XML_OUTPUT_FACTORY.createXMLStreamWriter(result);
88 } catch (final XMLStreamException e) {
89 throw new RuntimeException(e);
93 private static final Function<PathArgument, QName> PATH_ARG_TO_QNAME = new Function<YangInstanceIdentifier.PathArgument, QName>() {
95 public QName apply(final YangInstanceIdentifier.PathArgument input) {
96 return input.getNodeType();
100 private SchemaPath getSchemaPath(final YangInstanceIdentifier dataRoot) {
101 return SchemaPath.create(Iterables.transform(dataRoot.getPathArguments(), PATH_ARG_TO_QNAME), dataRoot.equals(ROOT));
104 // TODO this code is located in Restconf already
105 private void writeRootElement(final XMLStreamWriter xmlWriter, final NormalizedNodeWriter nnWriter, final ContainerNode data) {
107 final QName name = SchemaContext.NAME;
108 for (final DataContainerChild<? extends PathArgument, ?> child : data.getValue()) {
109 nnWriter.write(child);
113 } catch (XMLStreamException | IOException e) {
114 Throwables.propagate(e);
118 protected static final class GetConfigExecution {
119 private final Optional<Datastore> datastore;
121 public GetConfigExecution(final Optional<Datastore> datastore) {
122 this.datastore = datastore;
125 public Optional<Datastore> getDatastore() {
129 static GetConfigExecution fromXml(final XmlElement xml, final String operationName) throws NetconfDocumentedException {
131 validateInputRpc(xml, operationName);
132 } catch (final NetconfDocumentedException e) {
133 throw new NetconfDocumentedException("Incorrect RPC: " + e.getMessage(), e.getErrorType(), e.getErrorTag(), e.getErrorSeverity(), e.getErrorInfo());
136 final Optional<Datastore> sourceDatastore;
138 sourceDatastore = parseSource(xml);
139 } catch (final NetconfDocumentedException e) {
140 throw new NetconfDocumentedException("Get-config source attribute error: " + e.getMessage(), e.getErrorType(), e.getErrorTag(), e.getErrorSeverity(), e.getErrorInfo());
145 return new GetConfigExecution(sourceDatastore);
148 private static Optional<Datastore> parseSource(final XmlElement xml) throws NetconfDocumentedException {
149 final Optional<XmlElement> sourceElement = xml.getOnlyChildElementOptionally(XmlNetconfConstants.SOURCE_KEY,
150 XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
152 return sourceElement.isPresent() ?
153 Optional.of(Datastore.valueOf(sourceElement.get().getOnlyChildElement().getName())) : Optional.<Datastore>absent();
156 private static void validateInputRpc(final XmlElement xml, String operationName) throws NetconfDocumentedException{
157 xml.checkName(operationName);
158 xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);