KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > nu > xom > NodeFactory


1 /* Copyright 2002-2004 Elliotte Rusty Harold
2    
3    This library is free software; you can redistribute it and/or modify
4    it under the terms of version 2.1 of the GNU Lesser General Public
5    License as published by the Free Software Foundation.
6    
7    This library is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10    GNU Lesser General Public License for more details.
11    
12    You should have received a copy of the GNU Lesser General Public
13    License along with this library; if not, write to the
14    Free Software Foundation, Inc., 59 Temple Place, Suite 330,
15    Boston, MA 02111-1307 USA
16    
17    You can contact Elliotte Rusty Harold by sending e-mail to
18    elharo@metalab.unc.edu. Please include the word "XOM" in the
19    subject line. The XOM home page is located at http://www.xom.nu/
20 */

21
22 package nu.xom;
23
24 /**
25  * <p>
26  * Builders use a <code>NodeFactory</code> object
27  * to construct each <code>Node</code> object (<code>Element</code>,
28  * <code>Text</code>, <code>Attribute</code>, etc.) they add to the
29  * tree. The default implementation simply calls the relevant
30  * constructor, stuffs the resulting <code>Node</code> object in a
31  * length one <code>Nodes</code> object, and returns it.
32  * </p>
33  *
34  * <p>
35  * Subclassing this class allows builders to produce
36  * instance of subclasses (for example,
37  * <code>HTMLElement</code>) instead of the
38  * base classes.
39  * </p>
40  *
41  * <p>
42  * Subclasses can also filter content while building.
43  * For example, namespaces could be added to or changed
44  * on all elements. Comments could be deleted. Processing
45  * instructions can be changed into elements. An
46  * <code>xinclude:include</code> element could be replaced
47  * with the content it references. All such changes must be
48  * consistent with the usual rules of well-formedness. For
49  * example, the <code>makeDocType()</code> method should not
50  * return a list containing two <code>DocType</code> objects
51  * because an XML document can have at most one document type
52  * declaration. Nor should it return a list containing an element,
53  * because an element cannot appear in a document prolog. However,
54  * it could return a list containing any number of comments and
55  * processing instructions, and not more than one <code>DocType</code>
56  * object.
57  * </p>
58  *
59  * @author Elliotte Rusty Harold
60  * @version 1.0
61  *
62  */

