Last active
June 21, 2023 18:07
-
-
Save audinue/b88afbc9332aaef8138645c942b19a76 to your computer and use it in GitHub Desktop.
Tested minimal DOM node implementation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Node { | |
public Node getParentNode() { | |
return parentNode; | |
} | |
public Node getPreviousSibling() { | |
return previousSibling; | |
} | |
public Node getNextSibling() { | |
return nextSibling; | |
} | |
public Node getFirstChild() { | |
return firstChild; | |
} | |
public Node getLastChild() { | |
return lastChild; | |
} | |
public void appendChild(Node newChild) { | |
validateNewChild(newChild); | |
appendChildNoValidate(newChild); | |
} | |
public void prependChild(Node newChild) { | |
validateNewChild(newChild); | |
if (firstChild == null) { | |
appendChildNoValidate(newChild); | |
} else { | |
insertBeforeNoValidate(newChild, firstChild); | |
} | |
} | |
public void insertBefore(Node newChild, Node oldChild) { | |
validateOldChild(oldChild); | |
validateNewChild(newChild); | |
insertBeforeNoValidate(newChild, oldChild); | |
} | |
public void insertAfter(Node newChild, Node oldChild) { | |
validateOldChild(oldChild); | |
validateNewChild(newChild); | |
if (oldChild == lastChild) { | |
appendChildNoValidate(newChild); | |
} else { | |
insertBeforeNoValidate(newChild, oldChild.nextSibling); | |
} | |
} | |
public void replaceChild(Node newChild, Node oldChild) { | |
validateOldChild(oldChild); | |
validateNewChild(newChild); | |
if (newChild.parentNode != null) { | |
newChild.parentNode.removeChild(newChild); | |
} | |
if (oldChild == firstChild) { | |
firstChild = newChild; | |
} | |
if (oldChild == lastChild) { | |
lastChild = newChild; | |
} | |
if (oldChild.previousSibling != null) { | |
oldChild.previousSibling.nextSibling = newChild; | |
} | |
if (oldChild.nextSibling != null) { | |
oldChild.nextSibling.previousSibling = newChild; | |
} | |
newChild.parentNode = this; | |
newChild.previousSibling = oldChild.previousSibling; | |
newChild.nextSibling = oldChild.nextSibling; | |
oldChild.parentNode = null; | |
oldChild.previousSibling = null; | |
oldChild.nextSibling = null; | |
} | |
public void removeChild(Node oldChild) { | |
validateOldChild(oldChild); | |
if (oldChild == firstChild) { | |
firstChild = oldChild.nextSibling; | |
} | |
if (oldChild == lastChild) { | |
lastChild = oldChild.previousSibling; | |
} | |
if (oldChild.previousSibling != null) { | |
oldChild.previousSibling.nextSibling = oldChild.nextSibling; | |
} | |
if (oldChild.nextSibling != null) { | |
oldChild.nextSibling.previousSibling = oldChild.previousSibling; | |
} | |
oldChild.parentNode = null; | |
oldChild.previousSibling = null; | |
oldChild.nextSibling = null; | |
} | |
private void validateOldChild(Node oldChild) { | |
if (oldChild == null || oldChild.parentNode != this) { | |
throw new IllegalArgumentException(); | |
} | |
} | |
private void appendChildNoValidate(Node newChild) { | |
if (newChild.parentNode != null) { | |
newChild.parentNode.removeChild(newChild); | |
} | |
if (lastChild == null) { | |
lastChild = newChild; | |
firstChild = newChild; | |
} else { | |
newChild.previousSibling = lastChild; | |
lastChild.nextSibling = newChild; | |
lastChild = newChild; | |
} | |
newChild.parentNode = this; | |
} | |
private boolean isThisOrAncestor(Node node) { | |
while (node != null) { | |
if (node == this) { | |
return true; | |
} | |
node = node.parentNode; | |
} | |
return false; | |
} | |
private void validateNewChild(Node newChild) { | |
if (newChild == null || isThisOrAncestor(newChild)) { | |
throw new IllegalArgumentException(); | |
} | |
} | |
private void insertBeforeNoValidate(Node newChild, Node oldChild) { | |
if (newChild.parentNode != null) { | |
newChild.parentNode.removeChild(newChild); | |
} | |
if (oldChild == firstChild) { | |
firstChild = newChild; | |
} else { | |
oldChild.previousSibling.nextSibling = newChild; | |
} | |
newChild.previousSibling = oldChild.previousSibling; | |
newChild.nextSibling = oldChild; | |
newChild.parentNode = this; | |
oldChild.previousSibling = newChild; | |
} | |
private Node parentNode; | |
private Node previousSibling; | |
private Node nextSibling; | |
private Node firstChild; | |
private Node lastChild; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Test { | |
public static void main(String[] args) { | |
testAppendChild1(); | |
testAppendChild2(); | |
testAppendChild3(); | |
testRemoveChild1(); | |
testRemoveChild2(); | |
testRemoveChild3(); | |
testRemoveChild4(); | |
testRemoveChild5(); | |
testRemoveChild6(); | |
testReplaceChild1(); | |
testReplaceChild2(); | |
testReplaceChild3(); | |
testInsertBefore1(); | |
testInsertBefore2(); | |
} | |
private static void testRemoveChild1() { | |
Node a = new Node(); | |
Node b = new Node(); | |
a.appendChild(b); | |
a.removeChild(b); | |
assert (a.getParentNode() == null); | |
assert (a.getPreviousSibling() == null); | |
assert (a.getNextSibling() == null); | |
assert (a.getFirstChild() == null); | |
assert (a.getLastChild() == null); | |
assert (b.getParentNode() == null); | |
assert (b.getPreviousSibling() == null); | |
assert (b.getNextSibling() == null); | |
assert (b.getFirstChild() == null); | |
assert (b.getLastChild() == null); | |
} | |
private static void testRemoveChild5() { | |
Node a = new Node(); | |
Node b = new Node(); | |
Node c = new Node(); | |
Node d = new Node(); | |
a.appendChild(b); | |
a.appendChild(c); | |
a.appendChild(d); | |
a.removeChild(b); | |
assert (a.getParentNode() == null); | |
assert (a.getPreviousSibling() == null); | |
assert (a.getNextSibling() == null); | |
assert (a.getFirstChild() == c); | |
assert (a.getLastChild() == d); | |
assert (b.getParentNode() == null); | |
assert (b.getPreviousSibling() == null); | |
assert (b.getNextSibling() == null); | |
assert (b.getFirstChild() == null); | |
assert (b.getLastChild() == null); | |
assert (c.getParentNode() == a); | |
assert (c.getPreviousSibling() == null); | |
assert (c.getNextSibling() == d); | |
assert (c.getFirstChild() == null); | |
assert (c.getLastChild() == null); | |
assert (d.getParentNode() == a); | |
assert (d.getPreviousSibling() == c); | |
assert (d.getNextSibling() == null); | |
assert (d.getFirstChild() == null); | |
assert (d.getLastChild() == null); | |
} | |
private static void testReplaceChild1() { | |
Node a = new Node(); | |
Node b = new Node(); | |
Node c = new Node(); | |
a.appendChild(b); | |
a.replaceChild(c, b); | |
assert (a.getParentNode() == null); | |
assert (a.getPreviousSibling() == null); | |
assert (a.getNextSibling() == null); | |
assert (a.getFirstChild() == c); | |
assert (a.getLastChild() == c); | |
assert (b.getParentNode() == null); | |
assert (b.getPreviousSibling() == null); | |
assert (b.getNextSibling() == null); | |
assert (b.getFirstChild() == null); | |
assert (b.getLastChild() == null); | |
assert (c.getParentNode() == a); | |
assert (c.getPreviousSibling() == null); | |
assert (c.getNextSibling() == null); | |
assert (c.getFirstChild() == null); | |
assert (c.getLastChild() == null); | |
} | |
private static void testAppendChild2() { | |
Node a = new Node(); | |
Node b = new Node(); | |
Node c = new Node(); | |
a.appendChild(b); | |
a.appendChild(c); | |
assert (a.getParentNode() == null); | |
assert (a.getPreviousSibling() == null); | |
assert (a.getNextSibling() == null); | |
assert (a.getFirstChild() == b); | |
assert (a.getLastChild() == c); | |
assert (b.getParentNode() == a); | |
assert (b.getPreviousSibling() == null); | |
assert (b.getNextSibling() == c); | |
assert (b.getFirstChild() == null); | |
assert (b.getLastChild() == null); | |
assert (c.getParentNode() == a); | |
assert (c.getPreviousSibling() == b); | |
assert (c.getNextSibling() == null); | |
assert (c.getFirstChild() == null); | |
assert (c.getLastChild() == null); | |
} | |
private static void testRemoveChild3() { | |
Node a = new Node(); | |
Node b = new Node(); | |
Node c = new Node(); | |
a.appendChild(b); | |
a.appendChild(c); | |
a.removeChild(c); | |
assert (a.getParentNode() == null); | |
assert (a.getPreviousSibling() == null); | |
assert (a.getNextSibling() == null); | |
assert (a.getFirstChild() == b); | |
assert (a.getLastChild() == b); | |
assert (b.getParentNode() == a); | |
assert (b.getPreviousSibling() == null); | |
assert (b.getNextSibling() == null); | |
assert (b.getFirstChild() == null); | |
assert (b.getLastChild() == null); | |
assert (c.getParentNode() == null); | |
assert (c.getPreviousSibling() == null); | |
assert (c.getNextSibling() == null); | |
assert (c.getFirstChild() == null); | |
assert (c.getLastChild() == null); | |
} | |
private static void testReplaceChild3() { | |
Node a = new Node(); | |
Node b = new Node(); | |
Node c = new Node(); | |
Node d = new Node(); | |
a.appendChild(b); | |
a.appendChild(c); | |
a.replaceChild(d, c); | |
assert (a.getParentNode() == null); | |
assert (a.getPreviousSibling() == null); | |
assert (a.getNextSibling() == null); | |
assert (a.getFirstChild() == b); | |
assert (a.getLastChild() == d); | |
assert (b.getParentNode() == a); | |
assert (b.getPreviousSibling() == null); | |
assert (b.getNextSibling() == d); | |
assert (b.getFirstChild() == null); | |
assert (b.getLastChild() == null); | |
assert (c.getParentNode() == null); | |
assert (c.getPreviousSibling() == null); | |
assert (c.getNextSibling() == null); | |
assert (c.getFirstChild() == null); | |
assert (c.getLastChild() == null); | |
assert (d.getParentNode() == a); | |
assert (d.getPreviousSibling() == b); | |
assert (d.getNextSibling() == null); | |
assert (d.getFirstChild() == null); | |
assert (d.getLastChild() == null); | |
} | |
private static void testRemoveChild2() { | |
Node a = new Node(); | |
Node b = new Node(); | |
Node c = new Node(); | |
a.appendChild(b); | |
a.appendChild(c); | |
a.removeChild(b); | |
assert (a.getParentNode() == null); | |
assert (a.getPreviousSibling() == null); | |
assert (a.getNextSibling() == null); | |
assert (a.getFirstChild() == c); | |
assert (a.getLastChild() == c); | |
assert (b.getParentNode() == null); | |
assert (b.getPreviousSibling() == null); | |
assert (b.getNextSibling() == null); | |
assert (b.getFirstChild() == null); | |
assert (b.getLastChild() == null); | |
assert (c.getParentNode() == a); | |
assert (c.getPreviousSibling() == null); | |
assert (c.getNextSibling() == null); | |
assert (c.getFirstChild() == null); | |
assert (c.getLastChild() == null); | |
} | |
private static void testRemoveChild4() { | |
Node a = new Node(); | |
Node b = new Node(); | |
Node c = new Node(); | |
Node d = new Node(); | |
a.appendChild(b); | |
a.appendChild(c); | |
a.appendChild(d); | |
a.removeChild(c); | |
assert (a.getParentNode() == null); | |
assert (a.getPreviousSibling() == null); | |
assert (a.getNextSibling() == null); | |
assert (a.getFirstChild() == b); | |
assert (a.getLastChild() == d); | |
assert (b.getParentNode() == a); | |
assert (b.getPreviousSibling() == null); | |
assert (b.getNextSibling() == d); | |
assert (b.getFirstChild() == null); | |
assert (b.getLastChild() == null); | |
assert (c.getParentNode() == null); | |
assert (c.getPreviousSibling() == null); | |
assert (c.getNextSibling() == null); | |
assert (c.getFirstChild() == null); | |
assert (c.getLastChild() == null); | |
assert (d.getParentNode() == a); | |
assert (d.getPreviousSibling() == b); | |
assert (d.getNextSibling() == null); | |
assert (d.getFirstChild() == null); | |
assert (d.getLastChild() == null); | |
} | |
private static void testAppendChild3() { | |
Node a = new Node(); | |
Node b = new Node(); | |
Node c = new Node(); | |
Node d = new Node(); | |
a.appendChild(b); | |
a.appendChild(c); | |
a.appendChild(d); | |
assert (a.getParentNode() == null); | |
assert (a.getPreviousSibling() == null); | |
assert (a.getNextSibling() == null); | |
assert (a.getFirstChild() == b); | |
assert (a.getLastChild() == d); | |
assert (b.getParentNode() == a); | |
assert (b.getPreviousSibling() == null); | |
assert (b.getNextSibling() == c); | |
assert (b.getFirstChild() == null); | |
assert (b.getLastChild() == null); | |
assert (c.getParentNode() == a); | |
assert (c.getPreviousSibling() == b); | |
assert (c.getNextSibling() == d); | |
assert (c.getFirstChild() == null); | |
assert (c.getLastChild() == null); | |
assert (d.getParentNode() == a); | |
assert (d.getPreviousSibling() == c); | |
assert (d.getNextSibling() == null); | |
assert (d.getFirstChild() == null); | |
assert (d.getLastChild() == null); | |
} | |
private static void testRemoveChild6() { | |
Node a = new Node(); | |
Node b = new Node(); | |
Node c = new Node(); | |
Node d = new Node(); | |
a.appendChild(b); | |
a.appendChild(c); | |
a.appendChild(d); | |
a.removeChild(d); | |
assert (a.getParentNode() == null); | |
assert (a.getPreviousSibling() == null); | |
assert (a.getNextSibling() == null); | |
assert (a.getFirstChild() == b); | |
assert (a.getLastChild() == c); | |
assert (b.getParentNode() == a); | |
assert (b.getPreviousSibling() == null); | |
assert (b.getNextSibling() == c); | |
assert (b.getFirstChild() == null); | |
assert (b.getLastChild() == null); | |
assert (c.getParentNode() == a); | |
assert (c.getPreviousSibling() == b); | |
assert (c.getNextSibling() == null); | |
assert (c.getFirstChild() == null); | |
assert (c.getLastChild() == null); | |
assert (d.getParentNode() == null); | |
assert (d.getPreviousSibling() == null); | |
assert (d.getNextSibling() == null); | |
assert (d.getFirstChild() == null); | |
assert (d.getLastChild() == null); | |
} | |
private static void testInsertBefore1() { | |
Node a = new Node(); | |
Node b = new Node(); | |
Node c = new Node(); | |
a.appendChild(b); | |
a.insertBefore(c, b); | |
assert (a.getParentNode() == null); | |
assert (a.getPreviousSibling() == null); | |
assert (a.getNextSibling() == null); | |
assert (a.getFirstChild() == c); | |
assert (a.getLastChild() == b); | |
assert (b.getParentNode() == a); | |
assert (b.getPreviousSibling() == c); | |
assert (b.getNextSibling() == null); | |
assert (b.getFirstChild() == null); | |
assert (b.getLastChild() == null); | |
assert (c.getParentNode() == a); | |
assert (c.getPreviousSibling() == null); | |
assert (c.getNextSibling() == b); | |
assert (c.getFirstChild() == null); | |
assert (c.getLastChild() == null); | |
} | |
private static void testInsertBefore2() { | |
Node a = new Node(); | |
Node b = new Node(); | |
Node c = new Node(); | |
Node d = new Node(); | |
a.appendChild(b); | |
a.appendChild(c); | |
a.insertBefore(d, c); | |
assert (a.getParentNode() == null); | |
assert (a.getPreviousSibling() == null); | |
assert (a.getNextSibling() == null); | |
assert (a.getFirstChild() == b); | |
assert (a.getLastChild() == c); | |
assert (b.getParentNode() == a); | |
assert (b.getPreviousSibling() == null); | |
assert (b.getNextSibling() == d); | |
assert (b.getFirstChild() == null); | |
assert (b.getLastChild() == null); | |
assert (c.getParentNode() == a); | |
assert (c.getPreviousSibling() == d); | |
assert (c.getNextSibling() == null); | |
assert (c.getFirstChild() == null); | |
assert (c.getLastChild() == null); | |
assert (d.getParentNode() == a); | |
assert (d.getPreviousSibling() == b); | |
assert (d.getNextSibling() == c); | |
assert (d.getFirstChild() == null); | |
assert (d.getLastChild() == null); | |
} | |
private static void testAppendChild1() { | |
Node a = new Node(); | |
Node b = new Node(); | |
a.appendChild(b); | |
assert (a.getParentNode() == null); | |
assert (a.getPreviousSibling() == null); | |
assert (a.getNextSibling() == null); | |
assert (a.getFirstChild() == b); | |
assert (a.getLastChild() == b); | |
assert (b.getParentNode() == a); | |
assert (b.getPreviousSibling() == null); | |
assert (b.getNextSibling() == null); | |
assert (b.getFirstChild() == null); | |
assert (b.getLastChild() == null); | |
} | |
private static void testReplaceChild2() { | |
Node a = new Node(); | |
Node b = new Node(); | |
Node c = new Node(); | |
Node d = new Node(); | |
a.appendChild(b); | |
a.appendChild(c); | |
a.replaceChild(d, b); | |
assert (a.getParentNode() == null); | |
assert (a.getPreviousSibling() == null); | |
assert (a.getNextSibling() == null); | |
assert (a.getFirstChild() == d); | |
assert (a.getLastChild() == c); | |
assert (b.getParentNode() == null); | |
assert (b.getPreviousSibling() == null); | |
assert (b.getNextSibling() == null); | |
assert (b.getFirstChild() == null); | |
assert (b.getLastChild() == null); | |
assert (c.getParentNode() == a); | |
assert (c.getPreviousSibling() == d); | |
assert (c.getNextSibling() == null); | |
assert (c.getFirstChild() == null); | |
assert (c.getLastChild() == null); | |
assert (d.getParentNode() == a); | |
assert (d.getPreviousSibling() == null); | |
assert (d.getNextSibling() == c); | |
assert (d.getFirstChild() == null); | |
assert (d.getLastChild() == null); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment