1
/* Copyright 2002-2005 Elliotte Rusty Harold
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.
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.
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
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/
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.
35
* Subclassing this class allows builders to produce
36
* instance of subclasses (for example,
37
* <code>HTMLElement</code>) instead of the
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>
59
* @author Elliotte Rusty Harold
63
public class NodeFactory {
67
* Constructs a new node factory.
71
public NodeFactory() {}
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.
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>.
92
* @param name the qualified name of the element
93
* @param namespace the namespace URI of the element
95
* @return the new root element
97
public Element makeRootElement(String name, String namespace) {
98
return startMakingElement(name, namespace);
104
* Creates a new <code>Element</code> in the specified namespace
105
* with the specified name.
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.
121
* @param name the qualified name of the element
122
* @param namespace the namespace URI of the element
124
* @return the new element
126
public Element startMakingElement(String name, String namespace) {
127
return new Element(name, namespace);
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.
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
165
* Do not detach <code>element</code> or any of its ancestors
166
* while inside this method. Doing so can royally muck up the
170
* @param element the finished <code>Element</code>
172
* @return the nodes to be added to the tree
175
public Nodes finishMakingElement(Element element) {
176
return new Nodes(element);
182
* Creates a new <code>Document</code> object.
183
* The root element of this document is initially set to
184
* <code><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.
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.
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>.
204
* @return the newly created <code>Document</code>
206
public Document startMakingDocument() {
208
Element.build("root", "http://www.xom.nu/fakeRoot", "root")
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
221
* @param document the completed <code>Document</code>
223
public void finishMakingDocument(Document document) {}
228
* Returns a new <code>Nodes</code> object containing an
229
* attribute in the specified namespace
230
* with the specified name and type.
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.
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
249
* @return the nodes to be added to the tree
251
public Nodes makeAttribute(String name, String URI,
252
String value, Attribute.Type type) {
253
return new Nodes(new Attribute(name, URI, value, type));
259
* Returns a new <code>Nodes</code> object containing a
260
* comment with the specified text.
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
277
* @param data the complete text content of the comment
279
* @return the nodes to be added to the tree
281
public Nodes makeComment(String data) {
282
return new Nodes(new Comment(data));
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.
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
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
313
* @return the nodes to be added to the document
315
public Nodes makeDocType(String rootElementName,
316
String publicID, String systemID) {
317
return new Nodes(new DocType(rootElementName, publicID, systemID));
323
* Returns a new <code>Nodes</code> object containing a
324
* text node with the specified content.
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.
339
* @param data the complete text content of the node
341
* @return the nodes to be added to the tree
343
public Nodes makeText(String data) {
344
return new Nodes(new Text(data));
350
* Returns a new <code>Nodes</code> object containing a
351
* <code>CDATASection</code> node with the specified content.
354
* @param data the complete text content of the node
356
* @return the nodes to be added to the tree
358
Nodes makeCDATASection(String data) {
359
return makeText(data);
365
* Returns a new <code>Nodes</code> object containing a
366
* new <code>ProcessingInstruction</code> object with
367
* the specified target and data.
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
388
* @param target the target of the processing instruction
389
* @param data the data of the processing instruction
391
* @return the nodes to be added to the tree
393
public Nodes makeProcessingInstruction(
394
String target, String data) {
395
return new Nodes(new ProcessingInstruction(target, data));
399
void addAttribute(Element element, Attribute attribute) {
400
element.addAttribute(attribute);
404
void insertChild(Element element, Node child, int position) {
405
element.insertChild(child, position);