4 package org.opendaylight.controller.yang.data.impl;
\r
6 import java.util.HashMap;
\r
7 import java.util.HashSet;
\r
8 import java.util.List;
\r
9 import java.util.Map;
\r
10 import java.util.Set;
\r
11 import java.util.Stack;
\r
13 import org.opendaylight.controller.yang.common.QName;
\r
14 import org.opendaylight.controller.yang.data.api.CompositeNode;
\r
15 import org.opendaylight.controller.yang.data.api.ModifyAction;
\r
16 import org.opendaylight.controller.yang.data.api.MutableCompositeNode;
\r
17 import org.opendaylight.controller.yang.data.api.MutableNode;
\r
18 import org.opendaylight.controller.yang.data.api.MutableSimpleNode;
\r
19 import org.opendaylight.controller.yang.data.api.Node;
\r
20 import org.opendaylight.controller.yang.data.api.NodeModificationBuilder;
\r
21 import org.opendaylight.controller.yang.model.api.ListSchemaNode;
\r
22 import org.opendaylight.controller.yang.model.api.SchemaContext;
\r
25 * @author michal.rehak
\r
28 public class NodeModificationBuilderImpl implements NodeModificationBuilder {
\r
30 private SchemaContext context;
\r
32 private Set<MutableNode<?>> changeLog;
\r
33 private Map<Node<?>, Node<?>> originalToMutable;
\r
35 private MutableCompositeNode mutableRoot;
\r
38 * @param originalTreeRootNode
\r
41 public NodeModificationBuilderImpl(CompositeNode originalTreeRootNode, SchemaContext context) {
\r
42 this.context = context;
\r
43 originalToMutable = new HashMap<>();
\r
44 mutableRoot = NodeFactory.copyDeepNode(originalTreeRootNode, originalToMutable);
\r
45 changeLog = new HashSet<>();
\r
49 * add given node to it's parent's list of children
\r
52 private static void fixParentRelation(Node<?> newNode) {
\r
53 if (newNode.getParent() != null) {
\r
54 List<Node<?>> siblings = newNode.getParent().getChildren();
\r
55 if (!siblings.contains(newNode)) {
\r
56 siblings.add(newNode);
\r
65 private void addModificationToLog(MutableNode<?> modNode, ModifyAction action) {
\r
66 modNode.setModifyAction(action);
\r
67 changeLog.add(modNode);
\r
71 public void addNode(MutableSimpleNode<?> newNode) {
\r
72 fixParentRelation(newNode);
\r
73 addModificationToLog(newNode, ModifyAction.CREATE);
\r
77 public void addNode(MutableCompositeNode newNode) {
\r
78 fixParentRelation(newNode);
\r
79 addModificationToLog(newNode, ModifyAction.CREATE);
\r
83 public void replaceNode(MutableSimpleNode<?> replacementNode) {
\r
84 addModificationToLog(replacementNode, ModifyAction.REPLACE);
\r
88 public void replaceNode(MutableCompositeNode replacementNode) {
\r
89 addModificationToLog(replacementNode, ModifyAction.REPLACE);
\r
93 public void deleteNode(MutableCompositeNode deadNode) {
\r
94 addModificationToLog(deadNode, ModifyAction.DELETE);
\r
98 public void deleteNode(MutableSimpleNode<?> deadNode) {
\r
99 addModificationToLog(deadNode, ModifyAction.DELETE);
\r
103 public void removeNode(MutableSimpleNode<?> deadNode) {
\r
104 addModificationToLog(deadNode, ModifyAction.REMOVE);
\r
108 public void removeNode(MutableCompositeNode deadNode) {
\r
109 addModificationToLog(deadNode, ModifyAction.REMOVE);
\r
113 public void mergeNode(MutableCompositeNode alteredNode) {
\r
114 addModificationToLog(alteredNode, ModifyAction.MERGE);
\r
118 * @return minimalistic tree containing diffs only
\r
121 public CompositeNode buildDiffTree() {
\r
122 Set<Node<?>> wanted = new HashSet<>();
\r
124 // walk changeLog, collect all required nodes
\r
125 for (MutableNode<?> mutant : changeLog) {
\r
126 wanted.addAll(collectSelfAndAllParents(mutant));
\r
129 // TODO:: walk wanted and add relevant keys
\r
130 Map<String, ListSchemaNode> mapOfLists = NodeUtils.buildMapOfListNodes(context);
\r
131 Set<Node<?>> wantedKeys = new HashSet<>();
\r
132 for (Node<?> outlaw : wanted) {
\r
133 if (outlaw instanceof CompositeNode) {
\r
134 String path = NodeUtils.buildPath(outlaw);
\r
135 if (mapOfLists.containsKey(path)) {
\r
136 ListSchemaNode listSchema = mapOfLists.get(path);
\r
137 if (listSchema.getQName().equals(outlaw.getNodeType())) {
\r
138 // try to add key subnode to wanted list
\r
139 List<QName> supportedKeys = listSchema.getKeyDefinition();
\r
140 for (Node<?> outlawChildren : ((CompositeNode) outlaw).getChildren()) {
\r
141 if (supportedKeys.contains(outlawChildren.getNodeType())) {
\r
142 wantedKeys.add(outlawChildren);
\r
149 wanted.addAll(wantedKeys);
\r
151 // remove all unwanted nodes from tree
\r
152 removeUnrelevantNodes(mutableRoot, wanted);
\r
154 return mutableRoot;
\r
158 * @param mutableRoot2
\r
161 private static void removeUnrelevantNodes(MutableCompositeNode mutRoot,
\r
162 Set<Node<?>> wanted) {
\r
163 Stack<MutableNode<?>> jobQueue = new Stack<>();
\r
164 jobQueue.push(mutRoot);
\r
165 while (!jobQueue.isEmpty()) {
\r
166 MutableNode<?> mutNode = jobQueue.pop();
\r
167 if (!wanted.contains(mutNode)) {
\r
168 if (mutNode.getParent() != null) {
\r
169 mutNode.getParent().getChildren().remove(mutNode);
\r
172 if (mutNode instanceof MutableCompositeNode) {
\r
173 for (Node<?> mutChild : ((MutableCompositeNode) mutNode).getChildren()) {
\r
174 jobQueue.push((MutableNode<?>) mutChild);
\r
182 * @param focusedAncestor
\r
183 * @return set of parents and focusedAncestor itself
\r
185 private static Set<Node<?>> collectSelfAndAllParents(Node<?> focusedAncestor) {
\r
186 Set<Node<?>> family = new HashSet<>();
\r
187 Node<?> tmpNode = focusedAncestor;
\r
188 while (tmpNode != null) {
\r
189 family.add(tmpNode);
\r
190 tmpNode = tmpNode.getParent();
\r
196 * @param originalNode
\r
197 * @return mutable version of given node
\r
200 public Node<?> getMutableEquivalent(Node<?> originalNode) {
\r
201 return originalToMutable.get(originalNode);
\r