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

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


0001:        /*
0002:         * The Apache Software License, Version 1.1
0003:         *
0004:         *
0005:         * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights 
0006:         * reserved.
0007:         *
0008:         * Redistribution and use in source and binary forms, with or without
0009:         * modification, are permitted provided that the following conditions
0010:         * are met:
0011:         *
0012:         * 1. Redistributions of source code must retain the above copyright
0013:         *    notice, this list of conditions and the following disclaimer. 
0014:         *
0015:         * 2. Redistributions in binary form must reproduce the above copyright
0016:         *    notice, this list of conditions and the following disclaimer in
0017:         *    the documentation and/or other materials provided with the
0018:         *    distribution.
0019:         *
0020:         * 3. The end-user documentation included with the redistribution,
0021:         *    if any, must include the following acknowledgment:  
0022:         *       "This product includes software developed by the
0023:         *        Apache Software Foundation (http://www.apache.org/)."
0024:         *    Alternately, this acknowledgment may appear in the software itself,
0025:         *    if and wherever such third-party acknowledgments normally appear.
0026:         *
0027:         * 4. The names "Xerces" and "Apache Software Foundation" must
0028:         *    not be used to endorse or promote products derived from this
0029:         *    software without prior written permission. For written 
0030:         *    permission, please contact apache@apache.org.
0031:         *
0032:         * 5. Products derived from this software may not be called "Apache",
0033:         *    nor may "Apache" appear in their name, without prior written
0034:         *    permission of the Apache Software Foundation.
0035:         *
0036:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0037:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0038:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0039:         * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0040:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0041:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0042:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0043:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0044:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0045:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0046:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0047:         * SUCH DAMAGE.
0048:         * ====================================================================
0049:         *
0050:         * This software consists of voluntary contributions made by many
0051:         * individuals on behalf of the Apache Software Foundation and was
0052:         * originally based on software copyright (c) 1999, International
0053:         * Business Machines, Inc., http://www.apache.org.  For more
0054:         * information on the Apache Software Foundation, please see
0055:         * <http://www.apache.org/>.
0056:         */
0057:
0058:        package org.apache.xerces.dom;
0059:
0060:        import java.io.IOException;
0061:        import java.io.ObjectInputStream;
0062:        import java.io.ObjectOutputStream;
0063:
0064:        import org.w3c.dom.Attr;
0065:        import org.w3c.dom.DOMException;
0066:        import org.w3c.dom.Element;
0067:        import org.w3c.dom.Node;
0068:        import org.w3c.dom.NodeList;
0069:        import org.w3c.dom.Text;
0070:
0071:        /**
0072:         * Attribute represents an XML-style attribute of an
0073:         * Element. Typically, the allowable values are controlled by its
0074:         * declaration in the Document Type Definition (DTD) governing this
0075:         * kind of document.
0076:         * <P>
0077:         * If the attribute has not been explicitly assigned a value, but has
0078:         * been declared in the DTD, it will exist and have that default. Only
0079:         * if neither the document nor the DTD specifies a value will the
0080:         * Attribute really be considered absent and have no value; in that
0081:         * case, querying the attribute will return null.
0082:         * <P>
0083:         * Attributes may have multiple children that contain their data. (XML
0084:         * allows attributes to contain entity references, and tokenized
0085:         * attribute types such as NMTOKENS may have a child for each token.)
0086:         * For convenience, the Attribute object's getValue() method returns
0087:         * the string version of the attribute's value.
0088:         * <P>
0089:         * Attributes are not children of the Elements they belong to, in the
0090:         * usual sense, and have no valid Parent reference. However, the spec
0091:         * says they _do_ belong to a specific Element, and an INUSE exception
0092:         * is to be thrown if the user attempts to explicitly share them
0093:         * between elements.
0094:         * <P>
0095:         * Note that Elements do not permit attributes to appear to be shared
0096:         * (see the INUSE exception), so this object's mutability is
0097:         * officially not an issue.
0098:         * <p>
0099:         * Note: The ownerNode attribute is used to store the Element the Attr
0100:         * node is associated with. Attr nodes do not have parent nodes.
0101:         * Besides, the getOwnerElement() method can be used to get the element node
0102:         * this attribute is associated with.
0103:         * <P>
0104:         * AttrImpl does not support Namespaces. AttrNSImpl, which inherits from
0105:         * it, does.
0106:         *
0107:         * <p>AttrImpl used to inherit from ParentNode. It now directly inherits from
0108:         * NodeImpl and provide its own implementation of the ParentNode's behavior.
0109:         * The reason is that we now try and avoid to always create a Text node to
0110:         * hold the value of an attribute. The DOM spec requires it, so we still have
0111:         * to do it in case getFirstChild() is called for instance. The reason
0112:         * attribute values are stored as a list of nodes is so that they can carry
0113:         * more than a simple string. They can also contain EntityReference nodes.
0114:         * However, most of the times people only have a single string that they only
0115:         * set and get through Element.set/getAttribute or Attr.set/getValue. In this
0116:         * new version, the Attr node has a value pointer which can either be the
0117:         * String directly or a pointer to the first ChildNode. A flag tells which one
0118:         * it currently is. Note that while we try to stick with the direct String as
0119:         * much as possible once we've switched to a node there is no going back. This
0120:         * is because we have no way to know whether the application keeps referring to
0121:         * the node we once returned.
0122:         * <p> The gain in memory varies on the density of attributes in the document.
0123:         * But in the tests I've run I've seen up to 12% of memory gain. And the good
0124:         * thing is that it also leads to a slight gain in speed because we allocate
0125:         * fewer objects! I mean, that's until we have to actually create the node...
0126:         * <p>
0127:         * To avoid too much duplicated code, I got rid of ParentNode and renamed
0128:         * ChildAndParentNode, which I never really liked, to ParentNode for
0129:         * simplicity, this doesn't make much of a difference in memory usage because
0130:         * there are only very few objects that are only a Parent. This is only true
0131:         * now because AttrImpl now inherits directly from NodeImpl and has its own
0132:         * implementation of the ParentNode's node behavior. So there is still some
0133:         * duplicated code there.
0134:         * <p>
0135:         * This class doesn't directly support mutation events, however, it notifies
0136:         * the document when mutations are performed so that the document class do so.
0137:         *
0138:         * <p><b>WARNING</b>: Some of the code here is partially duplicated in
0139:         * ParentNode, be careful to keep these two classes in sync!
0140:         *
0141:         * @see AttrNSImpl
0142:         *
0143:         * @author Arnaud  Le Hors, IBM
0144:         * @author Joe Kesselman, IBM
0145:         * @author Andy Clark, IBM
0146:         * @version
0147:         * @since PR-DOM-Level-1-19980818.
0148:         *
0149:         */
0150:        public class AttrImpl extends NodeImpl implements  Attr {
0151:
0152:            //
0153:            // Constants
0154:            //
0155:
0156:            /** Serialization version. */
0157:            static final long serialVersionUID = 7277707688218972102L;
0158:
0159:            //
0160:            // Data
0161:            //
0162:
0163:            /** This can either be a String or the first child node. */
0164:            protected Object value = null;
0165:
0166:            /** Attribute name. */
0167:            protected String name;
0168:
0169:            protected static TextImpl textNode = null;
0170:
0171:            //
0172:            // Constructors
0173:            //
0174:
0175:            /**
0176:             * Attribute has no public constructor. Please use the factory
0177:             * method in the Document class.
0178:             */
0179:            protected AttrImpl(CoreDocumentImpl ownerDocument, String name) {
0180:                super (ownerDocument);
0181:                this .name = name;
0182:                /** False for default attributes. */
0183:                isSpecified(true);
0184:                hasStringValue(true);
0185:            }
0186:
0187:            // for AttrNSImpl
0188:            protected AttrImpl() {
0189:            }
0190:
0191:            // create a real text node as child if we don't have one yet
0192:            protected void makeChildNode() {
0193:                if (hasStringValue()) {
0194:                    if (value != null) {
0195:                        TextImpl text = (TextImpl) ownerDocument()
0196:                                .createTextNode((String) value);
0197:                        value = text;
0198:                        text.isFirstChild(true);
0199:                        text.previousSibling = text;
0200:                        text.ownerNode = this ;
0201:                        text.isOwned(true);
0202:                    }
0203:                    hasStringValue(false);
0204:                }
0205:            }
0206:
0207:            /**
0208:             * NON-DOM
0209:             * set the ownerDocument of this node and its children
0210:             */
0211:            void setOwnerDocument(CoreDocumentImpl doc) {
0212:                if (needsSyncChildren()) {
0213:                    synchronizeChildren();
0214:                }
0215:                super .setOwnerDocument(doc);
0216:                if (!hasStringValue()) {
0217:                    for (ChildNode child = (ChildNode) value; child != null; child = child.nextSibling) {
0218:                        child.setOwnerDocument(doc);
0219:                    }
0220:                }
0221:            }
0222:
0223:            //
0224:            // Node methods
0225:            //
0226:
0227:            public Node cloneNode(boolean deep) {
0228:
0229:                if (needsSyncChildren()) {
0230:                    synchronizeChildren();
0231:                }
0232:                AttrImpl clone = (AttrImpl) super .cloneNode(deep);
0233:
0234:                // take care of case where there are kids
0235:                if (!clone.hasStringValue()) {
0236:
0237:                    // Need to break the association w/ original kids
0238:                    clone.value = null;
0239:
0240:                    // Then, if deep, clone the kids too.
0241:                    if (deep) {
0242:                        for (Node child = (Node) value; child != null; child = child
0243:                                .getNextSibling()) {
0244:                            clone.appendChild(child.cloneNode(true));
0245:                        }
0246:                    }
0247:                }
0248:                clone.isSpecified(true);
0249:                return clone;
0250:            }
0251:
0252:            /**
0253:             * A short integer indicating what type of node this is. The named
0254:             * constants for this value are defined in the org.w3c.dom.Node interface.
0255:             */
0256:            public short getNodeType() {
0257:                return Node.ATTRIBUTE_NODE;
0258:            }
0259:
0260:            /**
0261:             * Returns the attribute name
0262:             */
0263:            public String getNodeName() {
0264:                if (needsSyncData()) {
0265:                    synchronizeData();
0266:                }
0267:                return name;
0268:            }
0269:
0270:            /**
0271:             * Implicit in the rerouting of getNodeValue to getValue is the
0272:             * need to redefine setNodeValue, for symmetry's sake.  Note that
0273:             * since we're explicitly providing a value, Specified should be set
0274:             * true.... even if that value equals the default.
0275:             */
0276:            public void setNodeValue(String value) throws DOMException {
0277:                setValue(value);
0278:            }
0279:
0280:            /**
0281:             * In Attribute objects, NodeValue is considered a synonym for
0282:             * Value.
0283:             *
0284:             * @see #getValue()
0285:             */
0286:            public String getNodeValue() {
0287:                return getValue();
0288:            }
0289:
0290:            //
0291:            // Attr methods
0292:            //
0293:
0294:            /**
0295:             * In Attributes, NodeName is considered a synonym for the
0296:             * attribute's Name
0297:             */
0298:            public String getName() {
0299:
0300:                if (needsSyncData()) {
0301:                    synchronizeData();
0302:                }
0303:                return name;
0304:
0305:            } // getName():String
0306:
0307:            /**
0308:             * The DOM doesn't clearly define what setValue(null) means. I've taken it
0309:             * as "remove all children", which from outside should appear
0310:             * similar to setting it to the empty string.
0311:             */
0312:            public void setValue(String newvalue) {
0313:
0314:                if (isReadOnly()) {
0315:                    throw new DOMException(
0316:                            DOMException.NO_MODIFICATION_ALLOWED_ERR,
0317:                            "DOM001 Modification not allowed");
0318:                }
0319:                CoreDocumentImpl ownerDocument = ownerDocument();
0320:                String oldvalue = "";
0321:                if (ownerDocument.getMutationEvents()) {
0322:                    // Can no longer just discard the kids; they may have
0323:                    // event listeners waiting for them to disconnect.
0324:                    if (needsSyncChildren()) {
0325:                        synchronizeChildren();
0326:                    }
0327:                    if (value != null) {
0328:                        if (hasStringValue()) {
0329:                            oldvalue = (String) value;
0330:                            // create an actual text node as our child so
0331:                            // that we can use it in the event
0332:                            if (textNode == null) {
0333:                                textNode = (TextImpl) ownerDocument
0334:                                        .createTextNode((String) value);
0335:                            } else {
0336:                                textNode.data = (String) value;
0337:                            }
0338:                            value = textNode;
0339:                            textNode.isFirstChild(true);
0340:                            textNode.previousSibling = textNode;
0341:                            textNode.ownerNode = this ;
0342:                            textNode.isOwned(true);
0343:                            hasStringValue(false);
0344:                            internalRemoveChild(textNode, true);
0345:                        } else {
0346:                            oldvalue = getValue();
0347:                            while (value != null) {
0348:                                internalRemoveChild((Node) value, true);
0349:                            }
0350:                        }
0351:                    }
0352:                } else {
0353:                    // simply discard children if any
0354:                    if (!hasStringValue() && value != null) {
0355:                        // remove ref from first child to last child
0356:                        ChildNode firstChild = (ChildNode) value;
0357:                        firstChild.previousSibling = null;
0358:                        firstChild.isFirstChild(false);
0359:                    }
0360:                    // then remove ref to current value
0361:                    value = null;
0362:                    needsSyncChildren(false);
0363:                }
0364:
0365:                // Create and add the new one, generating only non-aggregate events
0366:                // (There are no listeners on the new Text, but there may be
0367:                // capture/bubble listeners on the Attr.
0368:                // Note that aggregate events are NOT dispatched here,
0369:                // since we need to combine the remove and insert.
0370:                isSpecified(true);
0371:                if (ownerDocument.getMutationEvents()) {
0372:                    // if there are any event handlers create a real node
0373:                    internalInsertBefore(
0374:                            ownerDocument.createTextNode(newvalue), null, true);
0375:                    hasStringValue(false);
0376:                    // notify document
0377:                    ownerDocument.modifiedAttrValue(this , oldvalue);
0378:                } else {
0379:                    // directly store the string
0380:                    value = newvalue;
0381:                    hasStringValue(true);
0382:                    changed();
0383:                }
0384:
0385:            } // setValue(String)
0386:
0387:            /**
0388:             * The "string value" of an Attribute is its text representation,
0389:             * which in turn is a concatenation of the string values of its children.
0390:             */
0391:            public String getValue() {
0392:
0393:                if (needsSyncChildren()) {
0394:                    synchronizeChildren();
0395:                }
0396:                if (value == null) {
0397:                    return "";
0398:                }
0399:                if (hasStringValue()) {
0400:                    return (String) value;
0401:                }
0402:                ChildNode firstChild = ((ChildNode) value);
0403:                ChildNode node = firstChild.nextSibling;
0404:                if (node == null) {
0405:                    return firstChild.getNodeValue();
0406:                }
0407:                StringBuffer value = new StringBuffer(firstChild.getNodeValue());
0408:                while (node != null) {
0409:                    value.append(node.getNodeValue());
0410:                    node = node.nextSibling;
0411:                }
0412:                return value.toString();
0413:
0414:            } // getValue():String
0415:
0416:            /**
0417:             * The "specified" flag is true if and only if this attribute's
0418:             * value was explicitly specified in the original document. Note that
0419:             * the implementation, not the user, is in charge of this
0420:             * property. If the user asserts an Attribute value (even if it ends
0421:             * up having the same value as the default), it is considered a
0422:             * specified attribute. If you really want to revert to the default,
0423:             * delete the attribute from the Element, and the Implementation will
0424:             * re-assert the default (if any) in its place, with the appropriate
0425:             * specified=false setting.
0426:             */
0427:            public boolean getSpecified() {
0428:
0429:                if (needsSyncData()) {
0430:                    synchronizeData();
0431:                }
0432:                return isSpecified();
0433:
0434:            } // getSpecified():boolean
0435:
0436:            //
0437:            // Attr2 methods
0438:            //
0439:
0440:            /**
0441:             * Returns the element node that this attribute is associated with,
0442:             * or null if the attribute has not been added to an element.
0443:             *
0444:             * @see #getOwnerElement
0445:             *
0446:             * @deprecated Previous working draft of DOM Level 2. New method
0447:             *             is <tt>getOwnerElement()</tt>.
0448:             */
0449:            public Element getElement() {
0450:                // if we have an owner, ownerNode is our ownerElement, otherwise it's
0451:                // our ownerDocument and we don't have an ownerElement
0452:                return (Element) (isOwned() ? ownerNode : null);
0453:            }
0454:
0455:            /**
0456:             * Returns the element node that this attribute is associated with,
0457:             * or null if the attribute has not been added to an element.
0458:             *
0459:             * @since WD-DOM-Level-2-19990719
0460:             */
0461:            public Element getOwnerElement() {
0462:                // if we have an owner, ownerNode is our ownerElement, otherwise it's
0463:                // our ownerDocument and we don't have an ownerElement
0464:                return (Element) (isOwned() ? ownerNode : null);
0465:            }
0466:
0467:            public void normalize() {
0468:
0469:                // No need to normalize if already normalized or
0470:                // if value is kept as a String.
0471:                if (isNormalized() || hasStringValue())
0472:                    return;
0473:
0474:                Node kid, next;
0475:                ChildNode firstChild = (ChildNode) value;
0476:                for (kid = firstChild; kid != null; kid = next) {
0477:                    next = kid.getNextSibling();
0478:
0479:                    // If kid is a text node, we need to check for one of two
0480:                    // conditions:
0481:                    //   1) There is an adjacent text node
0482:                    //   2) There is no adjacent text node, but kid is
0483:                    //      an empty text node.
0484:                    if (kid.getNodeType() == Node.TEXT_NODE) {
0485:                        // If an adjacent text node, merge it with kid
0486:                        if (next != null
0487:                                && next.getNodeType() == Node.TEXT_NODE) {
0488:                            ((Text) kid).appendData(next.getNodeValue());
0489:                            removeChild(next);
0490:                            next = kid; // Don't advance; there might be another.
0491:                        } else {
0492:                            // If kid is empty, remove it
0493:                            if (kid.getNodeValue().length() == 0)
0494:                                removeChild(kid);
0495:                        }
0496:                    }
0497:                }
0498:
0499:                isNormalized(true);
0500:            } // normalize()
0501:
0502:            //
0503:            // Public methods
0504:            //
0505:
0506:            /** NON-DOM, for use by parser */
0507:            public void setSpecified(boolean arg) {
0508:
0509:                if (needsSyncData()) {
0510:                    synchronizeData();
0511:                }
0512:                isSpecified(arg);
0513:
0514:            } // setSpecified(boolean)
0515:
0516:            //
0517:            // Object methods
0518:            //
0519:
0520:            /** NON-DOM method for debugging convenience */
0521:            public String toString() {
0522:                return getName() + "=" + "\"" + getValue() + "\"";
0523:            }
0524:
0525:            /**
0526:             * Test whether this node has any children. Convenience shorthand
0527:             * for (Node.getFirstChild()!=null)
0528:             */
0529:            public boolean hasChildNodes() {
0530:                if (needsSyncChildren()) {
0531:                    synchronizeChildren();
0532:                }
0533:                return value != null;
0534:            }
0535:
0536:            /**
0537:             * Obtain a NodeList enumerating all children of this node. If there
0538:             * are none, an (initially) empty NodeList is returned.
0539:             * <p>
0540:             * NodeLists are "live"; as children are added/removed the NodeList
0541:             * will immediately reflect those changes. Also, the NodeList refers
0542:             * to the actual nodes, so changes to those nodes made via the DOM tree
0543:             * will be reflected in the NodeList and vice versa.
0544:             * <p>
0545:             * In this implementation, Nodes implement the NodeList interface and
0546:             * provide their own getChildNodes() support. Other DOMs may solve this
0547:             * differently.
0548:             */
0549:            public NodeList getChildNodes() {
0550:                // JKESS: KNOWN ISSUE HERE 
0551:
0552:                if (needsSyncChildren()) {
0553:                    synchronizeChildren();
0554:                }
0555:                return this ;
0556:
0557:            } // getChildNodes():NodeList
0558:
0559:            /** The first child of this Node, or null if none. */
0560:            public Node getFirstChild() {
0561:
0562:                if (needsSyncChildren()) {
0563:                    synchronizeChildren();
0564:                }
0565:                makeChildNode();
0566:                return (Node) value;
0567:
0568:            } // getFirstChild():Node
0569:
0570:            /** The last child of this Node, or null if none. */
0571:            public Node getLastChild() {
0572:
0573:                if (needsSyncChildren()) {
0574:                    synchronizeChildren();
0575:                }
0576:                return lastChild();
0577:
0578:            } // getLastChild():Node
0579:
0580:            final ChildNode lastChild() {
0581:                // last child is stored as the previous sibling of first child
0582:                makeChildNode();
0583:                return value != null ? ((ChildNode) value).previousSibling
0584:                        : null;
0585:            }
0586:
0587:            final void lastChild(ChildNode node) {
0588:                // store lastChild as previous sibling of first child
0589:                if (value != null) {
0590:                    ((ChildNode) value).previousSibling = node;
0591:                }
0592:            }
0593:
0594:            /**
0595:             * Move one or more node(s) to our list of children. Note that this
0596:             * implicitly removes them from their previous parent.
0597:             *
0598:             * @param newChild The Node to be moved to our subtree. As a
0599:             * convenience feature, inserting a DocumentNode will instead insert
0600:             * all its children.
0601:             *
0602:             * @param refChild Current child which newChild should be placed
0603:             * immediately before. If refChild is null, the insertion occurs
0604:             * after all existing Nodes, like appendChild().
0605:             *
0606:             * @returns newChild, in its new state (relocated, or emptied in the
0607:             * case of DocumentNode.)
0608:             *
0609:             * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
0610:             * type that shouldn't be a child of this node, or if newChild is an
0611:             * ancestor of this node.
0612:             *
0613:             * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
0614:             * different owner document than we do.
0615:             *
0616:             * @throws DOMException(NOT_FOUND_ERR) if refChild is not a child of
0617:             * this node.
0618:             *
0619:             * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
0620:             * read-only.
0621:             */
0622:            public Node insertBefore(Node newChild, Node refChild)
0623:                    throws DOMException {
0624:                // Tail-call; optimizer should be able to do good things with.
0625:                return internalInsertBefore(newChild, refChild, false);
0626:            } // insertBefore(Node,Node):Node
0627:
0628:            /** NON-DOM INTERNAL: Within DOM actions,we sometimes need to be able
0629:             * to control which mutation events are spawned. This version of the
0630:             * insertBefore operation allows us to do so. It is not intended
0631:             * for use by application programs.
0632:             */
0633:            Node internalInsertBefore(Node newChild, Node refChild,
0634:                    boolean replace) throws DOMException {
0635:
0636:                CoreDocumentImpl ownerDocument = ownerDocument();
0637:                boolean errorChecking = ownerDocument.errorChecking;
0638:
0639:                if (newChild.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) {
0640:                    // SLOW BUT SAFE: We could insert the whole subtree without
0641:                    // juggling so many next/previous pointers. (Wipe out the
0642:                    // parent's child-list, patch the parent pointers, set the
0643:                    // ends of the list.) But we know some subclasses have special-
0644:                    // case behavior they add to insertBefore(), so we don't risk it.
0645:                    // This approch also takes fewer bytecodes.
0646:
0647:                    // NOTE: If one of the children is not a legal child of this
0648:                    // node, throw HIERARCHY_REQUEST_ERR before _any_ of the children
0649:                    // have been transferred. (Alternative behaviors would be to
0650:                    // reparent up to the first failure point or reparent all those
0651:                    // which are acceptable to the target node, neither of which is
0652:                    // as robust. PR-DOM-0818 isn't entirely clear on which it
0653:                    // recommends?????
0654:
0655:                    // No need to check kids for right-document; if they weren't,
0656:                    // they wouldn't be kids of that DocFrag.
0657:                    if (errorChecking) {
0658:                        for (Node kid = newChild.getFirstChild(); // Prescan
0659:                        kid != null; kid = kid.getNextSibling()) {
0660:
0661:                            if (!ownerDocument.isKidOK(this , kid)) {
0662:                                throw new DOMException(
0663:                                        DOMException.HIERARCHY_REQUEST_ERR,
0664:                                        "DOM006 Hierarchy request error");
0665:                            }
0666:                        }
0667:                    }
0668:
0669:                    while (newChild.hasChildNodes()) {
0670:                        insertBefore(newChild.getFirstChild(), refChild);
0671:                    }
0672:                    return newChild;
0673:                }
0674:
0675:                if (newChild == refChild) {
0676:                    // stupid case that must be handled as a no-op triggering events...
0677:                    refChild = refChild.getNextSibling();
0678:                    removeChild(newChild);
0679:                    insertBefore(newChild, refChild);
0680:                    return newChild;
0681:                }
0682:
0683:                if (needsSyncChildren()) {
0684:                    synchronizeChildren();
0685:                }
0686:
0687:                if (errorChecking) {
0688:                    if (isReadOnly()) {
0689:                        throw new DOMException(
0690:                                DOMException.NO_MODIFICATION_ALLOWED_ERR,
0691:                                "DOM001 Modification not allowed");
0692:                    }
0693:                    if (newChild.getOwnerDocument() != ownerDocument) {
0694:                        throw new DOMException(DOMException.WRONG_DOCUMENT_ERR,
0695:                                "DOM005 Wrong document");
0696:                    }
0697:                    if (!ownerDocument.isKidOK(this , newChild)) {
0698:                        throw new DOMException(
0699:                                DOMException.HIERARCHY_REQUEST_ERR,
0700:                                "DOM006 Hierarchy request error");
0701:                    }
0702:                    // refChild must be a child of this node (or null)
0703:                    if (refChild != null && refChild.getParentNode() != this ) {
0704:                        throw new DOMException(DOMException.NOT_FOUND_ERR,
0705:                                "DOM008 Not found");
0706:                    }
0707:
0708:                    // Prevent cycles in the tree
0709:                    // newChild cannot be ancestor of this Node,
0710:                    // and actually cannot be this
0711:                    boolean treeSafe = true;
0712:                    for (NodeImpl a = this ; treeSafe && a != null; a = a
0713:                            .parentNode()) {
0714:                        treeSafe = newChild != a;
0715:                    }
0716:                    if (!treeSafe) {
0717:                        throw new DOMException(
0718:                                DOMException.HIERARCHY_REQUEST_ERR,
0719:                                "DOM006 Hierarchy request error");
0720:                    }
0721:                }
0722:
0723:                makeChildNode(); // make sure we have a node and not a string
0724:
0725:                // notify document
0726:                ownerDocument.insertingNode(this , replace);
0727:
0728:                // Convert to internal type, to avoid repeated casting
0729:                ChildNode newInternal = (ChildNode) newChild;
0730:
0731:                Node oldparent = newInternal.parentNode();
0732:                if (oldparent != null) {
0733:                    oldparent.removeChild(newInternal);
0734:                }
0735:
0736:                // Convert to internal type, to avoid repeated casting
0737:                ChildNode refInternal = (ChildNode) refChild;
0738:
0739:                // Attach up
0740:                newInternal.ownerNode = this ;
0741:                newInternal.isOwned(true);
0742:
0743:                // Attach before and after
0744:                // Note: firstChild.previousSibling == lastChild!!
0745:                ChildNode firstChild = (ChildNode) value;
0746:                if (firstChild == null) {
0747:                    // this our first and only child
0748:                    value = newInternal; // firstchild = newInternal;
0749:                    newInternal.isFirstChild(true);
0750:                    newInternal.previousSibling = newInternal;
0751:                } else {
0752:                    if (refInternal == null) {
0753:                        // this is an append
0754:                        ChildNode lastChild = firstChild.previousSibling;
0755:                        lastChild.nextSibling = newInternal;
0756:                        newInternal.previousSibling = lastChild;
0757:                        firstChild.previousSibling = newInternal;
0758:                    } else {
0759:                        // this is an insert
0760:                        if (refChild == firstChild) {
0761:                            // at the head of the list
0762:                            firstChild.isFirstChild(false);
0763:                            newInternal.nextSibling = firstChild;
0764:                            newInternal.previousSibling = firstChild.previousSibling;
0765:                            firstChild.previousSibling = newInternal;
0766:                            value = newInternal; // firstChild = newInternal;
0767:                            newInternal.isFirstChild(true);
0768:                        } else {
0769:                            // somewhere in the middle
0770:                            ChildNode prev = refInternal.previousSibling;
0771:                            newInternal.nextSibling = refInternal;
0772:                            prev.nextSibling = newInternal;
0773:                            refInternal.previousSibling = newInternal;
0774:                            newInternal.previousSibling = prev;
0775:                        }
0776:                    }
0777:                }
0778:
0779:                changed();
0780:
0781:                // notify document
0782:                ownerDocument.insertedNode(this , newInternal, replace);
0783:
0784:                checkNormalizationAfterInsert(newInternal);
0785:
0786:                return newChild;
0787:
0788:            } // internalInsertBefore(Node,Node,int):Node
0789:
0790:            /**
0791:             * Remove a child from this Node. The removed child's subtree
0792:             * remains intact so it may be re-inserted elsewhere.
0793:             *
0794:             * @return oldChild, in its new state (removed).
0795:             *
0796:             * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
0797:             * this node.
0798:             *
0799:             * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
0800:             * read-only.
0801:             */
0802:            public Node removeChild(Node oldChild) throws DOMException {
0803:                // Tail-call, should be optimizable
0804:                if (hasStringValue()) {
0805:                    // we don't have any child per say so it can't be one of them!
0806:                    throw new DOMException(DOMException.NOT_FOUND_ERR,
0807:                            "DOM008 Not found");
0808:                }
0809:                return internalRemoveChild(oldChild, false);
0810:            } // removeChild(Node) :Node
0811:
0812:            /** NON-DOM INTERNAL: Within DOM actions,we sometimes need to be able
0813:             * to control which mutation events are spawned. This version of the
0814:             * removeChild operation allows us to do so. It is not intended
0815:             * for use by application programs.
0816:             */
0817:            Node internalRemoveChild(Node oldChild, boolean replace)
0818:                    throws DOMException {
0819:
0820:                CoreDocumentImpl ownerDocument = ownerDocument();
0821:                if (ownerDocument.errorChecking) {
0822:                    if (isReadOnly()) {
0823:                        throw new DOMException(
0824:                                DOMException.NO_MODIFICATION_ALLOWED_ERR,
0825:                                "DOM001 Modification not allowed");
0826:                    }
0827:                    if (oldChild != null && oldChild.getParentNode() != this ) {
0828:                        throw new DOMException(DOMException.NOT_FOUND_ERR,
0829:                                "DOM008 Not found");
0830:                    }
0831:                }
0832:
0833:                ChildNode oldInternal = (ChildNode) oldChild;
0834:
0835:                // notify document
0836:                ownerDocument.removingNode(this , oldInternal, replace);
0837:
0838:                // Patch linked list around oldChild
0839:                // Note: lastChild == firstChild.previousSibling
0840:                if (oldInternal == value) { // oldInternal == firstChild
0841:                    // removing first child
0842:                    oldInternal.isFirstChild(false);
0843:                    // next line is: firstChild = oldInternal.nextSibling
0844:                    value = oldInternal.nextSibling;
0845:                    ChildNode firstChild = (ChildNode) value;
0846:                    if (firstChild != null) {
0847:                        firstChild.isFirstChild(true);
0848:                        firstChild.previousSibling = oldInternal.previousSibling;
0849:                    }
0850:                } else {
0851:                    ChildNode prev = oldInternal.previousSibling;
0852:                    ChildNode next = oldInternal.nextSibling;
0853:                    prev.nextSibling = next;
0854:                    if (next == null) {
0855:                        // removing last child
0856:                        ChildNode firstChild = (ChildNode) value;
0857:                        firstChild.previousSibling = prev;
0858:                    } else {
0859:                        // removing some other child in the middle
0860:                        next.previousSibling = prev;
0861:                    }
0862:                }
0863:
0864:                // Save previous sibling for normalization checking.
0865:                ChildNode oldPreviousSibling = oldInternal.previousSibling();
0866:
0867:                // Remove oldInternal's references to tree
0868:                oldInternal.ownerNode = ownerDocument;
0869:                oldInternal.isOwned(false);
0870:                oldInternal.nextSibling = null;
0871:                oldInternal.previousSibling = null;
0872:
0873:                changed();
0874:
0875:                // notify document
0876:                ownerDocument.removedNode(this , replace);
0877:
0878:                checkNormalizationAfterRemove(oldPreviousSibling);
0879:
0880:                return oldInternal;
0881:
0882:            } // internalRemoveChild(Node,int):Node
0883:
0884:            /**
0885:             * Make newChild occupy the location that oldChild used to
0886:             * have. Note that newChild will first be removed from its previous
0887:             * parent, if any. Equivalent to inserting newChild before oldChild,
0888:             * then removing oldChild.
0889:             *
0890:             * @returns oldChild, in its new state (removed).
0891:             *
0892:             * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
0893:             * type that shouldn't be a child of this node, or if newChild is
0894:             * one of our ancestors.
0895:             *
0896:             * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
0897:             * different owner document than we do.
0898:             *
0899:             * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
0900:             * this node.
0901:             *
0902:             * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
0903:             * read-only.
0904:             */
0905:            public Node replaceChild(Node newChild, Node oldChild)
0906:                    throws DOMException {
0907:
0908:                makeChildNode();
0909:
0910:                // If Mutation Events are being generated, this operation might
0911:                // throw aggregate events twice when modifying an Attr -- once 
0912:                // on insertion and once on removal. DOM Level 2 does not specify 
0913:                // this as either desirable or undesirable, but hints that
0914:                // aggregations should be issued only once per user request.
0915:
0916:                // notify document
0917:                CoreDocumentImpl ownerDocument = ownerDocument();
0918:                ownerDocument.replacingNode(this );
0919:
0920:                internalInsertBefore(newChild, oldChild, true);
0921:                if (newChild != oldChild) {
0922:                    internalRemoveChild(oldChild, true);
0923:                }
0924:
0925:                // notify document
0926:                ownerDocument.replacedNode(this );
0927:
0928:                return oldChild;
0929:            }
0930:
0931:            //
0932:            // NodeList methods
0933:            //
0934:
0935:            /**
0936:             * NodeList method: Count the immediate children of this node
0937:             * @return int
0938:             */
0939:            public int getLength() {
0940:
0941:                if (hasStringValue()) {
0942:                    return 1;
0943:                }
0944:                ChildNode node = (ChildNode) value;
0945:                int length = 0;
0946:                for (; node != null; node = node.nextSibling) {
0947:                    length++;
0948:                }
0949:                return length;
0950:
0951:            } // getLength():int
0952:
0953:            /**
0954:             * NodeList method: Return the Nth immediate child of this node, or
0955:             * null if the index is out of bounds.
0956:             * @return org.w3c.dom.Node
0957:             * @param Index int
0958:             */
0959:            public Node item(int index) {
0960:
0961:                if (hasStringValue()) {
0962:                    if (index != 0 || value == null) {
0963:                        return null;
0964:                    } else {
0965:                        makeChildNode();
0966:                        return (Node) value;
0967:                    }
0968:                }
0969:                ChildNode node = (ChildNode) value;
0970:                for (int i = 0; i < index && node != null; i++) {
0971:                    node = node.nextSibling;
0972:                }
0973:                return node;
0974:
0975:            } // item(int):Node
0976:
0977:            //
0978:            // DOM2: methods, getters, setters
0979:            //
0980:
0981:            //
0982:            // Public methods
0983:            //
0984:
0985:            /**
0986:             * Override default behavior so that if deep is true, children are also
0987:             * toggled.
0988:             * @see Node
0989:             * <P>
0990:             * Note: this will not change the state of an EntityReference or its
0991:             * children, which are always read-only.
0992:             */
0993:            public void setReadOnly(boolean readOnly, boolean deep) {
0994:
0995:                super .setReadOnly(readOnly, deep);
0996:
0997:                if (deep) {
0998:
0999:                    if (needsSyncChildren()) {
1000:                        synchronizeChildren();
1001:                    }
1002:
1003:                    if (hasStringValue()) {
1004:                        return;
1005:                    }
1006:                    // Recursively set kids
1007:                    for (ChildNode mykid = (ChildNode) value; mykid != null; mykid = mykid.nextSibling) {
1008:                        if (mykid.getNodeType() != Node.ENTITY_REFERENCE_NODE) {
1009:                            mykid.setReadOnly(readOnly, true);
1010:                        }
1011:                    }
1012:                }
1013:            } // setReadOnly(boolean,boolean)
1014:
1015:            //
1016:            // Protected methods
1017:            //
1018:
1019:            /**
1020:             * Override this method in subclass to hook in efficient
1021:             * internal data structure.
1022:             */
1023:            protected void synchronizeChildren() {
1024:                // By default just change the flag to avoid calling this method again
1025:                needsSyncChildren(false);
1026:            }
1027:
1028:            /**
1029:             * Checks the normalized state of this node after inserting a child.
1030:             * If the inserted child causes this node to be unnormalized, then this
1031:             * node is flagged accordingly.
1032:             * The conditions for changing the normalized state are:
1033:             * <ul>
1034:             * <li>The inserted child is a text node and one of its adjacent siblings
1035:             * is also a text node.
1036:             * <li>The inserted child is is itself unnormalized.
1037:             * </ul>
1038:             *
1039:             * @param insertedChild the child node that was inserted into this node
1040:             *
1041:             * @throws NullPointerException if the inserted child is <code>null</code>
1042:             */
1043:            void checkNormalizationAfterInsert(ChildNode insertedChild) {
1044:                // See if insertion caused this node to be unnormalized.
1045:                if (insertedChild.getNodeType() == Node.TEXT_NODE) {
1046:                    ChildNode prev = insertedChild.previousSibling();
1047:                    ChildNode next = insertedChild.nextSibling;
1048:                    // If an adjacent sibling of the new child is a text node,
1049:                    // flag this node as unnormalized.
1050:                    if ((prev != null && prev.getNodeType() == Node.TEXT_NODE)
1051:                            || (next != null && next.getNodeType() == Node.TEXT_NODE)) {
1052:                        isNormalized(false);
1053:                    }
1054:                } else {
1055:                    // If the new child is not normalized,
1056:                    // then this node is inherently not normalized.
1057:                    if (!insertedChild.isNormalized()) {
1058:                        isNormalized(false);
1059:                    }
1060:                }
1061:            } // checkNormalizationAfterInsert(ChildNode)
1062:
1063:            /**
1064:             * Checks the normalized of this node after removing a child.
1065:             * If the removed child causes this node to be unnormalized, then this
1066:             * node is flagged accordingly.
1067:             * The conditions for changing the normalized state are:
1068:             * <ul>
1069:             * <li>The removed child had two adjacent siblings that were text nodes.
1070:             * </ul>
1071:             *
1072:             * @param previousSibling the previous sibling of the removed child, or
1073:             * <code>null</code>
1074:             */
1075:            void checkNormalizationAfterRemove(ChildNode previousSibling) {
1076:                // See if removal caused this node to be unnormalized.
1077:                // If the adjacent siblings of the removed child were both text nodes,
1078:                // flag this node as unnormalized.
1079:                if (previousSibling != null
1080:                        && previousSibling.getNodeType() == Node.TEXT_NODE) {
1081:
1082:                    ChildNode next = previousSibling.nextSibling;
1083:                    if (next != null && next.getNodeType() == Node.TEXT_NODE) {
1084:                        isNormalized(false);
1085:                    }
1086:                }
1087:            } // checkNormalizationAfterRemove(ChildNode)
1088:
1089:            //
1090:            // Serialization methods
1091:            //
1092:
1093:            /** Serialize object. */
1094:            private void writeObject(ObjectOutputStream out) throws IOException {
1095:
1096:                // synchronize chilren
1097:                if (needsSyncChildren()) {
1098:                    synchronizeChildren();
1099:                }
1100:                // write object
1101:                out.defaultWriteObject();
1102:
1103:            } // writeObject(ObjectOutputStream)
1104:
1105:            /** Deserialize object. */
1106:            private void readObject(ObjectInputStream ois)
1107:                    throws ClassNotFoundException, IOException {
1108:
1109:                // perform default deseralization
1110:                ois.defaultReadObject();
1111:
1112:                // hardset synchildren - so we don't try to sync -
1113:                // it does not make any sense to try to synchildren when we just
1114:                // deserialize object.
1115:                needsSyncChildren(false);
1116:
1117:            } // readObject(ObjectInputStream)
1118:
1119:        } // class AttrImpl
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.