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