2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
\r
4 * This program and the accompanying materials are made available under the
\r
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
\r
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
\r
8 package org.opendaylight.controller.yang.data.impl;
\r
10 import java.util.AbstractMap.SimpleEntry;
\r
11 import java.util.ArrayList;
\r
12 import java.util.HashMap;
\r
13 import java.util.List;
\r
14 import java.util.Map;
\r
15 import java.util.Stack;
\r
16 import java.util.Vector;
\r
18 import javax.xml.parsers.DocumentBuilder;
\r
19 import javax.xml.parsers.DocumentBuilderFactory;
\r
20 import javax.xml.parsers.ParserConfigurationException;
\r
21 import javax.xml.xpath.XPath;
\r
22 import javax.xml.xpath.XPathConstants;
\r
23 import javax.xml.xpath.XPathExpression;
\r
24 import javax.xml.xpath.XPathExpressionException;
\r
25 import javax.xml.xpath.XPathFactory;
\r
27 import org.opendaylight.controller.yang.common.QName;
\r
28 import org.opendaylight.controller.yang.data.api.CompositeNode;
\r
29 import org.opendaylight.controller.yang.data.api.ModifyAction;
\r
30 import org.opendaylight.controller.yang.data.api.Node;
\r
31 import org.opendaylight.controller.yang.data.api.NodeModification;
\r
32 import org.opendaylight.controller.yang.data.api.SimpleNode;
\r
33 import org.opendaylight.controller.yang.model.api.DataNodeContainer;
\r
34 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
\r
35 import org.opendaylight.controller.yang.model.api.ListSchemaNode;
\r
36 import org.opendaylight.controller.yang.model.api.SchemaContext;
\r
37 import org.slf4j.Logger;
\r
38 import org.slf4j.LoggerFactory;
\r
39 import org.w3c.dom.Element;
\r
41 import com.google.common.base.Joiner;
\r
42 import com.google.common.collect.Lists;
\r
46 * @author michal.rehak
\r
49 public abstract class NodeUtils {
\r
51 private static final Logger LOG = LoggerFactory.getLogger(NodeUtils.class);
\r
56 private static final String USER_KEY_NODE = "node";
\r
60 * @return node path up till root node
\r
62 public static String buildPath(Node<?> node) {
\r
63 Vector<String> breadCrumbs = new Vector<>();
\r
64 Node<?> tmpNode = node;
\r
65 while (tmpNode != null) {
\r
66 breadCrumbs.insertElementAt(tmpNode.getNodeType().getLocalName(), 0);
\r
67 tmpNode = tmpNode.getParent();
\r
70 return Joiner.on(".").join(breadCrumbs);
\r
75 * @param treeRootNode
\r
76 * @return dom tree, containing same node structure, yang nodes are associated
\r
77 * to dom nodes as user data
\r
79 public static org.w3c.dom.Document buildShadowDomTree(CompositeNode treeRootNode) {
80 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
\r
81 org.w3c.dom.Document doc = null;
\r
83 DocumentBuilder bob = dbf.newDocumentBuilder();
\r
84 doc = bob.newDocument();
\r
85 } catch (ParserConfigurationException e) {
\r
86 LOG.error("documentBuilder problem", e);
\r
91 Stack<SimpleEntry<org.w3c.dom.Node, Node<?>>> jobQueue = new Stack<>();
\r
92 jobQueue.push(new SimpleEntry<org.w3c.dom.Node, Node<?>>(doc, treeRootNode));
\r
94 while (!jobQueue.isEmpty()) {
\r
95 SimpleEntry<org.w3c.dom.Node, Node<?>> job = jobQueue.pop();
\r
96 org.w3c.dom.Node jointPlace = job.getKey();
\r
97 Node<?> item = job.getValue();
\r
98 QName nodeType = item.getNodeType();
\r
99 Element itemEl = doc.createElementNS(nodeType.getNamespace().toString(),
\r
100 item.getNodeType().getLocalName());
\r
101 itemEl.setUserData(USER_KEY_NODE, item, null);
\r
102 if (item instanceof SimpleNode<?>) {
\r
103 Object value = ((SimpleNode<?>) item).getValue();
\r
104 itemEl.setTextContent(String.valueOf(value));
\r
105 //itemEl.setAttribute("type", value.getClass().getSimpleName());
\r
107 if (item instanceof NodeModification) {
\r
108 ModifyAction modificationAction = ((NodeModification) item).getModificationAction();
\r
109 if (modificationAction != null) {
\r
110 itemEl.setAttribute("modifyAction", modificationAction.toString());
\r
114 jointPlace.appendChild(itemEl);
\r
116 if (item instanceof CompositeNode) {
\r
117 for (Node<?> child : ((CompositeNode) item).getChildren()) {
\r
118 jobQueue.push(new SimpleEntry<org.w3c.dom.Node, Node<?>>(itemEl, child));
\r
129 * @return user data value on found node
\r
130 * @throws XPathExpressionException
\r
132 @SuppressWarnings("unchecked")
\r
133 public static <T> T findNodeByXpath(org.w3c.dom.Document doc, String xpathEx)
\r
134 throws XPathExpressionException {
\r
136 XPathFactory xPathfactory = XPathFactory.newInstance();
\r
137 XPath xpath = xPathfactory.newXPath();
\r
138 XPathExpression expr = xpath.compile(xpathEx);
\r
140 org.w3c.dom.Node result = (org.w3c.dom.Node) expr.evaluate(doc, XPathConstants.NODE);
\r
141 if (result != null) {
\r
142 userNode = (T) result.getUserData(USER_KEY_NODE);
\r
150 * build NodeMap, where key = qName; value = node
\r
153 * @return map of children, where key = qName and value is list of children groupped by qName
\r
155 public static Map<QName, List<Node<?>>> buildNodeMap(List<Node<?>> value) {
\r
156 Map<QName, List<Node<?>>> nodeMapTmp = new HashMap<>();
\r
157 if (value == null || value.isEmpty()) {
\r
158 throw new IllegalStateException(
\r
159 "nodeList should not be null or empty");
\r
161 for (Node<?> node : value) {
\r
162 List<Node<?>> qList = nodeMapTmp.get(node.getNodeType());
\r
163 if (qList == null) {
\r
164 qList = new ArrayList<>();
\r
165 nodeMapTmp.put(node.getNodeType(), qList);
\r
175 * @return map of lists, where key = path; value = {@link DataSchemaNode}
\r
177 public static Map<String, ListSchemaNode> buildMapOfListNodes(
\r
178 SchemaContext context) {
\r
179 Map<String, ListSchemaNode> mapOfLists = new HashMap<>();
\r
181 Stack<DataSchemaNode> jobQueue = new Stack<>();
\r
182 jobQueue.addAll(context.getDataDefinitions());
\r
184 while (!jobQueue.isEmpty()) {
\r
185 DataSchemaNode dataSchema = jobQueue.pop();
\r
186 if (dataSchema instanceof ListSchemaNode) {
\r
187 mapOfLists.put(schemaPathToPath(dataSchema.getPath().getPath()), (ListSchemaNode) dataSchema);
\r
190 if (dataSchema instanceof DataNodeContainer) {
\r
191 jobQueue.addAll(((DataNodeContainer) dataSchema).getChildNodes());
\r
202 private static String schemaPathToPath(List<QName> qNamesPath) {
\r
203 List<String> pathSeed = new ArrayList<>();
\r
204 for (QName qNameItem : qNamesPath) {
\r
205 pathSeed.add(qNameItem.getLocalName());
\r
207 return Joiner.on(".").join(pathSeed);
\r
211 * add given node to it's parent's list of children
\r
214 public static void fixParentRelation(Node<?> newNode) {
\r
215 if (newNode.getParent() != null) {
\r
216 List<Node<?>> siblings = newNode.getParent().getChildren();
\r
217 if (!siblings.contains(newNode)) {
\r
218 siblings.add(newNode);
\r
224 * crawl all children of given node and assign it as their parent
\r
225 * @param parentNode
\r
227 public static void fixChildrenRelation(CompositeNode parentNode) {
\r
228 if (parentNode.getChildren() != null) {
\r
229 for (Node<?> child : parentNode.getChildren()) {
\r
230 if (child instanceof AbstractNodeTO<?>) {
\r
231 ((AbstractNodeTO<?>) child).setParent(parentNode);
\r
241 * @return list of values of map, found by given keys
\r
243 public static <T, K> List<K> collectMapValues(List<T> keys,
\r
244 Map<T, K> dataMap) {
\r
245 List<K> valueSubList = new ArrayList<>();
\r
246 for (T key : keys) {
\r
247 valueSubList.add(dataMap.get(key));
\r
250 return valueSubList;
\r
255 * @return list of children in list of appropriate type
\r
257 public static List<Node<?>> buildChildrenList(Node<?>...nodes) {
\r
258 return Lists.newArrayList(nodes);
\r