Add netconf.api.NamespaceURN
[netconf.git] / protocol / netconf-server / src / main / java / org / opendaylight / netconf / server / api / operations / AbstractNetconfOperation.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netconf.server.api.operations;
9
10 import static java.util.Objects.requireNonNull;
11
12 import java.util.Map;
13 import java.util.Optional;
14 import org.eclipse.jdt.annotation.NonNull;
15 import org.opendaylight.netconf.api.DocumentedException;
16 import org.opendaylight.netconf.api.NamespaceURN;
17 import org.opendaylight.netconf.api.xml.XmlElement;
18 import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
19 import org.opendaylight.netconf.api.xml.XmlUtil;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.SessionIdType;
21 import org.w3c.dom.Attr;
22 import org.w3c.dom.Document;
23 import org.w3c.dom.Element;
24 import org.w3c.dom.NodeList;
25
26 public abstract class AbstractNetconfOperation implements NetconfOperation {
27     private final @NonNull SessionIdType sessionId;
28
29     protected AbstractNetconfOperation(final SessionIdType sessionId) {
30         this.sessionId = requireNonNull(sessionId);
31     }
32
33     public final @NonNull SessionIdType sessionId() {
34         return sessionId;
35     }
36
37     @Override
38     public HandlingPriority canHandle(final Document message) throws DocumentedException {
39         OperationNameAndNamespace operationNameAndNamespace = null;
40         operationNameAndNamespace = new OperationNameAndNamespace(message);
41         return canHandle(operationNameAndNamespace.getOperationName(), operationNameAndNamespace.getNamespace());
42     }
43
44     protected HandlingPriority canHandle(final String operationName, final String operationNamespace) {
45         return operationName.equals(getOperationName()) && operationNamespace.equals(getOperationNamespace())
46                 ? getHandlingPriority()
47                 : HandlingPriority.CANNOT_HANDLE;
48     }
49
50     public static final class OperationNameAndNamespace {
51         private final String operationName;
52         private final String namespace;
53         private final XmlElement operationElement;
54
55         public OperationNameAndNamespace(final Document message) throws DocumentedException {
56             final var requestElement = getRequestElementWithCheck(message);
57             operationElement = requestElement.getOnlyChildElement();
58             operationName = operationElement.getName();
59             namespace = operationElement.getNamespace();
60         }
61
62         public String getOperationName() {
63             return operationName;
64         }
65
66         public String getNamespace() {
67             return namespace;
68         }
69
70         public XmlElement getOperationElement() {
71             return operationElement;
72         }
73     }
74
75     protected static XmlElement getRequestElementWithCheck(final Document message) throws DocumentedException {
76         return XmlElement.fromDomElementWithExpected(message.getDocumentElement(), XmlNetconfConstants.RPC_KEY,
77             NamespaceURN.BASE);
78     }
79
80     protected HandlingPriority getHandlingPriority() {
81         return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;
82     }
83
84     protected String getOperationNamespace() {
85         return NamespaceURN.BASE;
86     }
87
88     protected abstract String getOperationName();
89
90     @Override
91     public Document handle(final Document requestMessage,
92             final NetconfOperationChainedExecution subsequentOperation) throws DocumentedException {
93
94         XmlElement requestElement = getRequestElementWithCheck(requestMessage);
95
96         Document document = XmlUtil.newDocument();
97
98         XmlElement operationElement = requestElement.getOnlyChildElement();
99         Map<String, Attr> attributes = requestElement.getAttributes();
100
101         Element response = handle(document, operationElement, subsequentOperation);
102         Element rpcReply = XmlUtil.createElement(document, XmlNetconfConstants.RPC_REPLY_KEY,
103                 Optional.of(NamespaceURN.BASE));
104
105         if (XmlElement.fromDomElement(response).hasNamespace()) {
106             rpcReply.appendChild(response);
107         } else {
108             Element responseNS = XmlUtil.createElement(document, response.getNodeName(),
109                     Optional.of(NamespaceURN.BASE));
110             NodeList list = response.getChildNodes();
111             while (list.getLength() != 0) {
112                 responseNS.appendChild(list.item(0));
113             }
114             rpcReply.appendChild(responseNS);
115         }
116
117         for (Attr attribute : attributes.values()) {
118             rpcReply.setAttributeNode((Attr) document.importNode(attribute, true));
119         }
120         document.appendChild(rpcReply);
121         return document;
122     }
123
124     protected abstract Element handle(Document document, XmlElement message,
125                                       NetconfOperationChainedExecution subsequentOperation)
126             throws DocumentedException;
127
128     @Override
129     public String toString() {
130         final StringBuilder sb = new StringBuilder(getClass().getName());
131         try {
132             sb.append("{name=").append(getOperationName());
133         } catch (UnsupportedOperationException e) {
134             // no problem
135         }
136         sb.append(", namespace=").append(getOperationNamespace());
137         sb.append(", session=").append(sessionId.getValue());
138         sb.append('}');
139         return sb.toString();
140     }
141 }