1 module hunt.markdown.node.Node; 2 3 import hunt.markdown.node.Visitor; 4 5 abstract class Node { 6 7 private Node parent = null; 8 private Node firstChild = null; 9 private Node lastChild = null; 10 private Node prev = null; 11 private Node next = null; 12 13 public abstract void accept(Visitor visitor); 14 15 public Node getNext() { 16 return next; 17 } 18 19 public Node getPrevious() { 20 return prev; 21 } 22 23 public Node getFirstChild() { 24 return firstChild; 25 } 26 27 public Node getLastChild() { 28 return lastChild; 29 } 30 31 public Node getParent() { 32 return parent; 33 } 34 35 protected void setParent(Node parent) { 36 this.parent = parent; 37 } 38 39 public void appendChild(Node child) { 40 child.unlink(); 41 child.setParent(this); 42 if (this.lastChild !is null) { 43 this.lastChild.next = child; 44 child.prev = this.lastChild; 45 this.lastChild = child; 46 } else { 47 this.firstChild = child; 48 this.lastChild = child; 49 } 50 } 51 52 public void prependChild(Node child) { 53 child.unlink(); 54 child.setParent(this); 55 if (this.firstChild !is null) { 56 this.firstChild.prev = child; 57 child.next = this.firstChild; 58 this.firstChild = child; 59 } else { 60 this.firstChild = child; 61 this.lastChild = child; 62 } 63 } 64 65 public void unlink() { 66 if (this.prev !is null) { 67 this.prev.next = this.next; 68 } else if (this.parent !is null) { 69 this.parent.firstChild = this.next; 70 } 71 if (this.next !is null) { 72 this.next.prev = this.prev; 73 } else if (this.parent !is null) { 74 this.parent.lastChild = this.prev; 75 } 76 this.parent = null; 77 this.next = null; 78 this.prev = null; 79 } 80 81 public void insertAfter(Node sibling) { 82 sibling.unlink(); 83 sibling.next = this.next; 84 if (sibling.next !is null) { 85 sibling.next.prev = sibling; 86 } 87 sibling.prev = this; 88 this.next = sibling; 89 sibling.parent = this.parent; 90 if (sibling.next is null) { 91 sibling.parent.lastChild = sibling; 92 } 93 } 94 95 public void insertBefore(Node sibling) { 96 sibling.unlink(); 97 sibling.prev = this.prev; 98 if (sibling.prev !is null) { 99 sibling.prev.next = sibling; 100 } 101 sibling.next = this; 102 this.prev = sibling; 103 sibling.parent = this.parent; 104 if (sibling.prev is null) { 105 sibling.parent.firstChild = sibling; 106 } 107 } 108 109 override public string toString() { 110 return typeid(this).name ~ "{" ~ toStringAttributes() ~ "}"; 111 } 112 113 protected string toStringAttributes() { 114 return ""; 115 } 116 }