Implementation for properties node serializer 31/61031/1
authorVidyashree Rama <vidyashree.rama@huawei.com>
Fri, 17 Aug 2018 06:51:05 +0000 (12:21 +0530)
committerVidyashree Rama <vidyashree.rama@huawei.com>
Fri, 17 Aug 2018 06:51:05 +0000 (12:21 +0530)
properties node serializer implementation

Issue-ID: CCSDK-378

Change-Id: I4eeecb45227e4152d9ff81551fd98efdd1371f84
Signed-off-by: Vidyashree Rama <vidyashree.rama@huawei.com>
restconf-client/provider/pom.xml
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/InnerNode.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderNode.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderNode.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeSerializer.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeUtils.java [new file with mode: 0644]
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/RootNode.java

index 5a74d8f..46e0000 100755 (executable)
             <artifactId>properties-node-provider</artifactId>
             <version>0.3.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-impl</artifactId>
+            <version>2.0.3</version>
+        </dependency>
+
     </dependencies>
 </project>
index 21f0b7c..063c3d0 100644 (file)
 package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
 
 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 
 import java.util.HashMap;
 import java.util.Map;
 
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.addToAugmentations;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.createNode;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getAugmentationNode;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getUri;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.isNamespaceAsParent;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.resolveName;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_HOLDER_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_HOLDER_NODE;
+import static org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils.findCorrespondingAugment;
+
 /**
  * Abstraction of an entity that represents an inner node to properties data
  * tree.
@@ -62,8 +74,31 @@ public abstract class InnerNode<T extends NodeChild> extends PropertiesNode {
     public PropertiesNode addChild(String name, Namespace namespace,
                                    NodeType type,
                                    Object appInfo) throws SvcLogicException {
-        // TODO : to be implemented
-        return null;
+        PropertiesNode node = ((PropertiesNode) children.get(name));
+        if (node != null) {
+            return node;
+        }
+
+        // get augment schema, if it is augmented node
+        AugmentationSchemaNode augSchema = null;
+        if (((DataSchemaNode) appInfo).isAugmenting()) {
+            augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()), ((DataSchemaNode) appInfo));
+            node = getAugmentationNode(augSchema, this, name);
+        }
+
+        // create node based on type
+        if (node == null) {
+            String uri = getUri(this, name, namespace);
+            node = createNode(name, namespace, uri, this, appInfo, type);
+        }
+
+        // If namespace is not same as parent then it is augmented node
+        if (augSchema != null && !isNamespaceAsParent(this, node)) {
+            addToAugmentations(augSchema, this, node);
+        } else {
+            children.put(name, ((T) node));
+        }
+        return node;
     }
 
     @Override
@@ -71,16 +106,65 @@ public abstract class InnerNode<T extends NodeChild> extends PropertiesNode {
                                    NodeType type, String value,
                                    Namespace valuens,
                                    Object appInfo) throws SvcLogicException {
-        // TODO : to be implemented
-        return null;
+        LeafNode node = ((LeafNode) children.get(name));
+        if (node != null) {
+            return  node;
+        }
+
+        AugmentationSchemaNode augSchema = null;
+        if (((DataSchemaNode) appInfo).isAugmenting()) {
+            augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+                                                 ((DataSchemaNode) appInfo));
+        }
+
+        String uri = getUri(this, name, namespace);
+        node = new LeafNode(name, namespace, uri, this,
+                            appInfo, type, value);
+
+        if (augSchema != null && !isNamespaceAsParent(this, node)) {
+            addToAugmentations(augSchema, this, node);
+        } else {
+            children.put(name, ((T) node));
+        }
+        return node;
     }
 
     @Override
     public PropertiesNode addChild(String index, String name,
                                    Namespace namespace, NodeType type,
                                    Object appInfo) throws SvcLogicException {
-        // TODO : to be implemented
-        return null;
+        String localname = resolveName(name);
+        PropertiesNode node = ((PropertiesNode) children.get(localname));
+
+        if (node == null) {
+            AugmentationSchemaNode augSchema = null;
+            if (((DataSchemaNode) appInfo).isAugmenting()) {
+                augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+                                                     ((DataSchemaNode) appInfo));
+                node = getAugmentationNode(augSchema, this, localname);
+            }
+
+            if (node == null) {
+                String uri = getUri(this, name, namespace);
+                node = new ListHolderNode(localname, namespace, uri,
+                                          this, appInfo, MULTI_INSTANCE_HOLDER_NODE);
+            }
+
+            if (augSchema != null && !isNamespaceAsParent(this, node)) {
+                addToAugmentations(augSchema, this, node);
+            } else {
+                children.put(localname, ((T) node));
+            }
+
+            node = node.addChild(index, localname, namespace, type, appInfo);
+        } else if (node instanceof ListHolderNode) {
+            ListHolderChild child = ((ListHolderNode) node).child(index);
+            node = (child != null ? ((MultiInstanceNode) child) :
+                    node.addChild(index, localname, namespace, type, appInfo));
+        } else {
+            throw new SvcLogicException("Duplicate node exist with same node");
+        }
+        return node;
     }
 
     @Override
@@ -88,7 +172,40 @@ public abstract class InnerNode<T extends NodeChild> extends PropertiesNode {
                                    Namespace namespace, NodeType type,
                                    String value, Namespace valueNs,
                                    Object appInfo) throws SvcLogicException {
-        // TODO : to be implemented
-        return null;
+        String localName = resolveName(name);
+        PropertiesNode node = ((PropertiesNode) children.get(localName));
+
+        if (node == null) {
+
+            AugmentationSchemaNode augSchema = null;
+            if (((DataSchemaNode) appInfo).isAugmenting()) {
+                augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+                                                     ((DataSchemaNode) appInfo));
+                node = getAugmentationNode(augSchema, this, localName);
+            }
+
+            if (node == null) {
+                String uri = getUri(this, name, namespace);
+                node = new LeafListHolderNode(localName, namespace, uri, this,
+                                              appInfo, MULTI_INSTANCE_LEAF_HOLDER_NODE);
+            }
+
+            if (augSchema != null && !isNamespaceAsParent(this, node)) {
+                addToAugmentations(augSchema, this, node);
+            } else {
+                children.put(localName, ((T) node));
+            }
+
+            node = node.addChild(index, localName, namespace, type, value, null, appInfo);
+        } else if (node instanceof LeafListHolderNode) {
+            LeafNode child = ((LeafNode) ((HolderNode) node).child(index));
+            node = (child != null ? child : node.addChild(index, localName,
+                                                          namespace, type,
+                                                          value, null,
+                                                          appInfo));
+        } else {
+            throw new SvcLogicException("Duplicate node exist with same node");
+        }
+        return node;
     }
 }
index aa10e33..94892dc 100644 (file)
@@ -75,7 +75,14 @@ public class LeafListHolderNode extends HolderNode<LeafListHolderChild> implemen
                                    Namespace namespace, NodeType type,
                                    String value, Namespace valueNs,
                                    Object appInfo) throws SvcLogicException {
-        // TODO : to be implemented
-        return null;
+        LeafNode node = ((LeafNode) children().get(index));
+        if (index == null) {
+            index = String.valueOf(children().size());
+        }
+        String uri = this.uri() + "[" + index + "]";
+        node = (node != null) ? node : new LeafNode(name, namespace, uri,
+                                                    this, appInfo, type, value);
+        children().put(index, node);
+        return node;
     }
 }
index 9d1168b..ba9da54 100644 (file)
@@ -52,8 +52,15 @@ public class ListHolderNode extends HolderNode<ListHolderChild> implements DataN
     public PropertiesNode addChild(String index, String name,
                                    Namespace namespace, NodeType type,
                                    Object appInfo) throws SvcLogicException {
-        // TODO : to be implemented
-        return null;
+        MultiInstanceNode node = ((MultiInstanceNode) children().get(index));
+        if (index == null) {
+            index = String.valueOf(children().size());
+        }
+        String uri = this.uri() + "[" + index + "]";
+        node = (node != null) ? node : new MultiInstanceNode(name, namespace, uri,
+                                                             this, appInfo, type);
+        children().put(index, node);
+        return node;
     }
 
     @Override
index 05e1ac1..405e241 100644 (file)
 
 package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
 
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+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 org.slf4j.Logger;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 
 import java.util.Map;
 
-import static org.slf4j.LoggerFactory.getLogger;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getChildSchemaNode;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getIndex;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getListName;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getNamespace;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getNodeType;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getRevision;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.resolveName;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_NODE;
 
 /**
  * Representation of mdsal based properties node serializer implementation.
@@ -35,7 +47,6 @@ public class MdsalPropertiesNodeSerializer extends PropertiesNodeSerializer<Sche
 
     private SchemaNode curSchema;
     private PropertiesNode node;
-    private static final Logger LOG = getLogger(MdsalPropertiesNodeSerializer.class);
 
     /**
      * Creates the properties node serializer.
@@ -44,13 +55,33 @@ public class MdsalPropertiesNodeSerializer extends PropertiesNodeSerializer<Sche
      * @param schemaCtx  schema context
      * @param uri        URL of the request
      */
