Bug 1025: Fixed incorrect revision in sal-remote-augment, which caused log polution.
[controller.git] / opendaylight / md-sal / sal-clustering-commons / src / main / java / org / opendaylight / controller / cluster / datastore / node / utils / serialization / PathArgumentSerializer.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.node.utils.serialization;
10
11 import com.google.common.base.Preconditions;
12 import org.opendaylight.controller.cluster.datastore.node.utils.NodeIdentifierFactory;
13 import org.opendaylight.controller.cluster.datastore.node.utils.QNameFactory;
14 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
15 import org.opendaylight.yangtools.yang.common.QName;
16 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
17
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Set;
25
26 import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.PathArgumentType.getSerializablePathArgumentType;
27
28 public class PathArgumentSerializer {
29     private static final Map<Class, PathArgumentAttributesGetter> pathArgumentAttributesGetters = new HashMap<>();
30
31     public static NormalizedNodeMessages.PathArgument serialize(NormalizedNodeSerializationContext context, YangInstanceIdentifier.PathArgument pathArgument){
32         Preconditions.checkNotNull(context, "context should not be null");
33         Preconditions.checkNotNull(pathArgument, "pathArgument should not be null");
34
35         QName nodeType = null;
36         if (!(pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier)) {
37             nodeType = pathArgument.getNodeType();
38         }
39
40         NormalizedNodeMessages.PathArgument.Builder builder =
41             NormalizedNodeMessages.PathArgument.newBuilder();
42
43         NormalizedNodeMessages.PathArgument serializablePathArgument =
44             builder
45                 .setIntType(getSerializablePathArgumentType(pathArgument))
46                 .setNodeType(encodeQName(context, nodeType))
47                 .addAllAttribute(getPathArgumentAttributes(context, pathArgument))
48                 .build();
49
50         return serializablePathArgument;
51     }
52
53
54     public static YangInstanceIdentifier.PathArgument deSerialize(NormalizedNodeDeSerializationContext context, NormalizedNodeMessages.PathArgument pathArgument){
55         Preconditions.checkNotNull(context, "context should not be null");
56         Preconditions.checkNotNull(pathArgument, "pathArgument should not be null");
57
58         return parsePathArgument(context, pathArgument);
59     }
60
61
62     private static interface PathArgumentAttributesGetter {
63         Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(NormalizedNodeSerializationContext context,
64             YangInstanceIdentifier.PathArgument pathArgument);
65     }
66
67     static {
68         pathArgumentAttributesGetters.put(YangInstanceIdentifier.NodeWithValue.class, new PathArgumentAttributesGetter() {
69             @Override
70             public Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
71                 NormalizedNodeSerializationContext context,
72                 YangInstanceIdentifier.PathArgument pathArgument) {
73                 List<NormalizedNodeMessages.PathArgumentAttribute> attributes =
74                     new ArrayList<>();
75
76                 YangInstanceIdentifier.NodeWithValue identifier
77                     = (YangInstanceIdentifier.NodeWithValue) pathArgument;
78
79                 NormalizedNodeMessages.PathArgumentAttribute attribute =
80                     buildAttribute(context, null, identifier.getValue());
81
82                 attributes.add(attribute);
83
84                 return attributes;
85
86             }
87         });
88
89         pathArgumentAttributesGetters.put(YangInstanceIdentifier.NodeIdentifierWithPredicates.class, new PathArgumentAttributesGetter() {
90             @Override
91             public Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
92                 NormalizedNodeSerializationContext context,
93                 YangInstanceIdentifier.PathArgument pathArgument) {
94
95                 List<NormalizedNodeMessages.PathArgumentAttribute> attributes =
96                     new ArrayList<>();
97
98                 YangInstanceIdentifier.NodeIdentifierWithPredicates identifier
99                     = (YangInstanceIdentifier.NodeIdentifierWithPredicates) pathArgument;
100
101                 for (QName key : identifier.getKeyValues().keySet()) {
102                     Object value = identifier.getKeyValues().get(key);
103                     NormalizedNodeMessages.PathArgumentAttribute attribute =
104                         buildAttribute(context, key, value);
105
106                     attributes.add(attribute);
107
108                 }
109
110                 return attributes;
111
112             }
113         });
114
115         pathArgumentAttributesGetters.put(YangInstanceIdentifier.AugmentationIdentifier.class, new PathArgumentAttributesGetter() {
116             @Override
117             public Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
118                 NormalizedNodeSerializationContext context,
119                 YangInstanceIdentifier.PathArgument pathArgument) {
120
121                 List<NormalizedNodeMessages.PathArgumentAttribute> attributes =
122                     new ArrayList<>();
123
124                 YangInstanceIdentifier.AugmentationIdentifier identifier
125                     = (YangInstanceIdentifier.AugmentationIdentifier) pathArgument;
126
127                 for (QName key : identifier.getPossibleChildNames()) {
128                     Object value = key;
129                     NormalizedNodeMessages.PathArgumentAttribute attribute =
130                         buildAttribute(context, key, value);
131
132                     attributes.add(attribute);
133
134                 }
135
136                 return attributes;
137
138             }
139         });
140
141
142         pathArgumentAttributesGetters.put(YangInstanceIdentifier.NodeIdentifier.class, new PathArgumentAttributesGetter() {
143             @Override
144             public Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
145                 NormalizedNodeSerializationContext context,
146                 YangInstanceIdentifier.PathArgument pathArgument) {
147                 return Collections.emptyList();
148             }
149         });
150     }
151
152     private static NormalizedNodeMessages.PathArgumentAttribute buildAttribute(NormalizedNodeSerializationContext context,QName name, Object value){
153         NormalizedNodeMessages.PathArgumentAttribute.Builder builder =
154             NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
155
156         builder.setName(encodeQName(context, name));
157         ValueSerializer.serialize(builder, context, value);
158
159         return builder.build();
160
161     }
162
163     private static NormalizedNodeMessages.QName.Builder encodeQName(NormalizedNodeSerializationContext context, QName qName){
164         if(qName == null){
165             return NormalizedNodeMessages.QName.getDefaultInstance().toBuilder();
166         }
167         NormalizedNodeMessages.QName.Builder qNameBuilder =
168             NormalizedNodeMessages.QName.newBuilder();
169
170         qNameBuilder.setNamespace(context.addNamespace(qName.getNamespace()));
171
172         qNameBuilder.setRevision(context.addRevision(qName.getRevision()));
173
174         qNameBuilder.setLocalName(context.addLocalName(qName.getLocalName()));
175
176         return qNameBuilder;
177     }
178
179     private static Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> getPathArgumentAttributes(
180             NormalizedNodeSerializationContext context,
181             YangInstanceIdentifier.PathArgument pathArgument) {
182
183         return pathArgumentAttributesGetters.get(pathArgument.getClass()).get(context, pathArgument);
184
185     }
186
187
188     private static String qNameToString(NormalizedNodeDeSerializationContext context,
189         NormalizedNodeMessages.QName qName){
190         // If this serializer is used qName cannot be null (see encodeQName)
191         // adding null check only in case someone tried to deSerialize a protocol buffer node
192         // that was not serialized using the PathArgumentSerializer
193         Preconditions.checkNotNull(qName, "qName should not be null");
194         Preconditions.checkArgument(!"".equals(qName.getLocalName()),
195             "qName.localName cannot be empty qName = " + qName.toString());
196         Preconditions.checkArgument(qName.getNamespace() != -1, "qName.namespace should be valid");
197
198         StringBuilder sb = new StringBuilder();
199         String namespace = context.getNamespace(qName.getNamespace());
200         String revision = "";
201         String localName = context.getLocalName(qName.getLocalName());
202         if(qName.getRevision() != -1){
203             revision = context.getRevision(qName.getRevision());
204             sb.append("(").append(namespace).append("?revision=").append(
205                 revision).append(")").append(
206                 localName);
207         } else {
208             sb.append("(").append(namespace).append(")").append(
209                 localName);
210         }
211
212         return sb.toString();
213
214     }
215
216     /**
217      * Parse a protocol buffer PathArgument and return an MD-SAL PathArgument
218      *
219      * @param pathArgument protocol buffer PathArgument
220      * @return MD-SAL PathArgument
221      */
222     private static YangInstanceIdentifier.PathArgument parsePathArgument(
223         NormalizedNodeDeSerializationContext context,
224         NormalizedNodeMessages.PathArgument pathArgument) {
225
226         Preconditions.checkArgument(pathArgument.getIntType() >= 0
227             && pathArgument.getIntType() < PathArgumentType.values().length,
228             "Illegal PathArgumentType " + pathArgument.getIntType());
229
230         switch(PathArgumentType.values()[pathArgument.getIntType()]){
231             case NODE_IDENTIFIER_WITH_VALUE : {
232
233                 YangInstanceIdentifier.NodeWithValue nodeWithValue =
234                     new YangInstanceIdentifier.NodeWithValue(
235                         QNameFactory.create(qNameToString(context, pathArgument.getNodeType())),
236                         parseAttribute(context, pathArgument.getAttribute(0)));
237
238                 return nodeWithValue;
239             }
240
241             case NODE_IDENTIFIER_WITH_PREDICATES : {
242
243                 YangInstanceIdentifier.NodeIdentifierWithPredicates
244                     nodeIdentifierWithPredicates =
245                     new YangInstanceIdentifier.NodeIdentifierWithPredicates(
246                         QNameFactory.create(qNameToString(context, pathArgument.getNodeType())),
247                         toAttributesMap(context, pathArgument.getAttributeList()));
248
249                 return nodeIdentifierWithPredicates;
250             }
251
252             case AUGMENTATION_IDENTIFIER: {
253
254                 Set<QName> qNameSet = new HashSet<>();
255
256                 for(NormalizedNodeMessages.PathArgumentAttribute attribute : pathArgument.getAttributeList()){
257                     qNameSet.add(QNameFactory.create(qNameToString(context, attribute.getName())));
258                 }
259
260                 return new YangInstanceIdentifier.AugmentationIdentifier(qNameSet);
261
262             }
263             default: {
264                 return NodeIdentifierFactory.getArgument(qNameToString(context,
265                     pathArgument.getNodeType()));
266             }
267
268         }
269     }
270
271     private static Map<QName, Object> toAttributesMap(
272         NormalizedNodeDeSerializationContext context,
273         List<NormalizedNodeMessages.PathArgumentAttribute> attributesList) {
274
275         Map<QName, Object> map = new HashMap<>();
276
277         for(NormalizedNodeMessages.PathArgumentAttribute attribute : attributesList){
278             NormalizedNodeMessages.QName name = attribute.getName();
279             Object value = parseAttribute(context, attribute);
280
281             map.put(QNameFactory.create(qNameToString(context, name)), value);
282         }
283
284         return map;
285     }
286
287     private static Object parseAttribute(NormalizedNodeDeSerializationContext context, NormalizedNodeMessages.PathArgumentAttribute attribute){
288         return ValueSerializer.deSerialize(context, attribute);
289     }
290
291 }