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;
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;
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;
26 import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.PathArgumentType.getSerializablePathArgumentType;
28 public class PathArgumentSerializer {
29 private static final Map<Class, PathArgumentAttributesGetter> pathArgumentAttributesGetters = new HashMap<>();
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");
35 QName nodeType = null;
36 if (!(pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier)) {
37 nodeType = pathArgument.getNodeType();
40 NormalizedNodeMessages.PathArgument.Builder builder =
41 NormalizedNodeMessages.PathArgument.newBuilder();
43 NormalizedNodeMessages.PathArgument serializablePathArgument =
45 .setIntType(getSerializablePathArgumentType(pathArgument))
46 .setNodeType(encodeQName(context, nodeType))
47 .addAllAttribute(getPathArgumentAttributes(context, pathArgument))
50 return serializablePathArgument;
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");
58 return parsePathArgument(context, pathArgument);
62 private static interface PathArgumentAttributesGetter {
63 Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(NormalizedNodeSerializationContext context,
64 YangInstanceIdentifier.PathArgument pathArgument);
68 pathArgumentAttributesGetters.put(YangInstanceIdentifier.NodeWithValue.class, new PathArgumentAttributesGetter() {
70 public Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
71 NormalizedNodeSerializationContext context,
72 YangInstanceIdentifier.PathArgument pathArgument) {
73 List<NormalizedNodeMessages.PathArgumentAttribute> attributes =
76 YangInstanceIdentifier.NodeWithValue identifier
77 = (YangInstanceIdentifier.NodeWithValue) pathArgument;
79 NormalizedNodeMessages.PathArgumentAttribute attribute =
80 buildAttribute(context, null, identifier.getValue());
82 attributes.add(attribute);
89 pathArgumentAttributesGetters.put(YangInstanceIdentifier.NodeIdentifierWithPredicates.class, new PathArgumentAttributesGetter() {
91 public Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
92 NormalizedNodeSerializationContext context,
93 YangInstanceIdentifier.PathArgument pathArgument) {
95 List<NormalizedNodeMessages.PathArgumentAttribute> attributes =
98 YangInstanceIdentifier.NodeIdentifierWithPredicates identifier
99 = (YangInstanceIdentifier.NodeIdentifierWithPredicates) pathArgument;
101 for (QName key : identifier.getKeyValues().keySet()) {
102 Object value = identifier.getKeyValues().get(key);
103 NormalizedNodeMessages.PathArgumentAttribute attribute =
104 buildAttribute(context, key, value);
106 attributes.add(attribute);
115 pathArgumentAttributesGetters.put(YangInstanceIdentifier.AugmentationIdentifier.class, new PathArgumentAttributesGetter() {
117 public Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
118 NormalizedNodeSerializationContext context,
119 YangInstanceIdentifier.PathArgument pathArgument) {
121 List<NormalizedNodeMessages.PathArgumentAttribute> attributes =
124 YangInstanceIdentifier.AugmentationIdentifier identifier
125 = (YangInstanceIdentifier.AugmentationIdentifier) pathArgument;
127 for (QName key : identifier.getPossibleChildNames()) {
129 NormalizedNodeMessages.PathArgumentAttribute attribute =
130 buildAttribute(context, key, value);
132 attributes.add(attribute);
142 pathArgumentAttributesGetters.put(YangInstanceIdentifier.NodeIdentifier.class, new PathArgumentAttributesGetter() {
144 public Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
145 NormalizedNodeSerializationContext context,
146 YangInstanceIdentifier.PathArgument pathArgument) {
147 return Collections.emptyList();
152 private static NormalizedNodeMessages.PathArgumentAttribute buildAttribute(NormalizedNodeSerializationContext context,QName name, Object value){
153 NormalizedNodeMessages.PathArgumentAttribute.Builder builder =
154 NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
156 builder.setName(encodeQName(context, name));
157 ValueSerializer.serialize(builder, context, value);
159 return builder.build();
163 private static NormalizedNodeMessages.QName.Builder encodeQName(NormalizedNodeSerializationContext context, QName qName){
165 return NormalizedNodeMessages.QName.getDefaultInstance().toBuilder();
167 NormalizedNodeMessages.QName.Builder qNameBuilder =
168 NormalizedNodeMessages.QName.newBuilder();
170 qNameBuilder.setNamespace(context.addNamespace(qName.getNamespace()));
172 qNameBuilder.setRevision(context.addRevision(qName.getRevision()));
174 qNameBuilder.setLocalName(context.addLocalName(qName.getLocalName()));
179 private static Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> getPathArgumentAttributes(
180 NormalizedNodeSerializationContext context,
181 YangInstanceIdentifier.PathArgument pathArgument) {
183 return pathArgumentAttributesGetters.get(pathArgument.getClass()).get(context, pathArgument);
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");
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(
208 sb.append("(").append(namespace).append(")").append(
212 return sb.toString();
217 * Parse a protocol buffer PathArgument and return an MD-SAL PathArgument
219 * @param pathArgument protocol buffer PathArgument
220 * @return MD-SAL PathArgument
222 private static YangInstanceIdentifier.PathArgument parsePathArgument(
223 NormalizedNodeDeSerializationContext context,
224 NormalizedNodeMessages.PathArgument pathArgument) {
226 Preconditions.checkArgument(pathArgument.getIntType() >= 0
227 && pathArgument.getIntType() < PathArgumentType.values().length,
228 "Illegal PathArgumentType " + pathArgument.getIntType());
230 switch(PathArgumentType.values()[pathArgument.getIntType()]){
231 case NODE_IDENTIFIER_WITH_VALUE : {
233 YangInstanceIdentifier.NodeWithValue nodeWithValue =
234 new YangInstanceIdentifier.NodeWithValue(
235 QNameFactory.create(qNameToString(context, pathArgument.getNodeType())),
236 parseAttribute(context, pathArgument.getAttribute(0)));
238 return nodeWithValue;
241 case NODE_IDENTIFIER_WITH_PREDICATES : {
243 YangInstanceIdentifier.NodeIdentifierWithPredicates
244 nodeIdentifierWithPredicates =
245 new YangInstanceIdentifier.NodeIdentifierWithPredicates(
246 QNameFactory.create(qNameToString(context, pathArgument.getNodeType())),
247 toAttributesMap(context, pathArgument.getAttributeList()));
249 return nodeIdentifierWithPredicates;
252 case AUGMENTATION_IDENTIFIER: {
254 Set<QName> qNameSet = new HashSet<>();
256 for(NormalizedNodeMessages.PathArgumentAttribute attribute : pathArgument.getAttributeList()){
257 qNameSet.add(QNameFactory.create(qNameToString(context, attribute.getName())));
260 return new YangInstanceIdentifier.AugmentationIdentifier(qNameSet);
264 return NodeIdentifierFactory.getArgument(qNameToString(context,
265 pathArgument.getNodeType()));
271 private static Map<QName, Object> toAttributesMap(
272 NormalizedNodeDeSerializationContext context,
273 List<NormalizedNodeMessages.PathArgumentAttribute> attributesList) {
275 Map<QName, Object> map = new HashMap<>();
277 for(NormalizedNodeMessages.PathArgumentAttribute attribute : attributesList){
278 NormalizedNodeMessages.QName name = attribute.getName();
279 Object value = parseAttribute(context, attribute);
281 map.put(QNameFactory.create(qNameToString(context, name)), value);
287 private static Object parseAttribute(NormalizedNodeDeSerializationContext context, NormalizedNodeMessages.PathArgumentAttribute attribute){
288 return ValueSerializer.deSerialize(context, attribute);