-    public MdsalPropertiesNodeSerializer(SchemaNode schemaNode, SchemaContext schemaCtx, String uri) {
+    public MdsalPropertiesNodeSerializer(SchemaNode schemaNode,
+                                         SchemaContext schemaCtx, String uri) {
         super(schemaNode, schemaCtx, uri);
     }
 
     @Override
-    public PropertiesNode encode(Map<String, String> paramMap) {
-        return null;
+    public PropertiesNode encode(Map<String, String> paramMap) throws SvcLogicException {
+        curSchema = schemaNode();
+        String nodeInUri[] = uri().split("\\/");
+        String lastNodeName = nodeInUri[nodeInUri.length - 1];
+        String rootUri = uri().replaceAll("\\/", "\\.");
+        node = createRootNode(lastNodeName, rootUri);
+
+        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
+            String[] names = entry.getKey().split("\\.");
+            for (int i = 0; i < names.length; i++) {
+                if (i < nodeInUri.length) {
+                    if (!(nodeInUri[i].equals(names[i]))) {
+                        break;
+                    }
+                } else {
+                    createPropertyNode(i, names.length, names[i],
+                                       entry.getValue());
+                }
+            }
+        }
+        return node;
     }
 
     @Override
@@ -58,4 +89,45 @@ public class MdsalPropertiesNodeSerializer extends PropertiesNodeSerializer<Sche
         return null;
     }
 
