d7b4818b41d7a4482b4d8a3c152435bb9216f442
[ccsdk/sli/plugins.git] / restconf-client / provider / src / main / java / org / onap / ccsdk / sli / plugins / yangserializers / pnserializer / MdsalPropertiesNodeUtils.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - CCSDK
4  * ================================================================================
5  * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
22
23 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.common.Revision;
26 import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
27 import org.opendaylight.yangtools.yang.data.util.ParserStreamUtils;
28 import org.opendaylight.yangtools.yang.data.util.codec.IdentityCodecUtil;
29 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
31 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
32 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
33 import org.opendaylight.yangtools.yang.model.api.Module;
34 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
35 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
36
37 import java.util.Collection;
38 import java.util.Deque;
39 import java.util.Iterator;
40 import java.util.Optional;
41
42 import static com.google.common.base.Preconditions.checkArgument;
43
44 /**
45  * Represents utilities for properties node tree.
46  */
47 public final class MdsalPropertiesNodeUtils {
48
49     private MdsalPropertiesNodeUtils() {
50     }
51
52     /**
53      * Returns the index from multi instance property name.
54      *
55      * @param name name of the property
56      * @return index from multi instance property name
57      */
58     public static String getIndex(String name) {
59         return name.substring(name.indexOf("[") + 1,
60                               name.indexOf("]"));
61     }
62
63     /**
64      * Returns the multi instance property name.
65      *
66      * @param name name of the property
67      * @return the multi instance property name
68      */
69     public static String getListName(String name) {
70         String[] s = name.split("\\[");
71         return s[0];
72     }
73
74     /**
75      * Returns true if property is multi instance.
76      *
77      * @param name name of the property
78      * @return true if property is multi instance
79      */
80     public static boolean isListEntry(String name) {
81         String s[] = name.split("\\[");
82         return s.length > 1;
83     }
84
85     /**
86      * Returns name of the property after pruning namespace and
87      * index if the property is multi instance.
88      *
89      * @param name name of the property
90      * @return name of the property
91      */
92     public static String resolveName(String name) {
93         String localName = getListName(name);
94         final int lastIndexOfColon = localName.lastIndexOf(":");
95         if (lastIndexOfColon != -1) {
96             localName = localName.substring(lastIndexOfColon + 1);
97         }
98         return localName;
99     }
100
101     /**
102      * Adds current node to parent's augmentation map.
103      *
104      * @param augSchema augment schema
105      * @param parent parent property node
106      * @param curNode current property node
107      */
108     public static void addToAugmentations(AugmentationSchemaNode augSchema,
109                                           PropertiesNode parent,
110                                           PropertiesNode curNode) {
111         Collection<PropertiesNode> childsFromAugmentation = parent
112                 .augmentations().get(augSchema);
113         if (!childsFromAugmentation.isEmpty()) {
114             for (PropertiesNode pNode : childsFromAugmentation) {
115                 if (pNode.name().equals(curNode.name())) {
116                     return;
117                 }
118             }
119         }
120         parent.augmentations().put(augSchema, curNode);
121     }
122
123
124     /**
125      * Returns augmented properties node if it is already
126      * added in properties tree.
127      *
128      * @param augSchema augmented schema node
129      * @param parent parent properties node
130      * @param name name of the properties
131      * @return augmented properties node if it is already added
132      */
133     public static PropertiesNode getAugmentationNode(
134             AugmentationSchemaNode augSchema,
135             PropertiesNode parent, String name) {
136         if (augSchema != null) {
137             Collection<PropertiesNode> childsFromAugmentation = parent
138                     .augmentations().get(augSchema);
139             if (!childsFromAugmentation.isEmpty()) {
140                 for (PropertiesNode pNode : childsFromAugmentation) {
141                     if (pNode.name().equals(name)) {
142                         return pNode;
143                     }
144                 }
145             }
146         }
147         return null;
148     }
149
150     /**
151      * Creates uri with specified name and namespace.
152      *
153      * @param parent parent properties node
154      * @param name name of the node
155      * @param ns namespace of the node
156      * @return uri with specified name and namespace
157      */
158     public static String getUri(PropertiesNode parent, String name,
159                                 Namespace ns) {
160         String uri = name;
161         if (!(parent.namespace().moduleNs().equals(ns.moduleNs()))) {
162             uri = ns.moduleName() + ":" + name;
163         }
164         return parent.uri() + "." + uri;
165     }
166
167     /**
168      * Creates new properties with specified parameters.
169      *
170      * @param name name of the properties node
171      * @param namespace namespace of the properties node
172      * @param uri uri of the properties node
173      * @param parent parent node
174      * @param appInfo application info
175      * @param type node type
176      * @return new properties node
177      */
178     public static PropertiesNode createNode(String name, Namespace namespace,
179                                             String uri, PropertiesNode parent,
180                                             Object appInfo, NodeType type) {
181         switch (type) {
182             case SINGLE_INSTANCE_NODE:
183                 return new SingleInstanceNode(name, namespace, uri, parent, appInfo, type);
184             case MULTI_INSTANCE_HOLDER_NODE:
185                 return new ListHolderNode(name, namespace, uri, parent, appInfo, type);
186             case MULTI_INSTANCE_LEAF_HOLDER_NODE:
187                 return new LeafListHolderNode(name, namespace, uri, parent, appInfo, type);
188             default:
189                 throw new RuntimeException("Invalid node type");
190         }
191     }
192
193     /**
194      * Returns true if namespace is same as parent's namespace.
195      *
196      * @param parent parent property node
197      * @param curNode current property node
198      * @return true if namespace is same as parent namespace
199      */
200     public static boolean isNamespaceAsParent(PropertiesNode parent,
201                                               PropertiesNode curNode) {
202         return parent.namespace().moduleNs().equals(curNode.namespace().moduleNs());
203     }
204
205     /**
206      * Returns namespace.
207      *
208      * @param childName name of the property
209      * @param ctx schema context
210      * @param parent parent property node
211      * @return namespace
212      */
213     public static Namespace getNamespace(String childName,
214                                          SchemaContext ctx,
215                                          PropertiesNode parent) {
216         int lastIndexOfColon = childName.lastIndexOf(":");
217         if (lastIndexOfColon != -1) {
218             String moduleName = childName.substring(0, lastIndexOfColon);
219             Iterator<Module> it = ctx.findModules(moduleName).iterator();
220             if (!it.hasNext()) {
221                 // module is not present in context
222                 return null;
223             }
224             Module m = it.next();
225             return new Namespace(moduleName, m.getQNameModule().getNamespace(),
226                                  getRevision(m.getRevision()));
227         }
228         Namespace parentNs = parent.namespace();
229         return new Namespace(parentNs.moduleName(), parentNs.moduleNs(),
230                              parentNs.revision());
231     }
232
233     /**
234      * Returns child schema node.
235      *
236      * @param curSchema current schema node
237      * @param name name of the property
238      * @param namespace namespace of the property
239      * @return child schema node
240      */
241     public static SchemaNode getChildSchemaNode(SchemaNode curSchema,
242                                                      String name,
243                                                 Namespace namespace) {
244         if (namespace == null) {
245             return null;
246         }
247
248         QName qname =  QName.create(namespace.moduleNs(),
249                                     Revision.of(namespace.revision()), name);
250
251         // YANG RPC will not be instance of DataSchemaNode
252         if (curSchema instanceof DataSchemaNode) {
253             Deque<DataSchemaNode> schemaNodeDeque = ParserStreamUtils.
254                     findSchemaNodeByNameAndNamespace(((DataSchemaNode)
255                             curSchema), name, namespace.moduleNs());
256             if (schemaNodeDeque.isEmpty()) {
257                 // could not find schema node
258                 return null;
259             }
260
261             DataSchemaNode schemaNode = schemaNodeDeque.pop();
262             if (schemaNodeDeque.isEmpty()){
263                 // Simple node
264                 return schemaNode;
265             }
266
267             // node is child of Choice/case
268             return SchemaUtils.findSchemaForChild(((ChoiceSchemaNode) schemaNode),
269                                                   qname);
270         } else {
271             return SchemaUtils.findDataChildSchemaByQName(curSchema, qname);
272         }
273     }
274
275     /**
276      * Returns the property node type.
277      *
278      * @param index current index
279      * @param length length of the properties
280      * @param name name of the property
281      * @return the property node type
282      */
283     public static NodeType getNodeType(int index, int length, String name) {
284         if (index == length-1) {
285             return (isListEntry(name) ? NodeType.MULTI_INSTANCE_LEAF_NODE :
286                     NodeType.SINGLE_INSTANCE_LEAF_NODE);
287         } else {
288             return (isListEntry(name) ? NodeType.MULTI_INSTANCE_NODE :
289                     NodeType.SINGLE_INSTANCE_NODE);
290         }
291     }
292
293     /**
294      * Returns revision in string.
295      *
296      * @param r YANG revision
297      * @return revision in string
298      */
299     public static String getRevision(Optional<Revision> r) {
300         return (r.isPresent()) ? r.get().toString() : null;
301     }
302
303     /**
304      * Returns value namespace for leaf value.
305      *
306      * @param value value of the leaf
307      * @param ctx schema context
308      * @return value namespace
309      * @throws SvcLogicException if identity/module could not be found
310      */
311     static Namespace getValueNamespace(String value,
312                                               SchemaContext ctx)
313             throws SvcLogicException {
314         String prefix = getPrefixFromValue(value);
315         if (prefix == null) {
316             return null;
317         }
318
319         IdentitySchemaNode id = IdentityCodecUtil.parseIdentity(value,
320                                                                 ctx,
321                                                                 prefixToModule -> {
322             final Iterator<Module> modules = ctx.findModules(prefix).iterator();
323             checkArgument(modules.hasNext(), "Could not find " +
324                                   "module %s", prefix);
325             return modules.next().getQNameModule();
326         });
327
328         if (id == null) {
329             throw new SvcLogicException("Could not find identity");
330         }
331
332         return getModuleNamespace(id.getQName(), ctx);
333     }
334
335     private static String getPrefixFromValue(String value) {
336         int lastIndexOfColon = value.lastIndexOf(":");
337         if (lastIndexOfColon != -1) {
338             return value.substring(0, lastIndexOfColon);
339         }
340         return null;
341     }
342
343     private static Namespace getModuleNamespace(QName qName, SchemaContext ctx)
344             throws SvcLogicException {
345         Optional<Module> module = ctx.findModule(qName.getModule());
346         if (!module.isPresent()) {
347             throw new SvcLogicException("Could not find module node");
348         }
349         Module m = module.get();
350         return new Namespace(m.getName(), m.getQNameModule().getNamespace(),
351                              getRevision(m.getRevision()));
352     }
353
354     static String getParsedValue(Namespace valNs, String value) {
355         if (valNs != null && value.contains(":")) {
356             String[] valArr = value.split(":");
357             return valArr[1];
358         }
359         return value;
360     }
361 }