Bug 8084 - FilterContentValidator.getKeyValues creates invalid YII key values
[netconf.git] / netconf / mdsal-netconf-connector / src / main / java / org / opendaylight / netconf / mdsal / connector / ops / get / UniversalNamespaceContextImpl.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.netconf.mdsal.connector.ops.get;
10
11 import java.util.HashMap;
12 import java.util.Iterator;
13 import java.util.Map;
14 import javax.xml.XMLConstants;
15 import javax.xml.namespace.NamespaceContext;
16 import org.w3c.dom.Attr;
17 import org.w3c.dom.Document;
18 import org.w3c.dom.NamedNodeMap;
19 import org.w3c.dom.Node;
20 import org.w3c.dom.NodeList;
21
22 public class UniversalNamespaceContextImpl implements NamespaceContext {
23     private static final String DEFAULT_NS = "DEFAULT";
24     private final Map<String, String> prefix2Uri = new HashMap<>();
25     private final Map<String, String> uri2Prefix = new HashMap<>();
26
27     /**
28      * This constructor parses the document and stores all namespaces it can
29      * find. If toplevelOnly is true, only namespaces in the root are used.
30      *
31      * @param document     source document
32      * @param toplevelOnly restriction of the search to enhance performance
33      */
34     public UniversalNamespaceContextImpl(final Document document, final boolean toplevelOnly) {
35         readNode(document.getFirstChild(), toplevelOnly);
36     }
37
38     /**
39      * A single node is read, the namespace attributes are extracted and stored.
40      *
41      * @param node            to examine
42      * @param attributesOnly, if true no recursion happens
43      */
44     private void readNode(final Node node, final boolean attributesOnly) {
45         final NamedNodeMap attributes = node.getAttributes();
46         for (int i = 0; i < attributes.getLength(); i++) {
47             final Node attribute = attributes.item(i);
48             storeAttr((Attr) attribute);
49         }
50
51         if (!attributesOnly) {
52             final NodeList chields = node.getChildNodes();
53             for (int i = 0; i < chields.getLength(); i++) {
54                 final Node chield = chields.item(i);
55                 if (chield.getNodeType() == Node.ELEMENT_NODE)
56                     readNode(chield, false);
57             }
58         }
59     }
60
61     /**
62      * This method looks at an attribute and stores it, if it is a namespace
63      * attribute.
64      *
65      * @param attribute to examine
66      */
67     private void storeAttr(final Attr attribute) {
68         // examine the attributes in namespace xmlns
69         if (attribute.getNamespaceURI() != null
70                 && attribute.getNamespaceURI().equals(
71                 XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) {
72             // Default namespace xmlns="uri goes here"
73             if (attribute.getNodeName().equals(XMLConstants.XMLNS_ATTRIBUTE)) {
74                 putInCache(DEFAULT_NS, attribute.getNodeValue());
75             } else {
76                 // The defined prefixes are stored here
77                 putInCache(attribute.getLocalName(), attribute.getNodeValue());
78             }
79         }
80
81     }
82
83     private void putInCache(final String prefix, final String uri) {
84         prefix2Uri.put(prefix, uri);
85         uri2Prefix.put(uri, prefix);
86     }
87
88     /**
89      * This method is called by XPath. It returns the default namespace, if the
90      * prefix is null or "".
91      *
92      * @param prefix to search for
93      * @return uri
94      */
95     public String getNamespaceURI(final String prefix) {
96         if (prefix == null || prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
97             return prefix2Uri.get(DEFAULT_NS);
98         } else {
99             return prefix2Uri.get(prefix);
100         }
101     }
102
103     /**
104      * This method is not needed in this context, but can be implemented in a
105      * similar way.
106      */
107     public String getPrefix(final String namespaceURI) {
108         return uri2Prefix.get(namespaceURI);
109     }
110
111     public Iterator getPrefixes(final String namespaceURI) {
112         // Not implemented
113         return null;
114     }
115
116 }