+    private RootNode createRootNode(String lastNodeName, String rootUri) {
+        Module m = SchemaContextUtil.findParentModule(schemaCtx(), curSchema);
+        Namespace ns = new Namespace(m.getName(), m.getNamespace(),
+                                     getRevision(m.getRevision()));
+        return new RootNode(lastNodeName, ns, schemaNode(), rootUri);
+    }
+
+    private void createPropertyNode(int index, int length, String name,
+                                    String value) throws SvcLogicException {
+        String localName = resolveName(name);
+        Namespace ns = getNamespace(getListName(name), schemaCtx(), node);
+        SchemaNode schema = getChildSchemaNode(curSchema, localName, ns);
+        if (schema == null) {
+            return;
+        }
+
+        switch (getNodeType(index, length, name)) {
+            case SINGLE_INSTANCE_NODE:
+                node = node.addChild(localName, ns,
+                                     SINGLE_INSTANCE_NODE, schema);
+                curSchema = schema;
+                break;
+            case MULTI_INSTANCE_NODE:
+                node = node.addChild(getIndex(name), localName, ns,
+                                     MULTI_INSTANCE_NODE, schema);
+                curSchema = schema;
+                break;
+            case SINGLE_INSTANCE_LEAF_NODE:
+                node = node.addChild(localName, ns, SINGLE_INSTANCE_LEAF_NODE,
+                                     value, null, schema);
+                node = node.endNode();
+                curSchema = ((SchemaNode) node.appInfo());
+                break;
+            case MULTI_INSTANCE_LEAF_NODE:
+                node = node.addChild(getIndex(name), localName, ns,
+                                     MULTI_INSTANCE_LEAF_NODE, value, null, schema);
+                node = node.endNode();
+                curSchema = ((SchemaNode) node.appInfo());
+                break;
+        }
+    }
 }
