2  * ============LICENSE_START=======================================================
 
   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
 
  11  *      http://www.apache.org/licenses/LICENSE-2.0
 
  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=========================================================
 
  21 package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
 
  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;
 
  37 import java.util.Collection;
 
  38 import java.util.Deque;
 
  39 import java.util.Iterator;
 
  40 import java.util.Optional;
 
  42 import static com.google.common.base.Preconditions.checkArgument;
 
  45  * Represents utilities for properties node tree.
 
  47 public final class MdsalPropertiesNodeUtils {
 
  49     private MdsalPropertiesNodeUtils() {
 
  53      * Returns the index from multi instance property name.
 
  55      * @param name name of the property
 
  56      * @return index from multi instance property name
 
  58     public static String getIndex(String name) {
 
  59         return name.substring(name.indexOf("[") + 1,
 
  64      * Returns the multi instance property name.
 
  66      * @param name name of the property
 
  67      * @return the multi instance property name
 
  69     public static String getListName(String name) {
 
  70         String[] s = name.split("\\[");
 
  75      * Returns true if property is multi instance.
 
  77      * @param name name of the property
 
  78      * @return true if property is multi instance
 
  80     public static boolean isListEntry(String name) {
 
  81         String s[] = name.split("\\[");
 
  86      * Returns name of the property after pruning namespace and
 
  87      * index if the property is multi instance.
 
  89      * @param name name of the property
 
  90      * @return name of the property
 
  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);
 
 102      * Adds current node to parent's augmentation map.
 
 104      * @param augSchema augment schema
 
 105      * @param parent parent property node
 
 106      * @param curNode current property node
 
 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())) {
 
 120         parent.augmentations().put(augSchema, curNode);
 
 125      * Returns augmented properties node if it is already
 
 126      * added in properties tree.
 
 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
 
 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)) {
 
 151      * Creates uri with specified name and namespace.
 
 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
 
 158     public static String getUri(PropertiesNode parent, String name,
 
 161         if (!(parent.namespace().moduleNs().equals(ns.moduleNs()))) {
 
 162             uri = ns.moduleName() + ":" + name;
 
 164         return parent.uri() + "." + uri;
 
 168      * Creates new properties with specified parameters.
 
 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
 
 178     public static PropertiesNode createNode(String name, Namespace namespace,
 
 179                                             String uri, PropertiesNode parent,
 
 180                                             Object appInfo, NodeType 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);
 
 189                 throw new RuntimeException("Invalid node type");
 
 194      * Returns true if namespace is same as parent's namespace.
 
 196      * @param parent parent property node
 
 197      * @param curNode current property node
 
 198      * @return true if namespace is same as parent namespace
 
 200     public static boolean isNamespaceAsParent(PropertiesNode parent,
 
 201                                               PropertiesNode curNode) {
 
 202         return parent.namespace().moduleNs().equals(curNode.namespace().moduleNs());
 
 208      * @param childName name of the property
 
 209      * @param ctx schema context
 
 210      * @param parent parent property node
 
 213     public static Namespace getNamespace(String childName,
 
 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();
 
 221                 // module is not present in context
 
 224             Module m = it.next();
 
 225             return new Namespace(moduleName, m.getQNameModule().getNamespace(),
 
 226                                  getRevision(m.getRevision()));
 
 228         Namespace parentNs = parent.namespace();
 
 229         return new Namespace(parentNs.moduleName(), parentNs.moduleNs(),
 
 230                              parentNs.revision());
 
 234      * Returns child schema node.
 
 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
 
 241     public static SchemaNode getChildSchemaNode(SchemaNode curSchema,
 
 243                                                 Namespace namespace) {
 
 244         if (namespace == null) {
 
 248         QName qname =  QName.create(namespace.moduleNs(),
 
 249                                     Revision.of(namespace.revision()), name);
 
 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
 
 261             DataSchemaNode schemaNode = schemaNodeDeque.pop();
 
 262             if (schemaNodeDeque.isEmpty()){
 
 267             // node is child of Choice/case
 
 268             return SchemaUtils.findSchemaForChild(((ChoiceSchemaNode) schemaNode),
 
 271             return SchemaUtils.findDataChildSchemaByQName(curSchema, qname);
 
 276      * Returns the property node type.
 
 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
 
 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);
 
 288             return (isListEntry(name) ? NodeType.MULTI_INSTANCE_NODE :
 
 289                     NodeType.SINGLE_INSTANCE_NODE);
 
 294      * Returns revision in string.
 
 296      * @param r YANG revision
 
 297      * @return revision in string
 
 299     public static String getRevision(Optional<Revision> r) {
 
 300         return (r.isPresent()) ? r.get().toString() : null;
 
 304      * Returns value namespace for leaf value.
 
 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
 
 311     static Namespace getValueNamespace(String value,
 
 313             throws SvcLogicException {
 
 314         String prefix = getPrefixFromValue(value);
 
 315         if (prefix == null) {
 
 319         IdentitySchemaNode id = IdentityCodecUtil.parseIdentity(value,
 
 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();
 
 329             throw new SvcLogicException("Could not find identity");
 
 332         return getModuleNamespace(id.getQName(), ctx);
 
 335     private static String getPrefixFromValue(String value) {
 
 336         int lastIndexOfColon = value.lastIndexOf(":");
 
 337         if (lastIndexOfColon != -1) {
 
 338             return value.substring(0, lastIndexOfColon);
 
 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");
 
 349         Module m = module.get();
 
 350         return new Namespace(m.getName(), m.getQNameModule().getNamespace(),
 
 351                              getRevision(m.getRevision()));
 
 354     static String getParsedValue(Namespace valNs, String value) {
 
 355         if (valNs != null && value.contains(":")) {
 
 356             String[] valArr = value.split(":");