3 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7 * and is available at http://www.eclipse.org/legal/epl-v10.html
11 package org.opendaylight.controller.cluster.datastore.util;
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.cluster.datastore.node.utils.serialization.PathArgumentSerializer;
16 import org.opendaylight.controller.cluster.datastore.node.utils.serialization.QNameDeSerializationContext;
17 import org.opendaylight.controller.cluster.datastore.node.utils.serialization.QNameDeSerializationContextImpl;
18 import org.opendaylight.controller.cluster.datastore.node.utils.serialization.QNameSerializationContext;
19 import org.opendaylight.controller.cluster.datastore.node.utils.serialization.QNameSerializationContextImpl;
20 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
21 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder;
22 import org.opendaylight.yangtools.yang.common.QName;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.List;
34 * This class contains utility methods for converting an MD-SAL
35 * YangInstanceIdentifier to and from other representations.
37 * The representations convered for now are,
41 * <li>Protocol Buffer</li>
44 public class InstanceIdentifierUtils {
46 protected static final Logger logger = LoggerFactory
47 .getLogger(InstanceIdentifierUtils.class);
50 * Convert an MD-SAL YangInstanceIdentifier into a protocol buffer version of it
52 * @param path an MD-SAL YangInstanceIdentifier
53 * @return a protocol buffer version of the MD-SAL YangInstanceIdentifier
55 public static NormalizedNodeMessages.InstanceIdentifier toSerializable(YangInstanceIdentifier path) {
56 QNameSerializationContextImpl context = new QNameSerializationContextImpl();
57 Builder builder = toSerializableBuilder(path, context);
58 return builder.addAllCode(context.getCodes()).build();
61 public static NormalizedNodeMessages.InstanceIdentifier toSerializable(
62 YangInstanceIdentifier path, QNameSerializationContext context) {
63 return toSerializableBuilder(path, context).build();
66 private static NormalizedNodeMessages.InstanceIdentifier.Builder toSerializableBuilder(
67 YangInstanceIdentifier path, QNameSerializationContext context) {
68 NormalizedNodeMessages.InstanceIdentifier.Builder builder =
69 NormalizedNodeMessages.InstanceIdentifier.newBuilder();
72 for (org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.
73 PathArgument pathArgument : path.getPathArguments()) {
74 NormalizedNodeMessages.PathArgument serializablePathArgument;
77 if(!(pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier)){
78 nodeType = pathArgument.getNodeType().toString();
81 serializablePathArgument = NormalizedNodeMessages.PathArgument.newBuilder()
82 .setValue(pathArgument.toString())
83 .setType(pathArgument.getClass().getSimpleName())
84 .setNodeType(NormalizedNodeMessages.QName.newBuilder().setValue(nodeType))
85 .addAllAttributes(getPathArgumentAttributes(pathArgument)).build();
87 serializablePathArgument = PathArgumentSerializer.serialize(context, pathArgument);
90 builder.addArguments(serializablePathArgument);
93 logger.error("An exception occurred", e);
101 * Convert a protocol buffer version of the MD-SAL YangInstanceIdentifier into
102 * the MD-SAL version of the YangInstanceIdentifier
104 * @param path a protocol buffer version of the MD-SAL YangInstanceIdentifier
105 * @return an MD-SAL YangInstanceIdentifier
107 public static YangInstanceIdentifier fromSerializable(NormalizedNodeMessages.InstanceIdentifier path) {
108 return fromSerializable(path, new QNameDeSerializationContextImpl(path.getCodeList()));
111 public static YangInstanceIdentifier fromSerializable(NormalizedNodeMessages.InstanceIdentifier path,
112 QNameDeSerializationContext context) {
114 List<YangInstanceIdentifier.PathArgument> pathArguments = new ArrayList<>();
116 for(NormalizedNodeMessages.PathArgument pathArgument : path.getArgumentsList()) {
117 if(context == null || pathArgument.hasType()) {
118 pathArguments.add(parsePathArgument(pathArgument));
120 pathArguments.add(PathArgumentSerializer.deSerialize(context, pathArgument));
124 return YangInstanceIdentifier.create(pathArguments);
128 * Take the various attributes of a PathArgument and package them up as
129 * protocol buffer attributes.
132 * PathArguments have 4 subtypes and each of the various subtypes have
133 * different attributes
136 * NodeIdentifier is the most basic PathArgument. It is used for
137 * ContainerNode, LeafNode etc and has no attributes
140 * NodeWithValue has only a single attribute. It is used for
141 * LeafListEntryNodes and the attribute it contains is the value
145 * NodeIdentifierWithPredicates has a map of attributes.
146 * It is used to represent a ListItemNode. Each entry
147 * in the map of attributes represents the key and value of the
148 * keys in that entry.
151 * AugmentationIdentifier has a list of unnamed attributes. Each
152 * attribute represents the possible children that can go within
153 * an augmentation entry.
156 * @param pathArgument
159 private static Iterable<? extends NormalizedNodeMessages.Attribute> getPathArgumentAttributes(
160 YangInstanceIdentifier.PathArgument pathArgument) {
161 List<NormalizedNodeMessages.Attribute> attributes = new ArrayList<>();
165 if (pathArgument instanceof YangInstanceIdentifier.NodeWithValue) {
166 YangInstanceIdentifier.NodeWithValue identifier
167 = (YangInstanceIdentifier.NodeWithValue) pathArgument;
169 NormalizedNodeMessages.Attribute attribute =
170 NormalizedNodeMessages.Attribute.newBuilder()
172 .setValue(identifier.getValue().toString())
173 .setType(identifier.getValue().getClass().getSimpleName())
176 attributes.add(attribute);
177 } else if (pathArgument instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
178 YangInstanceIdentifier.NodeIdentifierWithPredicates identifier
179 = (YangInstanceIdentifier.NodeIdentifierWithPredicates) pathArgument;
181 for (QName key : identifier.getKeyValues().keySet()) {
182 Object value = identifier.getKeyValues().get(key);
183 NormalizedNodeMessages.Attribute attribute =
184 NormalizedNodeMessages.Attribute.newBuilder()
185 .setName(key.toString())
186 .setValue(value.toString())
187 .setType(value.getClass().getSimpleName())
190 attributes.add(attribute);
194 } else if(pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier) {
195 YangInstanceIdentifier.AugmentationIdentifier identifier
196 = (YangInstanceIdentifier.AugmentationIdentifier) pathArgument;
198 for (QName key : identifier.getPossibleChildNames()) {
200 NormalizedNodeMessages.Attribute attribute =
201 NormalizedNodeMessages.Attribute.newBuilder()
202 .setName(key.toString())
203 .setValue(value.toString())
204 .setType(value.getClass().getSimpleName())
207 attributes.add(attribute);
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 NormalizedNodeMessages.PathArgument pathArgument) {
224 if (YangInstanceIdentifier.NodeWithValue.class.getSimpleName().equals(pathArgument.getType())) {
226 YangInstanceIdentifier.NodeWithValue nodeWithValue =
227 new YangInstanceIdentifier.NodeWithValue(
228 QNameFactory.create(pathArgument.getNodeType().getValue()),
229 parseAttribute(pathArgument.getAttributes(0)));
231 return nodeWithValue;
233 } else if(YangInstanceIdentifier.NodeIdentifierWithPredicates.class.getSimpleName().equals(pathArgument.getType())){
235 YangInstanceIdentifier.NodeIdentifierWithPredicates
236 nodeIdentifierWithPredicates =
237 new YangInstanceIdentifier.NodeIdentifierWithPredicates(
238 QNameFactory.create(pathArgument.getNodeType().getValue()), toAttributesMap(pathArgument.getAttributesList()));
240 return nodeIdentifierWithPredicates;
242 } else if(YangInstanceIdentifier.AugmentationIdentifier.class.getSimpleName().equals(pathArgument.getType())){
244 Set<QName> qNameSet = new HashSet<>();
246 for(NormalizedNodeMessages.Attribute attribute : pathArgument.getAttributesList()){
247 qNameSet.add(QNameFactory.create(attribute.getValue()));
250 return new YangInstanceIdentifier.AugmentationIdentifier(qNameSet);
253 return NodeIdentifierFactory.getArgument(pathArgument.getValue());
256 private static Map<QName, Object> toAttributesMap(
257 List<NormalizedNodeMessages.Attribute> attributesList) {
259 Map<QName, Object> map = new HashMap<>();
261 for(NormalizedNodeMessages.Attribute attribute : attributesList){
262 String name = attribute.getName();
263 Object value = parseAttribute(attribute);
265 map.put(QNameFactory.create(name), value);
272 * FIXME: This method only covers a subset of values that may go in an InstanceIdentifier
277 private static Object parseAttribute(NormalizedNodeMessages.Attribute attribute){
278 if(Short.class.getSimpleName().equals(attribute.getType())) {
279 return Short.parseShort(attribute.getValue());
280 } else if(Long.class.getSimpleName().equals(attribute.getType())){
281 return Long.parseLong(attribute.getValue());
282 } else if(Boolean.class.getSimpleName().equals(attribute.getType())){
283 return Boolean.parseBoolean(attribute.getValue());
284 } else if(Integer.class.getSimpleName().equals(attribute.getType())){
285 return Integer.parseInt(attribute.getValue());
288 return attribute.getValue();