1. /*
  2. * $Id: TextNode.java,v 1.2 2001/07/26 22:32:04 edwingo Exp $
  3. *
  4. * The Apache Software License, Version 1.1
  5. *
  6. *
  7. * Copyright (c) 2000 The Apache Software Foundation. All rights
  8. * reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. *
  14. * 1. Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. *
  17. * 2. Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in
  19. * the documentation and/or other materials provided with the
  20. * distribution.
  21. *
  22. * 3. The end-user documentation included with the redistribution,
  23. * if any, must include the following acknowledgment:
  24. * "This product includes software developed by the
  25. * Apache Software Foundation (http://www.apache.org/)."
  26. * Alternately, this acknowledgment may appear in the software itself,
  27. * if and wherever such third-party acknowledgments normally appear.
  28. *
  29. * 4. The names "Crimson" and "Apache Software Foundation" must
  30. * not be used to endorse or promote products derived from this
  31. * software without prior written permission. For written
  32. * permission, please contact apache@apache.org.
  33. *
  34. * 5. Products derived from this software may not be called "Apache",
  35. * nor may "Apache" appear in their name, without prior written
  36. * permission of the Apache Software Foundation.
  37. *
  38. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  39. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  40. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  41. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  42. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  43. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  44. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  45. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  46. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  47. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  48. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  49. * SUCH DAMAGE.
  50. * ====================================================================
  51. *
  52. * This software consists of voluntary contributions made by many
  53. * individuals on behalf of the Apache Software Foundation and was
  54. * originally based on software copyright (c) 1999, Sun Microsystems, Inc.,
  55. * http://www.sun.com. For more information on the Apache Software
  56. * Foundation, please see <http://www.apache.org/>.
  57. */
  58. package org.apache.crimson.tree;
  59. import java.io.Writer;
  60. import java.io.IOException;
  61. import org.w3c.dom.*;
  62. /**
  63. * Node representing XML text.
  64. *
  65. * <P> Subclasses should not currently attempt to modify the
  66. * representation of content, but may add new methods to support
  67. * more sophisticated access or manipulation of that content.
  68. *
  69. * @author David Brownell
  70. * @version $Revision: 1.2 $
  71. */
  72. public class TextNode extends DataNode implements Text
  73. {
  74. //
  75. // XXX Really want a more flexible representation of text than
  76. // we have here ... it should be possible to take up only part
  77. // of a buffer, and in fact to be able to share one with other
  78. // text nodes. For readonly trees that will reduce the heap
  79. // impact; and for editable ones it can facilitate intelligent
  80. // editing support. Text seems more expensive than attributes,
  81. // which is quite odd.
  82. //
  83. /**
  84. * Constructs a text object with no text and unattached
  85. * to any document.
  86. */
  87. public TextNode () { }
  88. /**
  89. * Constructs text object by copying text from the input buffer.
  90. */
  91. public TextNode (char buf [], int offset, int len)
  92. {
  93. super (buf, offset, len);
  94. }
  95. /**
  96. * Constructs a text object by copying text from the string.
  97. */
  98. public TextNode (String s)
  99. {
  100. super (s);
  101. }
  102. /**
  103. * Writes the text, escaping XML metacharacters as needed
  104. * to let this text be parsed again without change.
  105. */
  106. public void writeXml (XmlWriteContext context) throws IOException
  107. {
  108. Writer out = context.getWriter ();
  109. int start = 0, last = 0;
  110. // XXX saw this once -- being paranoid
  111. if (data == null)
  112. { System.err.println ("Null text data??"); return; }
  113. while (last < data.length) {
  114. char c = data [last];
  115. //
  116. // escape markup delimiters only ... and do bulk
  117. // writes wherever possible, for best performance
  118. //
  119. // note that character data can't have the CDATA
  120. // termination "]]>"; escaping ">" suffices, and
  121. // doing it very generally helps simple parsers
  122. // that may not be quite correct.
  123. //
  124. if (c == '<') { // not legal in char data
  125. out.write (data, start, last - start);
  126. start = last + 1;
  127. out.write ("<");
  128. } else if (c == '>') { // see above
  129. out.write (data, start, last - start);
  130. start = last + 1;
  131. out.write (">");
  132. } else if (c == '&') { // not legal in char data
  133. out.write (data, start, last - start);
  134. start = last + 1;
  135. out.write ("&");
  136. }
  137. last++;
  138. }
  139. out.write (data, start, last - start);
  140. }
  141. /**
  142. * Combines this text node with its next sibling to create a
  143. * single text node. If the next node is not text, nothing is
  144. * done. This should be used with care, since large spans of
  145. * text may not be efficient to represent.
  146. */
  147. public void joinNextText ()
  148. {
  149. Node next = getNextSibling ();
  150. char tmp [], nextText [];
  151. if (next == null || next.getNodeType () != TEXT_NODE)
  152. return;
  153. getParentNode ().removeChild (next);
  154. nextText = ((TextNode)next).getText ();
  155. tmp = new char [data.length + nextText.length];
  156. System.arraycopy (data, 0, tmp, 0, data.length);
  157. System.arraycopy (nextText, 0, tmp, data.length, nextText.length);
  158. data = tmp;
  159. }
  160. // DOM support
  161. /** DOM: Returns the TEXT_NODE node type constant. */
  162. public short getNodeType () { return TEXT_NODE; }
  163. /**
  164. * DOM: Splits this text node into two, returning the part
  165. * beginning at <em>offset</em>. The original node has that
  166. * text removed, and the two nodes are siblings in the natural
  167. * order.
  168. */
  169. public Text splitText (int offset)
  170. throws DOMException
  171. {
  172. TextNode retval;
  173. char delta [];
  174. if (isReadonly ())
  175. throw new DomEx (DomEx.NO_MODIFICATION_ALLOWED_ERR);
  176. try {
  177. retval = new TextNode (data, offset, data.length - offset);
  178. }
  179. catch (ArrayIndexOutOfBoundsException ae) {
  180. throw new DomEx (DOMException.INDEX_SIZE_ERR);
  181. }
  182. catch (NegativeArraySizeException nae) {
  183. throw new DomEx (DOMException.INDEX_SIZE_ERR);
  184. }
  185. getParentNode().insertBefore (retval, getNextSibling ());
  186. delta = new char [offset];
  187. System.arraycopy (data, 0, delta, 0, offset);
  188. data = delta;
  189. return retval;
  190. }
  191. /**
  192. * DOM: returns a new text node with the same contents as this one.
  193. */
  194. public Node cloneNode (boolean deep)
  195. {
  196. TextNode retval = new TextNode (data, 0, data.length);
  197. retval.setOwnerDocument ((XmlDocument) this.getOwnerDocument ());
  198. return retval;
  199. }
  200. /**
  201. * DOM: Returns the string "#text".
  202. */
  203. public String getNodeName () { return "#text"; }
  204. }