Merge "Minor fixes in md-sal and config."
[controller.git] / opendaylight / md-sal / sal-dom-broker / src / main / java / org / opendaylight / controller / sal / dom / broker / util / YangDataOperations.xtend
1 package org.opendaylight.controller.sal.dom.broker.util
2
3 import org.opendaylight.yangtools.yang.data.api.CompositeNode
4 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
5 import static com.google.common.base.Preconditions.*;
6 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
7 import java.util.ArrayList
8
9 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
10 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
11 import org.opendaylight.yangtools.yang.data.api.Node
12 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
13 import java.util.List
14 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
15 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
16 import java.util.Collections
17 import java.util.HashSet
18 import org.opendaylight.yangtools.yang.common.QName
19 import static extension org.opendaylight.controller.sal.dom.broker.util.YangDataUtils.*;
20
21 class YangDataOperations {
22
23     static def CompositeNode merge(DataSchemaNode schema, CompositeNode stored, CompositeNode modified, boolean config) {
24         if (stored === null) {
25             return modified;
26         }
27
28         if (schema instanceof ListSchemaNode || schema instanceof ContainerSchemaNode) {
29             return mergeContainer(schema as DataNodeContainer, stored, modified, config);
30         }
31         throw new IllegalArgumentException("Supplied node is not data node container.");
32     }
33
34     private def static checkConfigurational(DataSchemaNode node, boolean config) {
35         if (config) {
36             checkArgument(node.configuration, "Supplied composite node is not configurational.");
37         }
38     }
39
40     private static dispatch def Iterable<? extends Node<?>> mergeMultiple(LeafSchemaNode node, List<Node<?>> original,
41         List<Node<?>> modified, boolean configurational) {
42         checkArgument(original.size === 1);
43         checkArgument(modified.size === 1);
44         
45         return modified;
46     }
47
48     private static dispatch def Iterable<? extends Node<?>> mergeMultiple(LeafListSchemaNode node,
49         List<Node<?>> original, List<Node<?>> modified, boolean configurational) {
50         return modified;
51     }
52
53     private static dispatch def Iterable<? extends Node<?>> mergeMultiple(ContainerSchemaNode node,
54         List<Node<?>> original, List<Node<?>> modified, boolean configurational) {
55         checkArgument(original.size === 1);
56         checkArgument(modified.size === 1);
57         return Collections.singletonList(
58             merge(node, original.get(0) as CompositeNode, modified.get(0) as CompositeNode, configurational));
59     }
60
61     private static dispatch def Iterable<? extends Node<?>> mergeMultiple(ListSchemaNode node, List<Node<?>> original,
62         List<Node<?>> modified, boolean configurational) {
63         
64         if(node.keyDefinition === null || node.keyDefinition.empty) {
65             return modified;
66         } 
67         val originalMap = (original as List).toIndexMap(node.keyDefinition);
68         val modifiedMap = (modified as List).toIndexMap(node.keyDefinition);
69         
70         val List<Node<?>> mergedNodes = new ArrayList(original.size + modified.size);
71         for(entry : modifiedMap.entrySet) {
72             val originalEntry = originalMap.get(entry.key);
73             if(originalEntry != null) {
74                 originalMap.remove(entry.key);
75                 mergedNodes.add(merge(node,originalEntry,entry.value,configurational));
76                 
77             }
78         }
79         mergedNodes.addAll(originalMap.values);
80         return mergedNodes;
81     }
82
83     static private def CompositeNode mergeContainer(DataNodeContainer schema, CompositeNode stored,
84         CompositeNode modified, boolean config) {
85         if (stored == null) {
86             return modified;
87         }
88         checkNotNull(stored)
89         checkNotNull(modified)
90         checkArgument(stored.nodeType == modified.nodeType);
91
92         val mergedChildNodes = new ArrayList<Node<?>>(stored.children.size + modified.children.size);
93         
94         val toProcess = new HashSet<QName>(stored.keySet);
95         toProcess.addAll(modified.keySet);
96         
97         for (qname : toProcess) {
98             val schemaChild = schema.getDataChildByName(qname);
99             val storedChildren = stored.get(qname);
100             val modifiedChildren = modified.get(qname);
101
102             if (modifiedChildren !== null && !modifiedChildren.empty) {
103                 if (storedChildren === null || storedChildren.empty || schemaChild === null) {
104                     mergedChildNodes.addAll(modifiedChildren);
105                 } else {
106                     mergedChildNodes.addAll(mergeMultiple(schemaChild, storedChildren, modifiedChildren, config));
107                 }
108             } else if (storedChildren !== null && !storedChildren.empty) {
109                 mergedChildNodes.addAll(storedChildren);
110             }
111         }
112         return new CompositeNodeTOImpl(stored.nodeType, null, mergedChildNodes);
113     }
114
115 }