63 public class NodeFactory {
64
65     /**
66      * <p>
67      * Constructs a new node factory.
68      * </p>
69      *
70      */

71     public NodeFactory() {}
72     
73     /**
74      * <p>
75      * Creates a new element in the specified namespace
76      * with the specified name. The builder calls this
77      * method to make the root element of the document.
78      * </p>
79      *
80      * <p>
81      * Subclasses may change the name, namespace, content, or other
82      * characteristics of the element returned.
83      * The default implementation merely calls
84      * <code>startMakingElement</code>. However, when subclassing, it
85      * is often useful to be able to easily distinguish between the
86      * root element and a non-root element because the root element
87      * cannot be detached. Therefore, subclasses must not return null
88      * from this method. Doing so will cause a
89      * <code>NullPointerException</code>.
90      * </p>
91      *
92      * @param name the qualified name of the element
93      * @param namespace the namespace URI of the element
94      *
95      * @return the new root element
96      */

97     public Element makeRootElement(String JavaDoc name, String JavaDoc namespace) {
98         return startMakingElement(name, namespace);
99     }
100
101     
102     /**
103      * <p>
104      * Creates a new <code>Element</code> in the specified namespace
105      * with the specified name.
106      * </p>
107      *
108      * <p>
109      * Subclasses may change the name, namespace, content, or other
110      * characteristics of the <code>Element</code> returned.
111      * Subclasses may return null to indicate the
112      * <code>Element</code> should not be created.
113      * However, doing so will only remove the element's start-tag and
114      * end-tag from the result tree. Any content inside the element
115      * will be attached to the element's parent by default, unless it
116      * too is filtered. To remove an entire element, return an empty
117      * <code>Nodes</code> object from the
118      * <code>finishMakingElement()</code> method.
119      * </p>
120      *
121      * @param name the qualified name of the element
122      * @param namespace the namespace URI of the element
123      *
124      * @return the new element
125      */

126     public Element startMakingElement(String JavaDoc name, String JavaDoc namespace) {
127         return new Element(name, namespace);
128     }
129    
130     
131     /**
132      * <p>
133      * Signals the end of an element. This method should return
134      * the <code>Nodes</code> to be added to the tree.
135      * They need not contain the <code>Element</code> that
136      * was passed to this method, though most often they will.
137      * By default the <code>Nodes</code> returned contain
138      * only the built element. However, subclasses may return
139      * a list containing any number of nodes, all of which will be
140      * added to the tree at the current position in the order given by
141      * the list (subject to the usual well-formedness constraints, of
142      * course. For instance, the list should not contain a
143      * <code>DocType</code> object unless the element is the root
144      * element, and the document does not already have a
145      * <code>DocType</code>). All of the nodes returned must be
146      * parentless. If this method returns an empty list,
147      * then the element (including all its contents) is not included
148      * in the finished document.
149      * </p>
150      *
151      * <p>
152      * To process an element at a time, override this method in a
153      * subclass so that it functions as a callback. When you're done
154      * processing the <code>Element</code>, return an empty list so
155      * that it will be removed from the tree and garbage collected.
156      * Be careful not to return an empty list for the root element
157      * though. That is, when the element passed to this method is the
158      * root element, the list returned must contain exactly one
159      * <code>Element</code> object. The simplest way to check this
160      * is testing if <code>element.getParent() instanceof
161      * Document</code>.
162      * </p>
163      *
164      * <p>
165      * Do not detach <code>element</code> or any of its ancestors
166      * while inside this method. Doing so can royally muck up the
167      * build.
168      * </p>
169      *
170      * @param element the finished <code>Element</code>
171      *
172      * @return the nodes to be added to the tree
173      *
174      */

175     public Nodes finishMakingElement(Element element) {
176         return new Nodes(element);
177     }
178
179
180     /**
181      * <p>
182      * Creates a new <code>Document</code> object.
183      * The root element of this document is initially set to
184      * <code>&lt;root xmlns=http://www.xom.nu/fakeRoot""/></code>.
185      * This is only temporary. As soon as the real root element's
186      * start-tag is read, this element is replaced by the real root.
187      * This fake root should never be exposed.
188      * </p>
189      *
190      * <p>
191      * The builder calls this method at the beginning of
192      * each document, before it calls any other method in this class.
193      * Thus this is a useful place to perform per-document
194      * initialization tasks.
195      * </p>
196      *
197      * <p>
198      * Subclasses may change the root element, content,
199      * or other characteristics of the document
200      * returned. However, this method must not return null
201      * or the builder will throw a <code>ParsingException</code>.
202      * </p>
203      *
204      * @return the newly created <code>Document</code>
205      */

206     public Document startMakingDocument() {
207         return new Document(
208           Element.build("root", "http://www.xom.nu/fakeRoot")
209         );
210     }
211     
212     
213     /**
214      * <p>
215      * Signals the end of a document. The default implementation of
216      * this method does nothing. The builder does not
217      * call this method if an exception is thrown while building
218      * a document.
219      * </p>
220      *
221      * @param document the completed <code>Document</code>
222      */

223     public void finishMakingDocument(Document document) {}
224
225     
226     /**
227      * <p>
228      * Returns a new <code>Nodes</code> object containing an
229      * attribute in the specified namespace
230      * with the specified name and type.
231      * </p>
232      *
233      * <p>
234      * Subclasses may change the nodes returned from this method.
235      * They may return a <code>Nodes</code> object containing any
236      * number of children and attributes which are appended and
237      * added to the current parent element. This <code>Nodes</code>
238      * object may not contain any <code>Document</code> objects.
239      * All of the nodes returned must be parentless.
240      * Subclasses may return an empty <code>Nodes</code> to indicate
241      * the attribute should not be created.
242      * </p>
243      *
244      * @param name the prefixed name of the attribute
245      * @param URI the namespace URI
246      * @param value the attribute value
247      * @param type the attribute type
248      *
249      * @return the nodes to be added to the tree
250      */

251     public Nodes makeAttribute(String JavaDoc name, String JavaDoc URI,
252       String JavaDoc value, Attribute.Type type) {
253         return new Nodes(new Attribute(name, URI, value, type));
254     }
255
256     
257     /**
258      * <p>
259      * Returns a new <code>Nodes</code> object containing a
260      * comment with the specified text.
261      * </p>
262      *
263      * <p>
264      * Subclasses may change the content or other
265      * characteristics of the comment returned.
266      * Subclasses may change the nodes returned from this method.
267      * They may return a <code>Nodes</code> object containing any
268      * number of children and attributes which are appended and
269      * added to the current parent element. This <code>Nodes</code>
270      * object should not contain any <code>Document</code> objects.
271      * All of the nodes returned must be parentless.
272      * Subclasses may return an empty <code>Nodes</code> to indicate
273      * the comment should not be included in the
274      * finished document.
275      * </p>
276      *
277      * @param data the complete text content of the comment
278      *
279      * @return the nodes to be added to the tree
280      */

281     public Nodes makeComment(String JavaDoc data) {
282         return new Nodes(new Comment(data));
283     }
284
285     
286     /**
287      * <p>
288      * Returns a new <code>Nodes</code> object containing a
289      * <code>DocType</code> object with the specified root element
290      * name, system ID, and public ID.
291      * </p>
292      *
293      * <p>
294      * Subclasses may change the root element name, public ID,
295      * system ID, or other characteristics of the <code>DocType</code>
296      * returned. Subclasses may change the nodes returned from this
297      * method. They may return a <code>Nodes</code> object containing
298      * any number of comments and processing instructions which are
299      * appended to the current parent node. This <code>Nodes</code>
300      * object may not contain any <code>Document</code>,
301      * <code>Element</code>, <code>Attribute</code>, or
302      * <code>Text</code> objects. All of the nodes returned must be
303      * parentless. Subclasses may return an empty <code>Nodes</code> to
304      * indicate the <code>DocType</code> should not be included in the
305      * finished document.
306      * </p>
307      *
308      * @param rootElementName the declared, qualified name
309      * for the root element
310      * @param publicID the public ID of the external DTD subset
311      * @param systemID the URL of the external DTD subset
312      *
313      * @return the nodes to be added to the document
314      */

315     public Nodes makeDocType(String JavaDoc rootElementName,
316       String JavaDoc publicID, String JavaDoc systemID) {
317         return new Nodes(new DocType(rootElementName, publicID, systemID));
318     }
319
320
321     /**
322      * <p>
323      * Returns a new <code>Nodes</code> object containing a
324      * text node with the specified content.
325      * </p>
326      *
327      * <p>
328      * Subclasses may change the content or other characteristics of
329      * the text returned. Subclasses may also change the nodes
330      * returned from this method. They may return a <code>Nodes</code>
331      * object containing any number of nodes which are added or
332      * appended to the current parent node. This <code>Nodes</code>
333      * object must not contain any <code>Document</code> nodes. All of
334      * the nodes returned must be parentless. Subclasses may return an
335      * empty <code>Nodes</code> to indicate the text should not be
336      * included in the finished document.
337      * </p>
338      *
339      * @param data the complete text content of the node
340      *
341      * @return the nodes to be added to the tree
342      */

343     public Nodes makeText(String JavaDoc data) {
344         return new Nodes(new Text(data));
345     }
346
347     
348     /**
349      * <p>
350      * Returns a new <code>Nodes</code> object containing a
351      * <code>CDATASection</code> node with the specified content.
352      * </p>
353      *
354      * @param data the complete text content of the node
355      *
356      * @return the nodes to be added to the tree
357      */

358     Nodes makeCDATASection(String JavaDoc data) {
359         return makeText(data);
360     }
361
362
363     /**
364      * <p>
365      * Returns a new <code>Nodes</code> object containing a
366      * new <code>ProcessingInstruction</code> object with
367      * the specified target and data.
368      * </p>
369      *
370      * <p>
371      * Subclasses may change the target, data, or other
372      * characteristics of the <code>ProcessingInstruction</code>
373      * returned. Subclasses may change the nodes returned from this
374      * method. They may return a <code>Nodes</code> object containing
375      * any number of nodes which are added or
376      * appended to the current parent node. This <code>Nodes</code>
377      * object must not contain any <code>Document</code> nodes.
378      * If the processing instruction appears in the prolog or epilog
379      * of the document, then it must also not contain any
380      * <code>Element</code>, <code>Attribute</code>, or
381      * <code>Text</code> objects.
382      * All of the nodes returned must be parentless. Subclasses
383      * may return an empty <code>Nodes</code> to indicate the
384      * processing instruction should not be included in the
385      * finished document.
386      * </p>
387      *
388      * @param target the target of the processing instruction
389      * @param data the data of the processing instruction
390      *
391      * @return the nodes to be added to the tree
392      */

393     public Nodes makeProcessingInstruction(
394       String JavaDoc target, String JavaDoc data) {
395         return new Nodes(new ProcessingInstruction(target, data));
396     }
397
398     
399     void addAttribute(Element element, Attribute attribute) {
400         element.addAttribute(attribute);
401     }
402   
403     
404     void insertChild(Element element, Node child, int position) {
405         element.insertChild(child, position);
406     }
407   
408     
409 }
410
Popular Tags