Source Code Cross Referenced for ParentNode.java in  » XML » xerces-2_9_1 » 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 » XML » xerces 2_9_1 » org.apache.xerces.dom 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         * 
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         * 
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:
0018:        package org.apache.xerces.dom;
0019:
0020:        import java.io.Serializable;
0021:        import java.io.IOException;
0022:        import java.io.ObjectInputStream;
0023:        import java.io.ObjectOutputStream;
0024:
0025:        import org.w3c.dom.DOMException;
0026:        import org.w3c.dom.Document;
0027:        import org.w3c.dom.Node;
0028:        import org.w3c.dom.NodeList;
0029:        import org.w3c.dom.UserDataHandler;
0030:
0031:        /**
0032:         * ParentNode inherits from ChildNode and adds the capability of having child
0033:         * nodes. Not every node in the DOM can have children, so only nodes that can
0034:         * should inherit from this class and pay the price for it.
0035:         * <P>
0036:         * ParentNode, just like NodeImpl, also implements NodeList, so it can
0037:         * return itself in response to the getChildNodes() query. This eliminiates
0038:         * the need for a separate ChildNodeList object. Note that this is an
0039:         * IMPLEMENTATION DETAIL; applications should _never_ assume that
0040:         * this identity exists. On the other hand, subclasses may need to override
0041:         * this, in case of conflicting names. This is the case for the classes
0042:         * HTMLSelectElementImpl and HTMLFormElementImpl of the HTML DOM.
0043:         * <P>
0044:         * While we have a direct reference to the first child, the last child is
0045:         * stored as the previous sibling of the first child. First child nodes are
0046:         * marked as being so, and getNextSibling hides this fact.
0047:         * <P>Note: Not all parent nodes actually need to also be a child. At some
0048:         * point we used to have ParentNode inheriting from NodeImpl and another class
0049:         * called ChildAndParentNode that inherited from ChildNode. But due to the lack
0050:         * of multiple inheritance a lot of code had to be duplicated which led to a
0051:         * maintenance nightmare. At the same time only a few nodes (Document,
0052:         * DocumentFragment, Entity, and Attribute) cannot be a child so the gain in
0053:         * memory wasn't really worth it. The only type for which this would be the
0054:         * case is Attribute, but we deal with there in another special way, so this is
0055:         * not applicable.
0056:         * <p>
0057:         * This class doesn't directly support mutation events, however, it notifies
0058:         * the document when mutations are performed so that the document class do so.
0059:         *
0060:         * <p><b>WARNING</b>: Some of the code here is partially duplicated in
0061:         * AttrImpl, be careful to keep these two classes in sync!
0062:         * 
0063:         * @xerces.internal
0064:         *
0065:         * @author Arnaud  Le Hors, IBM
0066:         * @author Joe Kesselman, IBM
0067:         * @author Andy Clark, IBM
0068:         * @version $Id: ParentNode.java 447266 2006-09-18 05:57:49Z mrglavas $
0069:         */
0070:        public abstract class ParentNode extends ChildNode {
0071:
0072:            /** Serialization version. */
0073:            static final long serialVersionUID = 2815829867152120872L;
0074:
0075:            /** Owner document. */
0076:            protected CoreDocumentImpl ownerDocument;
0077:
0078:            /** First child. */
0079:            protected ChildNode firstChild = null;
0080:
0081:            // transients
0082:
0083:            /** NodeList cache */
0084:            protected transient NodeListCache fNodeListCache = null;
0085:
0086:            //
0087:            // Constructors
0088:            //
0089:
0090:            /**
0091:             * No public constructor; only subclasses of ParentNode should be
0092:             * instantiated, and those normally via a Document's factory methods
0093:             */
0094:            protected ParentNode(CoreDocumentImpl ownerDocument) {
0095:                super (ownerDocument);
0096:                this .ownerDocument = ownerDocument;
0097:            }
0098:
0099:            /** Constructor for serialization. */
0100:            public ParentNode() {
0101:            }
0102:
0103:            //
0104:            // NodeList methods
0105:            //
0106:
0107:            /**
0108:             * Returns a duplicate of a given node. You can consider this a
0109:             * generic "copy constructor" for nodes. The newly returned object should
0110:             * be completely independent of the source object's subtree, so changes
0111:             * in one after the clone has been made will not affect the other.
0112:             * <p>
0113:             * Example: Cloning a Text node will copy both the node and the text it
0114:             * contains.
0115:             * <p>
0116:             * Example: Cloning something that has children -- Element or Attr, for
0117:             * example -- will _not_ clone those children unless a "deep clone"
0118:             * has been requested. A shallow clone of an Attr node will yield an
0119:             * empty Attr of the same name.
0120:             * <p>
0121:             * NOTE: Clones will always be read/write, even if the node being cloned
0122:             * is read-only, to permit applications using only the DOM API to obtain
0123:             * editable copies of locked portions of the tree.
0124:             */
0125:            public Node cloneNode(boolean deep) {
0126:
0127:                if (needsSyncChildren()) {
0128:                    synchronizeChildren();
0129:                }
0130:                ParentNode newnode = (ParentNode) super .cloneNode(deep);
0131:
0132:                // set owner document
0133:                newnode.ownerDocument = ownerDocument;
0134:
0135:                // Need to break the association w/ original kids
0136:                newnode.firstChild = null;
0137:
0138:                // invalidate cache for children NodeList
0139:                newnode.fNodeListCache = null;
0140:
0141:                // Then, if deep, clone the kids too.
0142:                if (deep) {
0143:                    for (ChildNode child = firstChild; child != null; child = child.nextSibling) {
0144:                        newnode.appendChild(child.cloneNode(true));
0145:                    }
0146:                }
0147:
0148:                return newnode;
0149:
0150:            } // cloneNode(boolean):Node
0151:
0152:            /**
0153:             * Find the Document that this Node belongs to (the document in
0154:             * whose context the Node was created). The Node may or may not
0155:             * currently be part of that Document's actual contents.
0156:             */
0157:            public Document getOwnerDocument() {
0158:                return ownerDocument;
0159:            }
0160:
0161:            /**
0162:             * same as above but returns internal type and this one is not overridden
0163:             * by CoreDocumentImpl to return null
0164:             */
0165:            CoreDocumentImpl ownerDocument() {
0166:                return ownerDocument;
0167:            }
0168:
0169:            /**
0170:             * NON-DOM
0171:             * set the ownerDocument of this node and its children
0172:             */
0173:            protected void setOwnerDocument(CoreDocumentImpl doc) {
0174:                if (needsSyncChildren()) {
0175:                    synchronizeChildren();
0176:                }
0177:                super .setOwnerDocument(doc);
0178:                ownerDocument = doc;
0179:                for (ChildNode child = firstChild; child != null; child = child.nextSibling) {
0180:                    child.setOwnerDocument(doc);
0181:                }
0182:            }
0183:
0184:            /**
0185:             * Test whether this node has any children. Convenience shorthand
0186:             * for (Node.getFirstChild()!=null)
0187:             */
0188:            public boolean hasChildNodes() {
0189:                if (needsSyncChildren()) {
0190:                    synchronizeChildren();
0191:                }
0192:                return firstChild != null;
0193:            }
0194:
0195:            /**
0196:             * Obtain a NodeList enumerating all children of this node. If there
0197:             * are none, an (initially) empty NodeList is returned.
0198:             * <p>
0199:             * NodeLists are "live"; as children are added/removed the NodeList
0200:             * will immediately reflect those changes. Also, the NodeList refers
0201:             * to the actual nodes, so changes to those nodes made via the DOM tree
0202:             * will be reflected in the NodeList and vice versa.
0203:             * <p>
0204:             * In this implementation, Nodes implement the NodeList interface and
0205:             * provide their own getChildNodes() support. Other DOMs may solve this
0206:             * differently.
0207:             */
0208:            public NodeList getChildNodes() {
0209:
0210:                if (needsSyncChildren()) {
0211:                    synchronizeChildren();
0212:                }
0213:                return this ;
0214:
0215:            } // getChildNodes():NodeList
0216:
0217:            /** The first child of this Node, or null if none. */
0218:            public Node getFirstChild() {
0219:
0220:                if (needsSyncChildren()) {
0221:                    synchronizeChildren();
0222:                }
0223:                return firstChild;
0224:
0225:            } // getFirstChild():Node
0226:
0227:            /** The last child of this Node, or null if none. */
0228:            public Node getLastChild() {
0229:
0230:                if (needsSyncChildren()) {
0231:                    synchronizeChildren();
0232:                }
0233:                return lastChild();
0234:
0235:            } // getLastChild():Node
0236:
0237:            final ChildNode lastChild() {
0238:                // last child is stored as the previous sibling of first child
0239:                return firstChild != null ? firstChild.previousSibling : null;
0240:            }
0241:
0242:            final void lastChild(ChildNode node) {
0243:                // store lastChild as previous sibling of first child
0244:                if (firstChild != null) {
0245:                    firstChild.previousSibling = node;
0246:                }
0247:            }
0248:
0249:            /**
0250:             * Move one or more node(s) to our list of children. Note that this
0251:             * implicitly removes them from their previous parent.
0252:             *
0253:             * @param newChild The Node to be moved to our subtree. As a
0254:             * convenience feature, inserting a DocumentNode will instead insert
0255:             * all its children.
0256:             *
0257:             * @param refChild Current child which newChild should be placed
0258:             * immediately before. If refChild is null, the insertion occurs
0259:             * after all existing Nodes, like appendChild().
0260:             *
0261:             * @return newChild, in its new state (relocated, or emptied in the case of
0262:             * DocumentNode.)
0263:             *
0264:             * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
0265:             * type that shouldn't be a child of this node, or if newChild is an
0266:             * ancestor of this node.
0267:             *
0268:             * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
0269:             * different owner document than we do.
0270:             *
0271:             * @throws DOMException(NOT_FOUND_ERR) if refChild is not a child of
0272:             * this node.
0273:             *
0274:             * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
0275:             * read-only.
0276:             */
0277:            public Node insertBefore(Node newChild, Node refChild)
0278:                    throws DOMException {
0279:                // Tail-call; optimizer should be able to do good things with.
0280:                return internalInsertBefore(newChild, refChild, false);
0281:            } // insertBefore(Node,Node):Node
0282:
0283:            /** NON-DOM INTERNAL: Within DOM actions,we sometimes need to be able
0284:             * to control which mutation events are spawned. This version of the
0285:             * insertBefore operation allows us to do so. It is not intended
0286:             * for use by application programs.
0287:             */
0288:            Node internalInsertBefore(Node newChild, Node refChild,
0289:                    boolean replace) throws DOMException {
0290:
0291:                boolean errorChecking = ownerDocument.errorChecking;
0292:
0293:                if (newChild.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) {
0294:                    // SLOW BUT SAFE: We could insert the whole subtree without
0295:                    // juggling so many next/previous pointers. (Wipe out the
0296:                    // parent's child-list, patch the parent pointers, set the
0297:                    // ends of the list.) But we know some subclasses have special-
0298:                    // case behavior they add to insertBefore(), so we don't risk it.
0299:                    // This approch also takes fewer bytecodes.
0300:
0301:                    // NOTE: If one of the children is not a legal child of this
0302:                    // node, throw HIERARCHY_REQUEST_ERR before _any_ of the children
0303:                    // have been transferred. (Alternative behaviors would be to
0304:                    // reparent up to the first failure point or reparent all those
0305:                    // which are acceptable to the target node, neither of which is
0306:                    // as robust. PR-DOM-0818 isn't entirely clear on which it
0307:                    // recommends?????
0308:
0309:                    // No need to check kids for right-document; if they weren't,
0310:                    // they wouldn't be kids of that DocFrag.
0311:                    if (errorChecking) {
0312:                        for (Node kid = newChild.getFirstChild(); // Prescan
0313:                        kid != null; kid = kid.getNextSibling()) {
0314:
0315:                            if (!ownerDocument.isKidOK(this , kid)) {
0316:                                throw new DOMException(
0317:                                        DOMException.HIERARCHY_REQUEST_ERR,
0318:                                        DOMMessageFormatter.formatMessage(
0319:                                                DOMMessageFormatter.DOM_DOMAIN,
0320:                                                "HIERARCHY_REQUEST_ERR", null));
0321:                            }
0322:                        }
0323:                    }
0324:
0325:                    while (newChild.hasChildNodes()) {
0326:                        insertBefore(newChild.getFirstChild(), refChild);
0327:                    }
0328:                    return newChild;
0329:                }
0330:
0331:                if (newChild == refChild) {
0332:                    // stupid case that must be handled as a no-op triggering events...
0333:                    refChild = refChild.getNextSibling();
0334:                    removeChild(newChild);
0335:                    insertBefore(newChild, refChild);
0336:                    return newChild;
0337:                }
0338:
0339:                if (needsSyncChildren()) {
0340:                    synchronizeChildren();
0341:                }
0342:
0343:                if (errorChecking) {
0344:                    if (isReadOnly()) {
0345:                        throw new DOMException(
0346:                                DOMException.NO_MODIFICATION_ALLOWED_ERR,
0347:                                DOMMessageFormatter.formatMessage(
0348:                                        DOMMessageFormatter.DOM_DOMAIN,
0349:                                        "NO_MODIFICATION_ALLOWED_ERR", null));
0350:                    }
0351:                    if (newChild.getOwnerDocument() != ownerDocument
0352:                            && newChild != ownerDocument) {
0353:                        throw new DOMException(DOMException.WRONG_DOCUMENT_ERR,
0354:                                DOMMessageFormatter.formatMessage(
0355:                                        DOMMessageFormatter.DOM_DOMAIN,
0356:                                        "WRONG_DOCUMENT_ERR", null));
0357:                    }
0358:                    if (!ownerDocument.isKidOK(this , newChild)) {
0359:                        throw new DOMException(
0360:                                DOMException.HIERARCHY_REQUEST_ERR,
0361:                                DOMMessageFormatter.formatMessage(
0362:                                        DOMMessageFormatter.DOM_DOMAIN,
0363:                                        "HIERARCHY_REQUEST_ERR", null));
0364:                    }
0365:                    // refChild must be a child of this node (or null)
0366:                    if (refChild != null && refChild.getParentNode() != this ) {
0367:                        throw new DOMException(DOMException.NOT_FOUND_ERR,
0368:                                DOMMessageFormatter.formatMessage(
0369:                                        DOMMessageFormatter.DOM_DOMAIN,
0370:                                        "NOT_FOUND_ERR", null));
0371:                    }
0372:
0373:                    // Prevent cycles in the tree
0374:                    // newChild cannot be ancestor of this Node,
0375:                    // and actually cannot be this
0376:                    boolean treeSafe = true;
0377:                    for (NodeImpl a = this ; treeSafe && a != null; a = a
0378:                            .parentNode()) {
0379:                        treeSafe = newChild != a;
0380:                    }
0381:                    if (!treeSafe) {
0382:                        throw new DOMException(
0383:                                DOMException.HIERARCHY_REQUEST_ERR,
0384:                                DOMMessageFormatter.formatMessage(
0385:                                        DOMMessageFormatter.DOM_DOMAIN,
0386:                                        "HIERARCHY_REQUEST_ERR", null));
0387:                    }
0388:                }
0389:
0390:                // notify document
0391:                ownerDocument.insertingNode(this , replace);
0392:
0393:                // Convert to internal type, to avoid repeated casting
0394:                ChildNode newInternal = (ChildNode) newChild;
0395:
0396:                Node oldparent = newInternal.parentNode();
0397:                if (oldparent != null) {
0398:                    oldparent.removeChild(newInternal);
0399:                }
0400:
0401:                // Convert to internal type, to avoid repeated casting
0402:                ChildNode refInternal = (ChildNode) refChild;
0403:
0404:                // Attach up
0405:                newInternal.ownerNode = this ;
0406:                newInternal.isOwned(true);
0407:
0408:                // Attach before and after
0409:                // Note: firstChild.previousSibling == lastChild!!
0410:                if (firstChild == null) {
0411:                    // this our first and only child
0412:                    firstChild = newInternal;
0413:                    newInternal.isFirstChild(true);
0414:                    newInternal.previousSibling = newInternal;
0415:                } else {
0416:                    if (refInternal == null) {
0417:                        // this is an append
0418:                        ChildNode lastChild = firstChild.previousSibling;
0419:                        lastChild.nextSibling = newInternal;
0420:                        newInternal.previousSibling = lastChild;
0421:                        firstChild.previousSibling = newInternal;
0422:                    } else {
0423:                        // this is an insert
0424:                        if (refChild == firstChild) {
0425:                            // at the head of the list
0426:                            firstChild.isFirstChild(false);
0427:                            newInternal.nextSibling = firstChild;
0428:                            newInternal.previousSibling = firstChild.previousSibling;
0429:                            firstChild.previousSibling = newInternal;
0430:                            firstChild = newInternal;
0431:                            newInternal.isFirstChild(true);
0432:                        } else {
0433:                            // somewhere in the middle
0434:                            ChildNode prev = refInternal.previousSibling;
0435:                            newInternal.nextSibling = refInternal;
0436:                            prev.nextSibling = newInternal;
0437:                            refInternal.previousSibling = newInternal;
0438:                            newInternal.previousSibling = prev;
0439:                        }
0440:                    }
0441:                }
0442:
0443:                changed();
0444:
0445:                // update cached length if we have any
0446:                if (fNodeListCache != null) {
0447:                    if (fNodeListCache.fLength != -1) {
0448:                        fNodeListCache.fLength++;
0449:                    }
0450:                    if (fNodeListCache.fChildIndex != -1) {
0451:                        // if we happen to insert just before the cached node, update
0452:                        // the cache to the new node to match the cached index
0453:                        if (fNodeListCache.fChild == refInternal) {
0454:                            fNodeListCache.fChild = newInternal;
0455:                        } else {
0456:                            // otherwise just invalidate the cache
0457:                            fNodeListCache.fChildIndex = -1;
0458:                        }
0459:                    }
0460:                }
0461:
0462:                // notify document
0463:                ownerDocument.insertedNode(this , newInternal, replace);
0464:
0465:                checkNormalizationAfterInsert(newInternal);
0466:
0467:                return newChild;
0468:
0469:            } // internalInsertBefore(Node,Node,boolean):Node
0470:
0471:            /**
0472:             * Remove a child from this Node. The removed child's subtree
0473:             * remains intact so it may be re-inserted elsewhere.
0474:             *
0475:             * @return oldChild, in its new state (removed).
0476:             *
0477:             * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
0478:             * this node.
0479:             *
0480:             * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
0481:             * read-only.
0482:             */
0483:            public Node removeChild(Node oldChild) throws DOMException {
0484:                // Tail-call, should be optimizable
0485:                return internalRemoveChild(oldChild, false);
0486:            } // removeChild(Node) :Node
0487:
0488:            /** NON-DOM INTERNAL: Within DOM actions,we sometimes need to be able
0489:             * to control which mutation events are spawned. This version of the
0490:             * removeChild operation allows us to do so. It is not intended
0491:             * for use by application programs.
0492:             */
0493:            Node internalRemoveChild(Node oldChild, boolean replace)
0494:                    throws DOMException {
0495:
0496:                CoreDocumentImpl ownerDocument = ownerDocument();
0497:                if (ownerDocument.errorChecking) {
0498:                    if (isReadOnly()) {
0499:                        throw new DOMException(
0500:                                DOMException.NO_MODIFICATION_ALLOWED_ERR,
0501:                                DOMMessageFormatter.formatMessage(
0502:                                        DOMMessageFormatter.DOM_DOMAIN,
0503:                                        "NO_MODIFICATION_ALLOWED_ERR", null));
0504:                    }
0505:                    if (oldChild != null && oldChild.getParentNode() != this ) {
0506:                        throw new DOMException(DOMException.NOT_FOUND_ERR,
0507:                                DOMMessageFormatter.formatMessage(
0508:                                        DOMMessageFormatter.DOM_DOMAIN,
0509:                                        "NOT_FOUND_ERR", null));
0510:                    }
0511:                }
0512:
0513:                ChildNode oldInternal = (ChildNode) oldChild;
0514:
0515:                // notify document
0516:                ownerDocument.removingNode(this , oldInternal, replace);
0517:
0518:                // update cached length if we have any
0519:                if (fNodeListCache != null) {
0520:                    if (fNodeListCache.fLength != -1) {
0521:                        fNodeListCache.fLength--;
0522:                    }
0523:                    if (fNodeListCache.fChildIndex != -1) {
0524:                        // if the removed node is the cached node
0525:                        // move the cache to its (soon former) previous sibling
0526:                        if (fNodeListCache.fChild == oldInternal) {
0527:                            fNodeListCache.fChildIndex--;
0528:                            fNodeListCache.fChild = oldInternal
0529:                                    .previousSibling();
0530:                        } else {
0531:                            // otherwise just invalidate the cache
0532:                            fNodeListCache.fChildIndex = -1;
0533:                        }
0534:                    }
0535:                }
0536:
0537:                // Patch linked list around oldChild
0538:                // Note: lastChild == firstChild.previousSibling
0539:                if (oldInternal == firstChild) {
0540:                    // removing first child
0541:                    oldInternal.isFirstChild(false);
0542:                    firstChild = oldInternal.nextSibling;
0543:                    if (firstChild != null) {
0544:                        firstChild.isFirstChild(true);
0545:                        firstChild.previousSibling = oldInternal.previousSibling;
0546:                    }
0547:                } else {
0548:                    ChildNode prev = oldInternal.previousSibling;
0549:                    ChildNode next = oldInternal.nextSibling;
0550:                    prev.nextSibling = next;
0551:                    if (next == null) {
0552:                        // removing last child
0553:                        firstChild.previousSibling = prev;
0554:                    } else {
0555:                        // removing some other child in the middle
0556:                        next.previousSibling = prev;
0557:                    }
0558:                }
0559:
0560:                // Save previous sibling for normalization checking.
0561:                ChildNode oldPreviousSibling = oldInternal.previousSibling();
0562:
0563:                // Remove oldInternal's references to tree
0564:                oldInternal.ownerNode = ownerDocument;
0565:                oldInternal.isOwned(false);
0566:                oldInternal.nextSibling = null;
0567:                oldInternal.previousSibling = null;
0568:
0569:                changed();
0570:
0571:                // notify document
0572:                ownerDocument.removedNode(this , replace);
0573:
0574:                checkNormalizationAfterRemove(oldPreviousSibling);
0575:
0576:                return oldInternal;
0577:
0578:            } // internalRemoveChild(Node,boolean):Node
0579:
0580:            /**
0581:             * Make newChild occupy the location that oldChild used to
0582:             * have. Note that newChild will first be removed from its previous
0583:             * parent, if any. Equivalent to inserting newChild before oldChild,
0584:             * then removing oldChild.
0585:             *
0586:             * @return oldChild, in its new state (removed).
0587:             *
0588:             * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
0589:             * type that shouldn't be a child of this node, or if newChild is
0590:             * one of our ancestors.
0591:             *
0592:             * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
0593:             * different owner document than we do.
0594:             *
0595:             * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
0596:             * this node.
0597:             *
0598:             * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
0599:             * read-only.
0600:             */
0601:            public Node replaceChild(Node newChild, Node oldChild)
0602:                    throws DOMException {
0603:                // If Mutation Events are being generated, this operation might
0604:                // throw aggregate events twice when modifying an Attr -- once 
0605:                // on insertion and once on removal. DOM Level 2 does not specify 
0606:                // this as either desirable or undesirable, but hints that
0607:                // aggregations should be issued only once per user request.
0608:
0609:                // notify document
0610:                ownerDocument.replacingNode(this );
0611:
0612:                internalInsertBefore(newChild, oldChild, true);
0613:                if (newChild != oldChild) {
0614:                    internalRemoveChild(oldChild, true);
0615:                }
0616:
0617:                // notify document
0618:                ownerDocument.replacedNode(this );
0619:
0620:                return oldChild;
0621:            }
0622:
0623:            /*
0624:             * Get Node text content
0625:             * @since DOM Level 3
0626:             */
0627:            public String getTextContent() throws DOMException {
0628:                Node child = getFirstChild();
0629:                if (child != null) {
0630:                    Node next = child.getNextSibling();
0631:                    if (next == null) {
0632:                        return hasTextContent(child) ? ((NodeImpl) child)
0633:                                .getTextContent() : "";
0634:                    }
0635:                    StringBuffer buf = new StringBuffer();
0636:                    getTextContent(buf);
0637:                    return buf.toString();
0638:                }
0639:                return "";
0640:            }
0641:
0642:            // internal method taking a StringBuffer in parameter
0643:            void getTextContent(StringBuffer buf) throws DOMException {
0644:                Node child = getFirstChild();
0645:                while (child != null) {
0646:                    if (hasTextContent(child)) {
0647:                        ((NodeImpl) child).getTextContent(buf);
0648:                    }
0649:                    child = child.getNextSibling();
0650:                }
0651:            }
0652:
0653:            // internal method returning whether to take the given node's text content
0654:            final boolean hasTextContent(Node child) {
0655:                return child.getNodeType() != Node.COMMENT_NODE
0656:                        && child.getNodeType() != Node.PROCESSING_INSTRUCTION_NODE
0657:                        && (child.getNodeType() != Node.TEXT_NODE || ((TextImpl) child)
0658:                                .isIgnorableWhitespace() == false);
0659:            }
0660:
0661:            /*
0662:             * Set Node text content
0663:             * @since DOM Level 3
0664:             */
0665:            public void setTextContent(String textContent) throws DOMException {
0666:                // get rid of any existing children
0667:                Node child;
0668:                while ((child = getFirstChild()) != null) {
0669:                    removeChild(child);
0670:                }
0671:                // create a Text node to hold the given content
0672:                if (textContent != null && textContent.length() != 0) {
0673:                    appendChild(ownerDocument().createTextNode(textContent));
0674:                }
0675:            }
0676:
0677:            //
0678:            // NodeList methods
0679:            //
0680:
0681:            /**
0682:             * Count the immediate children of this node.  Use to implement
0683:             * NodeList.getLength().
0684:             * @return int
0685:             */
0686:            private int nodeListGetLength() {
0687:
0688:                if (fNodeListCache == null) {
0689:                    if (needsSyncChildren()) {
0690:                        synchronizeChildren();
0691:                    }
0692:                    // get rid of trivial cases
0693:                    if (firstChild == null) {
0694:                        return 0;
0695:                    }
0696:                    if (firstChild == lastChild()) {
0697:                        return 1;
0698:                    }
0699:                    // otherwise request a cache object
0700:                    fNodeListCache = ownerDocument.getNodeListCache(this );
0701:                }
0702:                if (fNodeListCache.fLength == -1) { // is the cached length invalid ?
0703:                    int l;
0704:                    ChildNode n;
0705:                    // start from the cached node if we have one
0706:                    if (fNodeListCache.fChildIndex != -1
0707:                            && fNodeListCache.fChild != null) {
0708:                        l = fNodeListCache.fChildIndex;
0709:                        n = fNodeListCache.fChild;
0710:                    } else {
0711:                        n = firstChild;
0712:                        l = 0;
0713:                    }
0714:                    while (n != null) {
0715:                        l++;
0716:                        n = n.nextSibling;
0717:                    }
0718:                    fNodeListCache.fLength = l;
0719:                }
0720:
0721:                return fNodeListCache.fLength;
0722:
0723:            } // nodeListGetLength():int
0724:
0725:            /**
0726:             * NodeList method: Count the immediate children of this node
0727:             * @return int
0728:             */
0729:            public int getLength() {
0730:                return nodeListGetLength();
0731:            }
0732:
0733:            /**
0734:             * Return the Nth immediate child of this node, or null if the index is
0735:             * out of bounds.  Use to implement NodeList.item().
0736:             * @param index int
0737:             */
0738:            private Node nodeListItem(int index) {
0739:
0740:                if (fNodeListCache == null) {
0741:                    if (needsSyncChildren()) {
0742:                        synchronizeChildren();
0743:                    }
0744:                    // get rid of trivial case
0745:                    if (firstChild == lastChild()) {
0746:                        return index == 0 ? firstChild : null;
0747:                    }
0748:                    // otherwise request a cache object
0749:                    fNodeListCache = ownerDocument.getNodeListCache(this );
0750:                }
0751:                int i = fNodeListCache.fChildIndex;
0752:                ChildNode n = fNodeListCache.fChild;
0753:                boolean firstAccess = true;
0754:                // short way
0755:                if (i != -1 && n != null) {
0756:                    firstAccess = false;
0757:                    if (i < index) {
0758:                        while (i < index && n != null) {
0759:                            i++;
0760:                            n = n.nextSibling;
0761:                        }
0762:                    } else if (i > index) {
0763:                        while (i > index && n != null) {
0764:                            i--;
0765:                            n = n.previousSibling();
0766:                        }
0767:                    }
0768:                } else {
0769:                    // long way
0770:                    if (index < 0) {
0771:                        return null;
0772:                    }
0773:                    n = firstChild;
0774:                    for (i = 0; i < index && n != null; i++) {
0775:                        n = n.nextSibling;
0776:                    }
0777:                }
0778:
0779:                // release cache if reaching last child or first child
0780:                if (!firstAccess && (n == firstChild || n == lastChild())) {
0781:                    fNodeListCache.fChildIndex = -1;
0782:                    fNodeListCache.fChild = null;
0783:                    ownerDocument.freeNodeListCache(fNodeListCache);
0784:                    // we can keep using the cache until it is actually reused
0785:                    // fNodeListCache will be nulled by the pool (document) if that
0786:                    // happens.
0787:                    // fNodeListCache = null;
0788:                } else {
0789:                    // otherwise update it
0790:                    fNodeListCache.fChildIndex = i;
0791:                    fNodeListCache.fChild = n;
0792:                }
0793:                return n;
0794:
0795:            } // nodeListItem(int):Node
0796:
0797:            /**
0798:             * NodeList method: Return the Nth immediate child of this node, or
0799:             * null if the index is out of bounds.
0800:             * @return org.w3c.dom.Node
0801:             * @param index int
0802:             */
0803:            public Node item(int index) {
0804:                return nodeListItem(index);
0805:            } // item(int):Node
0806:
0807:            /**
0808:             * Create a NodeList to access children that is use by subclass elements
0809:             * that have methods named getLength() or item(int).  ChildAndParentNode
0810:             * optimizes getChildNodes() by implementing NodeList itself.  However if
0811:             * a subclass Element implements methods with the same name as the NodeList
0812:             * methods, they will override the actually methods in this class.
0813:             * <p>
0814:             * To use this method, the subclass should implement getChildNodes() and
0815:             * have it call this method.  The resulting NodeList instance maybe
0816:             * shared and cached in a transient field, but the cached value must be
0817:             * cleared if the node is cloned.
0818:             */
0819:            protected final NodeList getChildNodesUnoptimized() {
0820:                if (needsSyncChildren()) {
0821:                    synchronizeChildren();
0822:                }
0823:                return new NodeList() {
0824:                    /**
0825:                     * @see NodeList.getLength()
0826:                     */
0827:                    public int getLength() {
0828:                        return nodeListGetLength();
0829:                    } // getLength():int
0830:
0831:                    /**
0832:                     * @see NodeList.item(int)
0833:                     */
0834:                    public Node item(int index) {
0835:                        return nodeListItem(index);
0836:                    } // item(int):Node
0837:                };
0838:            } // getChildNodesUnoptimized():NodeList
0839:
0840:            //
0841:            // DOM2: methods, getters, setters
0842:            //
0843:
0844:            /**
0845:             * Override default behavior to call normalize() on this Node's
0846:             * children. It is up to implementors or Node to override normalize()
0847:             * to take action.
0848:             */
0849:            public void normalize() {
0850:                // No need to normalize if already normalized.
0851:                if (isNormalized()) {
0852:                    return;
0853:                }
0854:                if (needsSyncChildren()) {
0855:                    synchronizeChildren();
0856:                }
0857:                ChildNode kid;
0858:                for (kid = firstChild; kid != null; kid = kid.nextSibling) {
0859:                    kid.normalize();
0860:                }
0861:                isNormalized(true);
0862:            }
0863:
0864:            /**
0865:             * DOM Level 3 WD- Experimental.
0866:             * Override inherited behavior from NodeImpl to support deep equal.
0867:             */
0868:            public boolean isEqualNode(Node arg) {
0869:                if (!super .isEqualNode(arg)) {
0870:                    return false;
0871:                }
0872:                // there are many ways to do this test, and there isn't any way
0873:                // better than another. Performance may vary greatly depending on
0874:                // the implementations involved. This one should work fine for us.
0875:                Node child1 = getFirstChild();
0876:                Node child2 = arg.getFirstChild();
0877:                while (child1 != null && child2 != null) {
0878:                    if (!((NodeImpl) child1).isEqualNode(child2)) {
0879:                        return false;
0880:                    }
0881:                    child1 = child1.getNextSibling();
0882:                    child2 = child2.getNextSibling();
0883:                }
0884:                if (child1 != child2) {
0885:                    return false;
0886:                }
0887:                return true;
0888:            }
0889:
0890:            //
0891:            // Public methods
0892:            //
0893:
0894:            /**
0895:             * Override default behavior so that if deep is true, children are also
0896:             * toggled.
0897:             * @see Node
0898:             * <P>
0899:             * Note: this will not change the state of an EntityReference or its
0900:             * children, which are always read-only.
0901:             */
0902:            public void setReadOnly(boolean readOnly, boolean deep) {
0903:
0904:                super .setReadOnly(readOnly, deep);
0905:
0906:                if (deep) {
0907:
0908:                    if (needsSyncChildren()) {
0909:                        synchronizeChildren();
0910:                    }
0911:
0912:                    // Recursively set kids
0913:                    for (ChildNode mykid = firstChild; mykid != null; mykid = mykid.nextSibling) {
0914:                        if (mykid.getNodeType() != Node.ENTITY_REFERENCE_NODE) {
0915:                            mykid.setReadOnly(readOnly, true);
0916:                        }
0917:                    }
0918:                }
0919:            } // setReadOnly(boolean,boolean)
0920:
0921:            //
0922:            // Protected methods
0923:            //
0924:
0925:            /**
0926:             * Override this method in subclass to hook in efficient
0927:             * internal data structure.
0928:             */
0929:            protected void synchronizeChildren() {
0930:                // By default just change the flag to avoid calling this method again
0931:                needsSyncChildren(false);
0932:            }
0933:
0934:            /**
0935:             * Checks the normalized state of this node after inserting a child.
0936:             * If the inserted child causes this node to be unnormalized, then this
0937:             * node is flagged accordingly.
0938:             * The conditions for changing the normalized state are:
0939:             * <ul>
0940:             * <li>The inserted child is a text node and one of its adjacent siblings
0941:             * is also a text node.
0942:             * <li>The inserted child is is itself unnormalized.
0943:             * </ul>
0944:             *
0945:             * @param insertedChild the child node that was inserted into this node
0946:             *
0947:             * @throws NullPointerException if the inserted child is <code>null</code>
0948:             */
0949:            void checkNormalizationAfterInsert(ChildNode insertedChild) {
0950:                // See if insertion caused this node to be unnormalized.
0951:                if (insertedChild.getNodeType() == Node.TEXT_NODE) {
0952:                    ChildNode prev = insertedChild.previousSibling();
0953:                    ChildNode next = insertedChild.nextSibling;
0954:                    // If an adjacent sibling of the new child is a text node,
0955:                    // flag this node as unnormalized.
0956:                    if ((prev != null && prev.getNodeType() == Node.TEXT_NODE)
0957:                            || (next != null && next.getNodeType() == Node.TEXT_NODE)) {
0958:                        isNormalized(false);
0959:                    }
0960:                } else {
0961:                    // If the new child is not normalized,
0962:                    // then this node is inherently not normalized.
0963:                    if (!insertedChild.isNormalized()) {
0964:                        isNormalized(false);
0965:                    }
0966:                }
0967:            } // checkNormalizationAfterInsert(ChildNode)
0968:
0969:            /**
0970:             * Checks the normalized of this node after removing a child.
0971:             * If the removed child causes this node to be unnormalized, then this
0972:             * node is flagged accordingly.
0973:             * The conditions for changing the normalized state are:
0974:             * <ul>
0975:             * <li>The removed child had two adjacent siblings that were text nodes.
0976:             * </ul>
0977:             *
0978:             * @param previousSibling the previous sibling of the removed child, or
0979:             * <code>null</code>
0980:             */
0981:            void checkNormalizationAfterRemove(ChildNode previousSibling) {
0982:                // See if removal caused this node to be unnormalized.
0983:                // If the adjacent siblings of the removed child were both text nodes,
0984:                // flag this node as unnormalized.
0985:                if (previousSibling != null
0986:                        && previousSibling.getNodeType() == Node.TEXT_NODE) {
0987:
0988:                    ChildNode next = previousSibling.nextSibling;
0989:                    if (next != null && next.getNodeType() == Node.TEXT_NODE) {
0990:                        isNormalized(false);
0991:                    }
0992:                }
0993:            } // checkNormalizationAfterRemove(Node)
0994:
0995:            //
0996:            // Serialization methods
0997:            //
0998:
0999:            /** Serialize object. */
1000:            private void writeObject(ObjectOutputStream out) throws IOException {
1001:
1002:                // synchronize chilren
1003:                if (needsSyncChildren()) {
1004:                    synchronizeChildren();
1005:                }
1006:                // write object
1007:                out.defaultWriteObject();
1008:
1009:            } // writeObject(ObjectOutputStream)
1010:
1011:            /** Deserialize object. */
1012:            private void readObject(ObjectInputStream ois)
1013:                    throws ClassNotFoundException, IOException {
1014:
1015:                // perform default deseralization
1016:                ois.defaultReadObject();
1017:
1018:                // hardset synchildren - so we don't try to sync - it does not make any
1019:                // sense to try to synchildren when we just deserialize object.
1020:                needsSyncChildren(false);
1021:
1022:            } // readObject(ObjectInputStream)
1023:
1024:            /*
1025:             * a class to store some user data along with its handler
1026:             */
1027:            class UserDataRecord implements  Serializable {
1028:                /** Serialization version. */
1029:                private static final long serialVersionUID = 3258126977134310455L;
1030:
1031:                Object fData;
1032:                UserDataHandler fHandler;
1033:
1034:                UserDataRecord(Object data, UserDataHandler handler) {
1035:                    fData = data;
1036:                    fHandler = handler;
1037:                }
1038:            }
1039:        } // 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.