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 java.util.ArrayList;
11 import java.util.HashMap;
14 import java.util.Stack;
16 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
17 import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
18 import org.opendaylight.yangtools.yang.data.api.MutableNode;
19 import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
20 import org.opendaylight.yangtools.yang.data.api.Node;
21 import org.opendaylight.yangtools.yang.data.api.NodeModification;
22 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
25 * @author michal.rehak
28 public class LazyNodeToNodeMap {
30 private Map<Node<?>, Node<?>> node2node = new HashMap<>();
31 private CompositeNode originalRoot;
32 private MutableCompositeNode mutableRoot;
36 * @return mutable twin
38 public Node<?> getMutableEquivalent(Node<?> originalNode) {
39 Node<?> mutableNode = node2node.get(originalNode);
40 if (mutableNode == null) {
41 addPathMembers(originalNode);
42 mutableNode = node2node.get(originalNode);
51 private void addPathMembers(Node<?> originalNode) {
52 Stack<Node<?>> jobQueue = new Stack<>();
53 jobQueue.push(originalNode);
54 while (!jobQueue.isEmpty()) {
55 Node<?> node2add = jobQueue.pop();
56 boolean fixChildrenRefOnly = false;
57 if (node2node.containsKey(node2add)) {
58 if (node2add instanceof SimpleNode<?>) {
61 fixChildrenRefOnly = true;
64 CompositeNode nextParent = node2add.getParent();
65 MutableNode<?> mutableEquivalent = null;
67 if (node2add instanceof SimpleNode<?>) {
68 SimpleNode<?> node2addSimple = (SimpleNode<?>) node2add;
69 MutableSimpleNode<?> nodeMutant = NodeFactory.createMutableSimpleNode(
70 node2add.getNodeType(), null, node2addSimple.getValue(),
71 node2addSimple.getModificationAction(), node2addSimple);
72 mutableEquivalent = nodeMutant;
73 } else if (node2add instanceof CompositeNode) {
74 MutableCompositeNode nodeMutant = null;
75 if (fixChildrenRefOnly) {
76 nodeMutant = (MutableCompositeNode) node2node.get(node2add);
78 CompositeNode node2addComposite = (CompositeNode) node2add;
79 nodeMutant = NodeFactory.createMutableCompositeNode(node2add.getNodeType(),
81 ((NodeModification) node2add).getModificationAction(), node2addComposite);
84 mutableEquivalent = nodeMutant;
87 if (nodeMutant.getChildren() == null) {
88 nodeMutant.setValue(new ArrayList<Node<?>>());
90 for (Node<?> originalChildNode : ((CompositeNode) node2add).getChildren()) {
91 MutableNode<?> mutableChild = (MutableNode<?>) node2node.get(originalChildNode);
92 fixChildrenRef(nodeMutant, mutableChild);
95 if (nodeMutant.getChildren() != null && !nodeMutant.getChildren().isEmpty()) {
99 // store tree root, if occured
100 if (nextParent == null) {
101 if (originalRoot == null) {
102 originalRoot = (CompositeNode) node2add;
103 mutableRoot = nodeMutant;
105 if (!originalRoot.equals(node2add)) {
106 throw new IllegalStateException("Different tree root node obtained - " +
107 "perhaps nodes of different trees are getting mixed up.");
114 node2node.put(node2add, mutableEquivalent);
115 if (nextParent != null) {
116 jobQueue.push(nextParent);
123 * @param mutableChild
125 private static void fixChildrenRef(MutableCompositeNode nodeMutant,
126 MutableNode<?> mutableChild) {
127 if (mutableChild != null) {
128 if (!nodeMutant.getChildren().contains(mutableChild)) {
129 nodeMutant.getChildren().add(mutableChild);
131 CompositeNode parentOfChild = mutableChild.getParent();
132 if (parentOfChild == null) {
133 mutableChild.setParent(nodeMutant);
135 if (!parentOfChild.equals(nodeMutant)) {
136 throw new IllegalStateException("Different parent node obtained - " +
137 "perhaps nodes of different trees are getting mixed up.");
144 * @return the mutableRoot
146 public MutableCompositeNode getMutableRoot() {
151 * @return set of original nodes, registered in map as keys
153 public Set<Node<?>> getKeyNodes() {
154 return node2node.keySet();