comparison NGSrich_0.5.5/src/org/jdom/transform/JDOMResult.java @ 0:89ad0a9cca52 default tip

Uploaded
author pfrommolt
date Mon, 21 Nov 2011 08:12:19 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:89ad0a9cca52
1 /*--
2
3 $Id: JDOMResult.java,v 1.24 2007/11/10 05:29:02 jhunter Exp $
4
5 Copyright (C) 2001-2007 Jason Hunter & Brett McLaughlin.
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
10 are met:
11
12 1. Redistributions of source code must retain the above copyright
13 notice, this list of conditions, and the following disclaimer.
14
15 2. Redistributions in binary form must reproduce the above copyright
16 notice, this list of conditions, and the disclaimer that follows
17 these conditions in the documentation and/or other materials
18 provided with the distribution.
19
20 3. The name "JDOM" must not be used to endorse or promote products
21 derived from this software without prior written permission. For
22 written permission, please contact <request_AT_jdom_DOT_org>.
23
24 4. Products derived from this software may not be called "JDOM", nor
25 may "JDOM" appear in their name, without prior written permission
26 from the JDOM Project Management <request_AT_jdom_DOT_org>.
27
28 In addition, we request (but do not require) that you include in the
29 end-user documentation provided with the redistribution and/or in the
30 software itself an acknowledgement equivalent to the following:
31 "This product includes software developed by the
32 JDOM Project (http://www.jdom.org/)."
33 Alternatively, the acknowledgment may be graphical using the logos
34 available at http://www.jdom.org/images/logos.
35
36 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT
40 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 SUCH DAMAGE.
48
49 This software consists of voluntary contributions made by many
50 individuals on behalf of the JDOM Project and was originally
51 created by Jason Hunter <jhunter_AT_jdom_DOT_org> and
52 Brett McLaughlin <brett_AT_jdom_DOT_org>. For more information
53 on the JDOM Project, please see <http://www.jdom.org/>.
54
55 */
56
57 package org.jdom.transform;
58
59 import java.util.*;
60
61 import javax.xml.transform.sax.*;
62
63 import org.jdom.*;
64 import org.jdom.input.*;
65 import org.xml.sax.*;
66 import org.xml.sax.ext.*;
67 import org.xml.sax.helpers.*;
68
69 /**
70 * A holder for an XSL Transformation result, generally a list of nodes
71 * although it can be a JDOM Document also. As stated by the XSLT 1.0
72 * specification, the result tree generated by an XSL transformation is not
73 * required to be a well-formed XML document. The result tree may have "any
74 * sequence of nodes as children that would be possible for an
75 * element node".
76 * <p>
77 * The following example shows how to apply an XSL Transformation
78 * to a JDOM document and get the transformation result in the form
79 * of a list of JDOM nodes:
80 * <pre><code>
81 * public static List transform(Document doc, String stylesheet)
82 * throws JDOMException {
83 * try {
84 * Transformer transformer = TransformerFactory.newInstance()
85 * .newTransformer(new StreamSource(stylesheet));
86 * JDOMSource in = new JDOMSource(doc);
87 * JDOMResult out = new JDOMResult();
88 * transformer.transform(in, out);
89 * return out.getResult();
90 * }
91 * catch (TransformerException e) {
92 * throw new JDOMException("XSLT Transformation failed", e);
93 * }
94 * }
95 * </code></pre>
96 *
97 * @see org.jdom.transform.JDOMSource
98 *
99 * @version $Revision: 1.24 $, $Date: 2007/11/10 05:29:02 $
100 * @author Laurent Bihanic
101 * @author Jason Hunter
102 */
103 public class JDOMResult extends SAXResult {
104
105 private static final String CVS_ID =
106 "@(#) $RCSfile: JDOMResult.java,v $ $Revision: 1.24 $ $Date: 2007/11/10 05:29:02 $ $Name: jdom_1_1_1 $";
107
108 /**
109 * If {@link javax.xml.transform.TransformerFactory#getFeature}
110 * returns <code>true</code> when passed this value as an
111 * argument, the Transformer natively supports JDOM.
112 * <p>
113 * <strong>Note</strong>: This implementation does not override
114 * the {@link SAXResult#FEATURE} value defined by its superclass
115 * to be considered as a SAXResult by Transformer implementations
116 * not natively supporting JDOM.</p>
117 */
118 public final static String JDOM_FEATURE =
119 "http://org.jdom.transform.JDOMResult/feature";
120
121 /**
122 * The result of a transformation, as set by Transformer
123 * implementations that natively support JDOM, as a JDOM document
124 * or a list of JDOM nodes.
125 */
126 private Object result = null;
127
128 /**
129 * Whether the application queried the result (as a list or a
130 * document) since it was last set.
131 */
132 private boolean queried = false;
133
134 /**
135 * The custom JDOM factory to use when building the transformation
136 * result or <code>null</code> to use the default JDOM classes.
137 */
138 private JDOMFactory factory = null;
139
140 /**
141 * Public default constructor.
142 */
143 public JDOMResult() {
144 // Allocate custom builder object...
145 DocumentBuilder builder = new DocumentBuilder();
146
147 // And use it as ContentHandler and LexicalHandler.
148 super.setHandler(builder);
149 super.setLexicalHandler(builder);
150 }
151
152 /**
153 * Sets the object(s) produced as result of an XSL Transformation.
154 * <p>
155 * <strong>Note</strong>: This method shall be used by the
156 * {@link javax.xml.transform.Transformer} implementations that
157 * natively support JDOM to directly set the transformation
158 * result rather than considering this object as a
159 * {@link SAXResult}. Applications should <i>not</i> use this
160 * method.</p>
161 *
162 * @param result the result of a transformation as a
163 * {@link java.util.List list} of JDOM nodes
164 * (Elements, Texts, Comments, PIs...).
165 *
166 * @see #getResult
167 */
168 public void setResult(List result) {
169 this.result = result;
170 this.queried = false;
171 }
172
173 /**
174 * Returns the result of an XSL Transformation as a list of JDOM
175 * nodes.
176 * <p>
177 * If the result of the transformation is a JDOM document,
178 * this method converts it into a list of JDOM nodes; any
179 * subsequent call to {@link #getDocument} will return
180 * <code>null</code>.</p>
181 *
182 * @return the transformation result as a (possibly empty) list of
183 * JDOM nodes (Elements, Texts, Comments, PIs...).
184 */
185 public List getResult() {
186 List nodes = Collections.EMPTY_LIST;
187
188 // Retrieve result from the document builder if not set.
189 this.retrieveResult();
190
191 if (result instanceof List) {
192 nodes = (List)result;
193 }
194 else {
195 if ((result instanceof Document) && (queried == false)) {
196 List content = ((Document)result).getContent();
197 nodes = new ArrayList(content.size());
198
199 while (content.size() != 0)
200 {
201 Object o = content.remove(0);
202 nodes.add(o);
203 }
204 result = nodes;
205 }
206 }
207 queried = true;
208
209 return (nodes);
210 }
211
212 /**
213 * Sets the document produced as result of an XSL Transformation.
214 * <p>
215 * <strong>Note</strong>: This method shall be used by the
216 * {@link javax.xml.transform.Transformer} implementations that
217 * natively support JDOM to directly set the transformation
218 * result rather than considering this object as a
219 * {@link SAXResult}. Applications should <i>not</i> use this
220 * method.</p>
221 *
222 * @param document the JDOM document result of a transformation.
223 *
224 * @see #setResult
225 * @see #getDocument
226 */
227 public void setDocument(Document document) {
228 this.result = document;
229 this.queried = false;
230 }
231
232 /**
233 * Returns the result of an XSL Transformation as a JDOM document.
234 * <p>
235 * If the result of the transformation is a list of nodes,
236 * this method attempts to convert it into a JDOM document. If
237 * successful, any subsequent call to {@link #getResult} will
238 * return an empty list.</p>
239 * <p>
240 * <strong>Warning</strong>: The XSLT 1.0 specification states that
241 * the output of an XSL transformation is not a well-formed XML
242 * document but a list of nodes. Applications should thus use
243 * {@link #getResult} instead of this method or at least expect
244 * <code>null</code> documents to be returned.
245 *
246 * @return the transformation result as a JDOM document or
247 * <code>null</code> if the result of the transformation
248 * can not be converted into a well-formed document.
249 *
250 * @see #getResult
251 */
252 public Document getDocument() {
253 Document doc = null;
254
255 // Retrieve result from the document builder if not set.
256 this.retrieveResult();
257
258 if (result instanceof Document) {
259 doc = (Document)result;
260 }
261 else {
262 if ((result instanceof List) && (queried == false)) {
263 // Try to create a document from the result nodes
264 try {
265 JDOMFactory f = this.getFactory();
266 if (f == null) { f = new DefaultJDOMFactory(); }
267
268 doc = f.document(null);
269 doc.setContent((List)result);
270
271 result = doc;
272 }
273 catch (RuntimeException ex1) {
274 // Some of the result nodes are not valid children of a
275 // Document node. => return null.
276 }
277 }
278 }
279 queried = true;
280
281 return (doc);
282 }
283
284 /**
285 * Sets a custom JDOMFactory to use when building the
286 * transformation result. Use a custom factory to build the tree
287 * with your own subclasses of the JDOM classes.
288 *
289 * @param factory the custom <code>JDOMFactory</code> to use or
290 * <code>null</code> to use the default JDOM
291 * classes.
292 *
293 * @see #getFactory
294 */
295 public void setFactory(JDOMFactory factory) {
296 this.factory = factory;
297 }
298
299 /**
300 * Returns the custom JDOMFactory used to build the transformation
301 * result.
302 *
303 * @return the custom <code>JDOMFactory</code> used to build the
304 * transformation result or <code>null</code> if the
305 * default JDOM classes are being used.
306 *
307 * @see #setFactory
308 */
309 public JDOMFactory getFactory() {
310 return this.factory;
311 }
312
313 /**
314 * Checks whether a transformation result has been set and, if not,
315 * retrieves the result tree being built by the document builder.
316 */
317 private void retrieveResult() {
318 if (result == null) {
319 this.setResult(((DocumentBuilder)this.getHandler()).getResult());
320 }
321 }
322
323 //-------------------------------------------------------------------------
324 // SAXResult overwritten methods
325 //-------------------------------------------------------------------------
326
327 /**
328 * Sets the target to be a SAX2 ContentHandler.
329 *
330 * @param handler Must be a non-null ContentHandler reference.
331 */
332 public void setHandler(ContentHandler handler) { }
333
334 /**
335 * Sets the SAX2 LexicalHandler for the output.
336 * <p>
337 * This is needed to handle XML comments and the like. If the
338 * lexical handler is not set, an attempt should be made by the
339 * transformer to cast the ContentHandler to a LexicalHandler.</p>
340 *
341 * @param handler A non-null LexicalHandler for
342 * handling lexical parse events.
343 */
344 public void setLexicalHandler(LexicalHandler handler) { }
345
346
347 //=========================================================================
348 // FragmentHandler nested class
349 //=========================================================================
350
351 private static class FragmentHandler extends SAXHandler {
352 /**
353 * A dummy root element required by SAXHandler that can only
354 * cope with well-formed documents.
355 */
356 private Element dummyRoot = new Element("root", null, null);
357
358 /**
359 * Public constructor.
360 */
361 public FragmentHandler(JDOMFactory factory) {
362 super(factory);
363
364 // Add a dummy root element to the being-built document as XSL
365 // transformation can output node lists instead of well-formed
366 // documents.
367 this.pushElement(dummyRoot);
368 }
369
370 /**
371 * Returns the result of an XSL Transformation.
372 *
373 * @return the transformation result as a (possibly empty) list of
374 * JDOM nodes (Elements, Texts, Comments, PIs...).
375 */
376 public List getResult() {
377 // Flush remaining text content in case the last text segment is
378 // outside an element.
379 try {
380 this.flushCharacters();
381 }
382 catch (SAXException e) { /* Ignore... */ }
383 return this.getDetachedContent(dummyRoot);
384 }
385
386 /**
387 * Returns the content of a JDOM Element detached from it.
388 *
389 * @param elt the element to get the content from.
390 *
391 * @return a (possibly empty) list of JDOM nodes, detached from
392 * their parent.
393 */
394 private List getDetachedContent(Element elt) {
395 List content = elt.getContent();
396 List nodes = new ArrayList(content.size());
397
398 while (content.size() != 0)
399 {
400 Object o = content.remove(0);
401 nodes.add(o);
402 }
403 return (nodes);
404 }
405 }
406
407 //=========================================================================
408 // DocumentBuilder inner class
409 //=========================================================================
410
411 private class DocumentBuilder extends XMLFilterImpl
412 implements LexicalHandler {
413 /**
414 * The actual JDOM document builder.
415 */
416 private FragmentHandler saxHandler = null;
417
418 /**
419 * Whether the startDocument event was received. Some XSLT
420 * processors such as Oracle's do not fire this event.
421 */
422 private boolean startDocumentReceived = false;
423
424 /**
425 * Public default constructor.
426 */
427 public DocumentBuilder() { }
428
429 /**
430 * Returns the result of an XSL Transformation.
431 *
432 * @return the transformation result as a (possibly empty) list of
433 * JDOM nodes (Elements, Texts, Comments, PIs...) or
434 * <code>null</code> if no new transformation occurred
435 * since the result of the previous one was returned.
436 */
437 public List getResult() {
438 List result = null;
439
440 if (this.saxHandler != null) {
441 // Retrieve result from SAX content handler.
442 result = this.saxHandler.getResult();
443
444 // Detach the (non-reusable) SAXHandler instance.
445 this.saxHandler = null;
446
447 // And get ready for the next transformation.
448 this.startDocumentReceived = false;
449 }
450 return result;
451 }
452
453 private void ensureInitialization() throws SAXException {
454 // Trigger document initialization if XSLT processor failed to
455 // fire the startDocument event.
456 if (this.startDocumentReceived == false) {
457 this.startDocument();
458 }
459 }
460
461 //-----------------------------------------------------------------------
462 // XMLFilterImpl overwritten methods
463 //-----------------------------------------------------------------------
464
465 /**
466 * <i>[SAX ContentHandler interface support]</i> Processes a
467 * start of document event.
468 * <p>
469 * This implementation creates a new JDOM document builder and
470 * marks the current result as "under construction".</p>
471 *
472 * @throws SAXException if any error occurred while creating
473 * the document builder.
474 */
475 public void startDocument() throws SAXException {
476 this.startDocumentReceived = true;
477
478 // Reset any previously set result.
479 setResult(null);
480
481 // Create the actual JDOM document builder and register it as
482 // ContentHandler on the superclass (XMLFilterImpl): this
483 // implementation will take care of propagating the LexicalHandler
484 // events.
485 this.saxHandler = new FragmentHandler(getFactory());
486 super.setContentHandler(this.saxHandler);
487
488 // And propagate event.
489 super.startDocument();
490 }
491
492 /**
493 * <i>[SAX ContentHandler interface support]</i> Receives
494 * notification of the beginning of an element.
495 * <p>
496 * This implementation ensures that startDocument() has been
497 * called prior processing an element.
498 *
499 * @param nsURI the Namespace URI, or the empty string if
500 * the element has no Namespace URI or if
501 * Namespace processing is not being performed.
502 * @param localName the local name (without prefix), or the
503 * empty string if Namespace processing is
504 * not being performed.
505 * @param qName the qualified name (with prefix), or the
506 * empty string if qualified names are not
507 * available.
508 * @param atts The attributes attached to the element. If
509 * there are no attributes, it shall be an
510 * empty Attributes object.
511 *
512 * @throws SAXException if any error occurred while creating
513 * the document builder.
514 */
515 public void startElement(String nsURI, String localName, String qName,
516 Attributes atts) throws SAXException
517 {
518 this.ensureInitialization();
519 super.startElement(nsURI, localName, qName, atts);
520 }
521
522 /**
523 * <i>[SAX ContentHandler interface support]</i> Begins the
524 * scope of a prefix-URI Namespace mapping.
525 */
526 public void startPrefixMapping(String prefix, String uri)
527 throws SAXException {
528 this.ensureInitialization();
529 super.startPrefixMapping(prefix, uri);
530 }
531
532 /**
533 * <i>[SAX ContentHandler interface support]</i> Receives
534 * notification of character data.
535 */
536 public void characters(char ch[], int start, int length)
537 throws SAXException {
538 this.ensureInitialization();
539 super.characters(ch, start, length);
540 }
541
542 /**
543 * <i>[SAX ContentHandler interface support]</i> Receives
544 * notification of ignorable whitespace in element content.
545 */
546 public void ignorableWhitespace(char ch[], int start, int length)
547 throws SAXException {
548 this.ensureInitialization();
549 super.ignorableWhitespace(ch, start, length);
550 }
551
552 /**
553 * <i>[SAX ContentHandler interface support]</i> Receives
554 * notification of a processing instruction.
555 */
556 public void processingInstruction(String target, String data)
557 throws SAXException {
558 this.ensureInitialization();
559 super.processingInstruction(target, data);
560 }
561
562 /**
563 * <i>[SAX ContentHandler interface support]</i> Receives
564 * notification of a skipped entity.
565 */
566 public void skippedEntity(String name) throws SAXException {
567 this.ensureInitialization();
568 super.skippedEntity(name);
569 }
570
571 //-----------------------------------------------------------------------
572 // LexicalHandler interface support
573 //-----------------------------------------------------------------------
574
575 /**
576 * <i>[SAX LexicalHandler interface support]</i> Reports the
577 * start of DTD declarations, if any.
578 *
579 * @param name the document type name.
580 * @param publicId the declared public identifier for the
581 * external DTD subset, or <code>null</code>
582 * if none was declared.
583 * @param systemId the declared system identifier for the
584 * external DTD subset, or <code>null</code>
585 * if none was declared.
586 *
587 * @throws SAXException The application may raise an exception.
588 */
589 public void startDTD(String name, String publicId, String systemId)
590 throws SAXException {
591 this.ensureInitialization();
592 this.saxHandler.startDTD(name, publicId, systemId);
593 }
594
595 /**
596 * <i>[SAX LexicalHandler interface support]</i> Reports the end
597 * of DTD declarations.
598 *
599 * @throws SAXException The application may raise an exception.
600 */
601 public void endDTD() throws SAXException {
602 this.saxHandler.endDTD();
603 }
604
605 /**
606 * <i>[SAX LexicalHandler interface support]</i> Reports the
607 * beginning of some internal and external XML entities.
608 *
609 * @param name the name of the entity. If it is a parameter
610 * entity, the name will begin with '%', and if it
611 * is the external DTD subset, it will be "[dtd]".
612 *
613 * @throws SAXException The application may raise an exception.
614 */
615 public void startEntity(String name) throws SAXException {
616 this.ensureInitialization();
617 this.saxHandler.startEntity(name);
618 }
619
620 /**
621 * <i>[SAX LexicalHandler interface support]</i> Reports the end
622 * of an entity.
623 *
624 * @param name the name of the entity that is ending.
625 *
626 * @throws SAXException The application may raise an exception.
627 */
628 public void endEntity(String name) throws SAXException {
629 this.saxHandler.endEntity(name);
630 }
631
632 /**
633 * <i>[SAX LexicalHandler interface support]</i> Reports the
634 * start of a CDATA section.
635 *
636 * @throws SAXException The application may raise an exception.
637 */
638 public void startCDATA() throws SAXException {
639 this.ensureInitialization();
640 this.saxHandler.startCDATA();
641 }
642
643 /**
644 * <i>[SAX LexicalHandler interface support]</i> Reports the end
645 * of a CDATA section.
646 *
647 * @throws SAXException The application may raise an exception.
648 */
649 public void endCDATA() throws SAXException {
650 this.saxHandler.endCDATA();
651 }
652
653 /**
654 * <i>[SAX LexicalHandler interface support]</i> Reports an XML
655 * comment anywhere in the document.
656 *
657 * @param ch an array holding the characters in the comment.
658 * @param start the starting position in the array.
659 * @param length the number of characters to use from the array.
660 *
661 * @throws SAXException The application may raise an exception.
662 */
663 public void comment(char ch[], int start, int length)
664 throws SAXException {
665 this.ensureInitialization();
666 this.saxHandler.comment(ch, start, length);
667 }
668 }
669 }
670