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