2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.cluster.datastore.node.utils.serialization;
11 import com.google.common.base.Preconditions;
13 import org.opendaylight.controller.cluster.datastore.node.utils.NodeIdentifierFactory;
14 import org.opendaylight.controller.cluster.datastore.node.utils.QNameFactory;
15 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.List;
27 import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.PathArgumentType.getSerializablePathArgumentType;
29 public class PathArgumentSerializer {
30 private static final String REVISION_ARG = "?revision=";
31 private static final Map<Class, PathArgumentAttributesGetter> pathArgumentAttributesGetters = new HashMap<>();
33 public static NormalizedNodeMessages.PathArgument serialize(NormalizedNodeSerializationContext context, YangInstanceIdentifier.PathArgument pathArgument){
34 Preconditions.checkNotNull(context, "context should not be null");
35 Preconditions.checkNotNull(pathArgument, "pathArgument should not be null");
37 QName nodeType = null;
38 if (!(pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier)) {
39 nodeType = pathArgument.getNodeType();
42 NormalizedNodeMessages.PathArgument.Builder builder =
43 NormalizedNodeMessages.PathArgument.newBuilder();
45 NormalizedNodeMessages.PathArgument serializablePathArgument =
47 .setIntType(getSerializablePathArgumentType(pathArgument))
48 .setNodeType(encodeQName(context, nodeType))
49 .addAllAttribute(getPathArgumentAttributes(context, pathArgument))
52 return serializablePathArgument;
56 public static YangInstanceIdentifier.PathArgument deSerialize(NormalizedNodeDeSerializationContext context, NormalizedNodeMessages.PathArgument pathArgument){
57 Preconditions.checkNotNull(context, "context should not be null");
58 Preconditions.checkNotNull(pathArgument, "pathArgument should not be null");
60 return parsePathArgument(context, pathArgument);
64 private static interface PathArgumentAttributesGetter {
65 Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(NormalizedNodeSerializationContext context,
66 YangInstanceIdentifier.PathArgument pathArgument);
70 pathArgumentAttributesGetters.put(YangInstanceIdentifier.NodeWithValue.class, new PathArgumentAttributesGetter() {
72 public Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
73 NormalizedNodeSerializationContext context,
74 YangInstanceIdentifier.PathArgument pathArgument) {
75 List<NormalizedNodeMessages.PathArgumentAttribute> attributes =
78 YangInstanceIdentifier.NodeWithValue identifier
79 = (YangInstanceIdentifier.NodeWithValue) pathArgument;
81 NormalizedNodeMessages.PathArgumentAttribute attribute =
82 buildAttribute(context, null, identifier.getValue());
84 attributes.add(attribute);
91 pathArgumentAttributesGetters.put(YangInstanceIdentifier.NodeIdentifierWithPredicates.class, new PathArgumentAttributesGetter() {
93 public Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
94 NormalizedNodeSerializationContext context,
95 YangInstanceIdentifier.PathArgument pathArgument) {
97 List<NormalizedNodeMessages.PathArgumentAttribute> attributes =
100 YangInstanceIdentifier.NodeIdentifierWithPredicates identifier
101 = (YangInstanceIdentifier.NodeIdentifierWithPredicates) pathArgument;
103 for (QName key : identifier.getKeyValues().keySet()) {
104 Object value = identifier.getKeyValues().get(key);
105 NormalizedNodeMessages.PathArgumentAttribute attribute =
106 buildAttribute(context, key, value);
108 attributes.add(attribute);
117 pathArgumentAttributesGetters.put(YangInstanceIdentifier.AugmentationIdentifier.class, new PathArgumentAttributesGetter() {
119 public Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
120 NormalizedNodeSerializationContext context,
121 YangInstanceIdentifier.PathArgument pathArgument) {
123 List<NormalizedNodeMessages.PathArgumentAttribute> attributes =
126 YangInstanceIdentifier.AugmentationIdentifier identifier
127 = (YangInstanceIdentifier.AugmentationIdentifier) pathArgument;
129 for (QName key : identifier.getPossibleChildNames()) {
131 NormalizedNodeMessages.PathArgumentAttribute attribute =
132 buildAttribute(context, key, value);
134 attributes.add(attribute);
144 pathArgumentAttributesGetters.put(YangInstanceIdentifier.NodeIdentifier.class, new PathArgumentAttributesGetter() {
146 public Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
147 NormalizedNodeSerializationContext context,
148 YangInstanceIdentifier.PathArgument pathArgument) {
149 return Collections.emptyList();
154 private static NormalizedNodeMessages.PathArgumentAttribute buildAttribute(NormalizedNodeSerializationContext context,QName name, Object value){
155 NormalizedNodeMessages.PathArgumentAttribute.Builder builder =
156 NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
158 builder.setName(encodeQName(context, name));
159 ValueSerializer.serialize(builder, context, value);
161 return builder.build();
165 private static NormalizedNodeMessages.QName.Builder encodeQName(NormalizedNodeSerializationContext context, QName qName){
167 return NormalizedNodeMessages.QName.getDefaultInstance().toBuilder();
169 NormalizedNodeMessages.QName.Builder qNameBuilder =
170 NormalizedNodeMessages.QName.newBuilder();
172 qNameBuilder.setNamespace(context.addNamespace(qName.getNamespace()));
174 qNameBuilder.setRevision(context.addRevision(qName.getRevision()));
176 qNameBuilder.setLocalName(context.addLocalName(qName.getLocalName()));
181 private static Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> getPathArgumentAttributes(
182 NormalizedNodeSerializationContext context,
183 YangInstanceIdentifier.PathArgument pathArgument) {
185 return pathArgumentAttributesGetters.get(pathArgument.getClass()).get(context, pathArgument);
190 private static String qNameToString(NormalizedNodeDeSerializationContext context,
191 NormalizedNodeMessages.QName qName){
192 // If this serializer is used qName cannot be null (see encodeQName)
193 // adding null check only in case someone tried to deSerialize a protocol buffer node
194 // that was not serialized using the PathArgumentSerializer
195 // Preconditions.checkNotNull(qName, "qName should not be null");
196 // Preconditions.checkArgument(qName.getNamespace() != -1, "qName.namespace should be valid");
198 String namespace = context.getNamespace(qName.getNamespace());
199 String localName = context.getLocalName(qName.getLocalName());
201 if(qName.getRevision() != -1){
202 String revision = context.getRevision(qName.getRevision());
203 sb = new StringBuilder(namespace.length() + REVISION_ARG.length() + revision.length() +
204 localName.length() + 2);
205 sb.append('(').append(namespace).append(REVISION_ARG).append(
206 revision).append(')').append(localName);
208 sb = new StringBuilder(namespace.length() + localName.length() + 2);
209 sb.append('(').append(namespace).append(')').append(localName);
212 return sb.toString();
216 * Parse a protocol buffer PathArgument and return an MD-SAL PathArgument
218 * @param pathArgument protocol buffer PathArgument
219 * @return MD-SAL PathArgument
221 private static YangInstanceIdentifier.PathArgument parsePathArgument(
222 NormalizedNodeDeSerializationContext context,
223 NormalizedNodeMessages.PathArgument pathArgument) {
225 switch(PathArgumentType.values()[pathArgument.getIntType()]){
226 case NODE_IDENTIFIER_WITH_VALUE : {
228 YangInstanceIdentifier.NodeWithValue nodeWithValue =
229 new YangInstanceIdentifier.NodeWithValue(
230 QNameFactory.create(qNameToString(context, pathArgument.getNodeType())),
231 parseAttribute(context, pathArgument.getAttribute(0)));
233 return nodeWithValue;
236 case NODE_IDENTIFIER_WITH_PREDICATES : {
238 YangInstanceIdentifier.NodeIdentifierWithPredicates
239 nodeIdentifierWithPredicates =
240 new YangInstanceIdentifier.NodeIdentifierWithPredicates(
241 QNameFactory.create(qNameToString(context, pathArgument.getNodeType())),
242 toAttributesMap(context, pathArgument.getAttributeList()));
244 return nodeIdentifierWithPredicates;
247 case AUGMENTATION_IDENTIFIER: {
249 Set<QName> qNameSet = new HashSet<>();
251 for(NormalizedNodeMessages.PathArgumentAttribute attribute : pathArgument.getAttributeList()){
252 qNameSet.add(QNameFactory.create(qNameToString(context, attribute.getName())));
255 return new YangInstanceIdentifier.AugmentationIdentifier(qNameSet);
259 return NodeIdentifierFactory.getArgument(qNameToString(context,
260 pathArgument.getNodeType()));
266 private static Map<QName, Object> toAttributesMap(
267 NormalizedNodeDeSerializationContext context,
268 List<NormalizedNodeMessages.PathArgumentAttribute> attributesList) {
270 Map<QName, Object> map;
271 if(attributesList.size() == 1) {
272 NormalizedNodeMessages.PathArgumentAttribute attribute = attributesList.get(0);
273 NormalizedNodeMessages.QName name = attribute.getName();
274 Object value = parseAttribute(context, attribute);
275 map = Collections.singletonMap(QNameFactory.create(qNameToString(context, name)), value);
277 map = new HashMap<>();
279 for(NormalizedNodeMessages.PathArgumentAttribute attribute : attributesList){
280 NormalizedNodeMessages.QName name = attribute.getName();
281 Object value = parseAttribute(context, attribute);
283 map.put(QNameFactory.create(qNameToString(context, name)), value);
290 private static Object parseAttribute(NormalizedNodeDeSerializationContext context, NormalizedNodeMessages.PathArgumentAttribute attribute){
291 return ValueSerializer.deSerialize(context, attribute);