001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.xml.dom;
018:
019: import org.apache.avalon.framework.CascadingRuntimeException;
020:
021: import org.apache.cocoon.xml.AbstractXMLPipe;
022:
023: import org.w3c.dom.Document;
024: import org.w3c.dom.Node;
025: import org.xml.sax.SAXException;
026:
027: import javax.xml.transform.TransformerFactory;
028: import javax.xml.transform.dom.DOMResult;
029: import javax.xml.transform.sax.SAXTransformerFactory;
030: import javax.xml.transform.sax.TransformerHandler;
031:
032: /**
033: * The <code>DOMBuilder</code> is a utility class that will generate a W3C
034: * DOM Document from SAX events.
035: *
036: * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
037: * @version $Id: DOMBuilder.java 433543 2006-08-22 06:22:54Z crossley $
038: */
039: public class DOMBuilder extends AbstractXMLPipe {
040:
041: /** The default transformer factory shared by all instances */
042: protected static final SAXTransformerFactory FACTORY = (SAXTransformerFactory) TransformerFactory
043: .newInstance();
044:
045: /** The transformer factory */
046: protected SAXTransformerFactory factory;
047:
048: /** The listener */
049: protected Listener listener;
050:
051: /** The result */
052: protected DOMResult result;
053:
054: /** The parentNode */
055: protected Node parentNode;
056:
057: /**
058: * Construct a new instance of this DOMBuilder.
059: */
060: public DOMBuilder() {
061: this ((Listener) null, (Node) null);
062: }
063:
064: /**
065: * Construct a new instance of this DOMBuilder.
066: */
067: public DOMBuilder(SAXTransformerFactory factory) {
068: this (factory, null, null);
069: }
070:
071: /**
072: * Construct a new instance of this DOMBuilder.
073: * @deprecated Use DOMBuilder() instead.
074: */
075: public DOMBuilder(DOMFactory factory) {
076: this ((Listener) null, (Node) null);
077: }
078:
079: /**
080: * Construct a new instance of this DOMBuilder.
081: */
082: public DOMBuilder(Listener listener) {
083: this (listener, null);
084: }
085:
086: /**
087: * Construct a new instance of this DOMBuilder.
088: * @deprecated Use DOMBuilder(listener) instead.
089: */
090: public DOMBuilder(DOMFactory factory, Listener listener) {
091: this (listener, null);
092: }
093:
094: /**
095: * Construct a new instance of this DOMBuilder.
096: * @deprecated Use DOMBuilder(listener, parentNode) instead.
097: */
098: public DOMBuilder(DOMFactory domFactory, Listener listener,
099: Node parentNode) {
100: this (listener, parentNode);
101: }
102:
103: /**
104: * Constructs a new instance that appends nodes to the given parent node.
105: * <br/>
106: * <strong>Note:</strong> You cannot use a <code>Listener<code> when appending to a
107: * <code>Node</code>, because the notification occurs at <code>endDocument()</code>
108: * which does not happen here.
109: */
110: public DOMBuilder(Node parentNode) {
111: this (null, parentNode);
112: }
113:
114: /**
115: * Construct a new instance of this DOMBuilder.
116: */
117: public DOMBuilder(Listener listener, Node parentNode) {
118: this ((SAXTransformerFactory) null, listener, parentNode);
119: }
120:
121: /**
122: * Construct a new instance of this DOMBuilder.
123: */
124: public DOMBuilder(SAXTransformerFactory factory, Listener listener,
125: Node parentNode) {
126: super ();
127: this .factory = factory == null ? FACTORY : factory;
128: this .listener = listener;
129: this .parentNode = parentNode;
130: setup();
131: }
132:
133: /**
134: * Setup this instance transformer and result objects.
135: */
136: private void setup() {
137: try {
138: TransformerHandler handler = this .factory
139: .newTransformerHandler();
140: setContentHandler(handler);
141: setLexicalHandler(handler);
142: if (this .parentNode != null) {
143: this .result = new DOMResult(this .parentNode);
144: } else {
145: this .result = new DOMResult();
146: }
147: handler.setResult(this .result);
148: } catch (javax.xml.transform.TransformerException local) {
149: throw new CascadingRuntimeException(
150: "Fatal-Error: Unable to get transformer handler",
151: local);
152: }
153: }
154:
155: /**
156: * Recycle this builder, prepare for re-use.
157: */
158: public void recycle() {
159: super .recycle();
160: setup();
161: }
162:
163: /**
164: * Return the newly built Document.
165: */
166: public Document getDocument() {
167: if (this .result == null || this .result.getNode() == null) {
168: return null;
169: } else if (this .result.getNode().getNodeType() == Node.DOCUMENT_NODE) {
170: return (Document) this .result.getNode();
171: } else {
172: return this .result.getNode().getOwnerDocument();
173: }
174: }
175:
176: /**
177: * Receive notification of the end of a document.
178: *
179: * @exception SAXException If this method was not called appropriately.
180: */
181: public void endDocument() throws SAXException {
182: super .endDocument();
183: // Notify the listener
184: notifyListener();
185: }
186:
187: /**
188: * Receive notification of a successfully completed DOM tree generation.
189: */
190: protected void notifyListener() throws SAXException {
191: if (this .listener != null) {
192: this .listener.notify(getDocument());
193: }
194: }
195:
196: /**
197: * The Listener interface must be implemented by those objects willing to
198: * be notified of a successful DOM tree generation.
199: */
200: public interface Listener {
201:
202: /**
203: * Receive notification of a successfully completed DOM tree generation.
204: */
205: void notify(Document doc) throws SAXException;
206: }
207: }
|