Merge "BUG 2282 - JSON top level element without module name"
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / LazyNodeToNodeMap.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.data.impl;
9
10 import java.util.ArrayDeque;
11 import java.util.ArrayList;
12 import java.util.Deque;
13 import java.util.HashMap;
14 import java.util.Map;
15 import java.util.Set;
16
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;
24
25 /**
26  * @author michal.rehak
27  *
28  */
29 @Deprecated
30 public class LazyNodeToNodeMap {
31
32     private final Map<Node<?>, Node<?>> node2node = new HashMap<>();
33     private CompositeNode originalRoot;
34     private MutableCompositeNode mutableRoot;
35
36     /**
37      * @param originalNode
38      * @return mutable twin
39      */
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);
45         }
46
47         return mutableNode;
48     }
49
50     /**
51      * @param originalNode
52      */
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<?>) {
61                     continue;
62                 }
63                 fixChildrenRefOnly = true;
64             }
65
66             CompositeNode nextParent = node2add.getParent();
67             MutableNode<?> mutableEquivalent = null;
68
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);
79                 } else {
80                     CompositeNode node2addComposite = (CompositeNode) node2add;
81                     nodeMutant = NodeFactory.createMutableCompositeNode(node2add.getNodeType(),
82                             null, null,
83                             ((NodeModification) node2add).getModificationAction(), node2addComposite);
84                 }
85
86                 mutableEquivalent = nodeMutant;
87
88                 // tidy up children
89                 if (nodeMutant.getValue() == null) {
90                     nodeMutant.setValue(new ArrayList<Node<?>>());
91                 }
92                 for (Node<?> originalChildNode : ((CompositeNode) node2add).getValue()) {
93                     MutableNode<?> mutableChild = (MutableNode<?>) node2node.get(originalChildNode);
94                     fixChildrenRef(nodeMutant, mutableChild);
95                 }
96
97                 if (nodeMutant.getValue() != null && !nodeMutant.getValue().isEmpty()) {
98                     nodeMutant.init();
99                 }
100
101                 // store tree root, if occured
102                 if (nextParent == null) {
103                     if (originalRoot == null) {
104                         originalRoot = (CompositeNode) node2add;
105                         mutableRoot = nodeMutant;
106                     } else {
107                         if (!originalRoot.equals(node2add)) {
108                             throw new IllegalStateException("Different tree root node obtained - " +
109                                     "perhaps nodes of different trees are getting mixed up.");
110                         }
111                     }
112                 }
113             }
114
115             // feed jobQueue
116             node2node.put(node2add, mutableEquivalent);
117             if (nextParent != null) {
118                 jobQueue.push(nextParent);
119             }
120         }
121     }
122
123     /**
124      * @param nodeMutant
125      * @param mutableChild
126      */
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);
132             }
133             CompositeNode parentOfChild = mutableChild.getParent();
134             if (parentOfChild == null) {
135                 mutableChild.setParent(nodeMutant);
136             } else {
137                 if (!parentOfChild.equals(nodeMutant)) {
138                     throw new IllegalStateException("Different parent node obtained - " +
139                             "perhaps nodes of different trees are getting mixed up.");
140                 }
141             }
142         }
143     }
144
145     /**
146      * @return the mutableRoot
147      */
148     public MutableCompositeNode getMutableRoot() {
149         return mutableRoot;
150     }
151
152     /**
153      * @return set of original nodes, registered in map as keys
154      */
155     public Set<Node<?>> getKeyNodes() {
156         return node2node.keySet();
157     }
158 }