Source Code Cross Referenced for ParentNode.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) 


001:        /* $Id: ParentNode.java,v 1.27 2001/08/10 01:18:16 lehors Exp $ */
002:        /*
003:         * The Apache Software License, Version 1.1
004:         *
005:         *
006:         * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights 
007:         * reserved.
008:         *
009:         * Redistribution and use in source and binary forms, with or without
010:         * modification, are permitted provided that the following conditions
011:         * are met:
012:         *
013:         * 1. Redistributions of source code must retain the above copyright
014:         *    notice, this list of conditions and the following disclaimer. 
015:         *
016:         * 2. Redistributions in binary form must reproduce the above copyright
017:         *    notice, this list of conditions and the following disclaimer in
018:         *    the documentation and/or other materials provided with the
019:         *    distribution.
020:         *
021:         * 3. The end-user documentation included with the redistribution,
022:         *    if any, must include the following acknowledgment:  
023:         *       "This product includes software developed by the
024:         *        Apache Software Foundation (http://www.apache.org/)."
025:         *    Alternately, this acknowledgment may appear in the software itself,
026:         *    if and wherever such third-party acknowledgments normally appear.
027:         *
028:         * 4. The names "Xerces" and "Apache Software Foundation" must
029:         *    not be used to endorse or promote products derived from this
030:         *    software without prior written permission. For written 
031:         *    permission, please contact apache@apache.org.
032:         *
033:         * 5. Products derived from this software may not be called "Apache",
034:         *    nor may "Apache" appear in their name, without prior written
035:         *    permission of the Apache Software Foundation.
036:         *
037:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
038:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
039:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
040:         * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
041:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
042:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
043:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
044:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
045:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
046:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
047:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
048:         * SUCH DAMAGE.
049:         * ====================================================================
050:         *
051:         * This software consists of voluntary contributions made by many
052:         * individuals on behalf of the Apache Software Foundation and was
053:         * originally based on software copyright (c) 1999, International
054:         * Business Machines, Inc., http://www.apache.org.  For more
055:         * information on the Apache Software Foundation, please see
056:         * <http://www.apache.org/>.
057:         */
058:
059:        package org.apache.xerces.dom;
060:
061:        import java.io.IOException;
062:        import java.io.ObjectInputStream;
063:        import java.io.ObjectOutputStream;
064:
065:        import org.w3c.dom.DOMException;
066:        import org.w3c.dom.Document;
067:        import org.w3c.dom.Node;
068:        import org.w3c.dom.NodeList;
069:
070:        /**
071:         * ParentNode inherits from ChildNode and adds the capability of having child
072:         * nodes. Not every node in the DOM can have children, so only nodes that can
073:         * should inherit from this class and pay the price for it.
074:         * <P>
075:         * ParentNode, just like NodeImpl, also implements NodeList, so it can
076:         * return itself in response to the getChildNodes() query. This eliminiates
077:         * the need for a separate ChildNodeList object. Note that this is an
078:         * IMPLEMENTATION DETAIL; applications should _never_ assume that
079:         * this identity exists. On the other hand, subclasses may need to override
080:         * this, in case of conflicting names. This is the case for the classes
081:         * HTMLSelectElementImpl and HTMLFormElementImpl of the HTML DOM.
082:         * <P>
083:         * While we have a direct reference to the first child, the last child is
084:         * stored as the previous sibling of the first child. First child nodes are
085:         * marked as being so, and getNextSibling hides this fact.
086:         * <P>Note: Not all parent nodes actually need to also be a child. At some
087:         * point we used to have ParentNode inheriting from NodeImpl and another class
088:         * called ChildAndParentNode that inherited from ChildNode. But due to the lack
089:         * of multiple inheritance a lot of code had to be duplicated which led to a
090:         * maintenance nightmare. At the same time only a few nodes (Document,
091:         * DocumentFragment, Entity, and Attribute) cannot be a child so the gain in
092:         * memory wasn't really worth it. The only type for which this would be the
093:         * case is Attribute, but we deal with there in another special way, so this is
094:         * not applicable.
095:         * <p>
096:         * This class doesn't directly support mutation events, however, it notifies
097:         * the document when mutations are performed so that the document class do so.
098:         *
099:         * <p><b>WARNING</b>: Some of the code here is partially duplicated in
100:         * AttrImpl, be careful to keep these two classes in sync!
101:         *
102:         * @author Arnaud  Le Hors, IBM
103:         * @author Joe Kesselman, IBM
104:         * @author Andy Clark, IBM
105:         */
106:        public abstract class ParentNode extends ChildNode {
107:
108:            /** Serialization version. */
109:            static final long serialVersionUID = 2815829867152120872L;
110:
111:            /** Owner document. */
112:            protected CoreDocumentImpl ownerDocument;
113:
114:            /** First child. */
115:            protected ChildNode firstChild = null;
116:
117:            // transients
118:
119:            /** Cached node list length. */
120:            protected transient int fCachedLength = -1;
121:
122:            /** Last requested node. */
123:            protected transient ChildNode fCachedChild;
124:
125:            /** Last requested node index. */
126:            protected transient int fCachedChildIndex = -1;
127:
128:            //
129:            // Constructors
130:            //
131:
132:            /**
133:             * No public constructor; only subclasses of ParentNode should be
134:             * instantiated, and those normally via a Document's factory methods
135:             */
136:            protected ParentNode(CoreDocumentImpl ownerDocument) {
137:                super (ownerDocument);
138:                this .ownerDocument = ownerDocument;
139:            }
140:
141:            /** Constructor for serialization. */
142:            public ParentNode() {
143:            }
144:
145:            //
146:            // NodeList methods
147:            //
148:
149:            /**
150:             * Returns a duplicate of a given node. You can consider this a
151:             * generic "copy constructor" for nodes. The newly returned object should
152:             * be completely independent of the source object's subtree, so changes
153:             * in one after the clone has been made will not affect the other.
154:             * <p>
155:             * Example: Cloning a Text node will copy both the node and the text it
156:             * contains.
157:             * <p>
158:             * Example: Cloning something that has children -- Element or Attr, for
159:             * example -- will _not_ clone those children unless a "deep clone"
160:             * has been requested. A shallow clone of an Attr node will yield an
161:             * empty Attr of the same name.
162:             * <p>
163:             * NOTE: Clones will always be read/write, even if the node being cloned
164:             * is read-only, to permit applications using only the DOM API to obtain
165:             * editable copies of locked portions of the tree.
166:             */
167:            public Node cloneNode(boolean deep) {
168:
169:                if (needsSyncChildren()) {
170:                    synchronizeChildren();
171:                }
172:                ParentNode newnode = (ParentNode) super .cloneNode(deep);
173:
174:                // set owner document
175:                newnode.ownerDocument = ownerDocument;
176:
177:                // Need to break the association w/ original kids
178:                newnode.firstChild = null;
179:
180:                // invalidate cache for children NodeList
181:                newnode.fCachedChildIndex = -1;
182:                newnode.fCachedLength = -1;
183:
184:                // Then, if deep, clone the kids too.
185:                if (deep) {
186:                    for (ChildNode child = firstChild; child != null; child = child.nextSibling) {
187:                        newnode.appendChild(child.cloneNode(true));
188:                    }
189:                }
190:
191:                return newnode;
192:
193:            } // cloneNode(boolean):Node
194:
195:            /**
196:             * Find the Document that this Node belongs to (the document in
197:             * whose context the Node was created). The Node may or may not
198:             * currently be part of that Document's actual contents.
199:             */
200:            public Document getOwnerDocument() {
201:                return ownerDocument;
202:            }
203:
204:            /**
205:             * same as above but returns internal type and this one is not overridden
206:             * by CoreDocumentImpl to return null
207:             */
208:            CoreDocumentImpl ownerDocument() {
209:                return ownerDocument;
210:            }
211:
212:            /**
213:             * NON-DOM
214:             * set the ownerDocument of this node and its children
215:             */
216:            void setOwnerDocument(CoreDocumentImpl doc) {
217:                if (needsSyncChildren()) {
218:                    synchronizeChildren();
219:                }
220:                super .setOwnerDocument(doc);
221:                ownerDocument = doc;
222:                for (ChildNode child = firstChild; child != null; child = child.nextSibling) {
223:                    child.setOwnerDocument(doc);
224:                }
225:            }
226:
227:            /**
228:             * Test whether this node has any children. Convenience shorthand
229:             * for (Node.getFirstChild()!=null)
230:             */
231:            public boolean hasChildNodes() {
232:                if (needsSyncChildren()) {
233:                    synchronizeChildren();
234:                }
235:                return firstChild != null;
236:            }
237:
238:            /**
239:             * Obtain a NodeList enumerating all children of this node. If there
240:             * are none, an (initially) empty NodeList is returned.
241:             * <p>
242:             * NodeLists are "live"; as children are added/removed the NodeList
243:             * will immediately reflect those changes. Also, the NodeList refers
244:             * to the actual nodes, so changes to those nodes made via the DOM tree
245:             * will be reflected in the NodeList and vice versa.
246:             * <p>
247:             * In this implementation, Nodes implement the NodeList interface and
248:             * provide their own getChildNodes() support. Other DOMs may solve this
249:             * differently.
250:             */
251:            public NodeList getChildNodes() {
252:
253:                if (needsSyncChildren()) {
254:                    synchronizeChildren();
255:                }
256:                return this ;
257:
258:            } // getChildNodes():NodeList
259:
260:            /** The first child of this Node, or null if none. */
261:            public Node getFirstChild() {
262:
263:                if (needsSyncChildren()) {
264:                    synchronizeChildren();
265:                }
266:                return firstChild;
267:
268:            } // getFirstChild():Node
269:
270:            /** The last child of this Node, or null if none. */
271:            public Node getLastChild() {
272:
273:                if (needsSyncChildren()) {
274:                    synchronizeChildren();
275:                }
276:                return lastChild();
277:
278:            } // getLastChild():Node
279:
280:            final ChildNode lastChild() {
281:                // last child is stored as the previous sibling of first child
282:                return firstChild != null ? firstChild.previousSibling : null;
283:            }
284:
285:            final void lastChild(ChildNode node) {
286:                // store lastChild as previous sibling of first child
287:                if (firstChild != null) {
288:                    firstChild.previousSibling = node;
289:                }
290:            }
291:
292:            /**
293:             * Move one or more node(s) to our list of children. Note that this
294:             * implicitly removes them from their previous parent.
295:             *
296:             * @param newChild The Node to be moved to our subtree. As a
297:             * convenience feature, inserting a DocumentNode will instead insert
298:             * all its children.
299:             *
300:             * @param refChild Current child which newChild should be placed
301:             * immediately before. If refChild is null, the insertion occurs
302:             * after all existing Nodes, like appendChild().
303:             *
304:             * @returns newChild, in its new state (relocated, or emptied in the
305:             * case of DocumentNode.)
306:             *
307:             * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
308:             * type that shouldn't be a child of this node, or if newChild is an
309:             * ancestor of this node.
310:             *
311:             * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
312:             * different owner document than we do.
313:             *
314:             * @throws DOMException(NOT_FOUND_ERR) if refChild is not a child of
315:             * this node.
316:             *
317:             * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
318:             * read-only.
319:             */
320:            public Node insertBefore(Node newChild, Node refChild)
321:                    throws DOMException {
322:                // Tail-call; optimizer should be able to do good things with.
323:                return internalInsertBefore(newChild, refChild, false);
324:            } // insertBefore(Node,Node):Node
325:
326:            /** NON-DOM INTERNAL: Within DOM actions,we sometimes need to be able
327:             * to control which mutation events are spawned. This version of the
328:             * insertBefore operation allows us to do so. It is not intended
329:             * for use by application programs.
330:             */
331:            Node internalInsertBefore(Node newChild, Node refChild,
332:                    boolean replace) throws DOMException {
333:
334:                boolean errorChecking = ownerDocument.errorChecking;
335:
336:                if (newChild.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) {
337:                    // SLOW BUT SAFE: We could insert the whole subtree without
338:                    // juggling so many next/previous pointers. (Wipe out the
339:                    // parent's child-list, patch the parent pointers, set the
340:                    // ends of the list.) But we know some subclasses have special-
341:                    // case behavior they add to insertBefore(), so we don't risk it.
342:                    // This approch also takes fewer bytecodes.
343:
344:                    // NOTE: If one of the children is not a legal child of this
345:                    // node, throw HIERARCHY_REQUEST_ERR before _any_ of the children
346:                    // have been transferred. (Alternative behaviors would be to
347:                    // reparent up to the first failure point or reparent all those
348:                    // which are acceptable to the target node, neither of which is
349:                    // as robust. PR-DOM-0818 isn't entirely clear on which it
350:                    // recommends?????
351:
352:                    // No need to check kids for right-document; if they weren't,
353:                    // they wouldn't be kids of that DocFrag.
354:                    if (errorChecking) {
355:                        for (Node kid = newChild.getFirstChild(); // Prescan
356:                        kid != null; kid = kid.getNextSibling()) {
357:
358:                            if (!ownerDocument.isKidOK(this , kid)) {
359:                                throw new DOMException(
360:                                        DOMException.HIERARCHY_REQUEST_ERR,
361:                                        "DOM006 Hierarchy request error");
362:                            }
363:                        }
364:                    }
365:
366:                    while (newChild.hasChildNodes()) {
367:                        insertBefore(newChild.getFirstChild(), refChild);
368:                    }
369:                    return newChild;
370:                }
371:
372:                if (newChild == refChild) {
373:                    // stupid case that must be handled as a no-op triggering events...
374:                    refChild = refChild.getNextSibling();
375:                    removeChild(newChild);
376:                    insertBefore(newChild, refChild);
377:                    return newChild;
378:                }
379:
380:                if (needsSyncChildren()) {
381:                    synchronizeChildren();
382:                }
383:
384:                if (errorChecking) {
385:                    if (isReadOnly()) {
386:                        throw new DOMException(
387:                                DOMException.NO_MODIFICATION_ALLOWED_ERR,
388:                                "DOM001 Modification not allowed");
389:                    }
390:                    if (newChild.getOwnerDocument() != ownerDocument) {
391:                        throw new DOMException(DOMException.WRONG_DOCUMENT_ERR,
392:                                "DOM005 Wrong document");
393:                    }
394:                    if (!ownerDocument.isKidOK(this , newChild)) {
395:                        throw new DOMException(
396:                                DOMException.HIERARCHY_REQUEST_ERR,
397:                                "DOM006 Hierarchy request error");
398:                    }
399:                    // refChild must be a child of this node (or null)
400:                    if (refChild != null && refChild.getParentNode() != this ) {
401:                        throw new DOMException(DOMException.NOT_FOUND_ERR,
402:                                "DOM008 Not found");
403:                    }
404:
405:                    // Prevent cycles in the tree
406:                    // newChild cannot be ancestor of this Node,
407:                    // and actually cannot be this
408:                    boolean treeSafe = true;
409:                    for (NodeImpl a = this ; treeSafe && a != null; a = a
410:                            .parentNode()) {
411:                        treeSafe = newChild != a;
412:                    }
413:                    if (!treeSafe) {
414:                        throw new DOMException(
415:                                DOMException.HIERARCHY_REQUEST_ERR,
416:                                "DOM006 Hierarchy request error");
417:                    }
418:                }
419:
420:                // notify document
421:                ownerDocument.insertingNode(this , replace);
422:
423:                // Convert to internal type, to avoid repeated casting
424:                ChildNode newInternal = (ChildNode) newChild;
425:
426:                Node oldparent = newInternal.parentNode();
427:                if (oldparent != null) {
428:                    oldparent.removeChild(newInternal);
429:                }
430:
431:                // Convert to internal type, to avoid repeated casting
432:                ChildNode refInternal = (ChildNode) refChild;
433:
434:                // Attach up
435:                newInternal.ownerNode = this ;
436:                newInternal.isOwned(true);
437:
438:                // Attach before and after
439:                // Note: firstChild.previousSibling == lastChild!!
440:                if (firstChild == null) {
441:                    // this our first and only child
442:                    firstChild = newInternal;
443:                    newInternal.isFirstChild(true);
444:                    newInternal.previousSibling = newInternal;
445:                } else {
446:                    if (refInternal == null) {
447:                        // this is an append
448:                        ChildNode lastChild = firstChild.previousSibling;
449:                        lastChild.nextSibling = newInternal;
450:                        newInternal.previousSibling = lastChild;
451:                        firstChild.previousSibling = newInternal;
452:                    } else {
453:                        // this is an insert
454:                        if (refChild == firstChild) {
455:                            // at the head of the list
456:                            firstChild.isFirstChild(false);
457:                            newInternal.nextSibling = firstChild;
458:                            newInternal.previousSibling = firstChild.previousSibling;
459:                            firstChild.previousSibling = newInternal;
460:                            firstChild = newInternal;
461:                            newInternal.isFirstChild(true);
462:                        } else {
463:                            // somewhere in the middle
464:                            ChildNode prev = refInternal.previousSibling;
465:                            newInternal.nextSibling = refInternal;
466:                            prev.nextSibling = newInternal;
467:                            refInternal.previousSibling = newInternal;
468:                            newInternal.previousSibling = prev;
469:                        }
470:                    }
471:                }
472:
473:                changed();
474:
475:                // update cached length if we have any
476:                if (fCachedLength != -1) {
477:                    fCachedLength++;
478:                }
479:                if (fCachedChildIndex != -1) {
480:                    // if we happen to insert just before the cached node, update
481:                    // the cache to the new node to match the cached index
482:                    if (fCachedChild == refInternal) {
483:                        fCachedChild = newInternal;
484:                    } else {
485:                        // otherwise just invalidate the cache
486:                        fCachedChildIndex = -1;
487:                    }
488:                }
489:
490:                // notify document
491:                ownerDocument.insertedNode(this , newInternal, replace);
492:
493:                checkNormalizationAfterInsert(newInternal);
494:
495:                return newChild;
496:
497:            } // internalInsertBefore(Node,Node,boolean):Node
498:
499:            /**
500:             * Remove a child from this Node. The removed child's subtree
501:             * remains intact so it may be re-inserted elsewhere.
502:             *
503:             * @return oldChild, in its new state (removed).
504:             *
505:             * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
506:             * this node.
507:             *
508:             * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
509:             * read-only.
510:             */
511:            public Node removeChild(Node oldChild) throws DOMException {
512:                // Tail-call, should be optimizable
513:                return internalRemoveChild(oldChild, false);
514:            } // removeChild(Node) :Node
515:
516:            /** NON-DOM INTERNAL: Within DOM actions,we sometimes need to be able
517:             * to control which mutation events are spawned. This version of the
518:             * removeChild operation allows us to do so. It is not intended
519:             * for use by application programs.
520:             */
521:            Node internalRemoveChild(Node oldChild, boolean replace)
522:                    throws DOMException {
523:
524:                CoreDocumentImpl ownerDocument = ownerDocument();
525:                if (ownerDocument.errorChecking) {
526:                    if (isReadOnly()) {
527:                        throw new DOMException(
528:                                DOMException.NO_MODIFICATION_ALLOWED_ERR,
529:                                "DOM001 Modification not allowed");
530:                    }
531:                    if (oldChild != null && oldChild.getParentNode() != this ) {
532:                        throw new DOMException(DOMException.NOT_FOUND_ERR,
533:                                "DOM008 Not found");
534:                    }
535:                }
536:
537:                ChildNode oldInternal = (ChildNode) oldChild;
538:
539:                // notify document
540:                ownerDocument.removingNode(this , oldInternal, replace);
541:
542:                // update cached length if we have any
543:                if (fCachedLength != -1) {
544:                    fCachedLength--;
545:                }
546:                if (fCachedChildIndex != -1) {
547:                    // if the removed node is the cached node
548:                    // move the cache to its (soon former) previous sibling
549:                    if (fCachedChild == oldInternal) {
550:                        fCachedChildIndex--;
551:                        fCachedChild = oldInternal.previousSibling();
552:                    } else {
553:                        // otherwise just invalidate the cache
554:                        fCachedChildIndex = -1;
555:                    }
556:                }
557:
558:                // Patch linked list around oldChild
559:                // Note: lastChild == firstChild.previousSibling
560:                if (oldInternal == firstChild) {
561:                    // removing first child
562:                    oldInternal.isFirstChild(false);
563:                    firstChild = oldInternal.nextSibling;
564:                    if (firstChild != null) {
565:                        firstChild.isFirstChild(true);
566:                        firstChild.previousSibling = oldInternal.previousSibling;
567:                    }
568:                } else {
569:                    ChildNode prev = oldInternal.previousSibling;
570:                    ChildNode next = oldInternal.nextSibling;
571:                    prev.nextSibling = next;
572:                    if (next == null) {
573:                        // removing last child
574:                        firstChild.previousSibling = prev;
575:                    } else {
576:                        // removing some other child in the middle
577:                        next.previousSibling = prev;
578:                    }
579:                }
580:
581:                // Save previous sibling for normalization checking.
582:                ChildNode oldPreviousSibling = oldInternal.previousSibling();
583:
584:                // Remove oldInternal's references to tree
585:                oldInternal.ownerNode = ownerDocument;
586:                oldInternal.isOwned(false);
587:                oldInternal.nextSibling = null;
588:                oldInternal.previousSibling = null;
589:
590:                changed();
591:
592:                // notify document
593:                ownerDocument.removedNode(this , replace);
594:
595:                checkNormalizationAfterRemove(oldPreviousSibling);
596:
597:                return oldInternal;
598:
599:            } // internalRemoveChild(Node,boolean):Node
600:
601:            /**
602:             * Make newChild occupy the location that oldChild used to
603:             * have. Note that newChild will first be removed from its previous
604:             * parent, if any. Equivalent to inserting newChild before oldChild,
605:             * then removing oldChild.
606:             *
607:             * @returns oldChild, in its new state (removed).
608:             *
609:             * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
610:             * type that shouldn't be a child of this node, or if newChild is
611:             * one of our ancestors.
612:             *
613:             * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
614:             * different owner document than we do.
615:             *
616:             * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
617:             * this node.
618:             *
619:             * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
620:             * read-only.
621:             */
622:            public Node replaceChild(Node newChild, Node oldChild)
623:                    throws DOMException {
624:                // If Mutation Events are being generated, this operation might
625:                // throw aggregate events twice when modifying an Attr -- once 
626:                // on insertion and once on removal. DOM Level 2 does not specify 
627:                // this as either desirable or undesirable, but hints that
628:                // aggregations should be issued only once per user request.
629:
630:                // notify document
631:                ownerDocument.replacingNode(this );
632:
633:                internalInsertBefore(newChild, oldChild, true);
634:                if (newChild != oldChild) {
635:                    internalRemoveChild(oldChild, true);
636:                }
637:
638:                // notify document
639:                ownerDocument.replacedNode(this );
640:
641:                return oldChild;
642:            }
643:
644:            //
645:            // NodeList methods
646:            //
647:
648:            /**
649:             * Count the immediate children of this node.  Use to implement
650:             * NodeList.getLength().
651:             * @return int
652:             */
653:            private int nodeListGetLength() {
654:
655:                if (fCachedLength == -1) { // is the cached length invalid ?
656:                    ChildNode node;
657:                    // start from the cached node if we have one
658:                    if (fCachedChildIndex != -1 && fCachedChild != null) {
659:                        fCachedLength = fCachedChildIndex;
660:                        node = fCachedChild;
661:                    } else {
662:                        node = firstChild;
663:                        fCachedLength = 0;
664:                    }
665:                    for (; node != null; node = node.nextSibling) {
666:                        fCachedLength++;
667:                    }
668:                }
669:
670:                return fCachedLength;
671:
672:            } // nodeListGetLength():int
673:
674:            /**
675:             * NodeList method: Count the immediate children of this node
676:             * @return int
677:             */
678:            public int getLength() {
679:                return nodeListGetLength();
680:            }
681:
682:            /**
683:             * Return the Nth immediate child of this node, or null if the index is
684:             * out of bounds.  Use to implement NodeList.item().
685:             * @param index int
686:             */
687:            private Node nodeListItem(int index) {
688:                // short way
689:                if (fCachedChildIndex != -1 && fCachedChild != null) {
690:                    if (fCachedChildIndex < index) {
691:                        while (fCachedChildIndex < index
692:                                && fCachedChild != null) {
693:                            fCachedChildIndex++;
694:                            fCachedChild = fCachedChild.nextSibling;
695:                        }
696:                    } else if (fCachedChildIndex > index) {
697:                        while (fCachedChildIndex > index
698:                                && fCachedChild != null) {
699:                            fCachedChildIndex--;
700:                            fCachedChild = fCachedChild.previousSibling();
701:                        }
702:                    }
703:                    return fCachedChild;
704:                }
705:
706:                // long way
707:                fCachedChild = firstChild;
708:                for (fCachedChildIndex = 0; fCachedChildIndex < index
709:                        && fCachedChild != null; fCachedChildIndex++) {
710:                    fCachedChild = fCachedChild.nextSibling;
711:                }
712:                return fCachedChild;
713:
714:            } // nodeListItem(int):Node
715:
716:            /**
717:             * NodeList method: Return the Nth immediate child of this node, or
718:             * null if the index is out of bounds.
719:             * @return org.w3c.dom.Node
720:             * @param index int
721:             */
722:            public Node item(int index) {
723:                return nodeListItem(index);
724:            } // item(int):Node
725:
726:            /**
727:             * Create a NodeList to access children that is use by subclass elements
728:             * that have methods named getLength() or item(int).  ChildAndParentNode
729:             * optimizes getChildNodes() by implementing NodeList itself.  However if
730:             * a subclass Element implements methods with the same name as the NodeList
731:             * methods, they will override the actually methods in this class.
732:             * <p>
733:             * To use this method, the subclass should implement getChildNodes() and
734:             * have it call this method.  The resulting NodeList instance maybe
735:             * shared and cached in a transient field, but the cached value must be
736:             * cleared if the node is cloned.
737:             */
738:            protected final NodeList getChildNodesUnoptimized() {
739:                if (needsSyncChildren()) {
740:                    synchronizeChildren();
741:                }
742:                return new NodeList() {
743:                    /**
744:                     * @see NodeList.getLength()
745:                     */
746:                    public int getLength() {
747:                        return nodeListGetLength();
748:                    } // getLength():int
749:
750:                    /**
751:                     * @see NodeList.item(int)
752:                     */
753:                    public Node item(int index) {
754:                        return nodeListItem(index);
755:                    } // item(int):Node
756:                };
757:            } // getChildNodesUnoptimized():NodeList
758:
759:            //
760:            // DOM2: methods, getters, setters
761:            //
762:
763:            /**
764:             * Override default behavior to call normalize() on this Node's
765:             * children. It is up to implementors or Node to override normalize()
766:             * to take action.
767:             */
768:            public void normalize() {
769:                // No need to normalize if already normalized.
770:                if (isNormalized()) {
771:                    return;
772:                }
773:                if (needsSyncChildren()) {
774:                    synchronizeChildren();
775:                }
776:                ChildNode kid;
777:                for (kid = firstChild; kid != null; kid = kid.nextSibling) {
778:                    kid.normalize();
779:                }
780:                isNormalized(true);
781:            }
782:
783:            //
784:            // Public methods
785:            //
786:
787:            /**
788:             * Override default behavior so that if deep is true, children are also
789:             * toggled.
790:             * @see Node
791:             * <P>
792:             * Note: this will not change the state of an EntityReference or its
793:             * children, which are always read-only.
794:             */
795:            public void setReadOnly(boolean readOnly, boolean deep) {
796:
797:                super .setReadOnly(readOnly, deep);
798:
799:                if (deep) {
800:
801:                    if (needsSyncChildren()) {
802:                        synchronizeChildren();
803:                    }
804:
805:                    // Recursively set kids
806:                    for (ChildNode mykid = firstChild; mykid != null; mykid = mykid.nextSibling) {
807:                        if (mykid.getNodeType() != Node.ENTITY_REFERENCE_NODE) {
808:                            mykid.setReadOnly(readOnly, true);
809:                        }
810:                    }
811:                }
812:            } // setReadOnly(boolean,boolean)
813:
814:            //
815:            // Protected methods
816:            //
817:
818:            /**
819:             * Override this method in subclass to hook in efficient
820:             * internal data structure.
821:             */
822:            protected void synchronizeChildren() {
823:                // By default just change the flag to avoid calling this method again
824:                needsSyncChildren(false);
825:            }
826:
827:            /**
828:             * Checks the normalized state of this node after inserting a child.
829:             * If the inserted child causes this node to be unnormalized, then this
830:             * node is flagged accordingly.
831:             * The conditions for changing the normalized state are:
832:             * <ul>
833:             * <li>The inserted child is a text node and one of its adjacent siblings
834:             * is also a text node.
835:             * <li>The inserted child is is itself unnormalized.
836:             * </ul>
837:             *
838:             * @param insertedChild the child node that was inserted into this node
839:             *
840:             * @throws NullPointerException if the inserted child is <code>null</code>
841:             */
842:            void checkNormalizationAfterInsert(ChildNode insertedChild) {
843:                // See if insertion caused this node to be unnormalized.
844:                if (insertedChild.getNodeType() == Node.TEXT_NODE) {
845:                    ChildNode prev = insertedChild.previousSibling();
846:                    ChildNode next = insertedChild.nextSibling;
847:                    // If an adjacent sibling of the new child is a text node,
848:                    // flag this node as unnormalized.
849:                    if ((prev != null && prev.getNodeType() == Node.TEXT_NODE)
850:                            || (next != null && next.getNodeType() == Node.TEXT_NODE)) {
851:                        isNormalized(false);
852:                    }
853:                } else {
854:                    // If the new child is not normalized,
855:                    // then this node is inherently not normalized.
856:                    if (!insertedChild.isNormalized()) {
857:                        isNormalized(false);
858:                    }
859:                }
860:            } // checkNormalizationAfterInsert(ChildNode)
861:
862:            /**
863:             * Checks the normalized of this node after removing a child.
864:             * If the removed child causes this node to be unnormalized, then this
865:             * node is flagged accordingly.
866:             * The conditions for changing the normalized state are:
867:             * <ul>
868:             * <li>The removed child had two adjacent siblings that were text nodes.
869:             * </ul>
870:             *
871:             * @param previousSibling the previous sibling of the removed child, or
872:             * <code>null</code>
873:             */
874:            void checkNormalizationAfterRemove(ChildNode previousSibling) {
875:                // See if removal caused this node to be unnormalized.
876:                // If the adjacent siblings of the removed child were both text nodes,
877:                // flag this node as unnormalized.
878:                if (previousSibling != null
879:                        && previousSibling.getNodeType() == Node.TEXT_NODE) {
880:
881:                    ChildNode next = previousSibling.nextSibling;
882:                    if (next != null && next.getNodeType() == Node.TEXT_NODE) {
883:                        isNormalized(false);
884:                    }
885:                }
886:            } // checkNormalizationAfterRemove(Node)
887:
888:            //
889:            // Serialization methods
890:            //
891:
892:            /** Serialize object. */
893:            private void writeObject(ObjectOutputStream out) throws IOException {
894:
895:                // synchronize chilren
896:                if (needsSyncChildren()) {
897:                    synchronizeChildren();
898:                }
899:                // write object
900:                out.defaultWriteObject();
901:
902:            } // writeObject(ObjectOutputStream)
903:
904:            /** Deserialize object. */
905:            private void readObject(ObjectInputStream ois)
906:                    throws ClassNotFoundException, IOException {
907:
908:                // perform default deseralization
909:                ois.defaultReadObject();
910:
911:                // hardset synchildren - so we don't try to sync- it does not make any sense
912:                // to try to synchildren when we just desealize object.
913:
914:                needsSyncChildren(false);
915:
916:                // initialize transients
917:                fCachedLength = -1;
918:                fCachedChildIndex = -1;
919:
920:            } // readObject(ObjectInputStream)
921:
922:        } // class ParentNode
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.