diff --git a/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeUtils.java b/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeUtils.java
new file mode 100644 (file)
index 0000000..fb57d63
--- /dev/null
@@ -0,0 +1,297 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.Revision;
+import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
+import org.opendaylight.yangtools.yang.data.util.ParserStreamUtils;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+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;
+
+/**
+ * Represents utilities for properties node tree.
+ */
+public final class MdsalPropertiesNodeUtils {
+
+    private MdsalPropertiesNodeUtils() {
+    }
+
+    /**
+     * Returns the index from multi instance property name.
+     *
+     * @param name name of the property
+     * @return index from multi instance property name
+     */
+    public static String getIndex(String name) {
+        return name.substring(name.indexOf("[") + 1,
+                              name.indexOf("]"));
+    }
+
+    /**
+     * Returns the multi instance property name.
+     *
+     * @param name name of the property
+     * @return the multi instance property name
+     */
+    public static String getListName(String name) {
+        String[] s = name.split("\\[");
+        return s[0];
+    }
+
+    /**
+     * Returns true if property is multi instance.
+     *
+     * @param name name of the property
+     * @return true if property is multi instance
+     */
+    public static boolean isListEntry(String name) {
+        String s[] = name.split("\\[");
+        return s.length > 1;
+    }
+
+    /**
+     * Returns name of the property after pruning namespace and
+     * index if the property is multi instance.
+     *
+     * @param name name of the property
+     * @return name of the property
+     */
+    public static String resolveName(String name) {
+        String localName = getListName(name);
+        final int lastIndexOfColon = localName.lastIndexOf(":");
+        if (lastIndexOfColon != -1) {
+            localName = localName.substring(lastIndexOfColon + 1);
+        }
+        return localName;
+    }
+
+    /**
+     * Adds current node to parent's augmentation map.
+     *
+     * @param augSchema augment schema
+     * @param parent parent property node
+     * @param curNode current property node
+     */
+    public static void addToAugmentations(AugmentationSchemaNode augSchema,
+                                          PropertiesNode parent,
+                                          PropertiesNode curNode) {
+        Collection<PropertiesNode> childsFromAugmentation = parent
+                .augmentations().get(augSchema);
+        if (!childsFromAugmentation.isEmpty()) {
+            for (PropertiesNode pNode : childsFromAugmentation) {
+                if (pNode.name().equals(curNode.name())) {
+                    return;
+                }
+            }
+        }
+        parent.augmentations().put(augSchema, curNode);
+    }
+
+
+    /**
+     * Returns augmented properties node if it is already
+     * added in properties tree.
+     *
+     * @param augSchema augmented schema node
+     * @param parent parent properties node
+     * @param name name of the properties
+     * @return augmented properties node if it is already added
+     */
+    public static PropertiesNode getAugmentationNode(
+            AugmentationSchemaNode augSchema,
+            PropertiesNode parent, String name) {
+        if (augSchema != null) {
+            Collection<PropertiesNode> childsFromAugmentation = parent
+                    .augmentations().get(augSchema);
+            if (!childsFromAugmentation.isEmpty()) {
+                for (PropertiesNode pNode : childsFromAugmentation) {
+                    if (pNode.name().equals(name)) {
+                        return pNode;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Creates uri with specified name and namespace.
+     *
+     * @param parent parent properties node
+     * @param name name of the node
+     * @param ns namespace of the node
+     * @return uri with specified name and namespace
+     */
+    public static String getUri(PropertiesNode parent, String name,
+                                Namespace ns) {
+        String uri = name;
+        if (!(parent.namespace().moduleNs().equals(ns.moduleNs()))) {
+            uri = ns.moduleName() + ":" + name;
+        }
+        return parent.uri() + "." + uri;
+    }
+
+    /**
+     * Creates new properties with specified parameters.
+     *
+     * @param name name of the properties node
+     * @param namespace namespace of the properties node
+     * @param uri uri of the properties node
+     * @param parent parent node
+     * @param appInfo application info
+     * @param type node type
+     * @return new properties node
+     */
+    public static PropertiesNode createNode(String name, Namespace namespace,
+                                            String uri, PropertiesNode parent,
+                                            Object appInfo, NodeType type) {
+        switch (type) {
+            case SINGLE_INSTANCE_NODE:
+                return new SingleInstanceNode(name, namespace, uri, parent, appInfo, type);
+            case MULTI_INSTANCE_HOLDER_NODE:
+                return new ListHolderNode(name, namespace, uri, parent, appInfo, type);
+            case MULTI_INSTANCE_LEAF_HOLDER_NODE:
+                return new LeafListHolderNode(name, namespace, uri, parent, appInfo, type);
+            default:
+                throw new RuntimeException("Invalid node type");
+        }
+    }
+
+    /**
+     * Returns true if namespace is same as parent's namespace.
+     *
+     * @param parent parent property node
+     * @param curNode current property node
+     * @return true if namespace is same as parent namespace
+     */
+    public static boolean isNamespaceAsParent(PropertiesNode parent,
+                                              PropertiesNode curNode) {
+        return parent.namespace().moduleNs().equals(curNode.namespace().moduleNs());
+    }
+
+    /**
+     * Returns namespace.
+     *
+     * @param childName name of the property
+     * @param ctx schema context
+     * @param parent parent property node
+     * @return namespace
+     */
+    public static Namespace getNamespace(String childName,
+                                         SchemaContext ctx,
+                                         PropertiesNode parent) {
+        int lastIndexOfColon = childName.lastIndexOf(":");
+        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;
+            }
+            Module m = it.next();
+            return new Namespace(moduleName, m.getQNameModule().getNamespace(),
+                                 getRevision(m.getRevision()));
+        }
+        Namespace parentNs = parent.namespace();
+        return new Namespace(parentNs.moduleName(), parentNs.moduleNs(),
+                             parentNs.revision());
+    }
+
+    /**
+     * Returns child schema node.
+     *
+     * @param curSchema current schema node
+     * @param name name of the property
+     * @param namespace namespace of the property
+     * @return child schema node
+     */
+    public static SchemaNode getChildSchemaNode(SchemaNode curSchema,
+                                                     String name,
+                                                Namespace namespace) {
+        if (namespace == null) {
+            return null;
+        }
+
+        QName qname =  QName.create(namespace.moduleNs(),
+                                    Revision.of(namespace.revision()), name);
+
+        // YANG RPC will not be instance of DataSchemaNode
+        if (curSchema instanceof DataSchemaNode) {
+            Deque<DataSchemaNode> schemaNodeDeque = ParserStreamUtils.
+                    findSchemaNodeByNameAndNamespace(((DataSchemaNode)
+                            curSchema), name, namespace.moduleNs());
+            if (schemaNodeDeque.isEmpty()) {
+                // could not find schema node
+                return null;
+            }
+
+            DataSchemaNode schemaNode = schemaNodeDeque.pop();
+            if (schemaNodeDeque.isEmpty()){
+                // Simple node
+                return schemaNode;
+            }
+
+            // node is child of Choice/case
+            return SchemaUtils.findSchemaForChild(((ChoiceSchemaNode) schemaNode),
+                                                  qname);
+        } else {
+            return SchemaUtils.findDataChildSchemaByQName(curSchema, qname);
+        }
+    }
+
+    /**
+     * Returns the property node type.
+     *
+     * @param index current index
+     * @param length length of the properties
+     * @param name name of the property
+     * @return the property node type
+     */
+    public static NodeType getNodeType(int index, int length, String name) {
+        if (index == length-1) {
+            return (isListEntry(name) ? NodeType.MULTI_INSTANCE_LEAF_NODE :
+                    NodeType.SINGLE_INSTANCE_LEAF_NODE);
+        } else {
+            return (isListEntry(name) ? NodeType.MULTI_INSTANCE_NODE :
+                    NodeType.SINGLE_INSTANCE_NODE);
+        }
+    }
+
+    /**
+     * Returns revision in string.
+     *
+     * @param r YANG revision
+     * @return revision in string
+     */
+    public static String getRevision(Optional<Revision> r) {
+        return (r.isPresent()) ? r.get().toString() : null;
+    }
+}
index 5cb8e4c..0159683 100644 (file)
 package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
 
 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 
 import java.util.HashMap;
 import java.util.Map;
 
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.addToAugmentations;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.createNode;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getAugmentationNode;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getUri;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.isNamespaceAsParent;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.resolveName;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_HOLDER_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_HOLDER_NODE;
+import static org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils.findCorrespondingAugment;
+
 /**
  * Abstraction of node representing properties data tree.
  */
@@ -59,8 +71,32 @@ public class RootNode<T extends NodeChild> extends PropertiesNode {
     public PropertiesNode addChild(String name, Namespace namespace,
                                    NodeType type,
                                    Object appInfo) throws SvcLogicException {
-        // TODO : to be implemented
-        return null;
+        PropertiesNode node = ((PropertiesNode) children.get(name));
+        if (node != null) {
+            return node;
+        }
+
+        // get augment schema, if it is augmented node
+        AugmentationSchemaNode augSchema = null;
+        if (((DataSchemaNode) appInfo).isAugmenting()) {
+            augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+                                                 ((DataSchemaNode) appInfo));
+            node = getAugmentationNode(augSchema, this, name);
+        }
+
+        // create node based on type, this api will be invoked only for these three types
+        if (node == null) {
+            String uri = getUri(this, name, namespace);
+            node = createNode(name, namespace, uri, this, appInfo, type);
+        }
+
+        // If namespace is not same as parent then it is augmented node
+        if (augSchema != null && !isNamespaceAsParent(this, node)) {
+            addToAugmentations(augSchema, this, node);
+        } else {
+            children.put(name, ((T) node));
+        }
+        return node;
     }
 
     @Override
@@ -68,16 +104,63 @@ public class RootNode<T extends NodeChild> extends PropertiesNode {
                                    NodeType type, String value,
                                    Namespace valuens,
                                    Object appInfo) throws SvcLogicException {
-        // TODO : to be implemented
-        return null;
+        LeafNode node = ((LeafNode) children.get(name));
+        if (node != null) {
+            return  node;
+        }
+
+        AugmentationSchemaNode augSchema = null;
+        if (((DataSchemaNode) appInfo).isAugmenting()) {
+            augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+                                                 ((DataSchemaNode) appInfo));
+        }
+
+        String uri = getUri(this, name, namespace);
+        node = new LeafNode(name, namespace, uri, this,
+                            appInfo, type, value);
+
+        if (augSchema != null && !isNamespaceAsParent(this, node)) {
+            addToAugmentations(augSchema, this, node);
+        } else {
+            children.put(name, ((T) node));
+        }
+        return node;
     }
 
     @Override
     public PropertiesNode addChild(String index, String name,
                                    Namespace namespace, NodeType type,
                                    Object appInfo) throws SvcLogicException {
-        // TODO : to be implemented
-        return null;
+        String localname = resolveName(name);
+        PropertiesNode node = ((PropertiesNode) children.get(localname));
+        if (node == null) {
+            String uri = getUri(this, name, namespace);
+            AugmentationSchemaNode augSchema = null;
+            if (((DataSchemaNode) appInfo).isAugmenting()) {
+                augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+                                                     ((DataSchemaNode) appInfo));
+                node = getAugmentationNode(augSchema, this, localname);
+            }
+
+            if (node == null) {
+                node = new ListHolderNode(localname, namespace, uri,
+                                          this, appInfo, MULTI_INSTANCE_HOLDER_NODE);
+            }
+
+            if (augSchema != null && !isNamespaceAsParent(this, node)) {
+                addToAugmentations(augSchema, this, node);
+            } else {
+                children.put(localname, ((T) node));
+            }
+            node = node.addChild(index, localname, namespace, type, appInfo);
+        } else if (node instanceof ListHolderNode) {
+            ListHolderChild child = ((ListHolderNode) node).child(index);
+            node = (child != null ? ((MultiInstanceNode) child) :
+                    node.addChild(index, localname, namespace, type, appInfo));
+        } else {
+            throw new SvcLogicException("Duplicate node exist with same node");
+        }
+        return node;
     }
 
     @Override
@@ -85,7 +168,37 @@ public class RootNode<T extends NodeChild> extends PropertiesNode {
                                    Namespace namespace, NodeType type,
                                    String value, Namespace valueNs,
                                    Object appInfo) throws SvcLogicException {
-        // TODO : to be implemented
-        return null;
+        String localName = resolveName(name);
+        PropertiesNode node = ((PropertiesNode) children.get(localName));
+        if (node == null) {
+            String uri = getUri(this, name, namespace);
+            AugmentationSchemaNode augSchema = null;
+            if (((DataSchemaNode) appInfo).isAugmenting()) {
+                augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+                                                     ((DataSchemaNode) appInfo));
+                node = getAugmentationNode(augSchema, this, localName);
+            }
+
+            if (node == null) {
+                node = new LeafListHolderNode(localName, namespace, uri, this,
+                                              appInfo, MULTI_INSTANCE_LEAF_HOLDER_NODE);
+            }
+
+            if (augSchema != null && !isNamespaceAsParent(this, node)) {
+                addToAugmentations(augSchema, this, node);
+            } else {
+                children.put(localName, ((T) node));
+            }
+            node = node.addChild(index, localName, namespace, type, value, null, appInfo);
+        } else if (node instanceof LeafListHolderNode) {
+            LeafNode child = ((LeafNode) ((HolderNode) node).child(index));
+            node = (child != null ? child : node.addChild(index, localName,
+                                                          namespace, type,
+                                                          value, null,
+                                                          appInfo));
+        } else {
+            throw new SvcLogicException("Duplicate node exist with same node");
+        }
+        return node;
     }
 }