2 * Copyright (c) 2014, 2015 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.util;
11 import org.opendaylight.controller.cluster.datastore.node.utils.NodeIdentifierFactory;
12 import org.opendaylight.controller.cluster.datastore.node.utils.QNameFactory;
13 import org.opendaylight.controller.cluster.datastore.node.utils.serialization.PathArgumentSerializer;
14 import org.opendaylight.controller.cluster.datastore.node.utils.serialization.QNameDeSerializationContext;
15 import org.opendaylight.controller.cluster.datastore.node.utils.serialization.QNameDeSerializationContextImpl;
16 import org.opendaylight.controller.cluster.datastore.node.utils.serialization.QNameSerializationContext;
17 import org.opendaylight.controller.cluster.datastore.node.utils.serialization.QNameSerializationContextImpl;
18 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
19 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder;
20 import org.opendaylight.yangtools.yang.common.QName;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28 import java.util.ArrayList;
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.List;
36 * This class contains utility methods for converting an MD-SAL
37 * YangInstanceIdentifier to and from other representations.
39 * The representations convered for now are,
43 * <li>Protocol Buffer</li>
46 public class InstanceIdentifierUtils {
48 protected static final Logger logger = LoggerFactory
49 .getLogger(InstanceIdentifierUtils.class);
52 * Convert an MD-SAL YangInstanceIdentifier into a protocol buffer version of it
54 * @param path an MD-SAL YangInstanceIdentifier
55 * @return a protocol buffer version of the MD-SAL YangInstanceIdentifier
57 public static NormalizedNodeMessages.InstanceIdentifier toSerializable(YangInstanceIdentifier path) {
58 QNameSerializationContextImpl context = new QNameSerializationContextImpl();
59 Builder builder = toSerializableBuilder(path, context);
60 return builder.addAllCode(context.getCodes()).build();
63 public static NormalizedNodeMessages.InstanceIdentifier toSerializable(
64 YangInstanceIdentifier path, QNameSerializationContext context) {
65 return toSerializableBuilder(path, context).build();
68 private static NormalizedNodeMessages.InstanceIdentifier.Builder toSerializableBuilder(
69 YangInstanceIdentifier path, QNameSerializationContext context) {
70 NormalizedNodeMessages.InstanceIdentifier.Builder builder =
71 NormalizedNodeMessages.InstanceIdentifier.newBuilder();
74 for (PathArgument pathArgument : path.getPathArguments()) {
75 NormalizedNodeMessages.PathArgument serializablePathArgument;
78 if (!(pathArgument instanceof AugmentationIdentifier)) {
79 nodeType = pathArgument.getNodeType().toString();
82 serializablePathArgument = NormalizedNodeMessages.PathArgument.newBuilder()
83 .setValue(pathArgument.toString())
84 .setType(pathArgument.getClass().getSimpleName())
85 .setNodeType(NormalizedNodeMessages.QName.newBuilder().setValue(nodeType))
86 .addAllAttributes(getPathArgumentAttributes(pathArgument)).build();
88 serializablePathArgument = PathArgumentSerializer.serialize(context, pathArgument);
91 builder.addArguments(serializablePathArgument);
94 logger.error("An exception occurred", e);
102 * Convert a protocol buffer version of the MD-SAL YangInstanceIdentifier into
103 * the MD-SAL version of the YangInstanceIdentifier
105 * @param path a protocol buffer version of the MD-SAL YangInstanceIdentifier
106 * @return an MD-SAL YangInstanceIdentifier
108 public static YangInstanceIdentifier fromSerializable(NormalizedNodeMessages.InstanceIdentifier path) {
109 return fromSerializable(path, new QNameDeSerializationContextImpl(path.getCodeList()));
112 public static YangInstanceIdentifier fromSerializable(NormalizedNodeMessages.InstanceIdentifier path,
113 QNameDeSerializationContext context) {
115 List<PathArgument> pathArguments = new ArrayList<>();
117 for(NormalizedNodeMessages.PathArgument pathArgument : path.getArgumentsList()) {
118 if(context == null || pathArgument.hasType()) {
119 pathArguments.add(parsePathArgument(pathArgument));
121 pathArguments.add(PathArgumentSerializer.deSerialize(context, pathArgument));
125 return YangInstanceIdentifier.create(pathArguments);
129 * Take the various attributes of a PathArgument and package them up as
130 * protocol buffer attributes.
133 * PathArguments have 4 subtypes and each of the various subtypes have
134 * different attributes
137 * NodeIdentifier is the most basic PathArgument. It is used for
138 * ContainerNode, LeafNode etc and has no attributes
141 * NodeWithValue has only a single attribute. It is used for
142 * LeafListEntryNodes and the attribute it contains is the value
146 * NodeIdentifierWithPredicates has a map of attributes.
147 * It is used to represent a ListItemNode. Each entry
148 * in the map of attributes represents the key and value of the
149 * keys in that entry.
152 * AugmentationIdentifier has a list of unnamed attributes. Each
153 * attribute represents the possible children that can go within
154 * an augmentation entry.
157 * @param pathArgument
160 private static Iterable<? extends NormalizedNodeMessages.Attribute> getPathArgumentAttributes(
161 PathArgument pathArgument) {
162 List<NormalizedNodeMessages.Attribute> attributes = new ArrayList<>();
164 if (pathArgument instanceof NodeWithValue) {
165 NodeWithValue<?> identifier = (NodeWithValue<?>) pathArgument;
167 NormalizedNodeMessages.Attribute attribute =
168 NormalizedNodeMessages.Attribute.newBuilder()
170 .setValue(identifier.getValue().toString())
171 .setType(identifier.getValue().getClass().getSimpleName())
174 attributes.add(attribute);
175 } else if (pathArgument instanceof NodeIdentifierWithPredicates) {
176 NodeIdentifierWithPredicates identifier = (NodeIdentifierWithPredicates) pathArgument;
178 for (QName key : identifier.getKeyValues().keySet()) {
179 Object value = identifier.getKeyValues().get(key);
180 NormalizedNodeMessages.Attribute attribute =
181 NormalizedNodeMessages.Attribute.newBuilder()
182 .setName(key.toString())
183 .setValue(value.toString())
184 .setType(value.getClass().getSimpleName())
187 attributes.add(attribute);
191 } else if(pathArgument instanceof AugmentationIdentifier) {
192 AugmentationIdentifier identifier = (AugmentationIdentifier) pathArgument;
194 for (QName key : identifier.getPossibleChildNames()) {
196 NormalizedNodeMessages.Attribute attribute =
197 NormalizedNodeMessages.Attribute.newBuilder()
198 .setName(key.toString())
199 .setValue(value.toString())
200 .setType(value.getClass().getSimpleName())
203 attributes.add(attribute);
213 * Parse a protocol buffer PathArgument and return an MD-SAL PathArgument
215 * @param pathArgument protocol buffer PathArgument
216 * @return MD-SAL PathArgument
218 private static PathArgument parsePathArgument(
219 NormalizedNodeMessages.PathArgument pathArgument) {
220 if (NodeWithValue.class.getSimpleName().equals(pathArgument.getType())) {
222 NodeWithValue<?> nodeWithValue = new NodeWithValue<>(
223 QNameFactory.create(pathArgument.getNodeType().getValue()),
224 parseAttribute(pathArgument.getAttributes(0)));
226 return nodeWithValue;
228 } else if(NodeIdentifierWithPredicates.class.getSimpleName().equals(pathArgument.getType())){
230 NodeIdentifierWithPredicates nodeIdentifierWithPredicates =
231 new NodeIdentifierWithPredicates(
232 QNameFactory.create(pathArgument.getNodeType().getValue()), toAttributesMap(pathArgument.getAttributesList()));
234 return nodeIdentifierWithPredicates;
236 } else if(AugmentationIdentifier.class.getSimpleName().equals(pathArgument.getType())){
238 Set<QName> qNameSet = new HashSet<>();
240 for(NormalizedNodeMessages.Attribute attribute : pathArgument.getAttributesList()){
241 qNameSet.add(QNameFactory.create(attribute.getValue()));
244 return new AugmentationIdentifier(qNameSet);
247 return NodeIdentifierFactory.getArgument(pathArgument.getValue());
250 private static Map<QName, Object> toAttributesMap(
251 List<NormalizedNodeMessages.Attribute> attributesList) {
253 Map<QName, Object> map = new HashMap<>();
255 for(NormalizedNodeMessages.Attribute attribute : attributesList){
256 String name = attribute.getName();
257 Object value = parseAttribute(attribute);
259 map.put(QNameFactory.create(name), value);
266 * FIXME: This method only covers a subset of values that may go in an InstanceIdentifier
271 private static Object parseAttribute(NormalizedNodeMessages.Attribute attribute){
272 if(Short.class.getSimpleName().equals(attribute.getType())) {
273 return Short.parseShort(attribute.getValue());
274 } else if(Long.class.getSimpleName().equals(attribute.getType())){
275 return Long.parseLong(attribute.getValue());
276 } else if(Boolean.class.getSimpleName().equals(attribute.getType())){
277 return Boolean.parseBoolean(attribute.getValue());
278 } else if(Integer.class.getSimpleName().equals(attribute.getType())){
279 return Integer.parseInt(attribute.getValue());
282 return attribute.getValue();