[ONOS-3884] Base Data model node and parser interface
Change-Id: I94caf7fbf26125126d0779c283076c05fc7cd8cf
diff --git a/src/main/java/org/onosproject/yangutils/datamodel/YangNode.java b/src/main/java/org/onosproject/yangutils/datamodel/YangNode.java
new file mode 100644
index 0000000..c34e8dc
--- /dev/null
+++ b/src/main/java/org/onosproject/yangutils/datamodel/YangNode.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2016 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.yangutils.datamodel;
+
+import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
+
+/**
+ * Base class of a node in data model tree.
+ */
+public abstract class YangNode {
+
+ /* Type of information maintained in node */
+ private YangNodeType nodeType;
+
+ /* Parent reference */
+ private YangNode parent;
+
+ /* First child reference */
+ private YangNode child;
+
+ /* Next sibling reference */
+ private YangNode nextSibling;
+
+ /* Previous sibling reference */
+ private YangNode previousSibling;
+
+ /**
+ * Default constructor is made private to ensure node type is always set.
+ */
+ @SuppressWarnings("unused")
+ private YangNode() {
+
+ }
+
+ /**
+ * Create a specific type of node.
+ *
+ * @param type of YANG node
+ */
+ protected YangNode(YangNodeType type) {
+ setNodeType(type);
+ }
+
+ /**
+ * Get the node type.
+ *
+ * @return node type
+ */
+ public YangNodeType getNodeType() {
+ return nodeType;
+ }
+
+ /**
+ * Set the node type.
+ *
+ * @param nodeType type of node
+ */
+ private void setNodeType(YangNodeType nodeType) {
+ this.nodeType = nodeType;
+ }
+
+ /**
+ * Get the parent of node.
+ *
+ * @return parent of node
+ */
+ public YangNode getParent() {
+ return parent;
+ }
+
+ /**
+ * Set the parent of node.
+ *
+ * @param parent node
+ */
+ public void setParent(YangNode parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * Get the first child of node.
+ *
+ * @return first child of node
+ */
+ public YangNode getChild() {
+ return child;
+ }
+
+ /**
+ * Set the first instance of a child node.
+ *
+ * @param child is only child to be set
+ */
+ public void setChild(YangNode child) {
+ this.child = child;
+ }
+
+ /**
+ * Get the next sibling of node.
+ *
+ * @return next sibling of node
+ */
+ public YangNode getNextSibling() {
+ return nextSibling;
+ }
+
+ /**
+ * Set the next sibling of node.
+ *
+ * @param sibling YANG node
+ */
+ public void setNextSibling(YangNode sibling) {
+ nextSibling = sibling;
+ }
+
+ /**
+ * Get the previous sibling.
+ *
+ * @return previous sibling node
+ */
+ public YangNode getPreviousSibling() {
+ return previousSibling;
+ }
+
+ /**
+ * Set the previous sibling.
+ *
+ * @param previousSibling points to predecessor sibling
+ */
+ public void setPreviousSibling(YangNode previousSibling) {
+ this.previousSibling = previousSibling;
+ }
+
+ /**
+ * Add a child node, the children sibling list will be sorted based on node
+ * type.
+ *
+ * @param newChild refers to a child to be added
+ * @throws DataModelException due to violation in data model rules
+ */
+ void addChild(YangNode newChild) throws DataModelException {
+ if (newChild.getNodeType() == null) {
+ throw new DataModelException("Abstract node cannot be inserted into a tree");
+ }
+
+ if (newChild.getParent() == null) {
+ newChild.setParent(this);
+ } else if (newChild.getParent() != this) {
+ throw new DataModelException("Node is already part of a tree");
+ }
+
+ if (newChild.getChild() != null) {
+ throw new DataModelException("Child to be added is not atomic, it already has a child");
+ }
+
+ if (newChild.getNextSibling() != null) {
+ throw new DataModelException("Child to be added is not atomic, it already has a next sibling");
+ }
+
+ if (newChild.getPreviousSibling() != null) {
+ throw new DataModelException("Child to be added is not atomic, it already has a previous sibling");
+ }
+
+ /* First child to be added */
+ if (getChild() == null) {
+ setChild(newChild);
+ return;
+ }
+
+ YangNode curNode;
+ curNode = getChild();
+
+ /* If the new node needs to be the first child */
+ if (newChild.getNodeType().ordinal() < curNode.getNodeType().ordinal()) {
+ newChild.setNextSibling(curNode);
+ curNode.setPreviousSibling(newChild);
+ setChild(newChild);
+ return;
+ }
+
+ /*
+ * Get the predecessor child of new child
+ */
+ while (curNode.getNextSibling() != null
+ && newChild.getNodeType().ordinal() >= curNode.getNextSibling().getNodeType().ordinal()) {
+ curNode = curNode.getNextSibling();
+ }
+
+ /* If the new node needs to be the last child */
+ if (curNode.getNextSibling() == null) {
+ curNode.setNextSibling(newChild);
+ newChild.setPreviousSibling(curNode);
+ return;
+ }
+
+ /* Insert the new node in child node list sorted by type */
+ newChild.setNextSibling(curNode.getNextSibling());
+ newChild.setPreviousSibling(curNode);
+ curNode.getNextSibling().setPreviousSibling(newChild);
+ curNode.setNextSibling(newChild);
+ return;
+ }
+}