Merge "When a node is going down, remove edges in both directions associated with...
[controller.git] / opendaylight / sal / yang-prototype / yang / yang-data-impl / src / main / java / org / opendaylight / controller / yang / data / impl / NodeModificationBuilderImpl.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.HashSet;\r
11 import java.util.List;\r
12 import java.util.Map;\r
13 import java.util.Set;\r
14 \r
15 import org.opendaylight.controller.yang.common.QName;\r
16 import org.opendaylight.controller.yang.data.api.CompositeNode;\r
17 import org.opendaylight.controller.yang.data.api.ModifyAction;\r
18 import org.opendaylight.controller.yang.data.api.MutableCompositeNode;\r
19 import org.opendaylight.controller.yang.data.api.MutableNode;\r
20 import org.opendaylight.controller.yang.data.api.MutableSimpleNode;\r
21 import org.opendaylight.controller.yang.data.api.Node;\r
22 import org.opendaylight.controller.yang.data.api.NodeModificationBuilder;\r
23 import org.opendaylight.controller.yang.model.api.ListSchemaNode;\r
24 import org.opendaylight.controller.yang.model.api.SchemaContext;\r
25 \r
26 /**\r
27  * @author michal.rehak\r
28  *\r
29  */\r
30 public class NodeModificationBuilderImpl implements NodeModificationBuilder {\r
31     \r
32     private SchemaContext context;\r
33     \r
34     private Set<MutableNode<?>> changeLog;\r
35     private LazyNodeToNodeMap originalToMutable;\r
36 \r
37     /**\r
38      * @param originalTreeRootNode \r
39      * @param context\r
40      */\r
41     public NodeModificationBuilderImpl(CompositeNode originalTreeRootNode, SchemaContext context) {\r
42         this.context = context;\r
43         originalToMutable = new LazyNodeToNodeMap();\r
44         changeLog = new HashSet<>();\r
45     }\r
46 \r
47     /**\r
48      * @param modNode\r
49      * @param action \r
50      */\r
51     private void addModificationToLog(MutableNode<?> modNode, ModifyAction action) {\r
52         modNode.setModifyAction(action);\r
53         changeLog.add(modNode);\r
54     }\r
55 \r
56     @Override\r
57     public void addNode(MutableSimpleNode<?> newNode) {\r
58         NodeUtils.fixParentRelation(newNode);\r
59         addModificationToLog(newNode, ModifyAction.CREATE);\r
60     }\r
61     \r
62     @Override\r
63     public void addNode(MutableCompositeNode newNode) {\r
64         NodeUtils.fixParentRelation(newNode);\r
65         addModificationToLog(newNode, ModifyAction.CREATE);\r
66     }\r
67     \r
68     @Override\r
69     public void replaceNode(MutableSimpleNode<?> replacementNode) {\r
70         addModificationToLog(replacementNode, ModifyAction.REPLACE);\r
71     }\r
72     \r
73     @Override\r
74     public void replaceNode(MutableCompositeNode replacementNode) {\r
75         addModificationToLog(replacementNode, ModifyAction.REPLACE);\r
76     }\r
77 \r
78     @Override\r
79     public void deleteNode(MutableCompositeNode deadNode) {\r
80         addModificationToLog(deadNode, ModifyAction.DELETE);\r
81     }\r
82     \r
83     @Override\r
84     public void deleteNode(MutableSimpleNode<?> deadNode) {\r
85         addModificationToLog(deadNode, ModifyAction.DELETE);\r
86     }\r
87 \r
88     @Override\r
89     public void removeNode(MutableSimpleNode<?> deadNode) {\r
90         addModificationToLog(deadNode, ModifyAction.REMOVE);\r
91     }\r
92     \r
93     @Override\r
94     public void removeNode(MutableCompositeNode deadNode) {\r
95         addModificationToLog(deadNode, ModifyAction.REMOVE);\r
96     }\r
97     \r
98     @Override\r
99     public void mergeNode(MutableCompositeNode alteredNode) {\r
100         addModificationToLog(alteredNode, ModifyAction.MERGE);\r
101     }\r
102 \r
103     /**\r
104      * @return minimalistic tree containing diffs only\r
105      */\r
106     @Override\r
107     public CompositeNode buildDiffTree() {\r
108         Set<Node<?>> wanted = new HashSet<>();\r
109         \r
110         // walk changeLog, collect all required nodes\r
111         for (MutableNode<?> mutant : changeLog) {\r
112             wanted.addAll(collectSelfAndAllParents(mutant));\r
113         }\r
114         \r
115         // walk wanted and add relevant keys\r
116         Map<String, ListSchemaNode>  mapOfLists = NodeUtils.buildMapOfListNodes(context);\r
117         for (Node<?> outlaw : wanted) {\r
118             if (outlaw instanceof CompositeNode) {\r
119                 String path = NodeUtils.buildPath(outlaw);\r
120                 if (mapOfLists.containsKey(path)) {\r
121                     ListSchemaNode listSchema = mapOfLists.get(path);\r
122                     if (listSchema.getQName().equals(outlaw.getNodeType())) {\r
123                         // try to add key subnode to wanted list\r
124                         List<QName> supportedKeys = listSchema.getKeyDefinition();\r
125                         CompositeNode outlawOriginal = ((MutableCompositeNode) outlaw).getOriginal();\r
126                         for (Node<?> outlawOriginalChild : outlawOriginal.getChildren()) {\r
127                             if (supportedKeys.contains(outlawOriginalChild.getNodeType())) {\r
128                                 originalToMutable.getMutableEquivalent(outlawOriginalChild);\r
129                             }\r
130                         }\r
131                     }\r
132                 }\r
133             }\r
134         }\r
135         \r
136         return originalToMutable.getMutableRoot();\r
137     }\r
138 \r
139     /**\r
140      * @param focusedDescendant\r
141      * @return set of parents and focusedAncestor itself\r
142      */\r
143     private static Set<Node<?>> collectSelfAndAllParents(Node<?> focusedDescendant) {\r
144         Set<Node<?>> family = new HashSet<>();\r
145         Node<?> tmpNode = focusedDescendant;\r
146         while (tmpNode != null) {\r
147             family.add(tmpNode);\r
148             tmpNode = tmpNode.getParent();\r
149         }\r
150         return family;\r
151     }\r
152 \r
153     /**\r
154      * @param originalNode\r
155      * @return mutable version of given node\r
156      */\r
157     @Override\r
158     public Node<?> getMutableEquivalent(Node<?> originalNode) {\r
159         return originalToMutable.getMutableEquivalent(originalNode);\r
160     }\r
161 \r
162 }\r