Skip to content

Instantly share code, notes, and snippets.

@audinue
Last active June 21, 2023 18:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save audinue/b88afbc9332aaef8138645c942b19a76 to your computer and use it in GitHub Desktop.
Save audinue/b88afbc9332aaef8138645c942b19a76 to your computer and use it in GitHub Desktop.
Tested minimal DOM node implementation.
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;
}
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