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.ArrayDeque;
11 import java.util.ArrayList;
12 import java.util.Deque;
13 import java.util.HashMap;
17 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
18 import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
19 import org.opendaylight.yangtools.yang.data.api.MutableNode;
20 import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
21 import org.opendaylight.yangtools.yang.data.api.Node;
22 import org.opendaylight.yangtools.yang.data.api.NodeModification;
23 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
26 * @author michal.rehak
30 public class LazyNodeToNodeMap {
32 private final Map<Node<?>, Node<?>> node2node = new HashMap<>();
33 private CompositeNode originalRoot;
34 private MutableCompositeNode mutableRoot;
38 * @return mutable twin
40 public Node<?> getMutableEquivalent(final Node<?> originalNode) {
41 Node<?> mutableNode = node2node.get(originalNode);
42 if (mutableNode == null) {
43 addPathMembers(originalNode);
44 mutableNode = node2node.get(originalNode);
53 private void addPathMembers(final Node<?> originalNode) {
54 final Deque<Node<?>> jobQueue = new ArrayDeque<>();
55 jobQueue.push(originalNode);
56 while (!jobQueue.isEmpty()) {
57 Node<?> node2add = jobQueue.pop();
58 boolean fixChildrenRefOnly = false;
59 if (node2node.containsKey(node2add)) {
60 if (node2add instanceof SimpleNode<?>) {
63 fixChildrenRefOnly = true;
66 CompositeNode nextParent = node2add.getParent();
67 MutableNode<?> mutableEquivalent = null;
69 if (node2add instanceof SimpleNode<?>) {
70 SimpleNode<?> node2addSimple = (SimpleNode<?>) node2add;
71 MutableSimpleNode<?> nodeMutant = NodeFactory.createMutableSimpleNode(
72 node2add.getNodeType(), null, node2addSimple.getValue(),
73 node2addSimple.getModificationAction(), node2addSimple);
74 mutableEquivalent = nodeMutant;
75 } else if (node2add instanceof CompositeNode) {
76 MutableCompositeNode nodeMutant = null;
77 if (fixChildrenRefOnly) {
78 nodeMutant = (MutableCompositeNode) node2node.get(node2add);
80 CompositeNode node2addComposite = (CompositeNode) node2add;
81 nodeMutant = NodeFactory.createMutableCompositeNode(node2add.getNodeType(),
83 ((NodeModification) node2add).getModificationAction(), node2addComposite);
86 mutableEquivalent = nodeMutant;
89 if (nodeMutant.getValue() == null) {
90 nodeMutant.setValue(new ArrayList<Node<?>>());
92 for (Node<?> originalChildNode : ((CompositeNode) node2add).getValue()) {
93 MutableNode<?> mutableChild = (MutableNode<?>) node2node.get(originalChildNode);
94 fixChildrenRef(nodeMutant, mutableChild);
97 if (nodeMutant.getValue() != null && !nodeMutant.getValue().isEmpty()) {
101 // store tree root, if occured
102 if (nextParent == null) {
103 if (originalRoot == null) {
104 originalRoot = (CompositeNode) node2add;
105 mutableRoot = nodeMutant;
107 if (!originalRoot.equals(node2add)) {
108 throw new IllegalStateException("Different tree root node obtained - " +
109 "perhaps nodes of different trees are getting mixed up.");
116 node2node.put(node2add, mutableEquivalent);
117 if (nextParent != null) {
118 jobQueue.push(nextParent);
125 * @param mutableChild
127 private static void fixChildrenRef(final MutableCompositeNode nodeMutant,
128 final MutableNode<?> mutableChild) {
129 if (mutableChild != null) {
130 if (!nodeMutant.getValue().contains(mutableChild)) {
131 nodeMutant.getValue().add(mutableChild);
133 CompositeNode parentOfChild = mutableChild.getParent();
134 if (parentOfChild == null) {
135 mutableChild.setParent(nodeMutant);
137 if (!parentOfChild.equals(nodeMutant)) {
138 throw new IllegalStateException("Different parent node obtained - " +
139 "perhaps nodes of different trees are getting mixed up.");
146 * @return the mutableRoot
148 public MutableCompositeNode getMutableRoot() {
153 * @return set of original nodes, registered in map as keys
155 public Set<Node<?>> getKeyNodes() {
156 return node2node.keySet();