Fix minor bug in FRM proactive flow code path
[controller.git] / opendaylight / sal / yang-prototype / yang / yang-data-impl / src / main / java / org / opendaylight / controller / yang / data / impl / LazyNodeToNodeMap.java
1 /*\r
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 package org.opendaylight.controller.yang.data.impl;\r
9 \r
10 import java.util.ArrayList;\r
11 import java.util.HashMap;\r
12 import java.util.Map;\r
13 import java.util.Set;\r
14 import java.util.Stack;\r
15 \r
16 import org.opendaylight.controller.yang.data.api.CompositeNode;\r
17 import org.opendaylight.controller.yang.data.api.MutableCompositeNode;\r
18 import org.opendaylight.controller.yang.data.api.MutableNode;\r
19 import org.opendaylight.controller.yang.data.api.MutableSimpleNode;\r
20 import org.opendaylight.controller.yang.data.api.Node;\r
21 import org.opendaylight.controller.yang.data.api.NodeModification;\r
22 import org.opendaylight.controller.yang.data.api.SimpleNode;\r
23 \r
24 /**\r
25  * @author michal.rehak\r
26  *\r
27  */\r
28 public class LazyNodeToNodeMap {\r
29     \r
30     private Map<Node<?>, Node<?>> node2node = new HashMap<>();\r
31     private CompositeNode originalRoot;\r
32     private MutableCompositeNode mutableRoot;\r
33     \r
34     /**\r
35      * @param originalNode\r
36      * @return mutable twin\r
37      */\r
38     public Node<?> getMutableEquivalent(Node<?> originalNode) {\r
39         Node<?> mutableNode = node2node.get(originalNode);\r
40         if (mutableNode == null) {\r
41             addPathMembers(originalNode);\r
42             mutableNode = node2node.get(originalNode);\r
43         }\r
44         \r
45         return mutableNode;\r
46     }\r
47     \r
48     /**\r
49      * @param originalNode\r
50      */\r
51     private void addPathMembers(Node<?> originalNode) {\r
52         Stack<Node<?>> jobQueue = new Stack<>(); \r
53         jobQueue.push(originalNode);\r
54         while (!jobQueue.isEmpty()) {\r
55             Node<?> node2add = jobQueue.pop();\r
56             boolean fixChildrenRefOnly = false;\r
57             if (node2node.containsKey(node2add)) {\r
58                 if (node2add instanceof SimpleNode<?>) {\r
59                     continue;\r
60                 }\r
61                 fixChildrenRefOnly = true;\r
62             }\r
63             \r
64             CompositeNode nextParent = node2add.getParent();\r
65             MutableNode<?> mutableEquivalent = null;\r
66             \r
67             if (node2add instanceof SimpleNode<?>) {\r
68                 SimpleNode<?> node2addSimple = (SimpleNode<?>) node2add;\r
69                 MutableSimpleNode<?> nodeMutant = NodeFactory.createMutableSimpleNode(\r
70                         node2add.getNodeType(), null, node2addSimple.getValue(), \r
71                         node2addSimple.getModificationAction(), node2addSimple);\r
72                 mutableEquivalent = nodeMutant;\r
73             } else if (node2add instanceof CompositeNode) {\r
74                 MutableCompositeNode nodeMutant = null;\r
75                 if (fixChildrenRefOnly) {\r
76                     nodeMutant = (MutableCompositeNode) node2node.get(node2add);\r
77                 } else {\r
78                     CompositeNode node2addComposite = (CompositeNode) node2add;\r
79                     nodeMutant = NodeFactory.createMutableCompositeNode(node2add.getNodeType(), \r
80                         null, null, \r
81                         ((NodeModification) node2add).getModificationAction(), node2addComposite);\r
82                 }\r
83                 \r
84                 mutableEquivalent = nodeMutant;\r
85 \r
86                 // tidy up children\r
87                 if (nodeMutant.getChildren() == null) {\r
88                     nodeMutant.setValue(new ArrayList<Node<?>>());\r
89                 }\r
90                 for (Node<?> originalChildNode : ((CompositeNode) node2add).getChildren()) {\r
91                     MutableNode<?> mutableChild = (MutableNode<?>) node2node.get(originalChildNode);\r
92                     fixChildrenRef(nodeMutant, mutableChild);\r
93                 }\r
94                 \r
95                 if (nodeMutant.getChildren() != null && !nodeMutant.getChildren().isEmpty()) {\r
96                     nodeMutant.init();\r
97                 }\r
98 \r
99                 // store tree root, if occured\r
100                 if (nextParent == null) {\r
101                     if (originalRoot == null) {\r
102                         originalRoot = (CompositeNode) node2add;\r
103                         mutableRoot = nodeMutant;\r
104                     } else {\r
105                         if (!originalRoot.equals(node2add)) {\r
106                             throw new IllegalStateException("Different tree root node obtained - " +\r
107                                         "perhaps nodes of different trees are getting mixed up.");\r
108                         }\r
109                     }\r
110                 }\r
111             }\r
112             \r
113             // feed jobQueue\r
114             node2node.put(node2add, mutableEquivalent);\r
115             if (nextParent != null) {\r
116                 jobQueue.push(nextParent);\r
117             } \r
118         }\r
119     }\r
120 \r
121     /**\r
122      * @param nodeMutant\r
123      * @param mutableChild\r
124      */\r
125     private static void fixChildrenRef(MutableCompositeNode nodeMutant,\r
126             MutableNode<?> mutableChild) {\r
127         if (mutableChild != null) {\r
128             if (!nodeMutant.getChildren().contains(mutableChild)) {\r
129                 nodeMutant.getChildren().add(mutableChild);\r
130             }\r
131             CompositeNode parentOfChild = mutableChild.getParent();\r
132             if (parentOfChild == null) {\r
133                 mutableChild.setParent(nodeMutant);\r
134             } else {\r
135                 if (!parentOfChild.equals(nodeMutant)) {\r
136                     throw new IllegalStateException("Different parent node obtained - " +\r
137                             "perhaps nodes of different trees are getting mixed up.");\r
138                 }\r
139             }\r
140         }\r
141     }\r
142 \r
143     /**\r
144      * @return the mutableRoot\r
145      */\r
146     public MutableCompositeNode getMutableRoot() {\r
147         return mutableRoot;\r
148     }\r
149     \r
150     /**\r
151      * @return set of original nodes, registered in map as keys \r
152      */\r
153     public Set<Node<?>> getKeyNodes() {\r
154         return node2node.keySet();\r
155     }\r
156 }\r