Replacing ":" by "_" for parameters
[ccsdk/sli/plugins.git] / restconf-client / provider / src / main / java / org / onap / ccsdk / sli / plugins / yangserializers / pnserializer / MdsalPropertiesNodeUtils.java
index ccc4f2b..d0b34f9 100644 (file)
 
 package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
 
+import java.util.Collection;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.Optional;
+
 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
+import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.Revision;
 import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
@@ -33,19 +40,38 @@ import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-
-import java.util.Collection;
-import java.util.Deque;
-import java.util.Iterator;
-import java.util.Optional;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import static com.google.common.base.Preconditions.checkArgument;
+import static java.lang.String.format;
+import static java.util.regex.Pattern.quote;
+import static org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier.toInstanceIdentifier;
 
 /**
  * Represents utilities for properties node tree.
  */
 public final class MdsalPropertiesNodeUtils {
 
+    static final String COLON = ":";
+
+    static final String UNDERSCORE = "_";
+
+    static final String SLASH = "/";
+
+    static final String DOT_REGEX = "\\.";
+
+    private static final String INFO_MSG = "The %s formed is currently not" +
+            " valid";
+
+    private static final String EXC_MSG = "Unable to form a formatted path";
+
+    /**
+     * Logger for the Mdsal properties util class.
+     */
+    private static final Logger log = LoggerFactory.getLogger(
+            MdsalPropertiesNodeUtils.class);
+
     private MdsalPropertiesNodeUtils() {
     }
 
@@ -89,7 +115,7 @@ public final class MdsalPropertiesNodeUtils {
      * @param name name of the property
      * @return name of the property
      */
-    public static String resolveName(String name) {
+    static String resolveName(String name) {
         String localName = getListName(name);
         final int lastIndexOfColon = localName.lastIndexOf(":");
         if (lastIndexOfColon != -1) {
@@ -98,6 +124,24 @@ public final class MdsalPropertiesNodeUtils {
         return localName;
     }
 
+    /**
+     * Returns name of the property after pruning namespace and index if the
+     * property is multi instance by knowing the module name from namespace.
+     *
+     * @param ns   namespace
+     * @param name name of the node
+     * @return resolved name
+     */
+    static String resolveName(Namespace ns, String name) {
+        String localName = getListName(name);
+        String modName = ns.moduleName();
+        if ((localName.contains(COLON) || localName.contains(UNDERSCORE))
+                && localName.startsWith(modName)) {
+            localName = localName.substring(modName.length()+1);
+        }
+        return localName;
+    }
+
     /**
      * Adds current node to parent's augmentation map.
      *
@@ -203,31 +247,182 @@ public final class MdsalPropertiesNodeUtils {
     }
 
     /**
-     * Returns namespace.
+     * Returns the schema path holder with a formatted url and the instance
+     * identifier context from a given uri or the parameters from svc logic
+     * context.
      *
-     * @param childName name of the property
-     * @param ctx schema context
-     * @param parent parent property node
-     * @return namespace
+     * @param uri     unformatted uri or parameter
+     * @param context schema context
+     * @return schema path holder
+     */
+    public static SchemaPathHolder getProcessedPath(String uri,
+                                                    SchemaContext context) {
+
+        String uri1 = uri.replaceAll(UNDERSCORE, COLON);
+        try {
+            InstanceIdentifierContext<?> id = toInstanceIdentifier(
+                    uri1, context, null);
+            return new SchemaPathHolder(id, uri1);
+        } catch (IllegalArgumentException | RestconfDocumentedException
+                | NullPointerException e) {
+            return processNodesAndAppendPath(uri, context);
+        }
+    }
+
+    /**
+     * Processes the nodes in the given uri and finds instance identifier
+     * context till it reaches the last node in uri. If its not able to find
+     * schema for the path, it appends the suffix part and puts it back in
+     * the param list.
+     *
+     * @param uri     uri with underscore
+     * @param context schema context
+     * @return schema and path holder
+     */
+    private static SchemaPathHolder processNodesAndAppendPath(String uri,
+                                                              SchemaContext context) {
+
+        String actPath = "";
+        SchemaPathHolder id = new SchemaPathHolder(null, "");
+        String[] uriParts = uri.split(SLASH);
+        String sec = "";
+        if (uri.contains(UNDERSCORE)) {
+            sec = uri.substring(uriParts[0].length()+1);
+        }
+        for (int i = 0; i<uriParts.length; i++) {
+
+            try {
+                id = processIdentifier(uriParts[i], context, actPath);
+            } catch (IllegalArgumentException e) {
+                id.setUri(actPath+ uriParts[i] + sec);
+                return id;
+            }
+
+            actPath = actPath + id.getUri() + SLASH;
+            if (sec.startsWith(SLASH)) {
+                sec = sec.replaceFirst(SLASH, "");
+            }
+            if (i+1 < uriParts.length) {
+                sec = sec.replaceFirst(quote(uriParts[i + 1]), "");
+            }
+        }
+        id.setUri(actPath.substring(0,actPath.length() - 1));
+        return id;
+    }
+
+    /**
+     * Processes the schema and path holder for a given node in the path. It
+     * figures if the path is valid by replacing underscore in the node
+     * consecutively, till it finds the proper schema for the node.
+     *
+     * @param node    node in the path
+     * @param context schema context
+     * @param prefix  prefix for the node in the path
+     * @return schema and path holder
      */
-    public static Namespace getNamespace(String childName,
-                                         SchemaContext ctx,
-                                         PropertiesNode parent) {
-        int lastIndexOfColon = childName.lastIndexOf(":");
+    private static SchemaPathHolder processIdentifier(String node,
+                                                      SchemaContext context,
+                                                      String prefix) {
+
+        String[] values = node.split(UNDERSCORE);
+        String val = values[0];
+        StringBuilder firstHalf = new StringBuilder();
+        String secondHalf = "";
+        if (node.contains(UNDERSCORE)) {
+            secondHalf = node.substring(values[0].length()+1);
+        }
+        InstanceIdentifierContext<?> id;
+        for (int i = 0; i< values.length-1; i++) {
+            val = values[i];
+            val = firstHalf + val + COLON + secondHalf;
+            try {
+                id = toInstanceIdentifier(prefix + val, context, null);
+                return new SchemaPathHolder(id, val);
+            } catch (IllegalArgumentException | RestconfDocumentedException |
+                    NullPointerException e) {
+                log.info(format(INFO_MSG, val));
+            }
+            firstHalf.append(values[i]).append(UNDERSCORE);
+            secondHalf = secondHalf.replaceFirst(
+                    values[i + 1] + UNDERSCORE,"");
+        }
+        val = val.replace(COLON,UNDERSCORE);
+        try {
+            id = toInstanceIdentifier(prefix + val, context, null);
+            return new SchemaPathHolder(id, val);
+        } catch (IllegalArgumentException | RestconfDocumentedException |
+                NullPointerException e1) {
+            throw new IllegalArgumentException(EXC_MSG, e1);
+        }
+    }
+
+    /**
+     * Returns the namespace of the given node name. If the node name is
+     * separated by colon, the it splits with colon and forms the namespace.
+     * If the node name is formed with underscore, then it splits the node
+     * name consecutively to figure out the proper module name.
+     *
+     * @param childName node name
+     * @param ctx       schema context
+     * @param parent    parent properties node
+     * @param curSchema current schema
+     * @return namespace of the given node
+     */
+    static Namespace getNamespace(String childName, SchemaContext ctx,
+                                  PropertiesNode parent, SchemaNode curSchema) {
+
+        Namespace parentNs = parent.namespace();
+        Namespace ns = new Namespace(parentNs.moduleName(),
+                                     parentNs.moduleNs(), parentNs.revision());
+        int lastIndexOfColon = childName.lastIndexOf(COLON);
         if (lastIndexOfColon != -1) {
             String moduleName = childName.substring(0, lastIndexOfColon);
-            Iterator<Module> it = ctx.findModules(moduleName).iterator();
-            if (!it.hasNext()) {
-                // module is not present in context
-                return null;
+            childName = childName.substring(lastIndexOfColon+1);
+            Namespace ns1 = getNs(moduleName, ctx);
+            if (ns1 != null) {
+                ns = ns1;
             }
+        }
+
+        SchemaNode child = getChildSchemaNode(curSchema, childName, ns);
+
+        if (child == null && childName.contains(UNDERSCORE)) {
+            String[] children = childName.split(UNDERSCORE);
+            String second = childName.substring(children[0].length() + 1);
+            StringBuilder first = new StringBuilder();
+
+            for (int i =0; i< children.length; i++) {
+                String moduleName = first + children[i];
+                Namespace newNs = getNs(moduleName, ctx);
+                if (newNs != null) {
+                    return newNs;
+                }
+                first.append(children[i]).append(UNDERSCORE);
+                if (i + 1 < children.length) {
+                    second = second.replaceFirst(
+                            children[i + 1] + UNDERSCORE, "");
+                }
+            }
+            return ns;
+        }
+        return ns;
+    }
+
+    /**
+     * Returns the namespace by finding the given module in the schema context.
+     *
+     * @param modName module name
+     * @param ctx     schema context
+     * @return namespace of the given node name
+     */
+    private static Namespace getNs(String modName, SchemaContext ctx) {
+        Iterator<Module> it = ctx.findModules(modName).iterator();
+        if (it.hasNext()) {
             Module m = it.next();
-            return new Namespace(moduleName, m.getQNameModule().getNamespace(),
+            return new Namespace(modName, m.getQNameModule().getNamespace(),
                                  getRevision(m.getRevision()));
         }
-        Namespace parentNs = parent.namespace();
-        return new Namespace(parentNs.moduleName(), parentNs.moduleNs(),
-                             parentNs.revision());
+        return null;
     }
 
     /**
@@ -239,7 +434,7 @@ public final class MdsalPropertiesNodeUtils {
      * @return child schema node
      */
     public static SchemaNode getChildSchemaNode(SchemaNode curSchema,
-                                                     String name,
+                                                String name,
                                                 Namespace namespace) {
         if (namespace == null) {
             return null;