YANG uses Intra file linking
Change-Id: I45936bee910ba4c81805f59daf2702bea5e60d08
diff --git a/src/main/java/org/onosproject/yangutils/datamodel/YangNode.java b/src/main/java/org/onosproject/yangutils/datamodel/YangNode.java
index beb8aa6..0413e65 100644
--- a/src/main/java/org/onosproject/yangutils/datamodel/YangNode.java
+++ b/src/main/java/org/onosproject/yangutils/datamodel/YangNode.java
@@ -16,11 +16,17 @@
package org.onosproject.yangutils.datamodel;
import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
+import org.onosproject.yangutils.translator.tojava.TraversalType;
+
+import static org.onosproject.yangutils.translator.tojava.TraversalType.CHILD;
+import static org.onosproject.yangutils.translator.tojava.TraversalType.PARENT;
+import static org.onosproject.yangutils.translator.tojava.TraversalType.SIBILING;
/**
* Represents base class of a node in data model tree.
*/
-public abstract class YangNode {
+public abstract class YangNode
+ implements Cloneable {
/**
* Type of node.
@@ -146,7 +152,7 @@
*
* @param sibling YANG node
*/
- public void setNextSibling(YangNode sibling) {
+ private void setNextSibling(YangNode sibling) {
nextSibling = sibling;
}
@@ -164,7 +170,7 @@
*
* @param previousSibling points to predecessor sibling
*/
- public void setPreviousSibling(YangNode previousSibling) {
+ private void setPreviousSibling(YangNode previousSibling) {
this.previousSibling = previousSibling;
}
@@ -175,7 +181,8 @@
* @param newChild refers to a child to be added
* @throws DataModelException due to violation in data model rules
*/
- public void addChild(YangNode newChild) throws DataModelException {
+ public void addChild(YangNode newChild)
+ throws DataModelException {
if (newChild.getNodeType() == null) {
throw new DataModelException("Abstract node cannot be inserted into a tree");
}
@@ -207,24 +214,10 @@
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()
- */) {
+ while (curNode.getNextSibling() != null) {
curNode = curNode.getNextSibling();
}
@@ -233,16 +226,143 @@
if (curNode.getNextSibling() == null) {
curNode.setNextSibling(newChild);
newChild.setPreviousSibling(curNode);
+ }
+ }
+
+ /**
+ * Clone the current node contents and create a new node.
+ *
+ * @return cloned node
+ * @throws CloneNotSupportedException clone is not supported by the referred node
+ */
+ public YangNode clone()
+ throws CloneNotSupportedException {
+ YangNode clonedNode = (YangNode) super.clone();
+ clonedNode.setParent(null);
+ clonedNode.setChild(null);
+ clonedNode.setNextSibling(null);
+ clonedNode.setPreviousSibling(null);
+ return clonedNode;
+ }
+
+ /**
+ * Clone the subtree from the specified source node to the mentioned target node.
+ * The source and target root node cloning is carried out by the caller.
+ *
+ * @param srcRootNode source node for sub tree cloning
+ * @param dstRootNode destination node where the sub tree needs to be cloned
+ * @throws DataModelException data model error
+ */
+ public static void cloneSubTree(YangNode srcRootNode, YangNode dstRootNode)
+ throws DataModelException {
+
+ YangNode nextNodeToClone = srcRootNode;
+ TraversalType curTraversal;
+
+
+ YangNode clonedTreeCurNode = dstRootNode;
+ YangNode newNode = null;
+
+ nextNodeToClone = nextNodeToClone.getChild();
+ if (nextNodeToClone == null) {
return;
+ } else {
+ /**
+ * Root level cloning is taken care in the caller.
+ */
+ curTraversal = CHILD;
}
- /*-
- * 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;
+ /**
+ * Caller ensures the cloning of the root nodes
*/
+ try {
+ while (nextNodeToClone != srcRootNode) {
+ if (nextNodeToClone == null) {
+ throw new DataModelException("Internal error: Cloning failed, source tree null pointer reached");
+ }
+
+ if (curTraversal == CHILD) {
+ newNode = nextNodeToClone.clone();
+
+ /**
+ * add the new node to the cloned tree.
+ */
+ clonedTreeCurNode.addChild(newNode);
+
+ /**
+ * update the cloned tree's travesal current node as the new node.
+ */
+ clonedTreeCurNode = newNode;
+ } else if (curTraversal == SIBILING) {
+ newNode = nextNodeToClone.clone();
+
+ clonedTreeCurNode.addNextSibling(newNode);
+ clonedTreeCurNode = newNode;
+ } else if (curTraversal == PARENT) {
+ clonedTreeCurNode = clonedTreeCurNode.getParent();
+ }
+
+ if (curTraversal != PARENT && nextNodeToClone.getChild() != null) {
+ curTraversal = CHILD;
+
+ /**
+ * update the traversal's current node.
+ */
+ nextNodeToClone = nextNodeToClone.getChild();
+
+ } else if (nextNodeToClone.getNextSibling() != null) {
+
+ curTraversal = SIBILING;
+
+ nextNodeToClone = nextNodeToClone.getNextSibling();
+ } else {
+ curTraversal = PARENT;
+ nextNodeToClone = nextNodeToClone.getParent();
+ }
+ }
+ } catch (CloneNotSupportedException e) {
+ throw new DataModelException("Failed to clone the tree");
+ }
+
+ }
+
+ /**
+ * Add a new next sibling.
+ *
+ * @param newSibling new sibling to be added
+ * @throws DataModelException data model error
+ */
+ private void addNextSibling(YangNode newSibling)
+ throws DataModelException {
+
+ if (newSibling.getNodeType() == null) {
+ throw new DataModelException("Cloned abstract node cannot be inserted into a tree");
+ }
+
+ if (newSibling.getParent() == null) {
+ /**
+ * Since the siblings needs to have a common parent, set the parent as the current node's parent
+ */
+ newSibling.setParent(this.getParent());
+
+ } else {
+ throw new DataModelException("Node is already part of a tree, and cannot be added as a sibling");
+ }
+
+ if (newSibling.getPreviousSibling() == null) {
+ newSibling.setPreviousSibling(this);
+ setNextSibling(newSibling);
+ } else {
+ throw new DataModelException("New sibling to be added is not atomic, it already has a previous sibling");
+ }
+
+ if (newSibling.getChild() != null) {
+ throw new DataModelException("Sibling to be added is not atomic, it already has a child");
+ }
+
+ if (newSibling.getNextSibling() != null) {
+ throw new DataModelException("Sibling to be added is not atomic, it already has a next sibling");
+ }
}
}