1 module deepmagic.dom.xml.document;
2 
3 import deepmagic.dom;
4 
5 class Document : Element
6 {
7 	/**
8 	 * Contains all text which occurs before the root element.
9 	 * Defaults to <?xml version="1.0"?>
10 	 */
11 	string prolog = "<?xml version=\"1.0\"?>";
12 	/**
13 	 * Contains all text which occurs after the root element.
14 	 * Defaults to the empty string
15 	 */
16 	string epilog;
17 
18 	/**
19 	 * Constructs a Document by parsing XML text.
20 	 *
21 	 * This function creates a complete DOM (Document Object Model) tree.
22 	 *
23 	 * The input to this function MUST be valid XML.
24 	 * This is enforced by DocumentParser's in contract.
25 	 *
26 	 * Params:
27 	 *	  s = the complete XML text.
28 	 */
29 	this(string s)
30 	in
31 	{
32 		assert(s.length != 0);
33 	}
34 	body
35 	{
36 		auto xml = new DocumentParser(s);
37 		string tagString = xml.tag.tagString;
38 
39 		this(xml.tag);
40 		prolog = s[0 .. tagString.ptr - s.ptr];
41 		this.parse(xml);
42 		epilog = *xml.s;
43 	}
44 
45 	/**
46 	 * Constructs a Document from a Tag.
47 	 *
48 	 * Params:
49 	 *	  tag = the start tag of the document.
50 	 */
51 	this(const(Tag) tag)
52 	{
53 		super(tag);
54 	}
55 
56 	const
57 	{
58 		/**
59 		 * Compares two Documents for equality
60 		 *
61 		 * Examples:
62 		 * --------------
63 		 * Document d1,d2;
64 		 * if (d1 == d2) { }
65 		 * --------------
66 		 */
67 		override bool opEquals(Object o)
68 		{
69 			const doc = toType!(const Document)(o);
70 			return
71 				(prolog != doc.prolog			) ? false : (
72 				(super  != cast(const Element)doc) ? false : (
73 				(epilog != doc.epilog			) ? false : (
74 			true )));
75 		}
76 
77 		/**
78 		 * Compares two Documents
79 		 *
80 		 * You should rarely need to call this function. It exists so that
81 		 * Documents can be used as associative array keys.
82 		 *
83 		 * Examples:
84 		 * --------------
85 		 * Document d1,d2;
86 		 * if (d1 < d2) { }
87 		 * --------------
88 		 */
89 		override int opCmp(Object o)
90 		{
91 			const doc = toType!(const Document)(o);
92 			return
93 				((prolog != doc.prolog			)
94 					? ( prolog < doc.prolog			 ? -1 : 1 ) :
95 				((super  != cast(const Element)doc)
96 					? ( cast()super  < cast()cast(const Element)doc ? -1 : 1 ) :
97 				((epilog != doc.epilog			)
98 					? ( epilog < doc.epilog			 ? -1 : 1 ) :
99 			0 )));
100 		}
101 
102 		/**
103 		 * Returns the hash of a Document
104 		 *
105 		 * You should rarely need to call this function. It exists so that
106 		 * Documents can be used as associative array keys.
107 		 */
108 		override size_t toHash() @trusted
109 		{
110 			return hash(prolog, hash(epilog, (cast()super).toHash()));
111 		}
112 
113 		/**
114 		 * Returns the string representation of a Document. (That is, the
115 		 * complete XML of a document).
116 		 */
117 		override string toString()
118 		{
119 			return prolog ~ super.toString() ~ epilog;
120 		}
121 	}
122 }