1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.millscript.millscript.loaders;
22
23 import org.millscript.commons.alert.alerts.Fault;
24 import org.millscript.commons.util.IList;
25 import org.millscript.commons.util.list.ELinkedList;
26 import org.millscript.commons.xml.api.token.AttListDeclToken;
27 import org.millscript.commons.xml.api.token.CharDataToken;
28 import org.millscript.commons.xml.api.token.CommentToken;
29 import org.millscript.commons.xml.api.token.DTDToken;
30 import org.millscript.commons.xml.api.token.ElementDeclToken;
31 import org.millscript.commons.xml.api.token.EmptyElementToken;
32 import org.millscript.commons.xml.api.token.EndTagToken;
33 import org.millscript.commons.xml.api.token.EntityDeclToken;
34 import org.millscript.commons.xml.api.token.NotationDeclToken;
35 import org.millscript.commons.xml.api.token.PIToken;
36 import org.millscript.commons.xml.api.token.StartTagToken;
37 import org.millscript.commons.xml.api.token.TokenVisitor;
38 import org.millscript.commons.xml.api.token.XmlDeclToken;
39 import org.millscript.millscript.alert.Alerts;
40 import org.millscript.millscript.datatypes.XmlComment;
41 import org.millscript.millscript.datatypes.XmlElement;
42
43 /**
44 * This class provides validation and handling logic for loading an XML
45 * document into a static XML object.
46 */
47 public class XMLLoaderTokenVisitor implements TokenVisitor {
48
49 /**
50 * This body expression for the element.
51 */
52 ELinkedList< Object > body = new ELinkedList< Object >();
53
54 /**
55 * The parent token visitor we should return to once this one has finished
56 * what it is supposed to do.
57 */
58 final XMLLoaderTokenVisitor parentTokenVisitor;
59
60 /**
61 * The start tag that began the section this token visitor represents.
62 */
63 final StartTagToken startTagToken;
64
65 /**
66 * The loader that is controlling the XML parse.
67 */
68 final XMLLoader xmlLoader;
69
70 /**
71 * This class is used when visiting an XML element and it handles the
72 * tokens visited in the elements content.
73 */
74 private class ElementTokenVisitor extends XMLLoaderTokenVisitor {
75
76 /**
77 * Constructs a new element token visitor, with the specified
78 * controlling loader, parent token visitor and start tag.
79 *
80 * @param xml the controlling loader
81 * @param ptv the parent token visitor
82 * @param stt the start tag token
83 */
84 public ElementTokenVisitor( final XMLLoader xml, final XMLLoaderTokenVisitor ptv, final StartTagToken stt ) {
85 super( xml, ptv, stt );
86 }
87
88 /**
89 * @see org.millscript.commons.xml.api.token.TokenVisitor#visit(org.millscript.commons.xml.api.token.CharDataToken)
90 */
91 @Override
92 public void visit( final CharDataToken token ) {
93 if ( token.getCharData().length() == 0 ) {
94
95 throw new Fault(
96 "Appending empty character data"
97 ).mishap();
98 }
99
100 this.pushChildElement(
101 token.getCharData()
102 );
103 }
104
105 /**
106 * @see org.millscript.commons.xml.api.token.TokenVisitor#visit(org.millscript.commons.xml.api.token.CommentToken)
107 */
108 @Override
109 public void visit( final CommentToken token ) {
110 if ( token.getCommentText().length() == 0 ) {
111
112
113 throw new Fault(
114 "Appending empty comment"
115 ).mishap();
116 }
117
118
119 this.pushChildElement(
120 new XmlComment( token.getCommentText() )
121 );
122 }
123
124 /**
125 * @see org.millscript.commons.xml.api.token.TokenVisitor#visit(org.millscript.commons.xml.api.token.EndTagToken)
126 */
127 @Override
128 public void visit( final EndTagToken token ) {
129
130
131 this.parentTokenVisitor.pushChildElement(
132 new XmlElement(
133 this.startTagToken.getName(),
134 this.startTagToken.getAttributes(),
135 body.toArray()
136 )
137 );
138
139 this.xmlLoader.tokenVisitor = this.parentTokenVisitor;
140 }
141
142 }
143
144 /**
145 * Constructs a new XML loader token visitor, with the specified
146 * controlling loader, parent token visitor and start tag.
147 *
148 * @param xml the controlling loader
149 * @param ptv the parent token visitor
150 * @param stt the start tag token
151 */
152 public XMLLoaderTokenVisitor( final XMLLoader xml, final XMLLoaderTokenVisitor ptv, final StartTagToken stt ) {
153 this.parentTokenVisitor = ptv;
154 this.startTagToken = stt;
155 this.xmlLoader = xml;
156 }
157
158 /**
159 * Returns the body expression for this element.
160 *
161 * @return an Expr for this elements body
162 */
163 IList getBody() {
164 return this.body;
165 }
166
167 /**
168 * Pushes the expression as part of this elements body.
169 *
170 * @param o the next body element for this element
171 */
172 void pushChildElement( final Object o ) {
173 this.body.addLast( o );
174 }
175
176 /**
177 * @see org.millscript.commons.xml.api.token.TokenVisitor#visit(org.millscript.commons.xml.api.token.AttListDeclToken)
178 */
179 public void visit( final AttListDeclToken token ) {
180
181 throw(
182 Alerts.unimplemented(
183 "Attribute list declarations cannot be compiled at the moment, sorry!"
184 ).decorate( token ).mishap()
185 );
186 }
187
188 /**
189 * @see org.millscript.commons.xml.api.token.TokenVisitor#visit(org.millscript.commons.xml.api.token.CharDataToken)
190 */
191 public void visit( final CharDataToken token ) {
192
193
194 if ( ! token.isIgnorableWhitespace() ) {
195 throw(
196 Alerts.unimplemented(
197 "All character data must be within an element at the moment, sorry!"
198 ).decorate( token ).mishap()
199 );
200 }
201 }
202
203 /**
204 * @see org.millscript.commons.xml.api.token.TokenVisitor#visit(org.millscript.commons.xml.api.token.CommentToken)
205 */
206 public void visit( final CommentToken token ) {
207 throw(
208 Alerts.unimplemented(
209 "Comments must be within an element at the moment, sorry!"
210 ).decorate( token ).mishap()
211 );
212 }
213
214 /**
215 * @see org.millscript.commons.xml.api.token.TokenVisitor#visit(org.millscript.commons.xml.api.token.DTDToken)
216 */
217 public void visit( final DTDToken token ) {
218 throw(
219 Alerts.unimplemented(
220 "Document type declarations cannot be compiled at the moment, sorry!"
221 ).decorate( token ).mishap()
222 );
223 }
224
225 /**
226 * @see org.millscript.commons.xml.api.token.TokenVisitor#visit(org.millscript.commons.xml.api.token.ElementDeclToken)
227 */
228 public void visit( final ElementDeclToken token ) {
229 throw(
230 Alerts.unimplemented(
231 "Element declarations cannot be compiled at the moment, sorry!"
232 ).decorate( token ).mishap()
233 );
234 }
235
236 /**
237 * @see org.millscript.commons.xml.api.token.TokenVisitor#visit(org.millscript.commons.xml.api.token.EmptyElementToken)
238 */
239 public void visit( final EmptyElementToken token ) {
240
241 this.visit( (StartTagToken) token );
242
243
244 this.xmlLoader.tokenVisitor.visit( (EndTagToken)token );
245 }
246
247 /**
248 * @see org.millscript.commons.xml.api.token.TokenVisitor#visit(org.millscript.commons.xml.api.token.EndTagToken)
249 */
250 public void visit( final EndTagToken token ) {
251 throw new Fault(
252 "EndTagToken should never be reported on XMLLoaderTokenVisitor"
253 ).mishap();
254 }
255
256 /**
257 * @see org.millscript.commons.xml.api.token.TokenVisitor#visit(org.millscript.commons.xml.api.token.EntityDeclToken)
258 */
259 public void visit( final EntityDeclToken token ) {
260 throw(
261 Alerts.unimplemented(
262 "Entity declarations cannot be compiled at the moment, sorry!"
263 ).decorate( token ).mishap()
264 );
265 }
266
267 /**
268 * @see org.millscript.commons.xml.api.token.TokenVisitor#visit(org.millscript.commons.xml.api.token.NotationDeclToken)
269 */
270 public void visit( final NotationDeclToken token ) {
271 throw(
272 Alerts.unimplemented(
273 "Notation declarations cannot be compiled at the moment, sorry!"
274 ).decorate( token ).mishap()
275 );
276 }
277
278 /**
279 * @see org.millscript.commons.xml.api.token.TokenVisitor#visit(org.millscript.commons.xml.api.token.PIToken)
280 */
281 public void visit( final PIToken token ) {
282 throw(
283 Alerts.unimplemented(
284 "Processing instructions cannot be compiled at the moment, sorry!"
285 ).decorate( token ).mishap()
286 );
287 }
288
289 /**
290 * @see org.millscript.commons.xml.api.token.TokenVisitor#visit(org.millscript.commons.xml.api.token.StartTagToken)
291 */
292 public void visit( final StartTagToken token ) {
293
294 this.xmlLoader.tokenVisitor = new ElementTokenVisitor( this.xmlLoader, this.xmlLoader.tokenVisitor, token );
295 }
296
297 /**
298 * @see org.millscript.commons.xml.api.token.TokenVisitor#visit(org.millscript.commons.xml.api.token.XmlDeclToken)
299 */
300 public void visit( final XmlDeclToken token ) {
301
302 }
303
304 }