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 static org.opendaylight.controller.cluster.datastore.node.utils.serialization.PathArgumentType.getSerializablePathArgumentType;
13 import com.google.common.base.Preconditions;
14 import java.util.ArrayList;
15 import java.util.Arrays;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.HashSet;
19 import java.util.List;
21 import java.util.Map.Entry;
23 import org.opendaylight.controller.cluster.datastore.node.utils.NodeIdentifierFactory;
24 import org.opendaylight.controller.cluster.datastore.node.utils.QNameFactory;
25 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
26 import org.opendaylight.yangtools.yang.common.QName;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
29 public class PathArgumentSerializer {
30 private static final String REVISION_ARG = "?revision=";
31 private static final Map<Class<?>, PathArgumentAttributesGetter> PATH_ARGUMENT_ATTRIBUTES_GETTERS = new HashMap<>();
33 public static NormalizedNodeMessages.PathArgument serialize(QNameSerializationContext context,
34 YangInstanceIdentifier.PathArgument pathArgument) {
35 Preconditions.checkNotNull(context, "context should not be null");
36 Preconditions.checkNotNull(pathArgument, "pathArgument should not be null");
38 QName nodeType = null;
39 if (!(pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier)) {
40 nodeType = pathArgument.getNodeType();
43 NormalizedNodeMessages.PathArgument.Builder builder =
44 NormalizedNodeMessages.PathArgument.newBuilder();
46 NormalizedNodeMessages.PathArgument serializablePathArgument =
48 .setIntType(getSerializablePathArgumentType(pathArgument))
49 .setNodeType(encodeQName(context, nodeType))
50 .addAllAttribute(getPathArgumentAttributes(context, pathArgument))
53 return serializablePathArgument;
57 public static YangInstanceIdentifier.PathArgument deSerialize(QNameDeSerializationContext context,
58 NormalizedNodeMessages.PathArgument pathArgument) {
59 Preconditions.checkNotNull(context, "context should not be null");
60 Preconditions.checkNotNull(pathArgument, "pathArgument should not be null");
62 return parsePathArgument(context, pathArgument);
66 private interface PathArgumentAttributesGetter {
67 Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
68 QNameSerializationContext context, YangInstanceIdentifier.PathArgument pathArgument);
72 PATH_ARGUMENT_ATTRIBUTES_GETTERS.put(YangInstanceIdentifier.NodeWithValue.class, (context, pathArgument) -> {
73 YangInstanceIdentifier.NodeWithValue<?> identifier = (YangInstanceIdentifier.NodeWithValue<?>) pathArgument;
75 NormalizedNodeMessages.PathArgumentAttribute attribute = buildAttribute(context, null,
76 identifier.getValue());
78 return Arrays.asList(attribute);
81 PATH_ARGUMENT_ATTRIBUTES_GETTERS.put(YangInstanceIdentifier.NodeIdentifierWithPredicates.class,
82 (context, pathArgument) -> {
83 YangInstanceIdentifier.NodeIdentifierWithPredicates identifier =
84 (YangInstanceIdentifier.NodeIdentifierWithPredicates) pathArgument;
86 Map<QName, Object> keyValues = identifier.getKeyValues();
87 List<NormalizedNodeMessages.PathArgumentAttribute> attributes = new ArrayList<>(keyValues.size());
88 for (Entry<QName, Object> e : keyValues.entrySet()) {
89 NormalizedNodeMessages.PathArgumentAttribute attribute = buildAttribute(context, e.getKey(),
92 attributes.add(attribute);
98 PATH_ARGUMENT_ATTRIBUTES_GETTERS.put(YangInstanceIdentifier.AugmentationIdentifier.class,
99 (context, pathArgument) -> {
100 YangInstanceIdentifier.AugmentationIdentifier identifier =
101 (YangInstanceIdentifier.AugmentationIdentifier) pathArgument;
103 Set<QName> possibleChildNames = identifier.getPossibleChildNames();
104 List<NormalizedNodeMessages.PathArgumentAttribute> attributes = new ArrayList<>(
105 possibleChildNames.size());
106 for (QName key : possibleChildNames) {
108 NormalizedNodeMessages.PathArgumentAttribute attribute = buildAttribute(context, key, value);
110 attributes.add(attribute);
116 PATH_ARGUMENT_ATTRIBUTES_GETTERS.put(YangInstanceIdentifier.NodeIdentifier.class,
117 (context, pathArgument) -> Collections.emptyList());
120 private static NormalizedNodeMessages.PathArgumentAttribute buildAttribute(
121 QNameSerializationContext context, QName name, Object value) {
122 NormalizedNodeMessages.PathArgumentAttribute.Builder builder =
123 NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
125 builder.setName(encodeQName(context, name));
126 ValueSerializer.serialize(builder, context, value);
128 return builder.build();
132 private static NormalizedNodeMessages.QName.Builder encodeQName(QNameSerializationContext context, QName qname) {
134 return NormalizedNodeMessages.QName.getDefaultInstance().toBuilder();
136 NormalizedNodeMessages.QName.Builder qnameBuilder = NormalizedNodeMessages.QName.newBuilder();
138 qnameBuilder.setNamespace(context.addNamespace(qname.getNamespace()));
140 qnameBuilder.setRevision(context.addRevision(qname.getRevision()));
142 qnameBuilder.setLocalName(context.addLocalName(qname.getLocalName()));
147 private static Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> getPathArgumentAttributes(
148 QNameSerializationContext context, YangInstanceIdentifier.PathArgument pathArgument) {
150 return PATH_ARGUMENT_ATTRIBUTES_GETTERS.get(pathArgument.getClass()).get(context, pathArgument);
154 private static String qNameToString(QNameDeSerializationContext context, NormalizedNodeMessages.QName qname) {
155 // If this serializer is used qName cannot be null (see encodeQName)
156 // adding null check only in case someone tried to deSerialize a protocol buffer node
157 // that was not serialized using the PathArgumentSerializer
158 // Preconditions.checkNotNull(qName, "qName should not be null");
159 // Preconditions.checkArgument(qName.getNamespace() != -1, "qName.namespace should be valid");
161 String namespace = context.getNamespace(qname.getNamespace());
162 String localName = context.getLocalName(qname.getLocalName());
164 if (qname.getRevision() != -1) {
165 String revision = context.getRevision(qname.getRevision());
166 sb = new StringBuilder(namespace.length() + REVISION_ARG.length() + revision.length()
167 + localName.length() + 2);
168 sb.append('(').append(namespace).append(REVISION_ARG).append(
169 revision).append(')').append(localName);
171 sb = new StringBuilder(namespace.length() + localName.length() + 2);
172 sb.append('(').append(namespace).append(')').append(localName);
175 return sb.toString();
179 * Parse a protocol buffer PathArgument and return an MD-SAL PathArgument.
181 * @param pathArgument protocol buffer PathArgument
182 * @return MD-SAL PathArgument
184 private static YangInstanceIdentifier.PathArgument parsePathArgument(
185 QNameDeSerializationContext context, NormalizedNodeMessages.PathArgument pathArgument) {
187 switch (PathArgumentType.values()[pathArgument.getIntType()]) {
188 case NODE_IDENTIFIER_WITH_VALUE : {
189 YangInstanceIdentifier.NodeWithValue<?> nodeWithValue =
190 new YangInstanceIdentifier.NodeWithValue<>(
191 QNameFactory.create(qNameToString(context, pathArgument.getNodeType())),
192 parseAttribute(context, pathArgument.getAttribute(0)));
194 return nodeWithValue;
197 case NODE_IDENTIFIER_WITH_PREDICATES : {
198 YangInstanceIdentifier.NodeIdentifierWithPredicates
199 nodeIdentifierWithPredicates =
200 new YangInstanceIdentifier.NodeIdentifierWithPredicates(
201 QNameFactory.create(qNameToString(context, pathArgument.getNodeType())),
202 toAttributesMap(context, pathArgument.getAttributeList()));
204 return nodeIdentifierWithPredicates;
207 case AUGMENTATION_IDENTIFIER: {
208 Set<QName> qnameSet = new HashSet<>();
210 for (NormalizedNodeMessages.PathArgumentAttribute attribute : pathArgument.getAttributeList()) {
211 qnameSet.add(QNameFactory.create(qNameToString(context, attribute.getName())));
214 return new YangInstanceIdentifier.AugmentationIdentifier(qnameSet);
218 return NodeIdentifierFactory.getArgument(qNameToString(context,
219 pathArgument.getNodeType()));
225 private static Map<QName, Object> toAttributesMap(
226 QNameDeSerializationContext context,
227 List<NormalizedNodeMessages.PathArgumentAttribute> attributesList) {
229 Map<QName, Object> map;
230 if (attributesList.size() == 1) {
231 NormalizedNodeMessages.PathArgumentAttribute attribute = attributesList.get(0);
232 NormalizedNodeMessages.QName name = attribute.getName();
233 Object value = parseAttribute(context, attribute);
234 map = Collections.singletonMap(QNameFactory.create(qNameToString(context, name)), value);
236 map = new HashMap<>();
238 for (NormalizedNodeMessages.PathArgumentAttribute attribute : attributesList) {
239 NormalizedNodeMessages.QName name = attribute.getName();
240 Object value = parseAttribute(context, attribute);
242 map.put(QNameFactory.create(qNameToString(context, name)), value);
249 private static Object parseAttribute(QNameDeSerializationContext context,
250 NormalizedNodeMessages.PathArgumentAttribute attribute) {
251 return ValueSerializer.deSerialize(context, attribute);