1 /**
2  * Copyright:
3  * (C) 2016 Martin Brzenska
4  *
5  * License: 
6  * Distributed under the terms of the MIT license. 
7  * Consult the provided LICENSE.md file for details
8  */
9 module libdominator.Node;
10 
11 import std.string : toLower;
12 import std.format : format ;
13 import std.conv : to ;
14 
15 import libdominator;
16 
17 ///Represents a node in a DOM
18 class Node {
19   private string tag;
20   private Attribute[] arrAttributes;
21   private uint startPos, endPos;
22   private ushort startTagLength, endTagLength;
23   private bool is_comment;
24   private Node* parent;
25   private Node*[] children;
26 
27   ///Makes a naked node object
28   this() {}
29 
30   ///Makes a node with a given tagname
31   this(string tag) {
32     this.setTag(tag);
33   }
34 
35   ///Makes a node with a given tagname and with the information for the position in the Document
36   this(T)(string tag, T startPosition) {
37     this.setTag(tag);
38     this.setStartPosition(startPosition);
39   }
40 
41   ///Sets the tagname
42   public Node setTag(string tag) {
43     this.tag = toLower(tag);
44     return this;
45   }
46 
47   ///Sets the position in the document where this node begins
48   public Node setStartPosition(T)(T position) {
49     this.startPos = to!uint(position);
50     return this;
51   }
52 
53   ///Sets the position in the document where this node ends
54   public Node setEndPosition(T)(T position) {
55     this.endPos = to!uint(position);
56     return this;
57   }
58 
59   ///Does what the name says
60   public string getTag() {
61     return this.tag;
62   }
63   /// ditto
64   public Attribute[] getAttributes() {
65     return this.arrAttributes;
66   }
67 
68   /// ditto
69   public void addAttribute(Attribute attribute) {
70     this.arrAttributes ~= attribute;
71   }
72 
73   /// ditto
74   public uint getStartPosition() {
75     return this.startPos;
76   }
77 
78   /// ditto
79   public uint getEndPosition() {
80     return this.endPos;
81   }
82 
83   /// ditto
84   public Node setStartTagLength(T)(T length) {
85     this.startTagLength = to!ushort(length);
86     return this;
87   }
88 
89   /// ditto
90   public Node setEndTagLength(T)(T length) {
91     this.endTagLength = to!ushort(length);
92     return this;
93   }
94 
95   /// ditto
96   public ushort getStartTagLength() {
97     return this.startTagLength;
98   }
99 
100   /// ditto
101   public ushort getEndTagLength() {
102     return this.endTagLength;
103   }
104 
105   ///Markes this node to be inside of a comment
106   public Node isComment(bool sw) {
107     this.is_comment = sw;
108     return this;
109   }
110   
111   /**
112   * Returns: true if the node is marked to be inside of a comment, otherwise false.
113   */
114   public bool isComment() {
115     return this.is_comment;
116   }
117   
118   ///Sets the given node as the parent node
119   public void setParent(Node* pNode) {
120     this.parent = pNode;
121   }
122   
123   ///Does what the name says
124   public Node getParent() {
125     return this.parent is null ? new Node : (*this.parent);
126   }
127   
128   ///Adds a node as a child node
129   public void addChild(Node* pNode) {
130     this.children ~= pNode;
131   }
132   
133   ///Does what the name says
134   public Node[] getChildren() {
135     Node[] nodes;
136     foreach(Node* pNode ; this.children) {
137       if(pNode !is  null) { nodes ~= (*pNode); }
138     }
139     return nodes;
140   }
141   
142   /**
143   * Returns: true if the node has children nodes.
144   */
145   public size_t hasChildren() {
146     return this.children.length;
147   }
148   
149   /**
150   * Returns: true if the node has a parent node.
151   */
152   public bool hasParent() {
153     return (parent !is null);
154   }
155   
156 }