55cb341086078b79406d574c11cec8961813e6b6
[controller.git] / opendaylight / md-sal / sal-clustering-commons / src / main / java / org / opendaylight / controller / cluster / datastore / util / InstanceIdentifierUtils.java
1 /*
2  *
3  *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
4  *
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
8  *
9  */
10
11 package org.opendaylight.controller.cluster.datastore.util;
12
13 import org.opendaylight.controller.cluster.datastore.node.utils.NodeIdentifierFactory;
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;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Set;
26
27 /**
28  * This class contains utility methods for converting an MD-SAL
29  * YangInstanceIdentifier to and from other representations.
30  * <p>
31  * The representations convered for now are,
32  *
33  * <ul>
34  *     <li>String</li>
35  *     <li>Protocol Buffer</li>
36  * </ul>
37  */
38 public class InstanceIdentifierUtils {
39
40     protected static final Logger logger = LoggerFactory
41         .getLogger(InstanceIdentifierUtils.class);
42
43     @Deprecated
44     public static YangInstanceIdentifier from(String path) {
45         String[] ids = path.split("/");
46
47         List<YangInstanceIdentifier.PathArgument> pathArguments =
48             new ArrayList<>();
49         for (String nodeId : ids) {
50             if (!"".equals(nodeId)) {
51                 pathArguments
52                     .add(NodeIdentifierFactory.getArgument(nodeId));
53             }
54         }
55         final YangInstanceIdentifier instanceIdentifier =
56             YangInstanceIdentifier.create(pathArguments);
57         return instanceIdentifier;
58     }
59
60
61     /**
62      * Convert an MD-SAL YangInstanceIdentifier into a protocol buffer version of it
63      *
64      * @param path an MD-SAL YangInstanceIdentifier
65      * @return a protocol buffer version of the MD-SAL YangInstanceIdentifier
66      */
67     public static NormalizedNodeMessages.InstanceIdentifier toSerializable(YangInstanceIdentifier path){
68         NormalizedNodeMessages.InstanceIdentifier.Builder builder =
69             NormalizedNodeMessages.InstanceIdentifier.newBuilder();
70
71         try {
72
73             for (org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument pathArgument : path
74                 .getPathArguments()) {
75
76                 String nodeType = "";
77                 if(!(pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier)){
78                     nodeType = pathArgument.getNodeType().toString();
79                 }
80
81                 NormalizedNodeMessages.PathArgument serializablePathArgument =
82                     NormalizedNodeMessages.PathArgument.newBuilder()
83                         .setValue(pathArgument.toString())
84                         .setType(pathArgument.getClass().getSimpleName())
85                         .setNodeType(NormalizedNodeMessages.QName.newBuilder()
86                             .setValue(nodeType))
87                         .addAllAttributes(getPathArgumentAttributes(
88                             pathArgument))
89                         .build();
90
91                 builder.addArguments(serializablePathArgument);
92             }
93
94         } catch(Exception e){
95             logger.error("An exception occurred", e);
96         }
97         return builder.build();
98     }
99
100
101     /**
102      * Convert a protocol buffer version of the MD-SAL YangInstanceIdentifier into
103      * the MD-SAL version of the YangInstanceIdentifier
104      *
105      * @param path a protocol buffer version of the MD-SAL YangInstanceIdentifier
106      * @return  an MD-SAL YangInstanceIdentifier
107      */
108     public static YangInstanceIdentifier fromSerializable(NormalizedNodeMessages.InstanceIdentifier path){
109
110         List<YangInstanceIdentifier.PathArgument> pathArguments =
111             new ArrayList<>();
112
113         for(NormalizedNodeMessages.PathArgument pathArgument : path.getArgumentsList()){
114
115             pathArguments
116                 .add(parsePathArgument(pathArgument));
117
118         }
119
120         final YangInstanceIdentifier instanceIdentifier = YangInstanceIdentifier.create(pathArguments);
121
122         return instanceIdentifier;
123     }
124
125     /**
126      * Take the various attributes of a PathArgument and package them up as
127      * protocol buffer attributes.
128      * <p>
129      *
130      * PathArguments have 4 subtypes and each of the various subtypes have
131      * different attributes
132      * <ul>
133      *     <li>
134      *         NodeIdentifier is the most basic PathArgument. It is used for
135      *         ContainerNode, LeafNode etc and has no attributes
136      *     </li>
137      *     <li>
138      *         NodeWithValue has only a single attribute. It is used for
139      *         LeafListEntryNodes and the attribute it contains is the value
140      *         of the entry
141      *     </li>
142      *     <li>
143      *         NodeIdentifierWithPredicates has a map of attributes.
144      *         It is used to represent a ListItemNode. Each entry
145      *         in the map of attributes represents the key and value of the
146      *         keys in that entry.
147      *     </li>
148      *     <li>
149      *         AugmentationIdentifier has a list of unnamed attributes. Each
150      *         attribute represents the possible children that can go within
151      *         an augmentation entry.
152      *     </li>
153      * </ul>
154      * @param pathArgument
155      * @return
156      */
157     private static Iterable<? extends NormalizedNodeMessages.Attribute> getPathArgumentAttributes(
158         YangInstanceIdentifier.PathArgument pathArgument) {
159         List<NormalizedNodeMessages.Attribute> attributes = new ArrayList<>();
160
161
162
163         if (pathArgument instanceof YangInstanceIdentifier.NodeWithValue) {
164             YangInstanceIdentifier.NodeWithValue identifier
165                 = (YangInstanceIdentifier.NodeWithValue) pathArgument;
166
167             NormalizedNodeMessages.Attribute attribute =
168                 NormalizedNodeMessages.Attribute.newBuilder()
169                     .setName("name")
170                     .setValue(identifier.getValue().toString())
171                     .setType(identifier.getValue().getClass().getSimpleName())
172                     .build();
173
174             attributes.add(attribute);
175         } else if (pathArgument instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
176             YangInstanceIdentifier.NodeIdentifierWithPredicates identifier
177                 = (YangInstanceIdentifier.NodeIdentifierWithPredicates) pathArgument;
178
179             for (QName key : identifier.getKeyValues().keySet()) {
180                 Object value = identifier.getKeyValues().get(key);
181                 NormalizedNodeMessages.Attribute attribute =
182                     NormalizedNodeMessages.Attribute.newBuilder()
183                         .setName(key.toString())
184                         .setValue(value.toString())
185                         .setType(value.getClass().getSimpleName())
186                         .build();
187
188                 attributes.add(attribute);
189
190             }
191
192         } else if(pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier) {
193             YangInstanceIdentifier.AugmentationIdentifier identifier
194                 = (YangInstanceIdentifier.AugmentationIdentifier) pathArgument;
195
196             for (QName key : identifier.getPossibleChildNames()) {
197                 Object value = key;
198                 NormalizedNodeMessages.Attribute attribute =
199                     NormalizedNodeMessages.Attribute.newBuilder()
200                         .setName(key.toString())
201                         .setValue(value.toString())
202                         .setType(value.getClass().getSimpleName())
203                         .build();
204
205                 attributes.add(attribute);
206
207             }
208         }
209
210         return attributes;
211     }
212
213
214     /**
215      * Parse a protocol buffer PathArgument and return an MD-SAL PathArgument
216      *
217      * @param pathArgument protocol buffer PathArgument
218      * @return MD-SAL PathArgument
219      */
220     private static YangInstanceIdentifier.PathArgument parsePathArgument(NormalizedNodeMessages.PathArgument pathArgument) {
221         if (YangInstanceIdentifier.NodeWithValue.class.getSimpleName().equals(pathArgument.getType())) {
222
223             YangInstanceIdentifier.NodeWithValue nodeWithValue =
224                 new YangInstanceIdentifier.NodeWithValue(
225                     QName.create(pathArgument.getNodeType().getValue()),
226                     parseAttribute(pathArgument.getAttributes(0)));
227
228             return nodeWithValue;
229
230         } else if(YangInstanceIdentifier.NodeIdentifierWithPredicates.class.getSimpleName().equals(pathArgument.getType())){
231
232             YangInstanceIdentifier.NodeIdentifierWithPredicates
233                 nodeIdentifierWithPredicates =
234                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(
235                     QName.create(pathArgument.getNodeType().getValue()), toAttributesMap(pathArgument.getAttributesList()));
236
237             return nodeIdentifierWithPredicates;
238
239         } else if(YangInstanceIdentifier.AugmentationIdentifier.class.getSimpleName().equals(pathArgument.getType())){
240
241             Set<QName> qNameSet = new HashSet<>();
242
243             for(NormalizedNodeMessages.Attribute attribute : pathArgument.getAttributesList()){
244                 qNameSet.add(QName.create(attribute.getValue()));
245             }
246
247             return new YangInstanceIdentifier.AugmentationIdentifier(qNameSet);
248         }
249
250         return NodeIdentifierFactory.getArgument(pathArgument.getValue());
251     }
252
253     private static Map<QName, Object> toAttributesMap(
254         List<NormalizedNodeMessages.Attribute> attributesList) {
255
256         Map<QName, Object> map = new HashMap<>();
257
258         for(NormalizedNodeMessages.Attribute attribute : attributesList){
259             String name = attribute.getName();
260             Object value = parseAttribute(attribute);
261
262             map.put(QName.create(name), value);
263         }
264
265         return map;
266     }
267
268     /**
269      * FIXME: This method only covers a subset of values that may go in an InstanceIdentifier
270      *
271      * @param attribute
272      * @return
273      */
274     private static Object parseAttribute(NormalizedNodeMessages.Attribute attribute){
275         if(Short.class.getSimpleName().equals(attribute.getType())) {
276             return Short.parseShort(attribute.getValue());
277         } else if(Long.class.getSimpleName().equals(attribute.getType())){
278             return Long.parseLong(attribute.getValue());
279         } else if(Boolean.class.getSimpleName().equals(attribute.getType())){
280             return Boolean.parseBoolean(attribute.getValue());
281         } else if(Integer.class.getSimpleName().equals(attribute.getType())){
282             return Integer.parseInt(attribute.getValue());
283         }
284
285         return attribute.getValue();
286     }
287 }