Merge "Untangle the XML/Hello message decoders"
[controller.git] / opendaylight / md-sal / sal-dom-broker / src / main / java / org / opendaylight / controller / sal / dom / broker / util / YangDataOperations.xtend
1 /*
2  * Copyright (c) 2014 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.controller.sal.dom.broker.util
9
10 import org.opendaylight.yangtools.yang.data.api.CompositeNode
11 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
12 import static com.google.common.base.Preconditions.*;
13 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
14 import java.util.ArrayList
15
16 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
17 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
18 import org.opendaylight.yangtools.yang.data.api.Node
19 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
20 import java.util.List
21 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
22 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
23 import java.util.Collections
24 import java.util.HashSet
25 import org.opendaylight.yangtools.yang.common.QName
26 import static extension org.opendaylight.controller.sal.dom.broker.util.YangDataUtils.*;
27
28 class YangDataOperations {
29
30     static def CompositeNode merge(DataSchemaNode schema, CompositeNode stored, CompositeNode modified, boolean config) {
31         if (stored === null) {
32             return modified;
33         }
34
35         if (schema instanceof ListSchemaNode || schema instanceof ContainerSchemaNode) {
36             return mergeContainer(schema as DataNodeContainer, stored, modified, config);
37         }
38         throw new IllegalArgumentException("Supplied node is not data node container.");
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         
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         
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             } else {
78                 mergedNodes.add(entry.value);
79             }
80         }
81         mergedNodes.addAll(originalMap.values);
82         return mergedNodes;
83     }
84
85     static private def CompositeNode mergeContainer(DataNodeContainer schema, CompositeNode stored,
86         CompositeNode modified, boolean config) {
87         if (stored == null) {
88             return modified;
89         }
90         checkNotNull(stored)
91         checkNotNull(modified)
92         checkArgument(stored.nodeType == modified.nodeType);
93
94         val mergedChildNodes = new ArrayList<Node<?>>(stored.children.size + modified.children.size);
95         
96         val toProcess = new HashSet<QName>(stored.keySet);
97         toProcess.addAll(modified.keySet);
98         
99         for (qname : toProcess) {
100             val schemaChild = schema.getDataChildByName(qname);
101             val storedChildren = stored.get(qname);
102             val modifiedChildren = modified.get(qname);
103
104             if (modifiedChildren !== null && !modifiedChildren.empty) {
105                 if (storedChildren === null || storedChildren.empty || schemaChild === null) {
106                     mergedChildNodes.addAll(modifiedChildren);
107                 } else {
108                     mergedChildNodes.addAll(mergeMultiple(schemaChild, storedChildren, modifiedChildren, config));
109                 }
110             } else if (storedChildren !== null && !storedChildren.empty) {
111                 mergedChildNodes.addAll(storedChildren);
112             }
113         }
114         return new CompositeNodeTOImpl(stored.nodeType, null, mergedChildNodes);
115     }
116
117 }