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 java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.List;
17 import org.opendaylight.controller.cluster.datastore.node.utils.NodeIdentifierFactory;
18 import org.opendaylight.controller.cluster.datastore.node.utils.QNameFactory;
19 import org.opendaylight.controller.cluster.datastore.node.utils.serialization.PathArgumentSerializer;
20 import org.opendaylight.controller.cluster.datastore.node.utils.serialization.QNameDeSerializationContext;
21 import org.opendaylight.controller.cluster.datastore.node.utils.serialization.QNameDeSerializationContextImpl;
22 import org.opendaylight.controller.cluster.datastore.node.utils.serialization.QNameSerializationContext;
23 import org.opendaylight.controller.cluster.datastore.node.utils.serialization.QNameSerializationContextImpl;
24 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
25 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder;
26 import org.opendaylight.yangtools.yang.common.QName;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
30 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
31 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
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 {
47 private static final Logger LOG = LoggerFactory.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 @SuppressWarnings("checkstyle:IllegalCatch")
67 private static NormalizedNodeMessages.InstanceIdentifier.Builder toSerializableBuilder(
68 YangInstanceIdentifier path, QNameSerializationContext context) {
69 NormalizedNodeMessages.InstanceIdentifier.Builder builder =
70 NormalizedNodeMessages.InstanceIdentifier.newBuilder();
73 for (PathArgument pathArgument : path.getPathArguments()) {
74 NormalizedNodeMessages.PathArgument serializablePathArgument;
75 if (context == null) {
77 if (!(pathArgument instanceof 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);
92 } catch (Exception e) {
93 LOG.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<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.
131 * PathArguments have 4 subtypes and each of the various subtypes have
132 * different attributes
135 * NodeIdentifier is the most basic PathArgument. It is used for
136 * ContainerNode, LeafNode etc and has no attributes
139 * NodeWithValue has only a single attribute. It is used for
140 * LeafListEntryNodes and the attribute it contains is the value
144 * NodeIdentifierWithPredicates has a map of attributes.
145 * It is used to represent a ListItemNode. Each entry
146 * in the map of attributes represents the key and value of the
147 * keys in that entry.
150 * AugmentationIdentifier has a list of unnamed attributes. Each
151 * attribute represents the possible children that can go within
152 * an augmentation entry.
156 private static Iterable<? extends NormalizedNodeMessages.Attribute> getPathArgumentAttributes(
157 PathArgument pathArgument) {
158 List<NormalizedNodeMessages.Attribute> attributes = new ArrayList<>();
160 if (pathArgument instanceof NodeWithValue) {
161 NodeWithValue<?> identifier = (NodeWithValue<?>) pathArgument;
163 NormalizedNodeMessages.Attribute attribute =
164 NormalizedNodeMessages.Attribute.newBuilder()
166 .setValue(identifier.getValue().toString())
167 .setType(identifier.getValue().getClass().getSimpleName())
170 attributes.add(attribute);
171 } else if (pathArgument instanceof NodeIdentifierWithPredicates) {
172 NodeIdentifierWithPredicates identifier = (NodeIdentifierWithPredicates) pathArgument;
174 for (QName key : identifier.getKeyValues().keySet()) {
175 Object value = identifier.getKeyValues().get(key);
176 NormalizedNodeMessages.Attribute attribute =
177 NormalizedNodeMessages.Attribute.newBuilder()
178 .setName(key.toString())
179 .setValue(value.toString())
180 .setType(value.getClass().getSimpleName())
183 attributes.add(attribute);
187 } else if (pathArgument instanceof AugmentationIdentifier) {
188 AugmentationIdentifier identifier = (AugmentationIdentifier) pathArgument;
190 for (QName key : identifier.getPossibleChildNames()) {
192 NormalizedNodeMessages.Attribute attribute =
193 NormalizedNodeMessages.Attribute.newBuilder()
194 .setName(key.toString())
195 .setValue(value.toString())
196 .setType(value.getClass().getSimpleName())
199 attributes.add(attribute);
209 * Parse a protocol buffer PathArgument and return an MD-SAL PathArgument.
211 * @param pathArgument protocol buffer PathArgument
212 * @return MD-SAL PathArgument
214 private static PathArgument parsePathArgument(
215 NormalizedNodeMessages.PathArgument pathArgument) {
216 if (NodeWithValue.class.getSimpleName().equals(pathArgument.getType())) {
218 NodeWithValue<?> nodeWithValue = new NodeWithValue<>(
219 QNameFactory.create(pathArgument.getNodeType().getValue()),
220 parseAttribute(pathArgument.getAttributes(0)));
222 return nodeWithValue;
224 } else if (NodeIdentifierWithPredicates.class.getSimpleName().equals(pathArgument.getType())) {
226 NodeIdentifierWithPredicates nodeIdentifierWithPredicates =
227 new NodeIdentifierWithPredicates(QNameFactory.create(pathArgument.getNodeType().getValue()),
228 toAttributesMap(pathArgument.getAttributesList()));
230 return nodeIdentifierWithPredicates;
232 } else if (AugmentationIdentifier.class.getSimpleName().equals(pathArgument.getType())) {
234 Set<QName> qnameSet = new HashSet<>();
236 for (NormalizedNodeMessages.Attribute attribute : pathArgument.getAttributesList()) {
237 qnameSet.add(QNameFactory.create(attribute.getValue()));
240 return new AugmentationIdentifier(qnameSet);
243 return NodeIdentifierFactory.getArgument(pathArgument.getValue());
246 private static Map<QName, Object> toAttributesMap(
247 List<NormalizedNodeMessages.Attribute> attributesList) {
249 Map<QName, Object> map = new HashMap<>();
251 for (NormalizedNodeMessages.Attribute attribute : attributesList) {
252 String name = attribute.getName();
253 Object value = parseAttribute(attribute);
255 map.put(QNameFactory.create(name), value);
262 * FIXME: This method only covers a subset of values that may go in an InstanceIdentifier.
264 private static Object parseAttribute(NormalizedNodeMessages.Attribute attribute) {
265 if (Short.class.getSimpleName().equals(attribute.getType())) {
266 return Short.parseShort(attribute.getValue());
267 } else if (Long.class.getSimpleName().equals(attribute.getType())) {
268 return Long.parseLong(attribute.getValue());
269 } else if (Boolean.class.getSimpleName().equals(attribute.getType())) {
270 return Boolean.parseBoolean(attribute.getValue());
271 } else if (Integer.class.getSimpleName().equals(attribute.getType())) {
272 return Integer.parseInt(attribute.getValue());
275 return attribute.getValue();