Source Code Cross Referenced for DocumentImpl.java in  » Web-Server » Rimfaxe-Web-Server » org » apache » xerces » dom » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Server » Rimfaxe Web Server » org.apache.xerces.dom 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * The Apache Software License, Version 1.1
0003:         *
0004:         *
0005:         * Copyright (c) 2001 The Apache Software Foundation.  All rights
0006:         * reserved.
0007:         *
0008:         * Redistribution and use in source and binary forms, with or without
0009:         * modification, are permitted provided that the following conditions
0010:         * are met:
0011:         *
0012:         * 1. Redistributions of source code must retain the above copyright
0013:         *    notice, this list of conditions and the following disclaimer.
0014:         *
0015:         * 2. Redistributions in binary form must reproduce the above copyright
0016:         *    notice, this list of conditions and the following disclaimer in
0017:         *    the documentation and/or other materials provided with the
0018:         *    distribution.
0019:         *
0020:         * 3. The end-user documentation included with the redistribution,
0021:         *    if any, must include the following acknowledgment:
0022:         *       "This product includes software developed by the
0023:         *        Apache Software Foundation (http://www.apache.org/)."
0024:         *    Alternately, this acknowledgment may appear in the software itself,
0025:         *    if and wherever such third-party acknowledgments normally appear.
0026:         *
0027:         * 4. The names "Xerces" and "Apache Software Foundation" must
0028:         *    not be used to endorse or promote products derived from this
0029:         *    software without prior written permission. For written
0030:         *    permission, please contact apache@apache.org.
0031:         *
0032:         * 5. Products derived from this software may not be called "Apache",
0033:         *    nor may "Apache" appear in their name, without prior written
0034:         *    permission of the Apache Software Foundation.
0035:         *
0036:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0037:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0038:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0039:         * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0040:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0041:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0042:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0043:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0044:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0045:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0046:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0047:         * SUCH DAMAGE.
0048:         * ====================================================================
0049:         *
0050:         * This software consists of voluntary contributions made by many
0051:         * individuals on behalf of the Apache Software Foundation and was
0052:         * originally based on software copyright (c) 1999, International
0053:         * Business Machines, Inc., http://www.apache.org.  For more
0054:         * information on the Apache Software Foundation, please see
0055:         * <http://www.apache.org/>.
0056:         */
0057:
0058:        package org.apache.xerces.dom;
0059:
0060:        import java.util.Enumeration;
0061:        import java.util.Hashtable;
0062:        import java.util.Vector;
0063:
0064:        import org.w3c.dom.Attr;
0065:        import org.w3c.dom.DOMException;
0066:        import org.w3c.dom.DOMImplementation;
0067:        import org.w3c.dom.DocumentType;
0068:        import org.w3c.dom.NamedNodeMap;
0069:        import org.w3c.dom.Node;
0070:        import org.w3c.dom.NodeList;
0071:        import org.w3c.dom.Notation;
0072:        import org.w3c.dom.ProcessingInstruction;
0073:        import org.w3c.dom.Text;
0074:
0075:        import org.w3c.dom.events.DocumentEvent;
0076:        import org.w3c.dom.events.Event;
0077:        import org.w3c.dom.events.EventException;
0078:        import org.w3c.dom.events.EventListener;
0079:        import org.w3c.dom.events.EventTarget;
0080:        import org.w3c.dom.events.MutationEvent;
0081:        import org.w3c.dom.ranges.DocumentRange;
0082:        import org.w3c.dom.ranges.Range;
0083:        import org.w3c.dom.traversal.DocumentTraversal;
0084:        import org.w3c.dom.traversal.NodeIterator;
0085:        import org.w3c.dom.traversal.NodeFilter;
0086:        import org.w3c.dom.traversal.TreeWalker;
0087:
0088:        import org.apache.xerces.dom.events.EventImpl;
0089:        import org.apache.xerces.dom.events.MutationEventImpl;
0090:        import org.apache.xerces.utils.XMLCharacterProperties;
0091:
0092:        /**
0093:         * The Document interface represents the entire HTML or XML document.
0094:         * Conceptually, it is the root of the document tree, and provides the
0095:         * primary access to the document's data.
0096:         * <P>
0097:         * Since elements, text nodes, comments, processing instructions,
0098:         * etc. cannot exist outside the context of a Document, the Document
0099:         * interface also contains the factory methods needed to create these
0100:         * objects. The Node objects created have a ownerDocument attribute
0101:         * which associates them with the Document within whose context they
0102:         * were created.
0103:         * <p>
0104:         * The DocumentImpl class also implements the DOM Level 2 DocumentTraversal
0105:         * interface. This interface is comprised of factory methods needed to
0106:         * create NodeIterators and TreeWalkers. The process of creating NodeIterator
0107:         * objects also adds these references to this document.
0108:         * After finishing with an iterator it is important to remove the object
0109:         * using the remove methods in this implementation. This allows the release of
0110:         * the references from the iterator objects to the DOM Nodes.
0111:         * <p>
0112:         * <b>Note:</b> When any node in the document is serialized, the
0113:         * entire document is serialized along with it.
0114:         *
0115:         * @author Arnaud  Le Hors, IBM
0116:         * @author Joe Kesselman, IBM
0117:         * @author Andy Clark, IBM
0118:         * @author Ralf Pfeiffer, IBM
0119:         * @version
0120:         * @since  PR-DOM-Level-1-19980818.
0121:         */
0122:        public class DocumentImpl extends CoreDocumentImpl implements 
0123:                DocumentTraversal, DocumentEvent, DocumentRange {
0124:
0125:            //
0126:            // Constants
0127:            //
0128:
0129:            /** Serialization version. */
0130:            static final long serialVersionUID = 515687835542616694L;
0131:
0132:            //
0133:            // Data
0134:            //
0135:
0136:            /** Iterators */
0137:            // REVISIT: Should this be transient? -Ac
0138:            protected Vector iterators;
0139:
0140:            /** Ranges */
0141:            // REVISIT: Should this be transient? -Ac
0142:            protected Vector ranges;
0143:
0144:            /** Table for user data attached to this document nodes. */
0145:            protected Hashtable userData;
0146:
0147:            /** Table for event listeners registered to this document nodes. */
0148:            protected Hashtable eventListeners;
0149:
0150:            /** Bypass mutation events firing. */
0151:            protected boolean mutationEvents = false;
0152:
0153:            //
0154:            // Constructors
0155:            //
0156:
0157:            /**
0158:             * NON-DOM: Actually creating a Document is outside the DOM's spec,
0159:             * since it has to operate in terms of a particular implementation.
0160:             */
0161:            public DocumentImpl() {
0162:                super ();
0163:            }
0164:
0165:            /** Constructor. */
0166:            public DocumentImpl(boolean grammarAccess) {
0167:                super (grammarAccess);
0168:            }
0169:
0170:            /**
0171:             * For DOM2 support.
0172:             * The createDocument factory method is in DOMImplementation.
0173:             */
0174:            public DocumentImpl(DocumentType doctype) {
0175:                super (doctype);
0176:            }
0177:
0178:            /** For DOM2 support. */
0179:            public DocumentImpl(DocumentType doctype, boolean grammarAccess) {
0180:                super (doctype, grammarAccess);
0181:            }
0182:
0183:            //
0184:            // Node methods
0185:            //
0186:
0187:            /**
0188:             * Deep-clone a document, including fixing ownerDoc for the cloned
0189:             * children. Note that this requires bypassing the WRONG_DOCUMENT_ERR
0190:             * protection. I've chosen to implement it by calling importNode
0191:             * which is DOM Level 2.
0192:             *
0193:             * @return org.w3c.dom.Node
0194:             * @param deep boolean, iff true replicate children
0195:             */
0196:            public Node cloneNode(boolean deep) {
0197:
0198:                DocumentImpl newdoc = new DocumentImpl();
0199:                cloneNode(newdoc, deep);
0200:
0201:                // experimental
0202:                newdoc.mutationEvents = mutationEvents;
0203:
0204:                return newdoc;
0205:
0206:            } // cloneNode(boolean):Node
0207:
0208:            /**
0209:             * Retrieve information describing the abilities of this particular
0210:             * DOM implementation. Intended to support applications that may be
0211:             * using DOMs retrieved from several different sources, potentially
0212:             * with different underlying representations.
0213:             */
0214:            public DOMImplementation getImplementation() {
0215:                // Currently implemented as a singleton, since it's hardcoded
0216:                // information anyway.
0217:                return DOMImplementationImpl.getDOMImplementation();
0218:            }
0219:
0220:            /**
0221:             * Store user data related to a given node
0222:             * This is a place where we could use weak references! Indeed, the node
0223:             * here won't be GC'ed as long as some user data is attached to it, since
0224:             * the userData table will have a reference to the node.
0225:             */
0226:            protected void setUserData(NodeImpl n, Object data) {
0227:                if (userData == null) {
0228:                    userData = new Hashtable();
0229:                }
0230:                if (data == null) {
0231:                    userData.remove(n);
0232:                } else {
0233:                    userData.put(n, data);
0234:                }
0235:            }
0236:
0237:            /**
0238:             * Retreive user data related to a given node
0239:             */
0240:            protected Object getUserData(NodeImpl n) {
0241:                if (userData == null) {
0242:                    return null;
0243:                }
0244:                return userData.get(n);
0245:            }
0246:
0247:            //
0248:            // DocumentTraversal methods
0249:            //
0250:
0251:            /**
0252:             * NON-DOM extension:
0253:             * Create and return a NodeIterator. The NodeIterator is
0254:             * added to a list of NodeIterators so that it can be
0255:             * removed to free up the DOM Nodes it references.
0256:             * @see #removeNodeIterator
0257:             * @see #removeNodeIterators
0258:             *
0259:             * @param root The root of the iterator.
0260:             * @param whatToShow The whatToShow mask.
0261:             * @param filter The NodeFilter installed. Null means no filter.
0262:             */
0263:            public NodeIterator createNodeIterator(Node root, short whatToShow,
0264:                    NodeFilter filter) {
0265:                return createNodeIterator(root, whatToShow, filter, true);
0266:            }
0267:
0268:            /**
0269:             * Create and return a NodeIterator. The NodeIterator is
0270:             * added to a list of NodeIterators so that it can be
0271:             * removed to free up the DOM Nodes it references.
0272:             * @see #removeNodeIterator
0273:             * @see #removeNodeIterators
0274:             *
0275:             * @param root The root of the iterator.
0276:             * @param whatToShow The whatToShow mask.
0277:             * @param filter The NodeFilter installed. Null means no filter.
0278:             * @param entityReferenceExpansion true to expand the contents of
0279:             *                                 EntityReference nodes
0280:             * @since WD-DOM-Level-2-19990923
0281:             */
0282:            public NodeIterator createNodeIterator(Node root, int whatToShow,
0283:                    NodeFilter filter, boolean entityReferenceExpansion) {
0284:                NodeIterator iterator = new NodeIteratorImpl(this , root,
0285:                        whatToShow, filter, entityReferenceExpansion);
0286:                if (iterators == null) {
0287:                    iterators = new Vector();
0288:                }
0289:
0290:                iterators.addElement(iterator);
0291:
0292:                return iterator;
0293:            }
0294:
0295:            /**
0296:             * NON-DOM extension:
0297:             * Create and return a TreeWalker.
0298:             *
0299:             * @param root The root of the iterator.
0300:             * @param whatToShow The whatToShow mask.
0301:             * @param filter The NodeFilter installed. Null means no filter.
0302:             */
0303:            public TreeWalker createTreeWalker(Node root, short whatToShow,
0304:                    NodeFilter filter) {
0305:                return createTreeWalker(root, whatToShow, filter, true);
0306:            }
0307:
0308:            /**
0309:             * Create and return a TreeWalker.
0310:             *
0311:             * @param root The root of the iterator.
0312:             * @param whatToShow The whatToShow mask.
0313:             * @param filter The NodeFilter installed. Null means no filter.
0314:             * @param entityReferenceExpansion true to expand the contents of
0315:             *                                 EntityReference nodes
0316:             * @since WD-DOM-Level-2-19990923
0317:             */
0318:            public TreeWalker createTreeWalker(Node root, int whatToShow,
0319:                    NodeFilter filter, boolean entityReferenceExpansion) {
0320:                if (root == null) {
0321:                    throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
0322:                            "DOM007 Not supported");
0323:                }
0324:                return new TreeWalkerImpl(root, whatToShow, filter,
0325:                        entityReferenceExpansion);
0326:            }
0327:
0328:            //
0329:            // Not DOM Level 2. Support DocumentTraversal methods.
0330:            //
0331:
0332:            /** This is not called by the developer client. The
0333:             *  developer client uses the detach() function on the
0334:             *  NodeIterator itself. <p>
0335:             *
0336:             *  This function is called from the NodeIterator#detach().
0337:             */
0338:            void removeNodeIterator(NodeIterator nodeIterator) {
0339:
0340:                if (nodeIterator == null)
0341:                    return;
0342:                if (iterators == null)
0343:                    return;
0344:
0345:                iterators.removeElement(nodeIterator);
0346:            }
0347:
0348:            //
0349:            // DocumentRange methods
0350:            //
0351:            /**
0352:             */
0353:            public Range createRange() {
0354:
0355:                if (ranges == null) {
0356:                    ranges = new Vector();
0357:                }
0358:
0359:                Range range = new RangeImpl(this );
0360:
0361:                ranges.addElement(range);
0362:
0363:                return range;
0364:
0365:            }
0366:
0367:            /** Not a client function. Called by Range.detach(),
0368:             *  so a Range can remove itself from the list of
0369:             *  Ranges.
0370:             */
0371:            void removeRange(Range range) {
0372:
0373:                if (range == null)
0374:                    return;
0375:                if (ranges == null)
0376:                    return;
0377:
0378:                ranges.removeElement(range);
0379:            }
0380:
0381:            /**
0382:             * A method to be called when some text was changed in a text node,
0383:             * so that live objects can be notified.
0384:             */
0385:            void replacedText(NodeImpl node) {
0386:        // notify ranges
0387:        if (ranges != null) {
0388:            Enumeration enum = ranges.elements();
0389:            while (enum.hasMoreElements()) {
0390:                ((RangeImpl)enum.nextElement()).receiveReplacedText(node);
0391:            }
0392:        }
0393:    }
0394:
0395:            /**
0396:             * A method to be called when some text was deleted from a text node,
0397:             * so that live objects can be notified.
0398:             */
0399:            void deletedText(NodeImpl node, int offset, int count) {
0400:        // notify ranges
0401:        if (ranges != null) {
0402:            Enumeration enum = ranges.elements();
0403:            while (enum.hasMoreElements()) {
0404:                ((RangeImpl)enum.nextElement()).receiveDeletedText(node,
0405:                                                                   offset,
0406:                                                                   count);
0407:            }
0408:        }
0409:    }
0410:
0411:            /**
0412:             * A method to be called when some text was inserted into a text node,
0413:             * so that live objects can be notified.
0414:             */
0415:            void insertedText(NodeImpl node, int offset, int count) {
0416:        // notify ranges
0417:        if (ranges != null) {
0418:            Enumeration enum = ranges.elements();
0419:            while (enum.hasMoreElements()) {
0420:                ((RangeImpl)enum.nextElement()).receiveInsertedText(node,
0421:                                                                    offset,
0422:                                                                    count);
0423:            }
0424:        }
0425:    }
0426:
0427:            /**
0428:             * A method to be called when a text node has been split,
0429:             * so that live objects can be notified.
0430:             */
0431:            void splitData(Node node, Node newNode, int offset) {
0432:        // notify ranges
0433:        if (ranges != null) {
0434:            Enumeration enum = ranges.elements();
0435:            while (enum.hasMoreElements()) {
0436:                ((RangeImpl)enum.nextElement()).receiveSplitData(node,
0437:                                                                 newNode,
0438:                                                                 offset);
0439:            }
0440:        }
0441:    }
0442:
0443:            //
0444:            // DocumentEvent methods
0445:            //
0446:
0447:            /**
0448:             * Introduced in DOM Level 2. Optional. <p>
0449:             * Create and return Event objects.
0450:             *
0451:             * @param type The eventType parameter specifies the type of Event
0452:             * interface to be created.  If the Event interface specified is supported
0453:             * by the implementation this method will return a new Event of the
0454:             * interface type requested. If the Event is to be dispatched via the
0455:             * dispatchEvent method the appropriate event init method must be called
0456:             * after creation in order to initialize the Event's values.  As an
0457:             * example, a user wishing to synthesize some kind of Event would call
0458:             * createEvent with the parameter "Events". The initEvent method could then
0459:             * be called on the newly created Event to set the specific type of Event
0460:             * to be dispatched and set its context information.
0461:             * @return Newly created Event
0462:             * @exception DOMException NOT_SUPPORTED_ERR: Raised if the implementation
0463:             * does not support the type of Event interface requested
0464:             * @since WD-DOM-Level-2-19990923
0465:             */
0466:            public Event createEvent(String type) throws DOMException {
0467:                if (type.equalsIgnoreCase("Events") || "Event".equals(type))
0468:                    return new EventImpl();
0469:                if (type.equalsIgnoreCase("MutationEvents")
0470:                        || "MutationEvent".equals(type))
0471:                    return new MutationEventImpl();
0472:                else
0473:                    throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
0474:                            "DOM007 Not supported");
0475:            }
0476:
0477:            /**
0478:             * Sets whether the DOM implementation generates mutation events
0479:             * upon operations.
0480:             */
0481:            void setMutationEvents(boolean set) {
0482:                mutationEvents = set;
0483:            }
0484:
0485:            /**
0486:             * Returns true if the DOM implementation generates mutation events.
0487:             */
0488:            boolean getMutationEvents() {
0489:                return mutationEvents;
0490:            }
0491:
0492:            /**
0493:             * Store event listener registered on a given node
0494:             * This is another place where we could use weak references! Indeed, the
0495:             * node here won't be GC'ed as long as some listener is registered on it,
0496:             * since the eventsListeners table will have a reference to the node.
0497:             */
0498:            protected void setEventListeners(NodeImpl n, Vector listeners) {
0499:                if (eventListeners == null) {
0500:                    eventListeners = new Hashtable();
0501:                }
0502:                if (listeners == null) {
0503:                    eventListeners.remove(n);
0504:                    if (eventListeners.isEmpty()) {
0505:                        // stop firing events when there isn't any listener
0506:                        mutationEvents = false;
0507:                    }
0508:                } else {
0509:                    eventListeners.put(n, listeners);
0510:                    // turn mutation events on
0511:                    mutationEvents = true;
0512:                }
0513:            }
0514:
0515:            /**
0516:             * Retreive event listener registered on a given node
0517:             */
0518:            protected Vector getEventListeners(NodeImpl n) {
0519:                if (eventListeners == null) {
0520:                    return null;
0521:                }
0522:                return (Vector) eventListeners.get(n);
0523:            }
0524:
0525:            //
0526:            // EventTarget support (public and internal)
0527:            //
0528:
0529:            //
0530:            // Constants
0531:            //
0532:
0533:            /*
0534:             * NON-DOM INTERNAL: Class LEntry is just a struct used to represent
0535:             * event listeners registered with this node. Copies of this object
0536:             * are hung from the nodeListeners Vector.
0537:             * <p>
0538:             * I considered using two vectors -- one for capture,
0539:             * one for bubble -- but decided that since the list of listeners 
0540:             * is probably short in most cases, it might not be worth spending
0541:             * the space. ***** REVISIT WHEN WE HAVE MORE EXPERIENCE.
0542:             */
0543:            class LEntry {
0544:                String type;
0545:                EventListener listener;
0546:                boolean useCapture;
0547:
0548:                /** NON-DOM INTERNAL: Constructor for Listener list Entry 
0549:                 * @param type Event name (NOT event group!) to listen for.
0550:                 * @param listener Who gets called when event is dispatched
0551:                 * @param useCaptue True iff listener is registered on
0552:                 *  capturing phase rather than at-target or bubbling
0553:                 */
0554:                LEntry(String type, EventListener listener, boolean useCapture) {
0555:                    this .type = type;
0556:                    this .listener = listener;
0557:                    this .useCapture = useCapture;
0558:                }
0559:            } // LEntry
0560:
0561:            /**
0562:             * Introduced in DOM Level 2. <p> Register an event listener with this
0563:             * Node. A listener may be independently registered as both Capturing and
0564:             * Bubbling, but may only be registered once per role; redundant
0565:             * registrations are ignored.
0566:             * @param node node to add listener to
0567:             * @param type Event name (NOT event group!) to listen for.
0568:             * @param listener Who gets called when event is dispatched
0569:             * @param useCapture True iff listener is registered on
0570:             *  capturing phase rather than at-target or bubbling
0571:             */
0572:            protected void addEventListener(NodeImpl node, String type,
0573:                    EventListener listener, boolean useCapture) {
0574:                // We can't dispatch to blank type-name, and of course we need
0575:                // a listener to dispatch to
0576:                if (type == null || type.equals("") || listener == null)
0577:                    return;
0578:
0579:                // Each listener may be registered only once per type per phase.
0580:                // Simplest way to code that is to zap the previous entry, if any.
0581:                removeEventListener(node, type, listener, useCapture);
0582:
0583:                Vector nodeListeners = getEventListeners(node);
0584:                if (nodeListeners == null) {
0585:                    nodeListeners = new Vector();
0586:                    setEventListeners(node, nodeListeners);
0587:                }
0588:                nodeListeners
0589:                        .addElement(new LEntry(type, listener, useCapture));
0590:
0591:                // Record active listener
0592:                LCount lc = LCount.lookup(type);
0593:                if (useCapture)
0594:                    ++lc.captures;
0595:                else
0596:                    ++lc.bubbles;
0597:
0598:            } // addEventListener(NodeImpl,String,EventListener,boolean) :void
0599:
0600:            /**
0601:             * Introduced in DOM Level 2. <p> Deregister an event listener previously
0602:             * registered with this Node.  A listener must be independently removed
0603:             * from the Capturing and Bubbling roles. Redundant removals (of listeners
0604:             * not currently registered for this role) are ignored.
0605:             * @param node node to remove listener from
0606:             * @param type Event name (NOT event group!) to listen for.
0607:             * @param listener Who gets called when event is dispatched
0608:             * @param useCapture True iff listener is registered on
0609:             *  capturing phase rather than at-target or bubbling
0610:             */
0611:            protected void removeEventListener(NodeImpl node, String type,
0612:                    EventListener listener, boolean useCapture) {
0613:                // If this couldn't be a valid listener registration, ignore request
0614:                if (type == null || type.equals("") || listener == null)
0615:                    return;
0616:                Vector nodeListeners = getEventListeners(node);
0617:                if (nodeListeners == null)
0618:                    return;
0619:
0620:                // Note that addListener has previously ensured that 
0621:                // each listener may be registered only once per type per phase.
0622:                // count-down is OK for deletions!
0623:                for (int i = nodeListeners.size() - 1; i >= 0; --i) {
0624:                    LEntry le = (LEntry) nodeListeners.elementAt(i);
0625:                    if (le.useCapture == useCapture && le.listener == listener
0626:                            && le.type.equals(type)) {
0627:                        nodeListeners.removeElementAt(i);
0628:                        // Storage management: Discard empty listener lists
0629:                        if (nodeListeners.size() == 0)
0630:                            setEventListeners(node, null);
0631:
0632:                        // Remove active listener
0633:                        LCount lc = LCount.lookup(type);
0634:                        if (useCapture)
0635:                            --lc.captures;
0636:                        else
0637:                            --lc.bubbles;
0638:
0639:                        break; // Found it; no need to loop farther.
0640:                    }
0641:                }
0642:            } // removeEventListener(NodeImpl,String,EventListener,boolean) :void
0643:
0644:            /**
0645:             * Introduced in DOM Level 2. <p>
0646:             * Distribution engine for DOM Level 2 Events. 
0647:             * <p>
0648:             * Event propagation runs as follows:
0649:             * <ol>
0650:             * <li>Event is dispatched to a particular target node, which invokes
0651:             *   this code. Note that the event's stopPropagation flag is
0652:             *   cleared when dispatch begins; thereafter, if it has 
0653:             *   been set before processing of a node commences, we instead
0654:             *   immediately advance to the DEFAULT phase.
0655:             * <li>The node's ancestors are established as destinations for events.
0656:             *   For capture and bubble purposes, node ancestry is determined at 
0657:             *   the time dispatch starts. If an event handler alters the document 
0658:             *   tree, that does not change which nodes will be informed of the event. 
0659:             * <li>CAPTURING_PHASE: Ancestors are scanned, root to target, for 
0660:             *   Capturing listeners. If found, they are invoked (see below). 
0661:             * <li>AT_TARGET: 
0662:             *   Event is dispatched to NON-CAPTURING listeners on the
0663:             *   target node. Note that capturing listeners on this node are _not_
0664:             *   invoked.
0665:             * <li>BUBBLING_PHASE: Ancestors are scanned, target to root, for
0666:             *   non-capturing listeners. 
0667:             * <li>Default processing: Some DOMs have default behaviors bound to
0668:             *   specific nodes. If this DOM does, and if the event's preventDefault
0669:             *   flag has not been set, we now return to the target node and process
0670:             *   its default handler for this event, if any.
0671:             * </ol>
0672:             * <p>
0673:             * Note that registration of handlers during processing of an event does
0674:             * not take effect during this phase of this event; they will not be called
0675:             * until the next time this node is visited by dispatchEvent. On the other
0676:             * hand, removals take effect immediately.
0677:             * <p>
0678:             * If an event handler itself causes events to be dispatched, they are
0679:             * processed synchronously, before processing resumes
0680:             * on the event which triggered them. Please be aware that this may 
0681:             * result in events arriving at listeners "out of order" relative
0682:             * to the actual sequence of requests.
0683:             * <p>
0684:             * Note that our implementation resets the event's stop/prevent flags
0685:             * when dispatch begins.
0686:             * I believe the DOM's intent is that event objects be redispatchable,
0687:             * though it isn't stated in those terms.
0688:             * @param node node to dispatch to
0689:             * @param event the event object to be dispatched to 
0690:             *              registered EventListeners
0691:             * @return true if the event's <code>preventDefault()</code>
0692:             *              method was invoked by an EventListener; otherwise false.
0693:             */
0694:            protected boolean dispatchEvent(NodeImpl node, Event event) {
0695:                if (event == null)
0696:                    return false;
0697:
0698:                // Can't use anyone else's implementation, since there's no public
0699:                // API for setting the event's processing-state fields.
0700:                EventImpl evt = (EventImpl) event;
0701:
0702:                // VALIDATE -- must have been initialized at least once, must have
0703:                // a non-null non-blank name.
0704:                if (!evt.initialized || evt.type == null || evt.type.equals(""))
0705:                    throw new EventException(
0706:                            EventException.UNSPECIFIED_EVENT_TYPE_ERR,
0707:                            "DOM010 Unspecified event type");
0708:
0709:                // If nobody is listening for this event, discard immediately
0710:                LCount lc = LCount.lookup(evt.getType());
0711:                if (lc.captures + lc.bubbles + lc.defaults == 0)
0712:                    return evt.preventDefault;
0713:
0714:                // INITIALIZE THE EVENT'S DISPATCH STATUS
0715:                // (Note that Event objects are reusable in our implementation;
0716:                // that doesn't seem to be explicitly guaranteed in the DOM, but
0717:                // I believe it is the intent.)
0718:                evt.target = node;
0719:                evt.stopPropagation = false;
0720:                evt.preventDefault = false;
0721:
0722:                // Capture pre-event parentage chain, not including target;
0723:                // use pre-event-dispatch ancestors even if event handlers mutate
0724:                // document and change the target's context.
0725:                // Note that this is parents ONLY; events do not
0726:                // cross the Attr/Element "blood/brain barrier". 
0727:                // DOMAttrModified. which looks like an exception,
0728:                // is issued to the Element rather than the Attr
0729:                // and causes a _second_ DOMSubtreeModified in the Element's
0730:                // tree.
0731:                Vector pv = new Vector(10, 10);
0732:                Node p = node;
0733:                Node n = p.getParentNode();
0734:                while (n != null) {
0735:                    pv.addElement(n);
0736:                    p = n;
0737:                    n = n.getParentNode();
0738:                }
0739:
0740:                // CAPTURING_PHASE:
0741:                if (lc.captures > 0) {
0742:                    evt.eventPhase = Event.CAPTURING_PHASE;
0743:                    // Ancestors are scanned, root to target, for 
0744:                    // Capturing listeners.
0745:                    for (int j = pv.size() - 1; j >= 0; --j) {
0746:                        if (evt.stopPropagation)
0747:                            break; // Someone set the flag. Phase ends.
0748:
0749:                        // Handle all capturing listeners on this node
0750:                        NodeImpl nn = (NodeImpl) pv.elementAt(j);
0751:                        evt.currentTarget = nn;
0752:                        Vector nodeListeners = getEventListeners(nn);
0753:                        if (nodeListeners != null) {
0754:                            Vector nl = (Vector) nodeListeners.clone();
0755:                            // count-down more efficient
0756:                            for (int i = nl.size() - 1; i >= 0; --i) {
0757:                                LEntry le = (LEntry) nl.elementAt(i);
0758:                                if (le.useCapture && le.type.equals(evt.type)
0759:                                        && nodeListeners.contains(le)) {
0760:                                    try {
0761:                                        le.listener.handleEvent(evt);
0762:                                    } catch (Exception e) {
0763:                                        // All exceptions are ignored.
0764:                                    }
0765:                                }
0766:                            }
0767:                        }
0768:                    }
0769:                }
0770:
0771:                // Both AT_TARGET and BUBBLE use non-capturing listeners.
0772:                if (lc.bubbles > 0) {
0773:                    // AT_TARGET PHASE: Event is dispatched to NON-CAPTURING listeners
0774:                    // on the target node. Note that capturing listeners on the target
0775:                    // node are _not_ invoked, even during the capture phase.
0776:                    evt.eventPhase = Event.AT_TARGET;
0777:                    evt.currentTarget = node;
0778:                    Vector nodeListeners = getEventListeners(node);
0779:                    if (!evt.stopPropagation && nodeListeners != null) {
0780:                        Vector nl = (Vector) nodeListeners.clone();
0781:                        // count-down is more efficient
0782:                        for (int i = nl.size() - 1; i >= 0; --i) {
0783:                            LEntry le = (LEntry) nl.elementAt(i);
0784:                            if (!le.useCapture && le.type.equals(evt.type)
0785:                                    && nodeListeners.contains(le)) {
0786:                                try {
0787:                                    le.listener.handleEvent(evt);
0788:                                } catch (Exception e) {
0789:                                    // All exceptions are ignored.
0790:                                }
0791:                            }
0792:                        }
0793:                    }
0794:                    // BUBBLING_PHASE: Ancestors are scanned, target to root, for
0795:                    // non-capturing listeners. If the event's preventBubbling flag
0796:                    // has been set before processing of a node commences, we
0797:                    // instead immediately advance to the default phase.
0798:                    // Note that not all events bubble.
0799:                    if (evt.bubbles) {
0800:                        evt.eventPhase = Event.BUBBLING_PHASE;
0801:                        for (int j = 0; j < pv.size(); ++j) {
0802:                            if (evt.stopPropagation)
0803:                                break; // Someone set the flag. Phase ends.
0804:
0805:                            // Handle all bubbling listeners on this node
0806:                            NodeImpl nn = (NodeImpl) pv.elementAt(j);
0807:                            evt.currentTarget = nn;
0808:                            nodeListeners = getEventListeners(nn);
0809:                            if (nodeListeners != null) {
0810:                                Vector nl = (Vector) nodeListeners.clone();
0811:                                // count-down more efficient
0812:                                for (int i = nl.size() - 1; i >= 0; --i) {
0813:                                    LEntry le = (LEntry) nl.elementAt(i);
0814:                                    if (!le.useCapture
0815:                                            && le.type.equals(evt.type)
0816:                                            && nodeListeners.contains(le)) {
0817:                                        try {
0818:                                            le.listener.handleEvent(evt);
0819:                                        } catch (Exception e) {
0820:                                            // All exceptions are ignored.
0821:                                        }
0822:                                    }
0823:                                }
0824:                            }
0825:                        }
0826:                    }
0827:                }
0828:
0829:                // DEFAULT PHASE: Some DOMs have default behaviors bound to specific
0830:                // nodes. If this DOM does, and if the event's preventDefault flag has
0831:                // not been set, we now return to the target node and process its
0832:                // default handler for this event, if any.
0833:                // No specific phase value defined, since this is DOM-internal
0834:                if (lc.defaults > 0 && (!evt.cancelable || !evt.preventDefault)) {
0835:                    // evt.eventPhase = Event.DEFAULT_PHASE;
0836:                    // evt.currentTarget = node;
0837:                    // DO_DEFAULT_OPERATION
0838:                }
0839:
0840:                return evt.preventDefault;
0841:            } // dispatchEvent(NodeImpl,Event) :boolean
0842:
0843:            /**
0844:             * NON-DOM INTERNAL: DOMNodeInsertedIntoDocument and ...RemovedFrom...
0845:             * are dispatched to an entire subtree. This is the distribution code
0846:             * therefor. They DO NOT bubble, thanks be, but may be captured.
0847:             * <p>
0848:             * ***** At the moment I'm being sloppy and using the normal
0849:             * capture dispatcher on every node. This could be optimized hugely
0850:             * by writing a capture engine that tracks our position in the tree to
0851:             * update the capture chain without repeated chases up to root.
0852:             * @param node node to dispatch to
0853:             * @param n node which was directly inserted or removed
0854:             * @param e event to be sent to that node and its subtree
0855:             */
0856:            protected void dispatchEventToSubtree(NodeImpl node, Node n, Event e) {
0857:                Vector nodeListeners = getEventListeners(node);
0858:                if (nodeListeners == null || n == null)
0859:                    return;
0860:
0861:                // ***** Recursive implementation. This is excessively expensive,
0862:                // and should be replaced in conjunction with optimization
0863:                // mentioned above.
0864:                ((NodeImpl) n).dispatchEvent(e);
0865:                if (n.getNodeType() == Node.ELEMENT_NODE) {
0866:                    NamedNodeMap a = n.getAttributes();
0867:                    for (int i = a.getLength() - 1; i >= 0; --i)
0868:                        dispatchEventToSubtree(node, a.item(i), e);
0869:                }
0870:                dispatchEventToSubtree(node, n.getFirstChild(), e);
0871:                dispatchEventToSubtree(node, n.getNextSibling(), e);
0872:            } // dispatchEventToSubtree(NodeImpl,Node,Event) :void
0873:
0874:            /**
0875:             * NON-DOM INTERNAL: Return object for getEnclosingAttr. Carries
0876:             * (two values, the Attr node affected (if any) and its previous 
0877:             * string value. Simple struct, no methods.
0878:             */
0879:            class EnclosingAttr {
0880:                AttrImpl node;
0881:                String oldvalue;
0882:            }
0883:
0884:            EnclosingAttr savedEnclosingAttr;
0885:
0886:            /**
0887:             * NON-DOM INTERNAL: Convenience wrapper for calling
0888:             * dispatchAggregateEvents when the context was established
0889:             * by <code>savedEnclosingAttr</code>.
0890:             * @param node node to dispatch to
0891:             * @param ea description of Attr affected by current operation
0892:             */
0893:            protected void dispatchAggregateEvents(NodeImpl node,
0894:                    EnclosingAttr ea) {
0895:                if (ea != null)
0896:                    dispatchAggregateEvents(node, ea.node, ea.oldvalue,
0897:                            MutationEvent.MODIFICATION);
0898:                else
0899:                    dispatchAggregateEvents(node, null, null, (short) 0);
0900:
0901:            } // dispatchAggregateEvents(NodeImpl,EnclosingAttr) :void
0902:
0903:            /**
0904:             * NON-DOM INTERNAL: Generate the "aggregated" post-mutation events
0905:             * DOMAttrModified and DOMSubtreeModified.
0906:             * Both of these should be issued only once for each user-requested
0907:             * mutation operation, even if that involves multiple changes to
0908:             * the DOM.
0909:             * For example, if a DOM operation makes multiple changes to a single
0910:             * Attr before returning, it would be nice to generate only one 
0911:             * DOMAttrModified, and multiple changes over larger scope but within
0912:             * a recognizable single subtree might want to generate only one 
0913:             * DOMSubtreeModified, sent to their lowest common ancestor. 
0914:             * <p>
0915:             * To manage this, use the "internal" versions of insert and remove
0916:             * with MUTATION_LOCAL, then make an explicit call to this routine
0917:             * at the higher level. Some examples now exist in our code.
0918:             *
0919:             * @param node The node to dispatch to
0920:             * @param enclosingAttr The Attr node (if any) whose value has been changed
0921:             * as a result of the DOM operation. Null if none such.
0922:             * @param oldValue The String value previously held by the
0923:             * enclosingAttr. Ignored if none such.
0924:             * @param change Type of modification to the attr. See
0925:             * MutationEvent.attrChange
0926:             */
0927:            protected void dispatchAggregateEvents(NodeImpl node,
0928:                    AttrImpl enclosingAttr, String oldvalue, short change) {
0929:                // We have to send DOMAttrModified.
0930:                NodeImpl owner = null;
0931:                if (enclosingAttr != null) {
0932:                    LCount lc = LCount
0933:                            .lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
0934:                    owner = (NodeImpl) enclosingAttr.getOwnerElement();
0935:                    if (lc.captures + lc.bubbles + lc.defaults > 0) {
0936:                        if (owner != null) {
0937:                            MutationEventImpl me = new MutationEventImpl();
0938:                            me.initMutationEvent(
0939:                                    MutationEventImpl.DOM_ATTR_MODIFIED, true,
0940:                                    false, enclosingAttr, oldvalue,
0941:                                    enclosingAttr.getNodeValue(), enclosingAttr
0942:                                            .getNodeName(), change);
0943:                            owner.dispatchEvent(me);
0944:                        }
0945:                    }
0946:                }
0947:                // DOMSubtreeModified gets sent to the lowest common root of a
0948:                // set of changes. 
0949:                // "This event is dispatched after all other events caused by the
0950:                // mutation have been fired."
0951:                LCount lc = LCount
0952:                        .lookup(MutationEventImpl.DOM_SUBTREE_MODIFIED);
0953:                if (lc.captures + lc.bubbles + lc.defaults > 0) {
0954:                    MutationEvent me = new MutationEventImpl();
0955:                    me.initMutationEvent(
0956:                            MutationEventImpl.DOM_SUBTREE_MODIFIED, true,
0957:                            false, null, null, null, null, (short) 0);
0958:
0959:                    // If we're within an Attr, DStM gets sent to the Attr
0960:                    // and to its owningElement. Otherwise we dispatch it
0961:                    // locally.
0962:                    if (enclosingAttr != null) {
0963:                        dispatchEvent(enclosingAttr, me);
0964:                        if (owner != null)
0965:                            dispatchEvent(owner, me);
0966:                    } else
0967:                        dispatchEvent(node, me);
0968:                }
0969:            } // dispatchAggregateEvents(NodeImpl, AttrImpl,String) :void
0970:
0971:            /**
0972:             * NON-DOM INTERNAL: Pre-mutation context check, in
0973:             * preparation for later generating DOMAttrModified events.
0974:             * Determines whether this node is within an Attr
0975:             * @param node node to get enclosing attribute for
0976:             * @return either a description of that Attr, or null if none such. 
0977:             */
0978:            protected void saveEnclosingAttr(NodeImpl node) {
0979:                savedEnclosingAttr = null;
0980:                // MUTATION PREPROCESSING AND PRE-EVENTS:
0981:                // If we're within the scope of an Attr and DOMAttrModified 
0982:                // was requested, we need to preserve its previous value for
0983:                // that event.
0984:                LCount lc = LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
0985:                if (lc.captures + lc.bubbles + lc.defaults > 0) {
0986:                    NodeImpl eventAncestor = node;
0987:                    while (true) {
0988:                        if (eventAncestor == null)
0989:                            return;
0990:                        int type = eventAncestor.getNodeType();
0991:                        if (type == Node.ATTRIBUTE_NODE) {
0992:                            EnclosingAttr retval = new EnclosingAttr();
0993:                            retval.node = (AttrImpl) eventAncestor;
0994:                            retval.oldvalue = retval.node.getNodeValue();
0995:                            savedEnclosingAttr = retval;
0996:                            return;
0997:                        } else if (type == Node.ENTITY_REFERENCE_NODE)
0998:                            eventAncestor = eventAncestor.parentNode();
0999:                        else
1000:                            return;
1001:                        // Any other parent means we're not in an Attr
1002:                    }
1003:                }
1004:            } // saveEnclosingAttr(NodeImpl) :void
1005:
1006:            /**
1007:             * A method to be called when a character data node has been modified
1008:             */
1009:            void modifyingCharacterData(NodeImpl node) {
1010:                if (mutationEvents) {
1011:                    saveEnclosingAttr(node);
1012:                }
1013:            }
1014:
1015:            /**
1016:             * A method to be called when a character data node has been modified
1017:             */
1018:            void modifiedCharacterData(NodeImpl node, String oldvalue,
1019:                    String value) {
1020:                if (mutationEvents) {
1021:                    // MUTATION POST-EVENTS:
1022:                    LCount lc = LCount
1023:                            .lookup(MutationEventImpl.DOM_CHARACTER_DATA_MODIFIED);
1024:                    if (lc.captures + lc.bubbles + lc.defaults > 0) {
1025:                        MutationEvent me = new MutationEventImpl();
1026:                        me.initMutationEvent(
1027:                                MutationEventImpl.DOM_CHARACTER_DATA_MODIFIED,
1028:                                true, false, null, oldvalue, value, null,
1029:                                (short) 0);
1030:                        dispatchEvent(me);
1031:                    }
1032:
1033:                    // Subroutine: Transmit DOMAttrModified and DOMSubtreeModified,
1034:                    // if required. (Common to most kinds of mutation)
1035:                    dispatchAggregateEvents(node, savedEnclosingAttr);
1036:                } // End mutation postprocessing
1037:            }
1038:
1039:            /**
1040:             * A method to be called when a node is about to be inserted in the tree.
1041:             */
1042:            void insertingNode(NodeImpl node, boolean replace) {
1043:                if (mutationEvents) {
1044:                    if (!replace) {
1045:                        saveEnclosingAttr(node);
1046:                    }
1047:                }
1048:            }
1049:
1050:            /**
1051:             * A method to be called when a node has been inserted in the tree.
1052:             */
1053:            void insertedNode(NodeImpl node, NodeImpl newInternal,
1054:                    boolean replace) {
1055:                if (mutationEvents) {
1056:                    // MUTATION POST-EVENTS:
1057:                    // "Local" events (non-aggregated)
1058:                    // New child is told it was inserted, and where
1059:                    LCount lc = LCount
1060:                            .lookup(MutationEventImpl.DOM_NODE_INSERTED);
1061:                    if (lc.captures + lc.bubbles + lc.defaults > 0) {
1062:                        MutationEventImpl me = new MutationEventImpl();
1063:                        me.initMutationEvent(
1064:                                MutationEventImpl.DOM_NODE_INSERTED, true,
1065:                                false, node, null, null, null, (short) 0);
1066:                        dispatchEvent(newInternal, me);
1067:                    }
1068:
1069:                    // If within the Document, tell the subtree it's been added
1070:                    // to the Doc.
1071:                    lc = LCount
1072:                            .lookup(MutationEventImpl.DOM_NODE_INSERTED_INTO_DOCUMENT);
1073:                    if (lc.captures + lc.bubbles + lc.defaults > 0) {
1074:                        NodeImpl eventAncestor = node;
1075:                        if (savedEnclosingAttr != null)
1076:                            eventAncestor = (NodeImpl) savedEnclosingAttr.node
1077:                                    .getOwnerElement();
1078:                        if (eventAncestor != null) { // Might have been orphan Attr
1079:                            NodeImpl p = eventAncestor;
1080:                            while (p != null) {
1081:                                eventAncestor = p; // Last non-null ancestor
1082:                                // In this context, ancestry includes
1083:                                // walking back from Attr to Element
1084:                                if (p.getNodeType() == ATTRIBUTE_NODE) {
1085:                                    p = (NodeImpl) ((AttrImpl) p)
1086:                                            .getOwnerElement();
1087:                                } else {
1088:                                    p = p.parentNode();
1089:                                }
1090:                            }
1091:                            if (eventAncestor.getNodeType() == Node.DOCUMENT_NODE) {
1092:                                MutationEventImpl me = new MutationEventImpl();
1093:                                me
1094:                                        .initMutationEvent(
1095:                                                MutationEventImpl.DOM_NODE_INSERTED_INTO_DOCUMENT,
1096:                                                false, false, null, null, null,
1097:                                                null, (short) 0);
1098:                                dispatchEventToSubtree(node, newInternal, me);
1099:                            }
1100:                        }
1101:                    }
1102:                    if (!replace) {
1103:                        // Subroutine: Transmit DOMAttrModified and DOMSubtreeModified
1104:                        // (Common to most kinds of mutation)
1105:                        dispatchAggregateEvents(node, savedEnclosingAttr);
1106:                    }
1107:                }
1108:            }
1109:
1110:            /**
1111:             * A method to be called when a node is about to be removed from the tree.
1112:             */
1113:            void removingNode(NodeImpl node, NodeImpl oldChild, boolean replace) {
1114:
1115:        // notify iterators
1116:        if (iterators != null) {
1117:            Enumeration enum = iterators.elements();
1118:            while (enum.hasMoreElements()) {
1119:                ((NodeIteratorImpl)enum.nextElement()).removeNode(oldChild);
1120:            }
1121:        }
1122:
1123:        // notify ranges
1124:        if (ranges != null) {
1125:            Enumeration enum = ranges.elements();
1126:            while (enum.hasMoreElements()) {
1127:                ((RangeImpl)enum.nextElement()).removeNode(oldChild);
1128:            }
1129:        }
1130:
1131:        // mutation events
1132:        if (mutationEvents) {
1133:            // MUTATION PREPROCESSING AND PRE-EVENTS:
1134:            // If we're within the scope of an Attr and DOMAttrModified 
1135:            // was requested, we need to preserve its previous value for
1136:            // that event.
1137:            if (!replace) {
1138:                saveEnclosingAttr(node);
1139:            }
1140:            // Child is told that it is about to be removed
1141:            LCount lc = LCount.lookup(MutationEventImpl.DOM_NODE_REMOVED);
1142:            if (lc.captures + lc.bubbles + lc.defaults > 0) {
1143:                MutationEventImpl me= new MutationEventImpl();
1144:                me.initMutationEvent(MutationEventImpl.DOM_NODE_REMOVED,
1145:                                     true, false, node, null,
1146:                                     null, null, (short) 0);
1147:                dispatchEvent(oldChild, me);
1148:            }
1149:
1150:            // If within Document, child's subtree is informed that it's
1151:            // losing that status
1152:            lc = LCount.lookup(
1153:                             MutationEventImpl.DOM_NODE_REMOVED_FROM_DOCUMENT);
1154:            if (lc.captures + lc.bubbles + lc.defaults > 0) {
1155:                NodeImpl eventAncestor = this ;
1156:                if(savedEnclosingAttr != null)
1157:                    eventAncestor = (NodeImpl)
1158:                        savedEnclosingAttr.node.getOwnerElement();
1159:                if (eventAncestor != null) { // Might have been orphan Attr
1160:                    for (NodeImpl p = eventAncestor.parentNode();
1161:                         p != null; p = p.parentNode()) {
1162:                        eventAncestor = p; // Last non-null ancestor
1163:                    }
1164:                    if (eventAncestor.getNodeType() == Node.DOCUMENT_NODE){
1165:                        MutationEventImpl me = new MutationEventImpl();
1166:                        me.initMutationEvent(
1167:                              MutationEventImpl.DOM_NODE_REMOVED_FROM_DOCUMENT,
1168:                                             false, false, null,
1169:                                             null, null, null, (short) 0);
1170:                        dispatchEventToSubtree(node, oldChild, me);
1171:                    }
1172:                }
1173:            }
1174:        } // End mutation preprocessing
1175:    }
1176:
1177:            /**
1178:             * A method to be called when a node has been removed from the tree.
1179:             */
1180:            void removedNode(NodeImpl node, boolean replace) {
1181:                if (mutationEvents) {
1182:                    // MUTATION POST-EVENTS:
1183:                    // Subroutine: Transmit DOMAttrModified and DOMSubtreeModified,
1184:                    // if required. (Common to most kinds of mutation)
1185:                    if (!replace) {
1186:                        dispatchAggregateEvents(node, savedEnclosingAttr);
1187:                    }
1188:                } // End mutation postprocessing
1189:            }
1190:
1191:            /**
1192:             * A method to be called when a node is about to be replaced in the tree.
1193:             */
1194:            void replacingNode(NodeImpl node) {
1195:                if (mutationEvents) {
1196:                    saveEnclosingAttr(node);
1197:                }
1198:            }
1199:
1200:            /**
1201:             * A method to be called when a node has been replaced in the tree.
1202:             */
1203:            void replacedNode(NodeImpl node) {
1204:                if (mutationEvents) {
1205:                    dispatchAggregateEvents(node, savedEnclosingAttr);
1206:                }
1207:            }
1208:
1209:            /**
1210:             * A method to be called when an attribute value has been modified
1211:             */
1212:            void modifiedAttrValue(AttrImpl attr, String oldvalue) {
1213:                if (mutationEvents) {
1214:                    // MUTATION POST-EVENTS:
1215:                    dispatchAggregateEvents(attr, attr, oldvalue,
1216:                            MutationEvent.MODIFICATION);
1217:                }
1218:            }
1219:
1220:            /**
1221:             * A method to be called when an attribute node has been set
1222:             */
1223:            void setAttrNode(AttrImpl attr, AttrImpl previous) {
1224:                if (mutationEvents) {
1225:                    // MUTATION POST-EVENTS:
1226:                    if (previous == null) {
1227:                        dispatchAggregateEvents(attr.ownerNode, attr, null,
1228:                                MutationEvent.ADDITION);
1229:                    } else {
1230:                        dispatchAggregateEvents(attr.ownerNode, attr, previous
1231:                                .getNodeValue(), MutationEvent.MODIFICATION);
1232:                    }
1233:                }
1234:            }
1235:
1236:            /**
1237:             * A method to be called when an attribute node has been removed
1238:             */
1239:            void removedAttrNode(AttrImpl attr, NodeImpl oldOwner, String name) {
1240:                // We can't use the standard dispatchAggregate, since it assumes
1241:                // that the Attr is still attached to an owner. This code is
1242:                // similar but dispatches to the previous owner, "element".
1243:                if (mutationEvents) {
1244:                    // If we have to send DOMAttrModified (determined earlier),
1245:                    // do so.
1246:                    LCount lc = LCount
1247:                            .lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
1248:                    if (lc.captures + lc.bubbles + lc.defaults > 0) {
1249:                        MutationEventImpl me = new MutationEventImpl();
1250:                        me.initMutationEvent(
1251:                                MutationEventImpl.DOM_ATTR_MODIFIED, true,
1252:                                false, null, attr.getNodeValue(), null, name,
1253:                                MutationEvent.REMOVAL);
1254:                        dispatchEvent(oldOwner, me);
1255:                    }
1256:
1257:                    // We can hand off to process DOMSubtreeModified, though.
1258:                    // Note that only the Element needs to be informed; the
1259:                    // Attr's subtree has not been changed by this operation.
1260:                    dispatchAggregateEvents(oldOwner, null, null, (short) 0);
1261:                }
1262:            }
1263:
1264:        } // class DocumentImpl
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.