Merge "Prevent ConfigPusher from killing its thread"
[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 def static checkConfigurational(DataSchemaNode node, boolean config) {
42         if (config) {
43             checkArgument(node.configuration, "Supplied composite node is not configurational.");
44         }
45     }
46
47     private static dispatch def Iterable<? extends Node<?>> mergeMultiple(LeafSchemaNode node, List<Node<?>> original,
48         List<Node<?>> modified, boolean configurational) {
49         checkArgument(original.size === 1);
50         checkArgument(modified.size === 1);
51         
52         return modified;
53     }
54
55     private static dispatch def Iterable<? extends Node<?>> mergeMultiple(LeafListSchemaNode node,
56         List<Node<?>> original, List<Node<?>> modified, boolean configurational) {
57         return modified;
58     }
59
60     private static dispatch def Iterable<? extends Node<?>> mergeMultiple(ContainerSchemaNode node,
61         List<Node<?>> original, List<Node<?>> modified, boolean configurational) {
62         checkArgument(original.size === 1);
63         checkArgument(modified.size === 1);
64         return Collections.singletonList(
65             merge(node, original.get(0) as CompositeNode, modified.get(0) as CompositeNode, configurational));
66     }
67
68     private static dispatch def Iterable<? extends Node<?>> mergeMultiple(ListSchemaNode node, List<Node<?>> original,
69         List<Node<?>> modified, boolean configurational) {
70         
71         if(node.keyDefinition === null || node.keyDefinition.empty) {
72             return modified;
73         } 
74         val originalMap = (original as List).toIndexMap(node.keyDefinition);
75         val modifiedMap = (modified as List).toIndexMap(node.keyDefinition);
76         
77         val List<Node<?>> mergedNodes = new ArrayList(original.size + modified.size);
78         for(entry : modifiedMap.entrySet) {
79             val originalEntry = originalMap.get(entry.key);
80             if(originalEntry != null) {
81                 originalMap.remove(entry.key);
82                 mergedNodes.add(merge(node,originalEntry,entry.value,configurational));
83                 
84             }
85         }
86         mergedNodes.addAll(originalMap.values);
87         return mergedNodes;
88     }
89
90     static private def CompositeNode mergeContainer(DataNodeContainer schema, CompositeNode stored,
91         CompositeNode modified, boolean config) {
92         if (stored == null) {
93             return modified;
94         }
95         checkNotNull(stored)
96         checkNotNull(modified)
97         checkArgument(stored.nodeType == modified.nodeType);
98
99         val mergedChildNodes = new ArrayList<Node<?>>(stored.children.size + modified.children.size);
100         
101         val toProcess = new HashSet<QName>(stored.keySet);
102         toProcess.addAll(modified.keySet);
103         
104         for (qname : toProcess) {
105             val schemaChild = schema.getDataChildByName(qname);
106             val storedChildren = stored.get(qname);
107             val modifiedChildren = modified.get(qname);
108
109             if (modifiedChildren !== null && !modifiedChildren.empty) {
110                 if (storedChildren === null || storedChildren.empty || schemaChild === null) {
111                     mergedChildNodes.addAll(modifiedChildren);
112                 } else {
113                     mergedChildNodes.addAll(mergeMultiple(schemaChild, storedChildren, modifiedChildren, config));
114                 }
115             } else if (storedChildren !== null && !storedChildren.empty) {
116                 mergedChildNodes.addAll(storedChildren);
117             }
118         }
119         return new CompositeNodeTOImpl(stored.nodeType, null, mergedChildNodes);
120     }
121
122 }