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
29 public class LazyNodeToNodeMap {
31 private final Map<Node<?>, Node<?>> node2node = new HashMap<>();
32 private CompositeNode originalRoot;
33 private MutableCompositeNode mutableRoot;
37 * @return mutable twin
39 public Node<?> getMutableEquivalent(final Node<?> originalNode) {
40 Node<?> mutableNode = node2node.get(originalNode);
41 if (mutableNode == null) {
42 addPathMembers(originalNode);
43 mutableNode = node2node.get(originalNode);
52 private void addPathMembers(final Node<?> originalNode) {
53 final Deque<Node<?>> jobQueue = new ArrayDeque<>();
54 jobQueue.push(originalNode);
55 while (!jobQueue.isEmpty()) {
56 Node<?> node2add = jobQueue.pop();
57 boolean fixChildrenRefOnly = false;
58 if (node2node.containsKey(node2add)) {
59 if (node2add instanceof SimpleNode<?>) {
62 fixChildrenRefOnly = true;
65 CompositeNode nextParent = node2add.getParent();
66 MutableNode<?> mutableEquivalent = null;
68 if (node2add instanceof SimpleNode<?>) {
69 SimpleNode<?> node2addSimple = (SimpleNode<?>) node2add;
70 MutableSimpleNode<?> nodeMutant = NodeFactory.createMutableSimpleNode(
71 node2add.getNodeType(), null, node2addSimple.getValue(),
72 node2addSimple.getModificationAction(), node2addSimple);
73 mutableEquivalent = nodeMutant;
74 } else if (node2add instanceof CompositeNode) {
75 MutableCompositeNode nodeMutant = null;
76 if (fixChildrenRefOnly) {
77 nodeMutant = (MutableCompositeNode) node2node.get(node2add);
79 CompositeNode node2addComposite = (CompositeNode) node2add;
80 nodeMutant = NodeFactory.createMutableCompositeNode(node2add.getNodeType(),
82 ((NodeModification) node2add).getModificationAction(), node2addComposite);
85 mutableEquivalent = nodeMutant;
88 if (nodeMutant.getValue() == null) {
89 nodeMutant.setValue(new ArrayList<Node<?>>());
91 for (Node<?> originalChildNode : ((CompositeNode) node2add).getValue()) {
92 MutableNode<?> mutableChild = (MutableNode<?>) node2node.get(originalChildNode);
93 fixChildrenRef(nodeMutant, mutableChild);
96 if (nodeMutant.getValue() != null && !nodeMutant.getValue().isEmpty()) {
100 // store tree root, if occured
101 if (nextParent == null) {
102 if (originalRoot == null) {
103 originalRoot = (CompositeNode) node2add;
104 mutableRoot = nodeMutant;
106 if (!originalRoot.equals(node2add)) {
107 throw new IllegalStateException("Different tree root node obtained - " +
108 "perhaps nodes of different trees are getting mixed up.");
115 node2node.put(node2add, mutableEquivalent);
116 if (nextParent != null) {
117 jobQueue.push(nextParent);
124 * @param mutableChild
126 private static void fixChildrenRef(final MutableCompositeNode nodeMutant,
127 final MutableNode<?> mutableChild) {
128 if (mutableChild != null) {
129 if (!nodeMutant.getValue().contains(mutableChild)) {
130 nodeMutant.getValue().add(mutableChild);
132 CompositeNode parentOfChild = mutableChild.getParent();
133 if (parentOfChild == null) {
134 mutableChild.setParent(nodeMutant);
136 if (!parentOfChild.equals(nodeMutant)) {
137 throw new IllegalStateException("Different parent node obtained - " +
138 "perhaps nodes of different trees are getting mixed up.");
145 * @return the mutableRoot
147 public MutableCompositeNode getMutableRoot() {
152 * @return set of original nodes, registered in map as keys
154 public Set<Node<?>> getKeyNodes() {
155 return node2node.keySet();