2 * Copyright (c) 2013 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
8 package org.opendaylight.yangtools.yang.data.impl;
10 import com.google.common.base.Function;
11 import com.google.common.base.Joiner;
12 import com.google.common.base.Preconditions;
13 import com.google.common.collect.Iterables;
14 import com.google.common.collect.Lists;
15 import com.google.common.collect.Maps;
16 import java.util.AbstractMap.SimpleEntry;
17 import java.util.ArrayDeque;
18 import java.util.ArrayList;
19 import java.util.Deque;
20 import java.util.HashMap;
21 import java.util.List;
23 import javax.annotation.Nonnull;
24 import javax.xml.parsers.DocumentBuilder;
25 import javax.xml.parsers.DocumentBuilderFactory;
26 import javax.xml.parsers.ParserConfigurationException;
27 import javax.xml.xpath.XPath;
28 import javax.xml.xpath.XPathConstants;
29 import javax.xml.xpath.XPathExpression;
30 import javax.xml.xpath.XPathExpressionException;
31 import javax.xml.xpath.XPathFactory;
32 import org.opendaylight.yangtools.yang.common.QName;
33 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
34 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
35 import org.opendaylight.yangtools.yang.data.api.Node;
36 import org.opendaylight.yangtools.yang.data.api.NodeModification;
37 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
38 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
39 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
40 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
41 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
42 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45 import org.w3c.dom.Element;
48 * @author michal.rehak
50 * @deprecated Use {@link NormalizedNodes} instead.
53 public abstract class NodeUtils {
54 private static final Joiner DOT_JOINER = Joiner.on(".");
55 private static final Logger LOG = LoggerFactory.getLogger(NodeUtils.class);
56 private static final Function<QName, String> LOCALNAME_FUNCTION = new Function<QName, String>() {
58 public String apply(final @Nonnull QName input) {
59 Preconditions.checkNotNull(input);
60 return input.getLocalName();
67 private static final String USER_KEY_NODE = "node";
71 * @return node path up till root node
73 public static String buildPath(final Node<?> node) {
74 List<String> breadCrumbs = new ArrayList<>();
75 Node<?> tmpNode = node;
76 while (tmpNode != null) {
77 breadCrumbs.add(0, tmpNode.getNodeType().getLocalName());
78 tmpNode = tmpNode.getParent();
81 return DOT_JOINER.join(breadCrumbs);
86 * @return dom tree, containing same node structure, yang nodes are
87 * associated to dom nodes as user data
89 public static org.w3c.dom.Document buildShadowDomTree(final CompositeNode treeRootNode) {
90 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
91 org.w3c.dom.Document doc = null;
93 DocumentBuilder bob = dbf.newDocumentBuilder();
94 doc = bob.newDocument();
95 } catch (ParserConfigurationException e) {
96 LOG.error("documentBuilder problem", e);
100 final Deque<SimpleEntry<org.w3c.dom.Node, Node<?>>> jobQueue = new ArrayDeque<>();
101 jobQueue.push(new SimpleEntry<org.w3c.dom.Node, Node<?>>(doc, treeRootNode));
103 while (!jobQueue.isEmpty()) {
104 SimpleEntry<org.w3c.dom.Node, Node<?>> job = jobQueue.pop();
105 org.w3c.dom.Node jointPlace = job.getKey();
106 Node<?> item = job.getValue();
107 QName nodeType = item.getNodeType();
108 Element itemEl = doc.createElementNS(nodeType.getNamespace().toString(), item.getNodeType().getLocalName());
109 itemEl.setUserData(USER_KEY_NODE, item, null);
110 if (item instanceof SimpleNode<?>) {
111 Object value = ((SimpleNode<?>) item).getValue();
113 itemEl.setTextContent(String.valueOf(value));
116 if (item instanceof NodeModification) {
117 ModifyAction modificationAction = ((NodeModification) item).getModificationAction();
118 if (modificationAction != null) {
119 itemEl.setAttribute("modifyAction", modificationAction.toString());
123 jointPlace.appendChild(itemEl);
125 if (item instanceof CompositeNode) {
126 for (Node<?> child : ((CompositeNode) item).getValue()) {
127 jobQueue.push(new SimpleEntry<org.w3c.dom.Node, Node<?>>(itemEl, child));
138 * @return user data value on found node
139 * @throws XPathExpressionException
141 @SuppressWarnings("unchecked")
142 public static <T> T findNodeByXpath(final org.w3c.dom.Document doc, final String xpathEx) throws XPathExpressionException {
144 XPathFactory xPathfactory = XPathFactory.newInstance();
145 XPath xpath = xPathfactory.newXPath();
146 XPathExpression expr = xpath.compile(xpathEx);
148 org.w3c.dom.Node result = (org.w3c.dom.Node) expr.evaluate(doc, XPathConstants.NODE);
149 if (result != null) {
150 userNode = (T) result.getUserData(USER_KEY_NODE);
157 * build NodeMap, where key = qName; value = node
160 * @return map of children, where key = qName and value is list of children
163 public static Map<QName, List<Node<?>>> buildNodeMap(final List<Node<?>> value) {
164 Map<QName, List<Node<?>>> nodeMapTmp = Maps.newLinkedHashMap();
166 throw new IllegalStateException("nodeList should not be null or empty");
168 for (Node<?> node : value) {
169 List<Node<?>> qList = nodeMapTmp.get(node.getNodeType());
171 qList = new ArrayList<>();
172 nodeMapTmp.put(node.getNodeType(), qList);
181 * @return map of lists, where key = path; value = {@link DataSchemaNode}
183 public static Map<String, ListSchemaNode> buildMapOfListNodes(final SchemaContext context) {
184 Map<String, ListSchemaNode> mapOfLists = new HashMap<>();
186 final Deque<DataSchemaNode> jobQueue = new ArrayDeque<>();
187 jobQueue.addAll(context.getDataDefinitions());
189 while (!jobQueue.isEmpty()) {
190 DataSchemaNode dataSchema = jobQueue.pop();
191 if (dataSchema instanceof ListSchemaNode) {
192 mapOfLists.put(schemaPathToPath(dataSchema.getPath().getPathFromRoot()), (ListSchemaNode) dataSchema);
195 if (dataSchema instanceof DataNodeContainer) {
196 jobQueue.addAll(((DataNodeContainer) dataSchema).getChildNodes());
207 private static String schemaPathToPath(final Iterable<QName> qNamesPath) {
208 return DOT_JOINER.join(Iterables.transform(qNamesPath, LOCALNAME_FUNCTION));
212 * add given node to it's parent's list of children
216 public static void fixParentRelation(final Node<?> newNode) {
217 if (newNode.getParent() != null) {
218 List<Node<?>> siblings = newNode.getParent().getValue();
219 if (!siblings.contains(newNode)) {
220 siblings.add(newNode);
226 * crawl all children of given node and assign it as their parent
230 public static void fixChildrenRelation(final CompositeNode parentNode) {
231 if (parentNode.getValue() != null) {
232 for (Node<?> child : parentNode.getValue()) {
233 if (child instanceof AbstractNodeTO<?>) {
234 ((AbstractNodeTO<?>) child).setParent(parentNode);
243 * @return list of values of map, found by given keys
245 public static <T, K> List<K> collectMapValues(final List<T> keys, final Map<T, K> dataMap) {
246 List<K> valueSubList = new ArrayList<>();
248 valueSubList.add(dataMap.get(key));
256 * @return list of children in list of appropriate type
258 public static List<Node<?>> buildChildrenList(final Node<?>... nodes) {
259 return Lists.newArrayList(nodes);