Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/batik/dom/AbstractNode.java


1   /*
2   
3      Copyright 2000-2003  The Apache Software Foundation 
4   
5      Licensed under the Apache License, Version 2.0 (the "License");
6      you may not use this file except in compliance with the License.
7      You may obtain a copy of the License at
8   
9          http://www.apache.org/licenses/LICENSE-2.0
10  
11     Unless required by applicable law or agreed to in writing, software
12     distributed under the License is distributed on an "AS IS" BASIS,
13     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14     See the License for the specific language governing permissions and
15     limitations under the License.
16  
17   */
18  package org.apache.batik.dom;
19  
20  import java.io.Serializable;
21  
22  import org.apache.batik.dom.events.EventSupport;
23  import org.apache.batik.dom.events.NodeEventTarget;
24  import org.apache.batik.dom.util.DOMUtilities;
25  import org.apache.batik.dom.util.XMLSupport;
26  import org.w3c.dom.DOMException;
27  import org.w3c.dom.Document;
28  import org.w3c.dom.NamedNodeMap;
29  import org.w3c.dom.Node;
30  import org.w3c.dom.NodeList;
31  import org.w3c.dom.events.DocumentEvent;
32  import org.w3c.dom.events.Event;
33  import org.w3c.dom.events.EventException;
34  import org.w3c.dom.events.EventListener;
35  import org.w3c.dom.events.MutationEvent;
36  
37  /**
38   * This class implements the {@link org.w3c.dom.Node} interface.
39   *
40   * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
41   * @version $Id: AbstractNode.java,v 1.19 2005/03/27 08:58:32 cam Exp $
42   */
43  public abstract class AbstractNode
44      implements ExtendedNode,
45                 Serializable {
46  
47      /**
48       * An empty instance of NodeList.
49       */
50      protected final static NodeList EMPTY_NODE_LIST = new NodeList() {
51          public Node item(int i) { return null; }
52          public int  getLength() { return 0; }
53      };
54  
55      /**
56       * The owner document.
57       */
58      protected AbstractDocument ownerDocument;
59  
60      /**
61       * The event support.
62       */
63      protected transient EventSupport eventSupport;
64  
65      /**
66       * Sets the name of this node.
67       * Do nothing.
68       */
69      public void setNodeName(String v) {
70      }
71  
72      /**
73       * Sets the owner document of this node.
74       */
75      public void setOwnerDocument(Document doc) {
76          ownerDocument = (AbstractDocument)doc;
77      }
78  
79       /**
80       * Sets the value of the specified attribute. This method only applies
81       * to Attr objects.
82       */
83      public void setSpecified(boolean v) {
84          throw createDOMException(DOMException.INVALID_STATE_ERR,
85                                   "node.type",
86                                   new Object[] { new Integer(getNodeType()),
87                                                  getNodeName()});
88      }
89  
90      /**
91       * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getNodeValue()}.
92       * @return null.
93       */
94      public String getNodeValue() throws DOMException {
95          return null;
96      }
97  
98      /**
99       * <b>DOM</b>: Implements {@link org.w3c.dom.Node#setNodeValue(String)}.
100      * Do nothing.
101      */
102     public void setNodeValue(String nodeValue) throws DOMException {
103     }
104 
105     /**
106      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getParentNode()}.
107      * @return null.
108      */
109     public Node getParentNode() {
110         return null;
111     }
112 
113     /**
114      * Sets the parent node.
115      * Throws a HIERARCHY_REQUEST_ERR {@link org.w3c.dom.DOMException}.
116      */
117     public void setParentNode(Node v) {
118         throw createDOMException(DOMException.HIERARCHY_REQUEST_ERR,
119                                  "parent.not.allowed",
120                                  new Object[] { new Integer(getNodeType()),
121                                                 getNodeName() });
122     }
123 
124     /**
125      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getChildNodes()}.
126      * @return {@link #EMPTY_NODE_LIST}.
127      */
128     public NodeList getChildNodes() {
129         return EMPTY_NODE_LIST;
130     }
131 
132     /**
133      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getFirstChild()}.
134      * @return null.
135      */
136     public Node getFirstChild() {
137         return null;
138     }
139 
140     /**
141      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getLastChild()}.
142      * @return null.
143      */
144     public Node getLastChild() {
145         return null;
146     }
147 
148     /**
149      * Sets the node immediately preceding this node.
150      * Throws a HIERARCHY_REQUEST_ERR {@link org.w3c.dom.DOMException}.
151      */
152     public void setPreviousSibling(Node n) {
153         throw createDOMException(DOMException.HIERARCHY_REQUEST_ERR,
154                                  "sibling.not.allowed",
155                                  new Object[] { new Integer(getNodeType()),
156                                                 getNodeName() });
157     }
158 
159     /**
160      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getPreviousSibling()}.
161      * @return null.
162      */
163     public Node getPreviousSibling() {
164         return null;
165     }
166 
167     /**
168      * Sets the node immediately following this node.
169      * Throws a HIERARCHY_REQUEST_ERR {@link org.w3c.dom.DOMException}.
170      */
171     public void setNextSibling(Node n) {
172         throw createDOMException(DOMException.HIERARCHY_REQUEST_ERR,
173                                  "sibling.not.allowed",
174                                  new Object[] { new Integer(getNodeType()),
175                                                 getNodeName() });
176     }
177 
178     /**
179      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getNextSibling()}.
180      * @return null.
181      */
182     public Node getNextSibling() {
183         return null;
184     }
185 
186     /**
187      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#hasAttributes()}.
188      * @return false.
189      */
190     public boolean hasAttributes() {
191         return false;
192     }
193 
194     /**
195      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getAttributes()}.
196      * @return null.
197      */
198     public NamedNodeMap getAttributes() {
199         return null;
200     }
201 
202     /**
203      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getOwnerDocument()}.
204      * @return {@link #ownerDocument}.
205      */
206     public Document getOwnerDocument() {
207         return ownerDocument;
208     }
209 
210     /**
211      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getNamespaceURI()}.
212      * @return null.
213      */
214     public String getNamespaceURI() {
215         return null;
216     }
217 
218     /**
219      * <b>DOM</b>: Implements {@link
220      * org.w3c.dom.Node#insertBefore(Node, Node)}.
221      * Throws a HIERARCHY_REQUEST_ERR {@link org.w3c.dom.DOMException}.
222      */
223     public Node insertBefore(Node newChild, Node refChild)
224         throws DOMException {
225         throw createDOMException(DOMException.HIERARCHY_REQUEST_ERR,
226                                  "children.not.allowed",
227                                  new Object[] { new Integer(getNodeType()),
228                                                 getNodeName() });
229     }
230 
231     /**
232      * <b>DOM</b>: Implements {@link
233      * org.w3c.dom.Node#replaceChild(Node, Node)}.
234      * Throws a HIERARCHY_REQUEST_ERR {@link org.w3c.dom.DOMException}.
235      */
236     public Node replaceChild(Node newChild, Node oldChild)
237         throws DOMException {
238         throw createDOMException(DOMException.HIERARCHY_REQUEST_ERR,
239                                  "children.not.allowed",
240                                  new Object[] { new Integer(getNodeType()),
241                                                 getNodeName()});
242     }
243 
244     /**
245      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#removeChild(Node)}.
246      * Throws a HIERARCHY_REQUEST_ERR {@link org.w3c.dom.DOMException}.
247      */
248     public Node removeChild(Node oldChild) throws DOMException {
249         throw createDOMException(DOMException.HIERARCHY_REQUEST_ERR,
250                                  "children.not.allowed",
251                                  new Object[] { new Integer(getNodeType()),
252                                                 getNodeName() });
253     }
254 
255     /**
256      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#appendChild(Node)}.
257      * Throws a HIERARCHY_REQUEST_ERR {@link org.w3c.dom.DOMException}.
258      */
259     public Node appendChild(Node newChild) throws DOMException {
260         throw createDOMException(DOMException.HIERARCHY_REQUEST_ERR,
261                                  "children.not.allowed",
262                                  new Object[] { new Integer(getNodeType()),
263                                                 getNodeName() });
264     }
265 
266     /**
267      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#hasChildNodes()}.
268      * @return false.
269      */
270     public boolean hasChildNodes() {
271         return false;
272     }
273 
274     /**
275      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#cloneNode(boolean)}.
276      */
277     public Node cloneNode(boolean deep) {
278         return (deep) ? deepCopyInto(newNode()) : copyInto(newNode());
279     }
280 
281     /**
282      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#normalize()}.
283      * Do nothing.
284      */
285     public void normalize() {
286     }
287 
288     /**
289      * <b>DOM</b>: Implements {@link
290      * org.w3c.dom.Node#isSupported(String,String)}.
291      */
292     public boolean isSupported(String feature, String version) {
293         return getCurrentDocument().getImplementation().hasFeature(feature,
294                                                                    version);
295     }
296 
297     /**
298      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getPrefix()}.
299      */
300     public String getPrefix() {
301         return (getNamespaceURI() == null)
302             ? null
303             : DOMUtilities.getPrefix(getNodeName());
304     }
305 
306     /**
307      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#setPrefix(String)}.
308      */
309     public void setPrefix(String prefix) throws DOMException {
310         if (isReadonly()) {
311             throw createDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
312                                      "readonly.node",
313                                      new Object[] { new Integer(getNodeType()),
314                                                     getNodeName() });
315         }
316         String uri = getNamespaceURI();
317         if (uri == null) {
318             throw createDOMException(DOMException.NAMESPACE_ERR,
319                                      "namespace",
320                                      new Object[] { new Integer(getNodeType()),
321                                                     getNodeName() });
322         }
323 
324         String name = getLocalName();
325         if (prefix == null) {
326             setNodeName(name);
327         }
328         if (!prefix.equals("") && !DOMUtilities.isValidName(prefix)) {
329             throw createDOMException(DOMException.INVALID_CHARACTER_ERR,
330                                      "prefix",
331                                      new Object[] { new Integer(getNodeType()),
332                                                     getNodeName(),
333                                                     prefix });
334         }
335         if (!DOMUtilities.isValidPrefix(prefix)) {
336             throw createDOMException(DOMException.NAMESPACE_ERR,
337                                      "prefix",
338                                      new Object[] { new Integer(getNodeType()),
339                                                     getNodeName(),
340                                                     prefix });
341         }
342         if ((prefix.equals("xml") &&
343              !XMLSupport.XML_NAMESPACE_URI.equals(uri)) ||
344             (prefix.equals("xmlns") &&
345              !XMLSupport.XMLNS_NAMESPACE_URI.equals(uri))) {
346             throw createDOMException(DOMException.NAMESPACE_ERR,
347                                      "namespace.uri",
348                                      new Object[] { new Integer(getNodeType()),
349                                                     getNodeName(),
350                                                     uri });
351         }
352         setNodeName(prefix + ":" + name);
353     }
354 
355     /**
356      * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getLocalName()}.
357      */
358     public String getLocalName() {
359         return (getNamespaceURI() == null)
360             ? null
361             : DOMUtilities.getLocalName(getNodeName());
362     }
363 
364     /**
365      * Creates an exception with the appropriate error message.
366      */
367     public DOMException createDOMException(short    type,
368                                            String   key,
369                                            Object[] args) {
370         try {
371             return new DOMException
372                 (type, getCurrentDocument().formatMessage(key, args));
373         } catch (Exception e) {
374             return new DOMException(type, key);
375         }
376     }
377 
378     // EventTarget ////////////////////////////////////////////////////////////
379 
380     /**
381      * <b>DOM</b>: Implements
382      * {@link
383      * org.w3c.dom.events.EventTarget#addEventListener(String,EventListener,boolean)}.
384      */
385     public void addEventListener(String type,
386                                  EventListener listener,
387                                  boolean useCapture) {
388         if (eventSupport == null) {
389             eventSupport = new EventSupport();
390             AbstractDocument doc = getCurrentDocument();
391             doc.setEventsEnabled(true);
392         }
393         eventSupport.addEventListener(type, listener, useCapture);
394     }
395 
396     /**
397      * <b>DOM</b>: Implements
398      * {@link
399      * org.w3c.dom.events.EventTarget#removeEventListener(String,EventListener,boolean)}.
400      */
401     public void removeEventListener(String type,
402                                     EventListener listener,
403                                     boolean useCapture) {
404         if (eventSupport != null) {
405             eventSupport.removeEventListener(type, listener, useCapture);
406         }
407     }
408 
409     /**
410      * Implements {@link
411      * org.apache.batik.dom.events.NodeEventTarget#getParentNodeEventTarget()}.
412      */
413     public NodeEventTarget getParentNodeEventTarget() {
414         return (NodeEventTarget)getParentNode();
415     }
416 
417     /**
418      * <b>DOM</b>: Implements
419      * {@link org.w3c.dom.events.EventTarget#dispatchEvent(Event)}.
420      */
421     public boolean dispatchEvent(Event evt) throws EventException {
422         return EventSupport.dispatchEvent(this, evt);
423     }
424 
425     /**
426      * Returns the event support instance for this node, or null if any.
427      */
428     public EventSupport getEventSupport() {
429         return eventSupport;
430     }
431 
432     /**
433      * Recursively fires a DOMNodeInsertedIntoDocument event.
434      */
435     public void fireDOMNodeInsertedIntoDocumentEvent() {
436         AbstractDocument doc = getCurrentDocument();
437         if (doc.getEventsEnabled()) {
438             DocumentEvent de = (DocumentEvent)doc;
439             MutationEvent ev = (MutationEvent)de.createEvent("MutationEvents");
440             ev.initMutationEvent("DOMNodeInsertedIntoDocument",
441                                  true,   // canBubbleArg
442                                  false,  // cancelableArg
443                                  null,   // relatedNodeArg
444                                  null,   // prevValueArg
445                                  null,   // newValueArg
446                                  null,   // attrNameArg
447                                  MutationEvent.ADDITION);
448             dispatchEvent(ev);
449         }
450     }
451 
452     /**
453      * Recursively fires a DOMNodeRemovedFromDocument event.
454      */
455     public void fireDOMNodeRemovedFromDocumentEvent() {
456         AbstractDocument doc = getCurrentDocument();
457         if (doc.getEventsEnabled()) {
458             DocumentEvent de = (DocumentEvent)doc;
459             MutationEvent ev = (MutationEvent)de.createEvent("MutationEvents");
460             ev.initMutationEvent("DOMNodeRemovedFromDocument",
461                                  true,   // canBubbleArg
462                                  false,  // cancelableArg
463                                  null,   // relatedNodeArg
464                                  null,   // prevValueArg
465                                  null,   // newValueArg
466                                  null,   // attrNameArg
467                                  MutationEvent.REMOVAL);
468             dispatchEvent(ev);
469         }
470     }
471 
472     /**
473      * Fires a DOMCharacterDataModified event.
474      */
475     protected void fireDOMCharacterDataModifiedEvent(String oldv,
476                                                      String newv) {
477         AbstractDocument doc = getCurrentDocument();
478         if (doc.getEventsEnabled()) {
479             DocumentEvent de = (DocumentEvent)doc;
480             MutationEvent ev = (MutationEvent)de.createEvent("MutationEvents");
481             ev.initMutationEvent("DOMCharacterDataModified",
482                                  true,  // canBubbleArg
483                                  false, // cancelableArg
484                                  null,  // relatedNodeArg
485                                  oldv,  // prevValueArg
486                                  newv,  // newValueArg
487                                  null,  // attrNameArg
488                                  MutationEvent.MODIFICATION);
489             dispatchEvent(ev);
490         }
491     }
492 
493     /**
494      * Returns the current document.
495      */
496     protected AbstractDocument getCurrentDocument() {
497         return ownerDocument;
498     }
499 
500     /**
501      * Returns a new uninitialized instance of this object's class.
502      */
503     protected abstract Node newNode();
504 
505     /**
506      * Exports this node to the given document.
507      */
508     protected Node export(Node n, AbstractDocument d) {
509         AbstractNode p = (AbstractNode)n;
510         p.ownerDocument = d;
511         p.setReadonly(false);
512         return n;
513     }
514 
515     /**
516      * Deeply exports this node to the given document.
517      */
518     protected Node deepExport(Node n, AbstractDocument d) {
519         AbstractNode p = (AbstractNode)n;
520         p.ownerDocument = d;
521         p.setReadonly(false);
522         return n;
523     }
524 
525     /**
526      * Copy the fields of the current node into the given node.
527      * @param n a node of the type of this.
528      */
529     protected Node copyInto(Node n) {
530         AbstractNode an = (AbstractNode)n;
531         an.ownerDocument = ownerDocument;
532         return n;
533     }
534 
535     /**
536      * Deeply copy the fields of the current node into the given node.
537      * @param n a node of the type of this.
538      */
539     protected Node deepCopyInto(Node n) {
540         AbstractNode an = (AbstractNode)n;
541         an.ownerDocument = ownerDocument;
542         return n;
543     }
544 
545     /**
546      * Checks the validity of a node to be inserted.
547      */
548     protected void checkChildType(Node n, boolean replace) {
549         throw createDOMException(DOMException.HIERARCHY_REQUEST_ERR,
550                                  "children.not.allowed",
551                                  new Object[] { new Integer(getNodeType()),
552                                                 getNodeName() });
553     }
554 }