Resolve Bug:522
[controller.git] / opendaylight / netconf / netconf-util / src / main / java / org / opendaylight / controller / netconf / util / mapping / 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
9 package org.opendaylight.controller.netconf.util.mapping;
10
11 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
12 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
13 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
14 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
15 import org.opendaylight.controller.netconf.util.xml.XmlElement;
16 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
17 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
18 import org.w3c.dom.Attr;
19 import org.w3c.dom.Document;
20 import org.w3c.dom.Element;
21 import org.w3c.dom.NodeList;
22
23 import java.util.Map;
24
25 public abstract class AbstractNetconfOperation implements NetconfOperation {
26     private final String netconfSessionIdForReporting;
27
28     protected AbstractNetconfOperation(String netconfSessionIdForReporting) {
29         this.netconfSessionIdForReporting = netconfSessionIdForReporting;
30     }
31
32     public final String getNetconfSessionIdForReporting() {
33         return netconfSessionIdForReporting;
34     }
35
36     @Override
37     public HandlingPriority canHandle(Document message) {
38         OperationNameAndNamespace operationNameAndNamespace = new OperationNameAndNamespace(message);
39         return canHandle(operationNameAndNamespace.getOperationName(), operationNameAndNamespace.getNamespace());
40     }
41
42     public static class OperationNameAndNamespace {
43         private final String operationName, namespace;
44
45         public OperationNameAndNamespace(Document message) {
46             XmlElement requestElement = getRequestElementWithCheck(message);
47
48             XmlElement operationElement = requestElement.getOnlyChildElement();
49             operationName = operationElement.getName();
50             namespace = operationElement.getNamespace();
51         }
52
53         public String getOperationName() {
54             return operationName;
55         }
56
57         public String getNamespace() {
58             return namespace;
59         }
60     }
61
62     protected static XmlElement getRequestElementWithCheck(Document message) {
63         return XmlElement.fromDomElementWithExpected(message.getDocumentElement(), XmlNetconfConstants.RPC_KEY,
64                 XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
65     }
66
67     protected HandlingPriority canHandle(String operationName, String operationNamespace) {
68         return operationName.equals(getOperationName()) && operationNamespace.equals(getOperationNamespace())
69                 ? getHandlingPriority()
70                 : HandlingPriority.CANNOT_HANDLE;
71     }
72
73     protected HandlingPriority getHandlingPriority() {
74         return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;
75     }
76
77     protected String getOperationNamespace() {
78         return XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0;
79     }
80
81     protected abstract String getOperationName();
82
83     @Override
84     public Document handle(Document requestMessage,
85             NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException {
86
87         XmlElement requestElement = getRequestElementWithCheck(requestMessage);
88
89         Document document = XmlUtil.newDocument();
90
91         XmlElement operationElement = requestElement.getOnlyChildElement();
92         Map<String, Attr> attributes = requestElement.getAttributes();
93
94         Element response = handle(document, operationElement, subsequentOperation);
95         Element rpcReply = document.createElementNS(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0,
96                 XmlNetconfConstants.RPC_REPLY_KEY);
97
98         if(XmlElement.fromDomElement(response).hasNamespace()) {
99             rpcReply.appendChild(response);
100         } else {
101             Element responseNS = document.createElementNS(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, response.getNodeName());
102             NodeList list = response.getChildNodes();
103             while(list.getLength()!=0) {
104                 responseNS.appendChild(list.item(0));
105             }
106             rpcReply.appendChild(responseNS);
107         }
108
109         for (String attrName : attributes.keySet()) {
110             rpcReply.setAttributeNode((Attr) document.importNode(attributes.get(attrName), true));
111         }
112         document.appendChild(rpcReply);
113         return document;
114     }
115
116     protected abstract Element handle(Document document, XmlElement message, NetconfOperationChainedExecution subsequentOperation)
117             throws NetconfDocumentedException;
118
119     @Override
120     public String toString() {
121         final StringBuffer sb = new StringBuffer(getClass().getName());
122         try {
123             sb.append("{name=").append(getOperationName());
124         } catch(UnsupportedOperationException e) {
125             // no problem
126         }
127         sb.append(", namespace=").append(getOperationNamespace());
128         sb.append(", session=").append(netconfSessionIdForReporting);
129         sb.append('}');
130         return sb.toString();
131     }
132 }