[ONOS-5076] YANG data tree Builder

Change-Id: I25160b651c26e614d29d7fad85e63f77a262d77c
diff --git a/apps/yms/app/src/main/java/org/onosproject/yms/app/ydt/YdtNodeFactory.java b/apps/yms/app/src/main/java/org/onosproject/yms/app/ydt/YdtNodeFactory.java
new file mode 100644
index 0000000..43680da
--- /dev/null
+++ b/apps/yms/app/src/main/java/org/onosproject/yms/app/ydt/YdtNodeFactory.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.
+ */
+
+package org.onosproject.yms.app.ydt;
+
+import org.onosproject.yangutils.datamodel.YangSchemaNode;
+import org.onosproject.yangutils.datamodel.YangSchemaNodeIdentifier;
+import org.onosproject.yangutils.datamodel.YangSchemaNodeType;
+import org.onosproject.yms.app.ydt.exceptions.YdtException;
+import org.onosproject.yms.ydt.YdtContextOperationType;
+
+import static org.onosproject.yangutils.datamodel.YangSchemaNodeType.YANG_MULTI_INSTANCE_LEAF_NODE;
+import static org.onosproject.yangutils.datamodel.YangSchemaNodeType.YANG_MULTI_INSTANCE_NODE;
+import static org.onosproject.yangutils.datamodel.YangSchemaNodeType.YANG_SINGLE_INSTANCE_LEAF_NODE;
+import static org.onosproject.yangutils.datamodel.YangSchemaNodeType.YANG_SINGLE_INSTANCE_NODE;
+import static org.onosproject.yms.app.ydt.YdtAppNodeOperationType.DELETE_ONLY;
+import static org.onosproject.yms.app.ydt.YdtAppNodeOperationType.OTHER_EDIT;
+import static org.onosproject.yms.app.ydt.YdtConstants.errorMsg;
+
+/**
+ * Represents an YANG node factory to create different types of YANG data tree
+ * node.
+ */
+final class YdtNodeFactory {
+
+    // ydt formatted error string
+    private static final String FMT_NOT_EXIST =
+            "Schema node with name %s doesn't exist.";
+
+    // No instantiation
+    private YdtNodeFactory() {
+    }
+
+    /**
+     * Returns a YANG data tree node for a given name, set of values and
+     * instance type.
+     *
+     * @param id          dataNodeIdentifier of data tree node
+     * @param schemaNode  data node as per YANG schema metadata
+     * @param cardinality requested cardinality of node
+     * @param callType    identify the call type
+     * @return YANG data tree node
+     */
+    protected static YdtNode getNode(YangSchemaNodeIdentifier id,
+                                     YangSchemaNode schemaNode,
+                                     RequestedCardinality cardinality,
+                                     RequestedCallType callType) {
+
+        YdtNode newNode = null;
+        YangSchemaNodeType nodeType = schemaNode.getYangSchemaNodeType();
+
+        switch (cardinality) {
+
+            case UNKNOWN:
+                /*
+                 * if requested node type is UNKNOWN, check corresponding
+                 * yang data node type and create respective type node.
+                 */
+                newNode = getYangSchemaNodeTypeSpecificContext(id, nodeType,
+                                                               callType);
+                break;
+
+            /*
+             * if requested node type is specified and it exist as node of some
+             * other type in data model then throw exception
+             */
+            case SINGLE_INSTANCE:
+                validateNodeType(id, nodeType, YANG_SINGLE_INSTANCE_NODE);
+                newNode = new YdtSingleInstanceNode(id);
+                break;
+
+            case MULTI_INSTANCE:
+
+                validateNodeType(id, nodeType, YANG_MULTI_INSTANCE_NODE);
+                newNode = new YdtMultiInstanceNode(id);
+                break;
+
+            case SINGLE_INSTANCE_LEAF:
+
+                validateNodeType(id, nodeType, YANG_SINGLE_INSTANCE_LEAF_NODE);
+                newNode = new YdtSingleInstanceLeafNode(id);
+                break;
+
+            case MULTI_INSTANCE_LEAF:
+
+                validateNodeType(id, nodeType, YANG_MULTI_INSTANCE_LEAF_NODE);
+                newNode = new YdtMultiInstanceLeafNode(id);
+                break;
+
+            default:
+                throwNotExistError(id);
+        }
+
+        // set reference of yang data node in the requested node.
+        newNode.setYangSchemaNode(schemaNode);
+
+        return newNode;
+    }
+
+    /**
+     * Validates the requested ydt node type against the schema node type,
+     * if it is not equal then it will throw warning.
+     *
+     * @param id            dataNodeIdentifier of data tree node
+     * @param nodeType      actual node type
+     * @param requestedType user requested node type
+     */
+    private static void validateNodeType(YangSchemaNodeIdentifier id,
+                                         YangSchemaNodeType nodeType,
+                                         YangSchemaNodeType requestedType) {
+        if (nodeType != requestedType) {
+            throwNotExistError(id);
+        }
+    }
+
+    /**
+     * Creates Yang data tree node of YangSchemaNode type specific for
+     * requestedCardinality of type UNKNOWN and returns the same.
+     *
+     * @param id       node identifier of data tree node
+     * @param nodeType schema node type as per YANG schema metadata
+     * @param callType identify the call type
+     * @return YANG data tree node
+     */
+    private static YdtNode getYangSchemaNodeTypeSpecificContext(
+            YangSchemaNodeIdentifier id,
+            YangSchemaNodeType nodeType,
+            RequestedCallType callType) {
+        switch (callType) {
+            case LEAF:
+                switch (nodeType) {
+
+                    case YANG_SINGLE_INSTANCE_LEAF_NODE:
+                        return new YdtSingleInstanceLeafNode(id);
+
+                    case YANG_MULTI_INSTANCE_LEAF_NODE:
+                        return new YdtMultiInstanceLeafNode(id);
+
+                    default:
+                        throwNotExistError(id);
+                }
+
+            case OTHER:
+                switch (nodeType) {
+
+                    case YANG_SINGLE_INSTANCE_NODE:
+                        return new YdtSingleInstanceNode(id);
+
+                    case YANG_MULTI_INSTANCE_NODE:
+                        return new YdtMultiInstanceNode(id);
+
+                    default:
+                        throwNotExistError(id);
+                }
+
+            case MULTI_INSTANCE:
+                switch (nodeType) {
+
+                    case YANG_MULTI_INSTANCE_LEAF_NODE:
+                        return new YdtMultiInstanceLeafNode(id);
+
+                    case YANG_MULTI_INSTANCE_NODE:
+                        return new YdtMultiInstanceNode(id);
+
+                    default:
+                        throwNotExistError(id);
+                }
+
+            default:
+                throwNotExistError(id);
+        }
+
+        return null;
+    }
+
+    /**
+     * Create Yang data tree node of YangSchemaNode type specific and
+     * returns the same.
+     *
+     * @param id       node identifier of data tree node
+     * @param nodeType schema node type as per YANG schema metadata
+     * @return YANG data tree node
+     */
+    protected static YdtNode getYangSchemaNodeTypeSpecificContext(
+            YangSchemaNodeIdentifier id,
+            YangSchemaNodeType nodeType) {
+
+        switch (nodeType) {
+
+            case YANG_SINGLE_INSTANCE_LEAF_NODE:
+                return new YdtSingleInstanceLeafNode(id);
+
+            case YANG_MULTI_INSTANCE_LEAF_NODE:
+                return new YdtMultiInstanceLeafNode(id);
+
+            case YANG_SINGLE_INSTANCE_NODE:
+                return new YdtSingleInstanceNode(id);
+
+            case YANG_MULTI_INSTANCE_NODE:
+                return new YdtMultiInstanceNode(id);
+
+            default:
+                throwNotExistError(id);
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the app tree operation type with the help of YdtOperation type.
+     *
+     * @param opType ydt operation type
+     * @return app tree operation type
+     */
+    protected static YdtAppNodeOperationType getAppOpTypeFromYdtOpType(
+            YdtContextOperationType opType) {
+        // Get the app tree operation type.
+        switch (opType) {
+            case CREATE:
+            case MERGE:
+            case REPLACE:
+                return OTHER_EDIT;
+
+            case DELETE:
+            case REMOVE:
+                return DELETE_ONLY;
+
+            default:
+                return null;
+            //TODO handle the default data type.
+        }
+    }
+
+    /**
+     * Throws exception for requested ydt node by preparing error message with
+     * given node identifier.
+     *
+     * @param id node identifier
+     */
+    private static void throwNotExistError(YangSchemaNodeIdentifier id) {
+        throw new YdtException(errorMsg(FMT_NOT_EXIST, id.getName()));
+    }
+}