Merge "BUG 720 - YANG leaf as JSON input *<*:* couldn't be saved"
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / messages / DataChanged.java
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
9 package org.opendaylight.controller.cluster.datastore.messages;
10
11 import org.opendaylight.controller.cluster.datastore.node.NormalizedNodeToNodeCodec;
12 import org.opendaylight.controller.cluster.datastore.util.InstanceIdentifierUtils;
13 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
14 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
15 import org.opendaylight.controller.protobuff.messages.datachange.notification.DataChangeListenerMessages;
16 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
17 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
18 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Set;
26
27 public class DataChanged implements SerializableMessage {
28     public static final Class<DataChangeListenerMessages.DataChanged> SERIALIZABLE_CLASS =
29         DataChangeListenerMessages.DataChanged.class;
30
31     final private SchemaContext schemaContext;
32     private final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>>
33         change;
34
35
36
37     public DataChanged(SchemaContext schemaContext,
38         AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
39         this.change = change;
40         this.schemaContext = schemaContext;
41     }
42
43
44     public AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> getChange() {
45         return change;
46     }
47
48
49     private NormalizedNodeMessages.Node convertToNodeTree(
50         NormalizedNode<?, ?> normalizedNode) {
51
52         return new NormalizedNodeToNodeCodec(schemaContext)
53             .encode(normalizedNode)
54             .getNormalizedNode();
55
56     }
57
58     private Iterable<NormalizedNodeMessages.InstanceIdentifier> convertToRemovePaths(
59         Set<YangInstanceIdentifier> removedPaths) {
60         final Set<NormalizedNodeMessages.InstanceIdentifier> removedPathInstanceIds = new HashSet<>();
61         for (YangInstanceIdentifier id : removedPaths) {
62             removedPathInstanceIds.add(InstanceIdentifierUtils.toSerializable(id));
63         }
64         return new Iterable<NormalizedNodeMessages.InstanceIdentifier>() {
65             @Override
66             public Iterator<NormalizedNodeMessages.InstanceIdentifier> iterator() {
67                 return removedPathInstanceIds.iterator();
68             }
69         };
70
71     }
72
73     private NormalizedNodeMessages.NodeMap convertToNodeMap(
74         Map<YangInstanceIdentifier, NormalizedNode<?, ?>> data) {
75         NormalizedNodeToNodeCodec normalizedNodeToNodeCodec =
76             new NormalizedNodeToNodeCodec(schemaContext);
77         NormalizedNodeMessages.NodeMap.Builder nodeMapBuilder =
78             NormalizedNodeMessages.NodeMap.newBuilder();
79         NormalizedNodeMessages.NodeMapEntry.Builder builder =
80             NormalizedNodeMessages.NodeMapEntry.newBuilder();
81         for (Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry : data
82             .entrySet()) {
83
84
85             NormalizedNodeMessages.InstanceIdentifier instanceIdentifier =
86                 InstanceIdentifierUtils.toSerializable(entry.getKey());
87
88             builder.setInstanceIdentifierPath(instanceIdentifier)
89                 .setNormalizedNode(normalizedNodeToNodeCodec
90                     .encode(entry.getValue())
91                     .getNormalizedNode());
92             nodeMapBuilder.addMapEntries(builder.build());
93         }
94         return nodeMapBuilder.build();
95     }
96
97
98     @Override
99     public Object toSerializable() {
100         return DataChangeListenerMessages.DataChanged.newBuilder()
101             .addAllRemovedPaths(convertToRemovePaths(change.getRemovedPaths()))
102             .setCreatedData(convertToNodeMap(change.getCreatedData()))
103             .setOriginalData(convertToNodeMap(change.getOriginalData()))
104             .setUpdatedData(convertToNodeMap(change.getUpdatedData()))
105             .setOriginalSubTree(convertToNodeTree(change.getOriginalSubtree()))
106             .setUpdatedSubTree(convertToNodeTree(change.getUpdatedSubtree()))
107             .build();
108     }
109
110     public static DataChanged fromSerialize(SchemaContext sc, Object message,
111         YangInstanceIdentifier pathId) {
112         DataChangeListenerMessages.DataChanged dataChanged =
113             (DataChangeListenerMessages.DataChanged) message;
114         DataChangedEvent event = new DataChangedEvent(sc);
115         if (dataChanged.getCreatedData() != null && dataChanged.getCreatedData()
116             .isInitialized()) {
117             event.setCreatedData(dataChanged.getCreatedData());
118         }
119         if (dataChanged.getOriginalData() != null && dataChanged
120             .getOriginalData().isInitialized()) {
121             event.setOriginalData(dataChanged.getOriginalData());
122         }
123
124         if (dataChanged.getUpdatedData() != null && dataChanged.getUpdatedData()
125             .isInitialized()) {
126             event.setUpdateData(dataChanged.getUpdatedData());
127         }
128
129         if (dataChanged.getOriginalSubTree() != null && dataChanged
130             .getOriginalSubTree().isInitialized()) {
131             event.setOriginalSubtree(dataChanged.getOriginalSubTree(), pathId);
132         }
133
134         if (dataChanged.getUpdatedSubTree() != null && dataChanged
135             .getUpdatedSubTree().isInitialized()) {
136             event.setUpdatedSubtree(dataChanged.getOriginalSubTree(), pathId);
137         }
138
139         if (dataChanged.getRemovedPathsList() != null && !dataChanged
140             .getRemovedPathsList().isEmpty()) {
141             event.setRemovedPaths(dataChanged.getRemovedPathsList());
142         }
143
144         return new DataChanged(sc, event);
145
146     }
147
148     static class DataChangedEvent implements
149         AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> {
150         private Map<YangInstanceIdentifier, NormalizedNode<?, ?>> createdData;
151         private final NormalizedNodeToNodeCodec nodeCodec;
152         private Map<YangInstanceIdentifier, NormalizedNode<?, ?>> updatedData;
153         private Map<YangInstanceIdentifier, NormalizedNode<?, ?>> originalData;
154         private NormalizedNode<?, ?> originalSubTree;
155         private NormalizedNode<?, ?> updatedSubTree;
156         private Set<YangInstanceIdentifier> removedPathIds;
157
158         DataChangedEvent(SchemaContext schemaContext) {
159             nodeCodec = new NormalizedNodeToNodeCodec(schemaContext);
160         }
161
162         @Override
163         public Map<YangInstanceIdentifier, NormalizedNode<?, ?>> getCreatedData() {
164             if(createdData == null){
165                 return Collections.emptyMap();
166             }
167             return createdData;
168         }
169
170         DataChangedEvent setCreatedData(
171             NormalizedNodeMessages.NodeMap nodeMap) {
172             this.createdData = convertNodeMapToMap(nodeMap);
173             return this;
174         }
175
176         private Map<YangInstanceIdentifier, NormalizedNode<?, ?>> convertNodeMapToMap(
177             NormalizedNodeMessages.NodeMap nodeMap) {
178             Map<YangInstanceIdentifier, NormalizedNode<?, ?>> mapEntries =
179                 new HashMap<YangInstanceIdentifier, NormalizedNode<?, ?>>();
180             for (NormalizedNodeMessages.NodeMapEntry nodeMapEntry : nodeMap
181                 .getMapEntriesList()) {
182                 YangInstanceIdentifier id = InstanceIdentifierUtils
183                     .fromSerializable(nodeMapEntry.getInstanceIdentifierPath());
184                 mapEntries.put(id,
185                     nodeCodec.decode(nodeMapEntry.getNormalizedNode()));
186             }
187             return mapEntries;
188         }
189
190
191         @Override
192         public Map<YangInstanceIdentifier, NormalizedNode<?, ?>> getUpdatedData() {
193             if(updatedData == null){
194                 return Collections.emptyMap();
195             }
196             return updatedData;
197         }
198
199         DataChangedEvent setUpdateData(NormalizedNodeMessages.NodeMap nodeMap) {
200             this.updatedData = convertNodeMapToMap(nodeMap);
201             return this;
202         }
203
204         @Override
205         public Set<YangInstanceIdentifier> getRemovedPaths() {
206             if (removedPathIds == null) {
207                 return Collections.emptySet();
208             }
209             return removedPathIds;
210         }
211
212         public DataChangedEvent setRemovedPaths(List<NormalizedNodeMessages.InstanceIdentifier> removedPaths) {
213             Set<YangInstanceIdentifier> removedIds = new HashSet<>();
214             for (NormalizedNodeMessages.InstanceIdentifier path : removedPaths) {
215                 removedIds.add(InstanceIdentifierUtils.fromSerializable(path));
216             }
217             this.removedPathIds = removedIds;
218             return this;
219         }
220
221         @Override
222         public Map<YangInstanceIdentifier, NormalizedNode<?, ?>> getOriginalData() {
223             if (originalData == null) {
224                 Collections.emptyMap();
225             }
226             return originalData;
227         }
228
229         DataChangedEvent setOriginalData(
230             NormalizedNodeMessages.NodeMap nodeMap) {
231             this.originalData = convertNodeMapToMap(nodeMap);
232             return this;
233         }
234
235         @Override
236         public NormalizedNode<?, ?> getOriginalSubtree() {
237             return originalSubTree;
238         }
239
240         DataChangedEvent setOriginalSubtree(NormalizedNodeMessages.Node node,
241             YangInstanceIdentifier instanceIdentifierPath) {
242             originalSubTree = nodeCodec.decode(node);
243             return this;
244         }
245
246         @Override
247         public NormalizedNode<?, ?> getUpdatedSubtree() {
248             return updatedSubTree;
249         }
250
251         DataChangedEvent setUpdatedSubtree(NormalizedNodeMessages.Node node,
252             YangInstanceIdentifier instanceIdentifierPath) {
253             updatedSubTree = nodeCodec.decode(node);
254             return this;
255         }
256
257
258     }
259
260
261
262 }