1. /*
  2. * $Id: NodeBase.java,v 1.3 2001/05/23 21:39:45 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 java.util.Locale;
  62. import org.w3c.dom.*;
  63. /**
  64. * Base class for DOM parse tree nodes which may appear in XmlDocument nodes.
  65. * This implements "parented by" and "owning document" relationships. If
  66. * the parent is not null, this also supports sibling relationships through
  67. * that parent. Children may be directly accessed through this class,
  68. * although it is subclasses which implement that access.
  69. *
  70. * @author David Brownell
  71. * @version $Revision: 1.3 $
  72. */
  73. // not public ... javadoc looks a bit odd (hidden base class)
  74. // but it's only subclassable within this package anyway
  75. abstract class NodeBase
  76. implements Node, NodeEx, NodeList, XmlWritable
  77. {
  78. private ParentNode parent;
  79. private int parentIndex = -1; // cache
  80. // package private for speed ...
  81. XmlDocument ownerDocument;
  82. boolean readonly;
  83. /**
  84. * Constructs a node which will later have its parent set
  85. * by some other member of this package.
  86. */
  87. // package private
  88. NodeBase () { }
  89. /* Returns the node's parent; typesafe convenience rtn. */
  90. // package private ...
  91. ParentNode getParentImpl () { return parent; }
  92. /* not public yet ... */
  93. // package private
  94. public boolean isReadonly ()
  95. { return readonly; }
  96. /* not public yet ... */
  97. // package private
  98. public void setReadonly (boolean deep)
  99. {
  100. readonly = true;
  101. if (deep) {
  102. TreeWalker walker = new TreeWalker (this);
  103. Node next;
  104. while ((next = walker.getNext ()) != null)
  105. ((NodeBase)next).setReadonly (false);
  106. }
  107. }
  108. /**
  109. * Returns the language id (value of <code>xml:lang</code>
  110. * attribute) applicable to this node, if known. Traces up
  111. * through ancestors as needed.
  112. */
  113. public String getLanguage () {
  114. return getInheritedAttribute ("xml:lang");
  115. }
  116. /**
  117. * Returns the value of a given attribute, tracing up through
  118. * ancestors if needed. In the XML standard, two attributes are
  119. * inherited: <em>xml:lang</em> and <em>xml:space</em>. This
  120. * mechanism can also be involved with Cascading Style Sheets (CSS).
  121. * The current version of XML Namespaces also uses inheritance.
  122. *
  123. * @param name identifies the attribute; colons may be included,
  124. * but namespace prefixes are not interpreted
  125. * @return the value of the inherited attribute, or null if
  126. * no value was inherited.
  127. */
  128. public String getInheritedAttribute (String name)
  129. {
  130. NodeBase current = this;
  131. Attr value = null;
  132. do {
  133. if (current instanceof ElementNode2) {
  134. ElementNode2 e = (ElementNode2) current;
  135. if ((value = e.getAttributeNode (name)) != null)
  136. break;
  137. }
  138. current = current.getParentImpl ();
  139. } while (current != null);
  140. if (value != null)
  141. return value.getValue ();
  142. return null;
  143. }
  144. /**
  145. * Does nothing; this type of node has no children.
  146. */
  147. public void writeChildrenXml (XmlWriteContext context) throws IOException
  148. {
  149. }
  150. // DOM support from W3C recommendation
  151. /**
  152. * <b>DOM:</b> Returns the node's parent. This will be null in cases such
  153. * as newly created or removed nodes, and for attributes, fragments,
  154. * and documents.
  155. */
  156. public Node getParentNode () {
  157. return parent;
  158. }
  159. /*
  160. * Assigns the node's parent, and remove it from its current parent.
  161. * The caller is responsible for letting the new parent know about
  162. * this child by inserting it into the set of children at the
  163. * appropriate place, if it's not null.
  164. *
  165. * <P> Note that this method, of necessity, involves the DOM being in
  166. * an internally inconsistent state, either with the new parent not yet
  167. * knowing about its child-to-be after this call, or this node not
  168. * knowing its true parent before the call. That's why it's not a
  169. * public API, here or in DOM.
  170. */
  171. void setParentNode (ParentNode arg, int index)
  172. throws DOMException
  173. {
  174. if (parent != null && arg != null)
  175. parent.removeChild (this);
  176. parent = arg;
  177. parentIndex = index;
  178. }
  179. // assigns the owner of this document
  180. protected void setOwnerDocument(XmlDocument doc) {
  181. ownerDocument = doc;
  182. }
  183. /**
  184. * <b>DOM:</b> Returns the document to which this node belongs.
  185. */
  186. public Document getOwnerDocument ()
  187. {
  188. return ownerDocument;
  189. }
  190. /**
  191. * <b>DOM:</b> Returns false.
  192. * Overridden by subclasses which support children.
  193. */
  194. public boolean hasChildNodes() { return false; }
  195. /**
  196. * <b>DOM:</b> does nothing; overridden by subclasses as needed.
  197. */
  198. public void setNodeValue (String value)
  199. {
  200. if (readonly)
  201. throw new DomEx (DomEx.NO_MODIFICATION_ALLOWED_ERR);
  202. }
  203. /**
  204. * <b>DOM:</b> Returns null; overridden by subclasses as needed.
  205. */
  206. public String getNodeValue ()
  207. { return null; }
  208. /**
  209. * <b>DOM:</b> Returns null.
  210. * Overridden by subclasses which support children.
  211. */
  212. public Node getFirstChild () { return null; }
  213. /**
  214. * <b>DOM:</b> Returns zero.
  215. * Overridden by subclasses which support children.
  216. */
  217. public int getLength () { return 0; }
  218. /**
  219. * <b>DOM:</b> Returns null.
  220. * Overridden by subclasses which support children.
  221. */
  222. public Node item (int i) { return null; }
  223. /**
  224. * <b>DOM:</b> Returns an object which permits "live" access to all
  225. * this node's children.
  226. *
  227. * <P> In this implementation, nodes provide such access without
  228. * needing another node as an intermediary; "this" is returned.
  229. */
  230. public NodeList getChildNodes ()
  231. { return this; }
  232. /**
  233. * <b>DOM:</b> returns null.
  234. * Overridden by subclasses which support children.
  235. */
  236. public Node getLastChild ()
  237. { return null; }
  238. /**
  239. * <b>DOM:</b> Throws a HIERARCHY_REQUEST_ERR DOMException.
  240. * Overridden by subclasses which support children.
  241. * @exception DOMException thrown always.
  242. */
  243. public Node appendChild (Node newChild)
  244. throws DOMException
  245. { throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR); }
  246. /**
  247. * <b>DOM:</b> Throws a HIERARCHY_REQUEST_ERR DOMException.
  248. * Overridden by subclasses which support children.
  249. * @exception DOMException thrown always.
  250. */
  251. public Node insertBefore (Node newChild, Node refChild)
  252. throws DOMException
  253. { throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR); }
  254. /**
  255. * <b>DOM:</b> Throws a HIERARCHY_REQUEST_ERR DOMException.
  256. * Overridden by subclasses which support children.
  257. * @exception DOMException thrown always.
  258. */
  259. public Node replaceChild (Node newChild, Node refChild)
  260. throws DOMException
  261. { throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR); }
  262. /**
  263. * <b>DOM:</b> Throws a HIERARCHY_REQUEST_ERR DOMException.
  264. * Overridden by subclasses which support children.
  265. * @exception DOMException thrown always.
  266. */
  267. public Node removeChild (Node oldChild)
  268. throws DOMException
  269. { throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR); }
  270. /**
  271. * <b>DOM:</b> Returns the node immediately following this node in a
  272. * breadth first traversal of the tree, or null if there is no
  273. * such sibling. In this implementation, sibling access from a
  274. * node is slower than indexed access from its parent.
  275. */
  276. public Node getNextSibling ()
  277. {
  278. if (parent == null)
  279. return null;
  280. if (parentIndex < 0 || parent.item (parentIndex) != this)
  281. parentIndex = parent.getIndexOf (this);
  282. return parent.item (parentIndex + 1);
  283. }
  284. /**
  285. * <b>DOM:</b> Returns the node immediately preceding this node in a
  286. * breadth first traversal of the tree, or null if there is no
  287. * such sibling. In this implementation, sibling access from a
  288. * node is slower than indexed access from its parent.
  289. */
  290. public Node getPreviousSibling ()
  291. {
  292. if (parent == null)
  293. return null;
  294. if (parentIndex < 0 || parent.item (parentIndex) != this)
  295. parentIndex = parent.getIndexOf (this);
  296. return parent.item (parentIndex - 1);
  297. }
  298. /**
  299. * <b>DOM:</b> returns null.
  300. * Overridden by the ElementNode2 subclass.
  301. */
  302. public NamedNodeMap getAttributes ()
  303. { return null; }
  304. /**
  305. * <b>DOM2:</b> noop.
  306. * @since DOM Level 2
  307. * Overridden by subclasses that need to support normalization.
  308. */
  309. public void normalize() {
  310. }
  311. /**
  312. * <b>DOM2:</b>
  313. * @since DOM Level 2
  314. */
  315. public boolean isSupported(String feature, String version) {
  316. return DOMImplementationImpl.hasFeature0(feature, version);
  317. }
  318. /**
  319. * <b>DOM2:</b> returns null.
  320. * Overridden by subclasses that support namespaces, ie. ElementNode2 and
  321. * AttributeNode.
  322. */
  323. public String getNamespaceURI() {
  324. return null;
  325. }
  326. /**
  327. * <b>DOM2:</b> returns null.
  328. * Overridden by subclasses that support namespaces.
  329. */
  330. public String getPrefix() {
  331. return null;
  332. }
  333. /**
  334. * <b>DOM2:</b> throws DOMException.NAMESPACE_ERR
  335. * Overridden by subclasses that support namespaces.
  336. */
  337. public void setPrefix(String prefix) throws DOMException {
  338. throw new DomEx(DomEx.NAMESPACE_ERR);
  339. }
  340. /**
  341. * <b>DOM2:</b> returns null.
  342. * Overridden by subclasses that support namespaces.
  343. */
  344. public String getLocalName() {
  345. return null;
  346. }
  347. /**
  348. * Returns whether this node (if it is an element) has any attributes.
  349. * Overridden by Element implementations
  350. * @since DOM Level 2
  351. */
  352. public boolean hasAttributes() {
  353. return false;
  354. }
  355. public int getIndexOf (Node maybeChild)
  356. { return -1; }
  357. /*
  358. * Gets the messages from the resource bundles for the given messageId.
  359. */
  360. String getMessage (String messageId) {
  361. return getMessage (messageId, null);
  362. }
  363. /*
  364. * Gets the messages from the resource bundles for the given messageId
  365. * after formatting it with the parameters passed to it.
  366. */
  367. String getMessage (String messageId, Object[] parameters) {
  368. Locale locale;
  369. if (this instanceof XmlDocument)
  370. locale = ((XmlDocument)this).getLocale ();
  371. else if (ownerDocument == null)
  372. locale = Locale.getDefault (); // sigh
  373. else
  374. locale = ownerDocument.getLocale ();
  375. return XmlDocument.catalog.getMessage (locale, messageId, parameters);
  376. }
  377. }