Source Code Cross Referenced for Element.java in  » Ajax » zk » org » zkoss » idom » 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 » Ajax » zk » org.zkoss.idom 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* Element.java
0002:
0003:        {{IS_NOTE
0004:
0005:        	Purpose:
0006:        	Description:
0007:        	History:
0008:        	2001/10/22 17:10:29, Create, Tom M. Yeh
0009:        }}IS_NOTE
0010:
0011:        Copyright (C) 2001 Potix Corporation. All Rights Reserved.
0012:
0013:        {{IS_RIGHT
0014:        	This program is distributed under GPL Version 2.0 in the hope that
0015:        	it will be useful, but WITHOUT ANY WARRANTY.
0016:        }}IS_RIGHT
0017:         */
0018:        package org.zkoss.idom;
0019:
0020:        import java.util.Map;
0021:        import java.util.LinkedHashMap;
0022:        import java.util.Collection;
0023:        import java.util.AbstractCollection;
0024:        import java.util.List;
0025:        import java.util.Iterator;
0026:        import java.util.LinkedList;
0027:        import java.util.Collections;
0028:        import java.util.NoSuchElementException;
0029:        import java.util.regex.Pattern;
0030:        import java.io.IOException;
0031:        import java.io.ObjectInputStream;
0032:        import java.io.ObjectOutputStream;
0033:        import javax.xml.transform.TransformerException;
0034:
0035:        import org.w3c.dom.Attr;
0036:        import org.w3c.dom.Node;
0037:        import org.w3c.dom.NodeList;
0038:        import org.w3c.dom.NamedNodeMap;
0039:        import org.w3c.dom.TypeInfo;
0040:
0041:        import org.zkoss.mesg.Messages;
0042:        import org.zkoss.mesg.MCommon;
0043:        import org.zkoss.util.CollectionsX;
0044:        import org.zkoss.util.CheckableTreeArray;
0045:        import org.zkoss.xml.FacadeNodeList;
0046:        import org.zkoss.idom.impl.*;
0047:
0048:        /**
0049:         * The iDOM element.
0050:         *
0051:         * @author tomyeh
0052:         * @see Attribute
0053:         */
0054:        public class Element extends AbstractGroup implements  Attributable,
0055:                Namespaceable, org.w3c.dom.Element {
0056:            /** The namespace. */
0057:            protected Namespace _ns;
0058:            /** The local name. */
0059:            protected String _lname;
0060:            /** The attributes. May be null. */
0061:            protected List _attrs = null;
0062:            /** Additional namespaces. May be null*/
0063:            protected Map _addNamespaces = null;
0064:            /** Whether it is aware of the attribute modification. */
0065:            boolean _attrModAware = false;
0066:
0067:            /**
0068:             * Constructor.
0069:             *
0070:             * @param nsURI the namespace URI
0071:             * @param tname the tag name
0072:             */
0073:            public Element(String nsURI, String tname) {
0074:                int kp = tname.indexOf(':');
0075:                String prefix = kp >= 0 ? tname.substring(0, kp) : "";
0076:                String lname = kp >= 0 ? tname.substring(kp + 1) : tname;
0077:                setNamespace(prefix, nsURI);
0078:                setLocalName(lname);
0079:            }
0080:
0081:            /**
0082:             * Constructor.
0083:             *
0084:             * @param ns the namespace; if null, the default namespace is assumed
0085:             * (not necessary {@link Namespace#NO_NAMESPACE}).
0086:             * @param lname the local name
0087:             */
0088:            public Element(Namespace ns, String lname) {
0089:                setNamespace(ns);
0090:                setLocalName(lname);
0091:            }
0092:
0093:            /**
0094:             * Constructor without a namespace (i.e., {@link Namespace#NO_NAMESPACE}).
0095:             *
0096:             * @param lname the local name
0097:             */
0098:            public Element(String lname) {
0099:                this (Namespace.NO_NAMESPACE, lname);
0100:            }
0101:
0102:            /**
0103:             * Constructor.
0104:             * Unlike other constructors, it doesn't set the modification flag.
0105:             */
0106:            protected Element() {
0107:                _ns = Namespace.NO_NAMESPACE;
0108:            }
0109:
0110:            //-- Element extras --//
0111:            /**
0112:             * Tests whether this element is the root element of
0113:             * the owning document.
0114:             *
0115:             * <p>Note: false is returned if it doesn't has any parent.
0116:             */
0117:            public final boolean isRootElement() {
0118:                return getParent() instanceof  Document;
0119:            }
0120:
0121:            /**
0122:             * Returns the Namespace in scope on this element for the given
0123:             * prefix (this involves searching up the tree, so the results depend
0124:             * on the current location of the element), or null if not found.
0125:             *
0126:             * <p>If prefix is empty, it searches for the "default" namespace
0127:             * in scope. Thus, to search for attribute's namespace, caller
0128:             * have to skip this one and use NO_NAMESPACE.
0129:             * (due XML, an attribute without prefix is NO_NAMESPACE)
0130:             *
0131:             * @param prefix namespace prefix to look up; null for empty
0132:             */
0133:            public final Namespace getNamespace(String prefix) {
0134:                if (prefix == null)
0135:                    prefix = "";
0136:
0137:                Namespace ns = Namespace.getSpecial(prefix);
0138:                if (ns != null)
0139:                    return ns;
0140:
0141:                ns = getNamespace(); //might be null if in constructor
0142:                if (ns != null && prefix.equals(ns.getPrefix()))
0143:                    return ns;
0144:
0145:                if (_addNamespaces != null) {
0146:                    ns = (Namespace) _addNamespaces.get(prefix);
0147:                    if (ns != null)
0148:                        return ns;
0149:                }
0150:
0151:                if (getParent() instanceof  Element) //only Element implements it; not Namespaceable
0152:                    return ((Element) getParent()).getNamespace(prefix);
0153:
0154:                return prefix.length() > 0 ? null : Namespace.NO_NAMESPACE;
0155:            }
0156:
0157:            /**
0158:             * Returns namespace declared on this element.
0159:             *
0160:             * <p>It is <i>not</i> a "live" representation. Also, it is read-only.
0161:             *
0162:             * <p>Note: Namespace.equals compares namespace's URI. However,
0163:             * the distinction here is the prefix, because it is mainly for
0164:             * getNamespace(prefix).
0165:             *
0166:             * @return the namespace declarations.
0167:             */
0168:            public final Collection getDeclaredNamespaces() {
0169:                return _addNamespaces == null ? Collections.EMPTY_LIST
0170:                        : _addNamespaces.values();
0171:            }
0172:
0173:            /**
0174:             * Adds a namespace to the namespace declaration.
0175:             *
0176:             * @return true if the namespace is added
0177:             * @exception DOMException if the name space with the same prefix
0178:             * already exists but with different URI
0179:             */
0180:            public final boolean addDeclaredNamespace(Namespace ns) {
0181:                if (_addNamespaces == null) {
0182:                    _addNamespaces = new LinkedHashMap(5);
0183:                } else {
0184:                    final Namespace old = (Namespace) _addNamespaces.get(ns
0185:                            .getPrefix());
0186:                    if (old != null) {
0187:                        if (!old.equals(ns))
0188:                            throw new DOMException(DOMException.NAMESPACE_ERR,
0189:                                    "Add a conflict namespace: " + ns
0190:                                            + ", while " + old
0191:                                            + " already exists");
0192:                        return false;
0193:                    }
0194:                }
0195:
0196:                _addNamespaces.put(ns.getPrefix(), ns);
0197:                return true;
0198:            }
0199:
0200:            /**
0201:             * Gets the content of this element.
0202:             *
0203:             * <p>The content of an element is the first Binary or Text child of
0204:             * the element. Each element can has zero or one content.
0205:             *
0206:             * <p>Note: {@link #getText} returns the catenation of all Text
0207:             * children, not just the first one.
0208:             *
0209:             * @return the content of this element; null if no such child
0210:             * @see #getContent(String)
0211:             */
0212:            public final Object getContent() {
0213:                for (final Iterator it = _children.iterator(); it.hasNext();) {
0214:                    Object o = it.next();
0215:                    if (o instanceof  Text) {
0216:                        return ((Text) o).getText();
0217:                    } else if (o instanceof  Binary) {
0218:                        return ((Binary) o).getValue();
0219:                    } else if (o instanceof  CData) {
0220:                        return ((CData) o).getText();
0221:                    }
0222:                }
0223:                return null;
0224:            }
0225:
0226:            /**
0227:             * Sets the content of this element.
0228:             *
0229:             * <p>All existent Binary or Text children of this element are removed
0230:             * first. If the object is a String, a Text item is created to hold
0231:             * it. Otherwise, a Binary item is created to hold it.
0232:             *
0233:             * <p>Non-Binary/Text children are preserved.
0234:             *
0235:             * <p>If obj is a {@link Item} or an array/collection of {@link Item},
0236:             * this method will add them as child vertices rather than
0237:             * being the content.
0238:             * Moreever, if the first item of the array/collection is {@link Item},
0239:             * it is assumed to be all valid component to being has valid vertices.
0240:             * If not, an exception is thrown.
0241:             *
0242:             * <p>Thus, getContent might not return the object being set by setContent.
0243:             *
0244:             * @param obj the object to set; null is OK
0245:             * @return the previous content
0246:             * @see #getContent()
0247:             */
0248:            public final Object setContent(Object obj) {
0249:                if (obj instanceof  Item) {
0250:                    getChildren().add(obj);
0251:                    return null; //done
0252:                }
0253:                if (obj instanceof  Collection) {
0254:                    final Collection c = (Collection) obj;
0255:                    final Iterator it = c.iterator();
0256:                    if (it.hasNext() && (it.next() instanceof  Item)) {
0257:                        getChildren().addAll(c);
0258:                        return null; //done
0259:                    }
0260:                } else if (obj instanceof  Object[]) {
0261:                    Object[] ary = (Object[]) obj;
0262:                    if (ary.length > 0 && (ary[0] instanceof  Item)) {
0263:                        for (int j = 0; j < ary.length; ++j)
0264:                            getChildren().add(ary[j]);
0265:                        return null; //done
0266:                    }
0267:                }
0268:
0269:                Object ret = null;
0270:                boolean retFound = false;
0271:                boolean bStr = obj instanceof  String;
0272:                for (final Iterator it = _children.iterator(); it.hasNext();) {
0273:                    Object o = it.next();
0274:                    if (o instanceof  Text) {
0275:                        if (!retFound) {
0276:                            retFound = true;
0277:                            ret = ((Text) o).getText();
0278:                        }
0279:                        if (!bStr || obj == null) {
0280:                            it.remove();
0281:                        } else {
0282:                            ((Text) o).setText((String) obj);
0283:                            obj = null; //then, the following will be removed
0284:                        }
0285:                    } else if (o instanceof  Binary) {
0286:                        if (!retFound) {
0287:                            retFound = true;
0288:                            ret = ((Binary) o).getValue();
0289:                        }
0290:                        if (bStr || obj == null) {
0291:                            it.remove();
0292:                        } else {
0293:                            ((Binary) o).setValue(obj);
0294:                            obj = null; //then, the following will be removed
0295:                        }
0296:                    } else if (o instanceof  CData) {
0297:                        if (!retFound) {
0298:                            retFound = true;
0299:                            ret = ((CData) o).getText();
0300:                        }
0301:                        it.remove(); //always remove and add
0302:                    }
0303:                }
0304:                if (obj != null)
0305:                    _children.add(0, bStr ? (Object) new Text((String) obj)
0306:                            : (Object) new Binary(obj));
0307:                return ret;
0308:            }
0309:
0310:            /**
0311:             * Returns the content of the child element with the giving path, or
0312:             * null if the content is null or the child element doesn't exist.
0313:             *
0314:             * <p>Note that there might be more than one child with the same path
0315:             * in an idom tree; this method simply picks the first one that matchs and
0316:             * returns its content. To access certain one, you might use [n] to
0317:             * [@attr = value] specify which one to access.
0318:             *
0319:             *
0320:             * <p>To know whether the child element exists or conent is null,
0321:             * use {@link #hasContent}.
0322:             *
0323:             * <p>The content of an element is a special feature of iDOM.
0324:             * Like a Map, it is designed to let developers use names (in a path-like
0325:             * format) to access objects. See {@link #setContent(String, Object)}.
0326:             *
0327:             * <p>Like Unix path, the giving name could use '/' to catenate a series
0328:             * of child elements.
0329:             *
0330:             * <p>An empty path denotes this element itself. Leading, ending
0331:             * and consecutive '/' will be ignored.
0332:             *
0333:             * <p>Example:<br>
0334:             * <code>Object o = element.getContent("abc/def");<br>
0335:             * String s = Objects.toString(element.getContent("ab/cd"));<br>
0336:             * element.setContent("t:ab/cd/f:ef", new Integer(10));</code>
0337:             *
0338:             * <p>TODO: support [n] and [@attr = value]
0339:             *
0340:             * @param path a path; e.g., "b", "a/b", "t:a/t:b"
0341:             * @see #getContent()
0342:             */
0343:            public final Object getContent(String path) {
0344:                Element e = this ;
0345:                int j = 0;
0346:                while (true) {
0347:                    int k = path.indexOf('/', j);
0348:                    String tname = k >= 0 ? path.substring(j, k) : path
0349:                            .substring(j);
0350:                    if (tname.length() > 0) {
0351:                        e = e.getElement(tname);
0352:                        if (e == null)
0353:                            return null;
0354:                    }
0355:
0356:                    if (k < 0)
0357:                        return e.getContent();
0358:                    j = k + 1;
0359:                }
0360:            }
0361:
0362:            /**
0363:             * Tests whether the child element with the giving path exists. Note that
0364:             * there might be more than one child with the same path in an idom tree;
0365:             * this method simply tell you that "yes", at least on such path exist.
0366:             *
0367:             * To get the content, use {@link #getContent(String)}.
0368:             */
0369:            public final boolean hasContent(String path) {
0370:                Element e = this ;
0371:                int j = 0;
0372:                while (true) {
0373:                    int k = path.indexOf('/', j);
0374:                    String tname = k >= 0 ? path.substring(j, k) : path
0375:                            .substring(j);
0376:                    if (tname.length() > 0) {
0377:                        e = e.getElement(tname);
0378:                        if (e == null)
0379:                            return false;
0380:                    }
0381:
0382:                    if (k < 0)
0383:                        return true;
0384:                    j = k + 1;
0385:                }
0386:            }
0387:
0388:            /**
0389:             * Sets the content of the child element with the giving path.
0390:             *
0391:             * <p>Note that there might be more than one child with the same path
0392:             * in an idom tree; this method simply pick one that matchs and set
0393:             * its content (see {@link #setContent(Object)}).
0394:             *
0395:             * <p>The content of an element is a special feature of iDOM.
0396:             * Like a Map, it is designed to let developers use names (in a path-like
0397:             * format) to access objects. See {@link #getContent(String)}.
0398:             *
0399:             * <p>Like Unix path, the giving name could use '/' to catenate a series
0400:             * of child elements.
0401:             *
0402:             * <p>An empty path denotes this element itself. Leading, ending
0403:             * and consecutive '/' will be ignored.
0404:             *
0405:             * <p>If any element in the path is not found, it will be created
0406:             * automatically.
0407:             *
0408:             * @param path a path; e.g., "b", "a/b", "t:a/t:b"
0409:             * @param obj the object to set; null is acceptable
0410:             * @return the previous content
0411:             *
0412:             * @see #setContent(Object)
0413:             * @see #removeContent
0414:             * @see #hasContent
0415:             */
0416:            public final Object setContent(String path, Object obj) {
0417:                Element e = this ;
0418:                int j = 0;
0419:                while (true) {
0420:                    int k = path.indexOf('/', j);
0421:                    String tname = k >= 0 ? path.substring(j, k) : path
0422:                            .substring(j);
0423:                    if (tname.length() > 0) {
0424:                        Element e2 = e.getElement(tname);
0425:                        if (e2 == null) {
0426:                            e2 = new Element(e.getNamespace().getURI(), tname);
0427:                            e.getChildren().add(e2);
0428:                        }
0429:                        e = e2;
0430:                    }
0431:
0432:                    if (k < 0)
0433:                        return e.setContent(obj);
0434:                    j = k + 1;
0435:                }
0436:            }
0437:
0438:            /**
0439:             * Removes the content of the child element with the giving path,
0440:             * and the child element itself if no other child.
0441:             *
0442:             * <p>Unlike {@link #setContent(String, Object)} with null,
0443:             * the child element identified by path will be detached if it has no
0444:             * other child (but the content). So does its parent
0445:             * <i>excluding</i> this element. Thus, removeContent(path)
0446:             * could undo setContent(path, v).
0447:             *
0448:             * @return the previous content
0449:             * @see #setContent(String, Object)
0450:             */
0451:            public final Object removeContent(String path) {
0452:                Element e = this ;
0453:                int j = 0;
0454:                while (true) {
0455:                    int k = path.indexOf('/', j);
0456:                    String tname = k >= 0 ? path.substring(j, k) : path
0457:                            .substring(j);
0458:                    if (tname.length() > 0) {
0459:                        e = e.getElement(tname);
0460:                        if (e == null)
0461:                            return null;
0462:                    }
0463:
0464:                    if (k < 0) {
0465:                        Object ret = e.setContent(null);
0466:
0467:                        //try to remove e; not including this
0468:                        for (Group group = e; group != this 
0469:                                && group.getChildren().size() == 0;) {
0470:                            Group parent = group.getParent();
0471:                            group.detach();
0472:                            group = parent;
0473:                        }
0474:                        return ret;
0475:                    }
0476:                    j = k + 1;
0477:                }
0478:            }
0479:
0480:            //-- utilities --//
0481:            /** Returns the text of a child; never null. */
0482:            private static final String getTextOfChild(Object o) {
0483:                if (!(o instanceof  AbstractTextual))
0484:                    return "";
0485:                final AbstractTextual t = (AbstractTextual) o;
0486:                return t.isPartOfParentText() ? t.getText() : "";
0487:            }
0488:
0489:            //-- Namespaceable --//
0490:            /**
0491:             * Sets the namespace.
0492:             * If ns is null, the default namespace is assumed (not necessary
0493:             * {@link Namespace#NO_NAMESPACE}.
0494:             * <p>According W3C/DOM, unlike element, an attribute doesn't allow
0495:             * a namespace that has an URI but without a prefix.
0496:             */
0497:            public final void setNamespace(Namespace ns) {
0498:                checkWritable();
0499:                if (ns == null) {
0500:                    if (_ns != null && _ns.getPrefix().length() == 0)
0501:                        return; //nothing to do
0502:                    ns = getNamespace("");
0503:                    if (ns == null)
0504:                        ns = Namespace.NO_NAMESPACE;
0505:                }
0506:                final Namespace old = getNamespace(ns.getPrefix());
0507:                if (old != null && old.equals(ns))
0508:                    ns = old; //re-use if already defined
0509:                _ns = ns;
0510:            }
0511:
0512:            /** Sets the namespace.
0513:             */
0514:            public final void setNamespace(String prefix, String nsURI) {
0515:                if (nsURI == null)
0516:                    nsURI = "";
0517:                final Namespace ns = getNamespace(prefix);
0518:                if (ns != null) {
0519:                    if (ns.getURI().equals(nsURI)) {
0520:                        setNamespace(ns);
0521:                        return;
0522:                    }
0523:                }
0524:                setNamespace(new Namespace(prefix, nsURI));
0525:            }
0526:
0527:            public final Namespace getNamespace() {
0528:                return _ns;
0529:            }
0530:
0531:            public final String getTagName() {
0532:                return _ns.tagNameOf(_lname);
0533:            }
0534:
0535:            public final void setTagName(String tname) {
0536:                checkWritable();
0537:                int kp = tname.indexOf(':');
0538:                String prefix = kp >= 0 ? tname.substring(0, kp) : "";
0539:                String lname = kp >= 0 ? tname.substring(kp + 1) : tname;
0540:                setPrefix(prefix);
0541:                setLocalName(lname);
0542:            }
0543:
0544:            public final String getLocalName() {
0545:                return _lname;
0546:            }
0547:
0548:            public final void setLocalName(String lname) {
0549:                checkWritable();
0550:                Verifier.checkElementName(lname, getLocator());
0551:                _lname = lname;
0552:            }
0553:
0554:            //-- Item --//
0555:            /** Clear the modification flag.
0556:             * <p>Note: if both includingDescendant and
0557:             * {@link #isAttributeModificationAware} are true, attributes'
0558:             * modified flags are cleaned.
0559:             */
0560:            public void clearModified(boolean includingDescendant) {
0561:                if (includingDescendant && _attrModAware) {
0562:                    for (final Iterator it = _attrs.iterator(); it.hasNext();)
0563:                        ((Item) it.next()).clearModified(true);
0564:                }
0565:                super .clearModified(includingDescendant);
0566:            }
0567:
0568:            public Item clone(boolean preserveModified) {
0569:                Element elem = (Element) super .clone(preserveModified);
0570:
0571:                if (_addNamespaces != null) {
0572:                    elem._addNamespaces = new LinkedHashMap();
0573:                    elem._addNamespaces.putAll(_addNamespaces);
0574:                }
0575:                if (_attrs != null) {
0576:                    elem._attrs = elem.newAttrArray();
0577:                    //NOTE: AttrArray is an inner class, so we must use the right
0578:                    //object to create the array. Here is 'elem'.
0579:
0580:                    for (final Iterator it = _attrs.iterator(); it.hasNext();) {
0581:                        Item v = ((Item) it.next()).clone(preserveModified);
0582:                        boolean bClearModified = !preserveModified
0583:                                || !v.isModified();
0584:
0585:                        elem._attrs.add(v); //v becomes modified (v.setParent is called)
0586:
0587:                        if (bClearModified)
0588:                            v.clearModified(false);
0589:                    }
0590:                }
0591:                elem._modified = preserveModified && _modified;
0592:                return elem;
0593:            }
0594:
0595:            /**
0596:             * Gets the tag name of the element -- the name with prefix.
0597:             * To get the local name, use getLocalName.
0598:             */
0599:            public final String getName() {
0600:                return getTagName();
0601:            }
0602:
0603:            /**
0604:             * Sets the tag name of the element.
0605:             * It will affect the local name and the namespace's prefix.
0606:             */
0607:            public final void setName(String tname) {
0608:                setTagName(tname);
0609:            }
0610:
0611:            /** Returns the catenation of {@link Textual} children; never null.
0612:             * Note: both &lt;tag/&gt; and &lt;tag&gt;&lt;/tag&gt; returns an
0613:             * empty string. To tell the difference, check the number of children.
0614:             * @see #getText(boolean)
0615:             */
0616:            public final String getText() {
0617:                if (_children.size() == 1) //optimize this case
0618:                    return getTextOfChild(_children.get(0));
0619:
0620:                final StringBuffer sb = new StringBuffer(256);
0621:                for (final Iterator it = _children.iterator(); it.hasNext();)
0622:                    sb.append(getTextOfChild(it.next()));
0623:                return sb.toString();
0624:            }
0625:
0626:            /** Returns the catenation of {@link Textual} children; never null.
0627:             *
0628:             * @param trim whether to trim before returning
0629:             * @see #getText()
0630:             */
0631:            public final String getText(boolean trim) {
0632:                String t = getText();
0633:                return trim && t != null ? t.trim() : t;
0634:            }
0635:
0636:            //-- Attributable --//
0637:            public final boolean isAttributeModificationAware() {
0638:                return _attrModAware;
0639:            }
0640:
0641:            public final void setAttributeModificationAware(boolean aware) {
0642:                _attrModAware = aware;
0643:            }
0644:
0645:            public final List getAttributeItems() {
0646:                if (_attrs == null)
0647:                    _attrs = newAttrArray();
0648:                return _attrs;
0649:            }
0650:
0651:            /** Creates an empty list of attributes.
0652:             */
0653:            protected List newAttrArray() {
0654:                return new AttrArray();
0655:            }
0656:
0657:            public final int getAttributeIndex(int indexFrom, String namespace,
0658:                    String name, int mode) {
0659:                if (_attrs == null || indexFrom < 0
0660:                        || indexFrom >= _attrs.size())
0661:                    return -1;
0662:
0663:                final Pattern ptn = (mode & FIND_BY_REGEX) != 0 ? Pattern
0664:                        .compile(name) : null;
0665:
0666:                final Iterator it = _attrs.listIterator(indexFrom);
0667:                for (int j = indexFrom; it.hasNext(); ++j)
0668:                    if (match((Attribute) it.next(), namespace, name, ptn, mode))
0669:                        return j;
0670:
0671:                return -1;
0672:            }
0673:
0674:            public final int getAttributeIndex(int indexFrom, String tname) {
0675:                return getAttributeIndex(indexFrom, null, tname,
0676:                        FIND_BY_TAGNAME);
0677:            }
0678:
0679:            public final Attribute getAttributeItem(String namespace,
0680:                    String name, int mode) {
0681:                int j = getAttributeIndex(0, namespace, name, mode);
0682:                return j >= 0 ? (Attribute) _attrs.get(j) : null;
0683:            }
0684:
0685:            public final Attribute getAttributeItem(String tname) {
0686:                int j = getAttributeIndex(0, tname);
0687:                return j >= 0 ? (Attribute) _attrs.get(j) : null;
0688:            }
0689:
0690:            public final List getAttributes(String namespace, String name,
0691:                    int mode) {
0692:                if (_attrs == null)
0693:                    return Collections.EMPTY_LIST;
0694:
0695:                Pattern ptn = (mode & FIND_BY_REGEX) != 0 ? Pattern
0696:                        .compile(name) : null;
0697:
0698:                final List list = new LinkedList();
0699:                for (final Iterator it = _attrs.iterator(); it.hasNext();) {
0700:                    Attribute attr = (Attribute) it.next();
0701:                    if (match(attr, namespace, name, ptn, mode))
0702:                        list.add(attr);
0703:                }
0704:                return list;
0705:            }
0706:
0707:            public final Attribute setAttribute(Attribute attr) {
0708:                checkWritable();
0709:                int j = getAttributeIndex(0, attr.getTagName());
0710:                if (j >= 0) {
0711:                    return (Attribute) getAttributeItems().set(j, attr);
0712:                } else {
0713:                    getAttributeItems().add(attr);
0714:                    return null;
0715:                }
0716:            }
0717:
0718:            public final String getAttributeValue(String namespace,
0719:                    String name, int mode) {
0720:                final Attribute attr = getAttributeItem(namespace, name, mode);
0721:                return attr != null ? attr.getValue() : null;
0722:            }
0723:
0724:            public final String getAttributeValue(String tname) {
0725:                Attribute attr = getAttributeItem(tname);
0726:                return attr != null ? attr.getValue() : null;
0727:            }
0728:
0729:            public final Attribute setAttributeValue(String tname, String value) {
0730:                checkWritable();
0731:                Attribute attr = getAttributeItem(tname);
0732:                if (attr != null)
0733:                    attr.setValue(value);
0734:                else
0735:                    getAttributeItems().add(new Attribute(tname, value));
0736:                return attr;
0737:            }
0738:
0739:            //-- Node --//
0740:            public final short getNodeType() {
0741:                return ELEMENT_NODE;
0742:            }
0743:
0744:            /**
0745:             * Always null. Unlike other nodes, it is not the same as getText.
0746:             */
0747:            public final String getNodeValue() {
0748:                return null;
0749:            }
0750:
0751:            public final NamedNodeMap getAttributes() {
0752:                return new AttrMap();
0753:            }
0754:
0755:            public final boolean hasAttributes() {
0756:                return _attrs != null && !_attrs.isEmpty();
0757:            }
0758:
0759:            public final String getNamespaceURI() {
0760:                return _ns.getURI();
0761:            }
0762:
0763:            public final String getPrefix() {
0764:                return _ns.getPrefix();
0765:            }
0766:
0767:            public final void setPrefix(String prefix) {
0768:                setNamespace(prefix, _ns.getURI());
0769:            }
0770:
0771:            //-- Element --//
0772:            public final NodeList getElementsByTagName(String tname) {
0773:                return new FacadeNodeList(getElements(null, tname,
0774:                        FIND_BY_TAGNAME | FIND_RECURSIVE));
0775:            }
0776:
0777:            public final NodeList getElementsByTagNameNS(String nsURI,
0778:                    String lname) {
0779:                return new FacadeNodeList(getElements(nsURI, lname,
0780:                        FIND_RECURSIVE));
0781:            }
0782:
0783:            public final Attr getAttributeNode(String tname) {
0784:                return getAttributeItem(tname);
0785:            }
0786:
0787:            public final Attr getAttributeNodeNS(String nsURI, String lname) {
0788:                return getAttributeItem(nsURI, lname, 0);
0789:            }
0790:
0791:            public final String getAttribute(String tname) {
0792:                String val = getAttributeValue(tname);
0793:                return val != null ? val : ""; //w3c spec
0794:            }
0795:
0796:            public final String getAttributeNS(String nsURI, String lname) {
0797:                Attribute attr = getAttributeItem(nsURI, lname, 0);
0798:                return attr != null ? attr.getValue() : "";
0799:            }
0800:
0801:            public final void setAttribute(String tname, String value) {
0802:                setAttributeValue(tname, value);
0803:            }
0804:
0805:            public final void setAttributeNS(String nsURI, String tname,
0806:                    String value) {
0807:                checkWritable();
0808:
0809:                int kp = tname.indexOf(':');
0810:                String prefix = kp >= 0 ? tname.substring(0, kp) : "";
0811:                String lname = kp >= 0 ? tname.substring(kp + 1) : tname;
0812:                Attribute attr = getAttributeItem(nsURI, lname, 0);
0813:                if (attr != null) {
0814:                    attr.setPrefix(prefix); //also change prefix
0815:                    attr.setValue(value);
0816:                } else {
0817:                    getAttributeItems().add(new Attribute(nsURI, tname, value));
0818:                }
0819:            }
0820:
0821:            public final Attr setAttributeNode(Attr newAttr) {
0822:                return setAttribute((Attribute) newAttr);
0823:            }
0824:
0825:            public final Attr setAttributeNodeNS(Attr newAttr) {
0826:                Attribute attr = (Attribute) newAttr;
0827:                int j = getAttributeIndex(0, attr.getNamespace().getURI(), attr
0828:                        .getLocalName(), 0);
0829:                if (j >= 0) {
0830:                    return (Attr) getAttributeItems().set(j, newAttr);
0831:                } else {
0832:                    getAttributeItems().add(newAttr);
0833:                    return null;
0834:                }
0835:            }
0836:
0837:            public final void removeAttribute(String tname) {
0838:                int j = getAttributeIndex(0, tname);
0839:                if (j >= 0)
0840:                    _attrs.remove(j);
0841:            }
0842:
0843:            public final void removeAttributeNS(String nsURI, String lname) {
0844:                int j = getAttributeIndex(0, nsURI, lname, 0);
0845:                if (j >= 0)
0846:                    _attrs.remove(j);
0847:            }
0848:
0849:            public final Attr removeAttributeNode(Attr oldAttr) {
0850:                Attribute attr = (Attribute) oldAttr;
0851:                int j = getAttributeIndex(0, attr.getTagName());
0852:                if (j >= 0) {
0853:                    return (Attr) _attrs.remove(j);
0854:                } else {
0855:                    throw new DOMException(DOMException.NOT_FOUND_ERR,
0856:                            getLocator());
0857:                }
0858:            }
0859:
0860:            public final boolean hasAttribute(String tname) {
0861:                return getAttributeIndex(0, tname) >= 0;
0862:            }
0863:
0864:            public final boolean hasAttributeNS(String nsURI, String lname) {
0865:                return getAttributeIndex(0, nsURI, lname, 0) >= 0;
0866:            }
0867:
0868:            public final String toString() {
0869:                StringBuffer sb = new StringBuffer(64).append("[Element: <")
0870:                        .append(getTagName());
0871:
0872:                String uri = getNamespace().getURI();
0873:                if (uri.length() != 0)
0874:                    sb.append(" [").append(uri).append(']');
0875:
0876:                if (_attrs != null) {
0877:                    for (final Iterator it = _attrs.iterator(); it.hasNext();) {
0878:                        Attribute attr = (Attribute) it.next();
0879:                        sb.append(' ').append(attr.getTagName()).append("=\"")
0880:                                .append(attr.getValue()).append('"');
0881:                    }
0882:                }
0883:
0884:                return sb.append("/>]").toString();
0885:            }
0886:
0887:            public TypeInfo getSchemaTypeInfo() {
0888:                throw new UnsupportedOperationException("DOM Level 3");
0889:            }
0890:
0891:            public void setIdAttribute(String name, boolean isId)
0892:                    throws DOMException {
0893:                //Level 3 not yet
0894:            }
0895:
0896:            public void setIdAttributeNS(String namespaceURI, String localName,
0897:                    boolean isId) throws DOMException {
0898:                //Level 3 not yet
0899:            }
0900:
0901:            public void setIdAttributeNode(Attr idAttr, boolean isId)
0902:                    throws DOMException {
0903:                //Level 3 not yet
0904:            }
0905:
0906:            //-- AttrArray --//
0907:            protected class AttrArray extends CheckableTreeArray {
0908:                protected AttrArray() {
0909:                }
0910:
0911:                //-- utilities --//
0912:                private Attribute checkAdd(Object newItem) {
0913:                    checkWritable();
0914:
0915:                    if (!(newItem instanceof  Attribute))
0916:                        throw new DOMException(
0917:                                DOMException.HIERARCHY_REQUEST_ERR,
0918:                                "Invalid type", getLocator());
0919:
0920:                    Attribute attr = (Attribute) newItem;
0921:                    if (attr.getOwner() != null)
0922:                        throw new DOMException(
0923:                                DOMException.HIERARCHY_REQUEST_ERR,
0924:                                "Attribute, "
0925:                                        + attr.toString()
0926:                                        + ", owned by other; detach or clone it",
0927:                                getLocator());
0928:
0929:                    return attr;
0930:                }
0931:
0932:                //-- CheckableTreeArray --//
0933:                protected void onAdd(Object newElement, Object followingElement) {
0934:                    checkAdd(newElement, followingElement, false);
0935:                }
0936:
0937:                protected void onSet(Object newElement, Object replaced) {
0938:                    assert (replaced != null);
0939:                    checkAdd(newElement, replaced, true);
0940:                }
0941:
0942:                private void checkAdd(Object newItem, Object other,
0943:                        boolean replace) {
0944:                    //first, remove any existent with the same uri and name
0945:                    Object attrRemoved = null;
0946:                    Attribute attr = checkAdd(newItem);
0947:
0948:                    int j = getAttributeIndex(0, attr.getTagName());
0949:                    if (j >= 0 && (!replace || get(j) != other))
0950:                        throw new DOMException(
0951:                                DOMException.HIERARCHY_REQUEST_ERR,
0952:                                "Attribute name, " + attr.getTagName()
0953:                                        + ", is conflicts with existent one ("
0954:                                        + j + ')', getLocator());
0955:
0956:                    try {
0957:                        if (replace)
0958:                            onRemove(other);
0959:                        attr.setOwner(Element.this );
0960:                    } catch (RuntimeException ex) {
0961:                        if (replace) {
0962:                            Attribute attrRep = (Attribute) other;
0963:                            if (attrRep.getOwner() == null)
0964:                                attrRep.setOwner(Element.this ); //restore it
0965:                        }
0966:                        if (attrRemoved != null)
0967:                            super .add(j, attrRemoved); //restore it
0968:                        throw ex;
0969:                    }
0970:                }
0971:
0972:                protected void onRemove(Object item) {
0973:                    checkWritable();
0974:                    ((Attribute) item).setOwner(null);
0975:                }
0976:
0977:            }
0978:
0979:            protected class AttrMap implements  NamedNodeMap {
0980:                protected AttrMap() {
0981:                }
0982:
0983:                //-- NamedNodeMap --//
0984:                public final int getLength() {
0985:                    return _attrs != null ? _attrs.size() : 0;
0986:                }
0987:
0988:                public final Node item(int index) {
0989:                    return index < 0 || index >= getLength() ? null
0990:                            : (Node) _attrs.get(index);
0991:                }
0992:
0993:                public final Node getNamedItem(String tname) {
0994:                    return getAttributeItem(tname);
0995:                }
0996:
0997:                public final Node getNamedItemNS(String nsURI, String lname) {
0998:                    return getAttributeItem(nsURI, lname, 0);
0999:                }
1000:
1001:                public final Node removeNamedItem(String tname) {
1002:                    int j = getAttributeIndex(0, tname);
1003:                    return j >= 0 ? (Node) _attrs.remove(j) : null;
1004:                }
1005:
1006:                public final Node removeNamedItemNS(String nsURI, String lname) {
1007:                    int j = getAttributeIndex(0, nsURI, lname, 0);
1008:                    return j >= 0 ? (Node) _attrs.remove(j) : null;
1009:                }
1010:
1011:                public final Node setNamedItem(Node node) {
1012:                    return setAttributeNode((Attr) node);
1013:                }
1014:
1015:                public final Node setNamedItemNS(Node node) {
1016:                    return setAttributeNodeNS((Attr) node);
1017:                }
1018:            }
1019:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.