View Javadoc
1   /*
2    * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package javax.xml.transform.dom;
27  
28  import javax.xml.transform.Result;
29  import org.w3c.dom.Node;
30  
31  /**
32   * <p>Acts as a holder for a transformation result tree in the form of a Document Object Model (DOM) tree.</p>
33   *
34   * <p>If no output DOM source is set, the transformation will create a Document node as the holder for the result of the transformation,
35   * which may be retrieved with {@link #getNode()}.</p>
36   *
37   * @author <a href="Jeff.Suttor@Sun.com">Jeff Suttor</a>
38   */
39  public class DOMResult implements Result {
40  
41      /** <p>If {@link javax.xml.transform.TransformerFactory#getFeature}
42       * returns <code>true</code> when passed this value as an argument,
43       * the <code>Transformer</code> supports <code>Result</code> output of this type.</p>
44       */
45      public static final String FEATURE = "http://javax.xml.transform.dom.DOMResult/feature";
46  
47      /**
48       * <p>Zero-argument default constructor.</p>
49       *
50       * <p><code>node</code>,
51       * <code>siblingNode</code> and
52       * <code>systemId</code>
53       * will be set to <code>null</code>.</p>
54       */
55      public DOMResult() {
56          setNode(null);
57          setNextSibling(null);
58          setSystemId(null);
59      }
60  
61      /**
62       * <p>Use a DOM node to create a new output target.</p>
63       *
64       * <p>In practice, the node should be
65       * a {@link org.w3c.dom.Document} node,
66       * a {@link org.w3c.dom.DocumentFragment} node, or
67       * a {@link org.w3c.dom.Element} node.
68       * In other words, a node that accepts children.</p>
69       *
70       * <p><code>siblingNode</code> and
71       * <code>systemId</code>
72       * will be set to <code>null</code>.</p>
73       *
74       * @param node The DOM node that will contain the result tree.
75       */
76      public DOMResult(Node node) {
77          setNode(node);
78          setNextSibling(null);
79          setSystemId(null);
80      }
81  
82      /**
83       * <p>Use a DOM node to create a new output target with the specified System ID.<p>
84       *
85       * <p>In practice, the node should be
86       * a {@link org.w3c.dom.Document} node,
87       * a {@link org.w3c.dom.DocumentFragment} node, or
88       * a {@link org.w3c.dom.Element} node.
89       * In other words, a node that accepts children.</p>
90       *
91       * <p><code>siblingNode</code> will be set to <code>null</code>.</p>
92       *
93       * @param node The DOM node that will contain the result tree.
94       * @param systemId The system identifier which may be used in association with this node.
95       */
96      public DOMResult(Node node, String systemId) {
97          setNode(node);
98          setNextSibling(null);
99          setSystemId(systemId);
100     }
101 
102     /**
103      * <p>Use a DOM node to create a new output target specifying the child node where the result nodes should be inserted before.</p>
104      *
105      * <p>In practice, <code>node</code> and <code>nextSibling</code> should be
106      * a {@link org.w3c.dom.Document} node,
107      * a {@link org.w3c.dom.DocumentFragment} node, or
108      * a {@link org.w3c.dom.Element} node.
109      * In other words, a node that accepts children.</p>
110      *
111      * <p>Use <code>nextSibling</code> to specify the child node
112      * where the result nodes should be inserted before.
113      * If <code>nextSibling</code> is not a sibling of <code>node</code>,
114      * then an <code>IllegalArgumentException</code> is thrown.
115      * If <code>node</code> is <code>null</code> and <code>nextSibling</code> is not <code>null</code>,
116      * then an <code>IllegalArgumentException</code> is thrown.
117      * If <code>nextSibling</code> is <code>null</code>,
118      * then the behavior is the same as calling {@link #DOMResult(Node node)},
119      * i.e. append the result nodes as the last child of the specified <code>node</code>.</p>
120      *
121      * <p><code>systemId</code> will be set to <code>null</code>.</p>
122      *
123      * @param node The DOM node that will contain the result tree.
124      * @param nextSibling The child node where the result nodes should be inserted before.
125      *
126      * @throws IllegalArgumentException If <code>nextSibling</code> is not a sibling of <code>node</code> or
127      *   <code>node</code> is <code>null</code> and <code>nextSibling</code>
128      *   is not <code>null</code>.
129      *
130      * @since 1.5
131      */
132     public DOMResult(Node node, Node nextSibling) {
133 
134         // does the corrent parent/child relationship exist?
135         if (nextSibling != null) {
136             // cannot be a sibling of a null node
137             if (node == null) {
138                 throw new IllegalArgumentException("Cannot create a DOMResult when the nextSibling is contained by the \"null\" node.");
139             }
140 
141             // nextSibling contained by node?
142             if ((node.compareDocumentPosition(nextSibling)&Node.DOCUMENT_POSITION_CONTAINED_BY)==0) {
143                 throw new IllegalArgumentException("Cannot create a DOMResult when the nextSibling is not contained by the node.");
144             }
145         }
146 
147         setNode(node);
148         setNextSibling(nextSibling);
149         setSystemId(null);
150     }
151 
152     /**
153      * <p>Use a DOM node to create a new output target specifying the child node where the result nodes should be inserted before and
154      * the specified System ID.</p>
155      *
156      * <p>In practice, <code>node</code> and <code>nextSibling</code> should be
157      * a {@link org.w3c.dom.Document} node,
158      * a {@link org.w3c.dom.DocumentFragment} node, or a
159      * {@link org.w3c.dom.Element} node.
160      * In other words, a node that accepts children.</p>
161      *
162      * <p>Use <code>nextSibling</code> to specify the child node
163      * where the result nodes should be inserted before.
164      * If <code>nextSibling</code> is not a sibling of <code>node</code>,
165      * then an <code>IllegalArgumentException</code> is thrown.
166      * If <code>node</code> is <code>null</code> and <code>nextSibling</code> is not <code>null</code>,
167      * then an <code>IllegalArgumentException</code> is thrown.
168      * If <code>nextSibling</code> is <code>null</code>,
169      * then the behavior is the same as calling {@link #DOMResult(Node node, String systemId)},
170      * i.e. append the result nodes as the last child of the specified node and use the specified System ID.</p>
171      *
172      * @param node The DOM node that will contain the result tree.
173      * @param nextSibling The child node where the result nodes should be inserted before.
174      * @param systemId The system identifier which may be used in association with this node.
175      *
176      * @throws IllegalArgumentException If <code>nextSibling</code> is not a
177      *   sibling of <code>node</code> or
178      *   <code>node</code> is <code>null</code> and <code>nextSibling</code>
179      *   is not <code>null</code>.
180      *
181      * @since 1.5
182      */
183     public DOMResult(Node node, Node nextSibling, String systemId) {
184 
185         // does the corrent parent/child relationship exist?
186         if (nextSibling != null) {
187             // cannot be a sibling of a null node
188             if (node == null) {
189                 throw new IllegalArgumentException("Cannot create a DOMResult when the nextSibling is contained by the \"null\" node.");
190             }
191 
192             // nextSibling contained by node?
193             if ((node.compareDocumentPosition(nextSibling)&Node.DOCUMENT_POSITION_CONTAINED_BY)==0) {
194                 throw new IllegalArgumentException("Cannot create a DOMResult when the nextSibling is not contained by the node.");
195             }
196         }
197 
198         setNode(node);
199         setNextSibling(nextSibling);
200         setSystemId(systemId);
201     }
202 
203     /**
204      * <p>Set the node that will contain the result DOM tree.<p>
205      *
206      * <p>In practice, the node should be
207      * a {@link org.w3c.dom.Document} node,
208      * a {@link org.w3c.dom.DocumentFragment} node, or
209      * a {@link org.w3c.dom.Element} node.
210      * In other words, a node that accepts children.</p>
211      *
212      * <p>An <code>IllegalStateException</code> is thrown if
213      * <code>nextSibling</code> is not <code>null</code> and
214      * <code>node</code> is not a parent of <code>nextSibling</code>.
215      * An <code>IllegalStateException</code> is thrown if <code>node</code> is <code>null</code> and
216      * <code>nextSibling</code> is not <code>null</code>.</p>
217      *
218      * @param node The node to which the transformation will be appended.
219      *
220      * @throws IllegalStateException If <code>nextSibling</code> is not
221      *   <code>null</code> and
222      *   <code>nextSibling</code> is not a child of <code>node</code> or
223      *   <code>node</code> is <code>null</code> and
224      *   <code>nextSibling</code> is not <code>null</code>.
225      */
226     public void setNode(Node node) {
227         // does the corrent parent/child relationship exist?
228         if (nextSibling != null) {
229             // cannot be a sibling of a null node
230             if (node == null) {
231                 throw new IllegalStateException("Cannot create a DOMResult when the nextSibling is contained by the \"null\" node.");
232             }
233 
234             // nextSibling contained by node?
235             if ((node.compareDocumentPosition(nextSibling)&Node.DOCUMENT_POSITION_CONTAINED_BY)==0) {
236                 throw new IllegalArgumentException("Cannot create a DOMResult when the nextSibling is not contained by the node.");
237             }
238         }
239 
240         this.node = node;
241     }
242 
243     /**
244      * <p>Get the node that will contain the result DOM tree.</p>
245      *
246      * <p>If no node was set via
247      * {@link #DOMResult(Node node)},
248      * {@link #DOMResult(Node node, String systeId)},
249      * {@link #DOMResult(Node node, Node nextSibling)},
250      * {@link #DOMResult(Node node, Node nextSibling, String systemId)} or
251      * {@link #setNode(Node node)},
252      * then the node will be set by the transformation, and may be obtained from this method once the transformation is complete.
253      * Calling this method before the transformation will return <code>null</code>.</p>
254      *
255      * @return The node to which the transformation will be appended.
256      */
257     public Node getNode() {
258         return node;
259     }
260 
261     /**
262      * <p>Set the child node before which the result nodes will be inserted.</p>
263      *
264      * <p>Use <code>nextSibling</code> to specify the child node
265      * before which the result nodes should be inserted.
266      * If <code>nextSibling</code> is not a descendant of <code>node</code>,
267      * then an <code>IllegalArgumentException</code> is thrown.
268      * If <code>node</code> is <code>null</code> and <code>nextSibling</code> is not <code>null</code>,
269      * then an <code>IllegalStateException</code> is thrown.
270      * If <code>nextSibling</code> is <code>null</code>,
271      * then the behavior is the same as calling {@link #DOMResult(Node node)},
272      * i.e. append the result nodes as the last child of the specified <code>node</code>.</p>
273      *
274      * @param nextSibling The child node before which the result nodes will be inserted.
275      *
276      * @throws IllegalArgumentException If <code>nextSibling</code> is not a
277      *   descendant of <code>node</code>.
278      * @throws IllegalStateException If <code>node</code> is <code>null</code>
279      *   and <code>nextSibling</code> is not <code>null</code>.
280      *
281      * @since 1.5
282      */
283     public void setNextSibling(Node nextSibling) {
284 
285         // does the corrent parent/child relationship exist?
286         if (nextSibling != null) {
287             // cannot be a sibling of a null node
288             if (node == null) {
289                 throw new IllegalStateException("Cannot create a DOMResult when the nextSibling is contained by the \"null\" node.");
290             }
291 
292             // nextSibling contained by node?
293             if ((node.compareDocumentPosition(nextSibling)&Node.DOCUMENT_POSITION_CONTAINED_BY)==0) {
294                 throw new IllegalArgumentException("Cannot create a DOMResult when the nextSibling is not contained by the node.");
295             }
296         }
297 
298         this.nextSibling = nextSibling;
299     }
300 
301     /**
302      * <p>Get the child node before which the result nodes will be inserted.</p>
303      *
304      * <p>If no node was set via
305      * {@link #DOMResult(Node node, Node nextSibling)},
306      * {@link #DOMResult(Node node, Node nextSibling, String systemId)} or
307      * {@link #setNextSibling(Node nextSibling)},
308      * then <code>null</code> will be returned.</p>
309      *
310      * @return The child node before which the result nodes will be inserted.
311      *
312      * @since 1.5
313      */
314     public Node getNextSibling() {
315         return nextSibling;
316     }
317 
318     /**
319      * <p>Set the systemId that may be used in association with the node.</p>
320      *
321      * @param systemId The system identifier as a URI string.
322      */
323     public void setSystemId(String systemId) {
324         this.systemId = systemId;
325     }
326 
327     /**
328      * <p>Get the System Identifier.</p>
329      *
330      * <p>If no System ID was set via
331      * {@link #DOMResult(Node node, String systemId)},
332      * {@link #DOMResult(Node node, Node nextSibling, String systemId)} or
333      * {@link #setSystemId(String systemId)},
334      * then <code>null</code> will be returned.</p>
335      *
336      * @return The system identifier.
337      */
338     public String getSystemId() {
339         return systemId;
340     }
341 
342     //////////////////////////////////////////////////////////////////////
343     // Internal state.
344     //////////////////////////////////////////////////////////////////////
345 
346     /**
347      * <p>The node to which the transformation will be appended.</p>
348      */
349     private Node node = null;
350 
351     /**
352      * <p>The child node before which the result nodes will be inserted.</p>
353      *
354      * @since 1.5
355      */
356     private Node nextSibling = null;
357 
358     /**
359      * <p>The System ID that may be used in association with the node.</p>
360      */
361     private String systemId = null;
362 }