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 * Acts as a holder for a transformation result tree 33 * in the form of a Document Object Model (DOM) tree. 34 * 35 * <p>If no output DOM source is set, the transformation will create 36 * a Document node as the holder for the result of the transformation, 37 * which may be retrieved with {@link #getNode()}. 38 * 39 * @author Jeff Suttor 40 * @since 1.4 41 */ 42 public class DOMResult implements Result { 43 44 /** 45 * If {@link javax.xml.transform.TransformerFactory#getFeature} 46 * returns {@code true} when passed this value as an argument, 47 * the {@code Transformer} supports {@code Result} output of this type. 48 */ 49 public static final String FEATURE = "http://javax.xml.transform.dom.DOMResult/feature"; 50 51 /** 52 * Zero-argument default constructor. 53 * 54 * <p>{@code node}, 55 * {@code siblingNode} and 56 * {@code systemId} 57 * will be set to {@code null}. 58 */ 59 public DOMResult() { 60 setNode(null); 61 setNextSibling(null); 62 setSystemId(null); 63 } 64 65 /** 66 * Use a DOM node to create a new output target. 67 * 68 * <p>In practice, the node should be 69 * a {@link org.w3c.dom.Document} node, 70 * a {@link org.w3c.dom.DocumentFragment} node, or 71 * a {@link org.w3c.dom.Element} node. 72 * In other words, a node that accepts children. 73 * 74 * <p>{@code siblingNode} and 75 * {@code systemId} 76 * will be set to {@code null}. 77 * 78 * @param node The DOM node that will contain the result tree. 79 */ 80 public DOMResult(Node node) { 81 setNode(node); 82 setNextSibling(null); 83 setSystemId(null); 84 } 85 86 /** 87 * Use a DOM node to create a new output target with the specified System ID. 88 * 89 * <p>In practice, the node should be 90 * a {@link org.w3c.dom.Document} node, 91 * a {@link org.w3c.dom.DocumentFragment} node, or 92 * a {@link org.w3c.dom.Element} node. 93 * In other words, a node that accepts children. 94 * 95 * <p>{@code siblingNode} will be set to {@code null}. 96 * 97 * @param node The DOM node that will contain the result tree. 98 * @param systemId The system identifier which may be used in association with this node. 99 */ 100 public DOMResult(Node node, String systemId) { 101 setNode(node); 102 setNextSibling(null); 103 setSystemId(systemId); 104 } 105 106 /** 107 * Use a DOM node to create a new output target specifying 108 * the child node where the result nodes should be inserted before. 109 * 110 * <p>In practice, {@code node} and {@code nextSibling} should be 111 * a {@link org.w3c.dom.Document} node, 112 * a {@link org.w3c.dom.DocumentFragment} node, or 113 * a {@link org.w3c.dom.Element} node. 114 * In other words, a node that accepts children. 115 * 116 * <p>Use {@code nextSibling} to specify the child node 117 * where the result nodes should be inserted before. 118 * If {@code nextSibling} is not a sibling of {@code node}, 119 * then an {@code IllegalArgumentException} is thrown. 120 * If {@code node} is {@code null} and {@code nextSibling} is not {@code null}, 121 * then an {@code IllegalArgumentException} is thrown. 122 * If {@code nextSibling} is {@code null}, 123 * then the behavior is the same as calling {@link #DOMResult(Node node)}, 124 * i.e. append the result nodes as the last child of the specified {@code node}. 125 * 126 * <p>{@code systemId} will be set to {@code null}. 127 * 128 * @param node The DOM node that will contain the result tree. 129 * @param nextSibling The child node where the result nodes should be inserted before. 130 * 131 * @throws IllegalArgumentException If {@code nextSibling} is not a sibling of {@code node} or 132 * {@code node} is {@code null} and {@code nextSibling} 133 * is not {@code null}. 134 * 135 * @since 1.5 136 */ 137 public DOMResult(Node node, Node nextSibling) { 138 139 // does the corrent parent/child relationship exist? 140 if (nextSibling != null) { 141 // cannot be a sibling of a null node 142 if (node == null) { 143 throw new IllegalArgumentException("Cannot create a DOMResult when the nextSibling is contained by the \"null\" node."); 144 } 145 146 // nextSibling contained by node? 147 if ((node.compareDocumentPosition(nextSibling)&Node.DOCUMENT_POSITION_CONTAINED_BY)==0) { 148 throw new IllegalArgumentException("Cannot create a DOMResult when the nextSibling is not contained by the node."); 149 } 150 } 151 152 setNode(node); 153 setNextSibling(nextSibling); 154 setSystemId(null); 155 } 156 157 /** 158 * Use a DOM node to create a new output target specifying the child 159 * node where the result nodes should be inserted before and 160 * the specified System ID. 161 * 162 * <p>In practice, {@code node} and {@code nextSibling} should be 163 * a {@link org.w3c.dom.Document} node, 164 * a {@link org.w3c.dom.DocumentFragment} node, or a 165 * {@link org.w3c.dom.Element} node. 166 * In other words, a node that accepts children. 167 * 168 * <p>Use {@code nextSibling} to specify the child node 169 * where the result nodes should be inserted before. 170 * If {@code nextSibling} is not a sibling of {@code node}, 171 * then an {@code IllegalArgumentException} is thrown. 172 * If {@code node} is {@code null} and {@code nextSibling} is not {@code null}, 173 * then an {@code IllegalArgumentException} is thrown. 174 * If {@code nextSibling} is {@code null}, 175 * then the behavior is the same as calling {@link #DOMResult(Node node, String systemId)}, 176 * i.e. append the result nodes as the last child of the specified 177 * node and use the specified System ID. 178 * 179 * @param node The DOM node that will contain the result tree. 180 * @param nextSibling The child node where the result nodes should be inserted before. 181 * @param systemId The system identifier which may be used in association with this node. 182 * 183 * @throws IllegalArgumentException If {@code nextSibling} is not a 184 * sibling of {@code node} or 185 * {@code node} is {@code null} and {@code nextSibling} 186 * is not {@code null}. 187 * 188 * @since 1.5 189 */ 190 public DOMResult(Node node, Node nextSibling, String systemId) { 191 192 // does the corrent parent/child relationship exist? 193 if (nextSibling != null) { 194 // cannot be a sibling of a null node 195 if (node == null) { 196 throw new IllegalArgumentException("Cannot create a DOMResult when the nextSibling is contained by the \"null\" node."); 197 } 198 199 // nextSibling contained by node? 200 if ((node.compareDocumentPosition(nextSibling)&Node.DOCUMENT_POSITION_CONTAINED_BY)==0) { 201 throw new IllegalArgumentException("Cannot create a DOMResult when the nextSibling is not contained by the node."); 202 } 203 } 204 205 setNode(node); 206 setNextSibling(nextSibling); 207 setSystemId(systemId); 208 } 209 210 /** 211 * Set the node that will contain the result DOM tree. 212 * 213 * <p>In practice, the node should be 214 * a {@link org.w3c.dom.Document} node, 215 * a {@link org.w3c.dom.DocumentFragment} node, or 216 * a {@link org.w3c.dom.Element} node. 217 * In other words, a node that accepts children. 218 * 219 * <p>An {@code IllegalStateException} is thrown if 220 * {@code nextSibling} is not {@code null} and 221 * {@code node} is not a parent of {@code nextSibling}. 222 * An {@code IllegalStateException} is thrown if {@code node} is {@code null} and 223 * {@code nextSibling} is not {@code null}. 224 * 225 * @param node The node to which the transformation will be appended. 226 * 227 * @throws IllegalStateException If {@code nextSibling} is not 228 * {@code null} and 229 * {@code nextSibling} is not a child of {@code node} or 230 * {@code node} is {@code null} and 231 * {@code nextSibling} is not {@code null}. 232 */ 233 public void setNode(Node node) { 234 // does the corrent parent/child relationship exist? 235 if (nextSibling != null) { 236 // cannot be a sibling of a null node 237 if (node == null) { 238 throw new IllegalStateException("Cannot create a DOMResult when the nextSibling is contained by the \"null\" node."); 239 } 240 241 // nextSibling contained by node? 242 if ((node.compareDocumentPosition(nextSibling)&Node.DOCUMENT_POSITION_CONTAINED_BY)==0) { 243 throw new IllegalArgumentException("Cannot create a DOMResult when the nextSibling is not contained by the node."); 244 } 245 } 246 247 this.node = node; 248 } 249 250 /** 251 * Get the node that will contain the result DOM tree. 252 * 253 * <p>If no node was set via 254 * {@link #DOMResult(Node node)}, 255 * {@link #DOMResult(Node node, String systeId)}, 256 * {@link #DOMResult(Node node, Node nextSibling)}, 257 * {@link #DOMResult(Node node, Node nextSibling, String systemId)} or 258 * {@link #setNode(Node node)}, 259 * then the node will be set by the transformation, and may be obtained from this method once the transformation is complete. 260 * Calling this method before the transformation will return {@code null}. 261 * 262 * @return The node to which the transformation will be appended. 263 */ 264 public Node getNode() { 265 return node; 266 } 267 268 /** 269 * Set the child node before which the result nodes will be inserted. 270 * 271 * <p>Use {@code nextSibling} to specify the child node 272 * before which the result nodes should be inserted. 273 * If {@code nextSibling} is not a descendant of {@code node}, 274 * then an {@code IllegalArgumentException} is thrown. 275 * If {@code node} is {@code null} and {@code nextSibling} is not {@code null}, 276 * then an {@code IllegalStateException} is thrown. 277 * If {@code nextSibling} is {@code null}, 278 * then the behavior is the same as calling {@link #DOMResult(Node node)}, 279 * i.e. append the result nodes as the last child of the specified {@code node}. 280 * 281 * @param nextSibling The child node before which the result nodes will be inserted. 282 * 283 * @throws IllegalArgumentException If {@code nextSibling} is not a 284 * descendant of {@code node}. 285 * @throws IllegalStateException If {@code node} is {@code null} 286 * and {@code nextSibling} is not {@code null}. 287 * 288 * @since 1.5 289 */ 290 public void setNextSibling(Node nextSibling) { 291 292 // does the corrent parent/child relationship exist? 293 if (nextSibling != null) { 294 // cannot be a sibling of a null node 295 if (node == null) { 296 throw new IllegalStateException("Cannot create a DOMResult when the nextSibling is contained by the \"null\" node."); 297 } 298 299 // nextSibling contained by node? 300 if ((node.compareDocumentPosition(nextSibling)&Node.DOCUMENT_POSITION_CONTAINED_BY)==0) { 301 throw new IllegalArgumentException("Cannot create a DOMResult when the nextSibling is not contained by the node."); 302 } 303 } 304 305 this.nextSibling = nextSibling; 306 } 307 308 /** 309 * Get the child node before which the result nodes will be inserted. 310 * 311 * <p>If no node was set via 312 * {@link #DOMResult(Node node, Node nextSibling)}, 313 * {@link #DOMResult(Node node, Node nextSibling, String systemId)} or 314 * {@link #setNextSibling(Node nextSibling)}, 315 * then {@code null} will be returned. 316 * 317 * @return The child node before which the result nodes will be inserted. 318 * 319 * @since 1.5 320 */ 321 public Node getNextSibling() { 322 return nextSibling; 323 } 324 325 /** 326 * Set the systemId that may be used in association with the node. 327 * 328 * @param systemId The system identifier as a URI string. 329 */ 330 public void setSystemId(String systemId) { 331 this.systemId = systemId; 332 } 333 334 /** 335 * Get the System Identifier. 336 * 337 * <p>If no System ID was set via 338 * {@link #DOMResult(Node node, String systemId)}, 339 * {@link #DOMResult(Node node, Node nextSibling, String systemId)} or 340 * {@link #setSystemId(String systemId)}, 341 * then {@code null} will be returned. 342 * 343 * @return The system identifier. 344 */ 345 public String getSystemId() { 346 return systemId; 347 } 348 349 ////////////////////////////////////////////////////////////////////// 350 // Internal state. 351 ////////////////////////////////////////////////////////////////////// 352 353 /** 354 * The node to which the transformation will be appended. 355 */ 356 private Node node = null; 357 358 /** 359 * The child node before which the result nodes will be inserted. 360 * 361 * @since 1.5 362 */ 363 private Node nextSibling = null; 364 365 /** 366 * The System ID that may be used in association with the node. 367 */ 368 private String systemId = null; 369 }