Source Code Cross Referenced for ElementNode.java in  » 6.0-JDK-Modules » j2me » com » sun » perseus » model » 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 » 6.0 JDK Modules » j2me » com.sun.perseus.model 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *
0003:         *
0004:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0006:         * 
0007:         * This program is free software; you can redistribute it and/or
0008:         * modify it under the terms of the GNU General Public License version
0009:         * 2 only, as published by the Free Software Foundation.
0010:         * 
0011:         * This program is distributed in the hope that it will be useful, but
0012:         * WITHOUT ANY WARRANTY; without even the implied warranty of
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014:         * General Public License version 2 for more details (a copy is
0015:         * included at /legal/license.txt).
0016:         * 
0017:         * You should have received a copy of the GNU General Public License
0018:         * version 2 along with this work; if not, write to the Free Software
0019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020:         * 02110-1301 USA
0021:         * 
0022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0023:         * Clara, CA 95054 or visit www.sun.com if you need additional
0024:         * information or have any questions.
0025:         */
0026:        package com.sun.perseus.model;
0027:
0028:        import com.sun.perseus.platform.MathSupport;
0029:
0030:        import com.sun.perseus.util.SimpleTokenizer;
0031:        import com.sun.perseus.util.SVGConstants;
0032:        import com.sun.perseus.parser.Length;
0033:
0034:        import org.w3c.dom.DOMException;
0035:        import org.w3c.dom.Element;
0036:        import org.w3c.dom.Node;
0037:
0038:        import org.w3c.dom.events.EventListener;
0039:
0040:        import org.w3c.dom.svg.SVGElement;
0041:        import org.w3c.dom.svg.SVGLocatableElement;
0042:        import org.w3c.dom.svg.SVGMatrix;
0043:        import org.w3c.dom.svg.SVGPath;
0044:        import org.w3c.dom.svg.SVGRect;
0045:        import org.w3c.dom.svg.SVGRGBColor;
0046:
0047:        import java.util.Hashtable;
0048:        import java.util.Vector;
0049:
0050:        import com.sun.perseus.j2d.RGB;
0051:        import com.sun.perseus.j2d.Path;
0052:        import com.sun.perseus.j2d.PaintDef;
0053:        import com.sun.perseus.j2d.PaintTarget;
0054:        import com.sun.perseus.j2d.PaintServer;
0055:        import com.sun.perseus.j2d.Transform;
0056:        import com.sun.perseus.j2d.Box;
0057:
0058:        /**
0059:         * <code>ElementNode</code> models <code>ModelNodes</code which 
0060:         * cna have children.
0061:         *
0062:         * <p>A <code>ElementNode</code> can have either <code>ElementNode</code>
0063:         * children and text content children 
0064:         * (see the {@link #appendTextChild} appendTextChild} method).</p>
0065:         *
0066:         * <p>In addition, <code>Element</code>s can have proxies (see
0067:         * {@link com.sun.perseus.model.ElementNodeProxy ElementNodeProxy}).
0068:         * The proxies are used for implementing the behavior of the 
0069:         * <code>&lt;use&gt;</code> element and the <code>&lt;text&gt;</code>
0070:         * element. The <code>buildProxy</code> and <code>removeProxy</code>
0071:         * methods are used to add or remove proxies from a node.</p>
0072:         *
0073:         * <p>Finally, the <code>ElementNode</code> class provides support
0074:         * for the common XML attributes supported by elements, such as
0075:         * the <code>id</code>, <code>uriBase</code> and conditional attributes.</p>
0076:         * 
0077:         * @version $Id: ElementNode.java,v 1.27 2006/06/29 10:47:30 ln156897 Exp $
0078:         */
0079:        public abstract class ElementNode extends CompositeNode implements 
0080:                SVGElement {
0081:            /*
0082:             * Constants for trait types.
0083:             */
0084:
0085:            /**
0086:             * String trait type.
0087:             */
0088:            static final String TRAIT_TYPE_STRING = "string";
0089:
0090:            /**
0091:             * Float trait type.
0092:             */
0093:            static final String TRAIT_TYPE_FLOAT = "float";
0094:
0095:            /**
0096:             * SVGMatrix trait type.
0097:             */
0098:            static final String TRAIT_TYPE_SVG_MATRIX = "SVGMatrix";
0099:
0100:            /**
0101:             * SVGPath trait type.
0102:             */
0103:            static final String TRAIT_TYPE_SVG_PATH = "SVGPath";
0104:
0105:            /**
0106:             * SVGRect trait type
0107:             */
0108:            static final String TRAIT_TYPE_SVG_RECT = "SVGRect";
0109:
0110:            /**
0111:             * SVGRGBColor trait type.
0112:             */
0113:            static final String TRAIT_TYPE_SVG_RGB_COLOR = "SVGRGBColor";
0114:
0115:            /**
0116:             * See the SVG 1.1 specification
0117:             */
0118:            public static final int XML_SPACE_PRESERVE = 0;
0119:
0120:            /**
0121:             * See the SVG 1.1 specification
0122:             */
0123:            public static final int XML_SPACE_DEFAULT = 1;
0124:
0125:            /**
0126:             * Use the parent node's xml:space setting
0127:             */
0128:            public static final int XML_SPACE_INHERIT = 2;
0129:
0130:            /**
0131:             * Constant used to identify the per-element partition
0132:             * (sometimes called anonymous) namespace.
0133:             */
0134:            static final String NULL_NS = "#!null/ns@!";
0135:
0136:            /**
0137:             * This node's id
0138:             */
0139:            protected String id = null;
0140:
0141:            /**
0142:             * This node's URI base
0143:             */
0144:            protected String uriBase = null;
0145:
0146:            /**
0147:             * This node's conditional attributes.
0148:             */
0149:            protected String[][] conditionalAttributes;
0150:
0151:            /**
0152:             * Index for requiredFeatures in conditionalAttributes.
0153:             */
0154:            public static final int REQUIRED_FEATURES_INDEX = 0;
0155:
0156:            /**
0157:             * Index for requiredExtensions in conditionalAttributes
0158:             */
0159:            public static final int REQUIRED_EXTENSIONS_INDEX = 1;
0160:
0161:            /**
0162:             * Index for systemLanguage in conditionalAttributes
0163:             */
0164:            public static final int SYSTEM_LANGUAGE_INDEX = 2;
0165:
0166:            /**
0167:             * Number of conditional attributes.
0168:             */
0169:            public static final int CONDITIONAl_ATTRIBUTES_LENGTH = 3;
0170:
0171:            /**
0172:             * The node's text white space handling policy
0173:             */
0174:            protected int xmlSpace = XML_SPACE_INHERIT;
0175:
0176:            /**
0177:             * Controls whether or not the node needs to be fully loaded
0178:             * before it can be painted.
0179:             */
0180:            protected boolean paintNeedsLoad = false;
0181:
0182:            /**
0183:             * First node proxy. May be null.
0184:             */
0185:            protected ElementNodeProxy firstProxy;
0186:
0187:            /**
0188:             * Last node proxy. May be null.
0189:             */
0190:            protected ElementNodeProxy lastProxy;
0191:
0192:            /**
0193:             * Used to detect circular references when building
0194:             * proxy chains.
0195:             */
0196:            protected boolean buildingProxy = false;
0197:
0198:            /**
0199:             * Maps namespaces to a map of (localName, TraitAnim)
0200:             */
0201:            protected Hashtable traitAnimsNS = null;
0202:
0203:            /**
0204:             * Only constructor.
0205:             *
0206:             * @param ownerDocument the document this node belongs to.
0207:             * @throws IllegalArgumentException if the input ownerDocument is null
0208:             */
0209:            public ElementNode(final DocumentNode ownerDocument) {
0210:
0211:                if (ownerDocument == null) {
0212:                    throw new IllegalArgumentException();
0213:                }
0214:
0215:                this .ownerDocument = ownerDocument;
0216:            }
0217:
0218:            /**
0219:             * Returns the <code>ModelNode</code>, if any, hit by the
0220:             * point at coordinate x/y in the proxy tree starting at 
0221:             * proxy.
0222:             * 
0223:             * @param pt the x/y coordinate. Should never be null and be
0224:             *        of size two. If not, the behavior is unspecified.
0225:             *        The coordinates are in viewport space.
0226:             * @param proxy the root of the proxy tree to test.
0227:             * @return the <tt>ModelNode</tt> hit at the given point or null
0228:             *         if none was hit.
0229:             */
0230:            ModelNode proxyNodeHitAt(final float[] pt,
0231:                    final ElementNodeProxy proxy) {
0232:                return null;
0233:            }
0234:
0235:            /**
0236:             * Recomputes the transform cache on proxy nodes.
0237:             */
0238:            protected void recomputeProxyTransformState() {
0239:                ElementNodeProxy proxy = firstProxy;
0240:                while (proxy != null) {
0241:                    proxy.recomputeTransformState();
0242:                    proxy = proxy.nextProxy;
0243:                }
0244:            }
0245:
0246:            /**
0247:             * Invoked before an element is added to the document tree, to let the 
0248:             * element perform any validation it needs. For example, the use element
0249:             * overrides this method to check that its reference is resolved.
0250:             *
0251:             * Note that the validate() method defined in some element implementations
0252:             * is meant to perform validation after the nodes has been inserted into the
0253:             * document tree.
0254:             */
0255:            protected void preValidate() {
0256:                // By default, do nothing.
0257:            }
0258:
0259:            /**
0260:             * By default, an <code>ElementNode</code> has no expanded content, so this 
0261:             * returns null.    
0262:             *
0263:             * @return a reference to the node's first expanded child, or null if there
0264:             *         are no expanded children. This forces the computation of expanded
0265:             *         content if needed.
0266:             */
0267:            ModelNode getFirstExpandedChild() {
0268:                return null;
0269:            }
0270:
0271:            /**
0272:             * Some node types (such as <code>ElementNodeProxy</code>) have
0273:             * expanded children that they compute in some specific
0274:             * way depending on the implementation.     
0275:             *
0276:             * @return a reference to the node's first expanded child, or null if there
0277:             *         are no expanded children. 
0278:             */
0279:            public ModelNode getFirstComputedExpandedChild() {
0280:                return null;
0281:            }
0282:
0283:            /**
0284:             * By default, an <code>ElementNode</code> has no expanded content, so this 
0285:             * returns null.    
0286:             *
0287:             * @return a reference to the node's last expanded child, or null if there
0288:             *         are no expanded children. This forces the computation of expanded
0289:             *         content if needed.
0290:             */
0291:            ModelNode getLastExpandedChild() {
0292:                return null;
0293:            }
0294:
0295:            /**
0296:             * Utility method. Unhooks the expanded content.
0297:             */
0298:            protected void unhookExpandedQuiet() {
0299:                // No expanded content by default.
0300:            }
0301:
0302:            /**
0303:             * Utility method. Unhooks the children.
0304:             */
0305:            protected void unhookChildrenQuiet() {
0306:                super .unhookChildrenQuiet();
0307:
0308:                // Need to clear the expanded content on proxies
0309:                ElementNodeProxy proxy = firstProxy;
0310:                while (proxy != null) {
0311:                    proxy.unhookExpandedQuiet();
0312:                    proxy = proxy.nextProxy;
0313:                }
0314:            }
0315:
0316:            /**
0317:             * By default, appending a text child does not do anything.
0318:             *
0319:             * @param text the text child to append to this node.
0320:             */
0321:            public void appendTextChild(final String text) {
0322:            }
0323:
0324:            /**
0325:             * Adds a proxy to this node. When this node is modified, the
0326:             * <code>ElementNodeProxy</code>'s corresponding modification
0327:             * methods will be called so that modifications also gets reported
0328:             * on the proxy.
0329:             *
0330:             * @param proxy new <code>ElementNodeProxy</code>
0331:             * @throws NullPointerException if the input proxy is null.
0332:             *
0333:             * @see UpdateListener#modifiedNode
0334:             * @see UpdateListener#modifyingNode
0335:             * @see UpdateListener#nodeInserted
0336:             */
0337:            protected void addProxy(final ElementNodeProxy proxy) {
0338:
0339:                if (proxy == null) {
0340:                    throw new NullPointerException();
0341:                }
0342:
0343:                if (firstProxy == null) {
0344:                    firstProxy = proxy;
0345:                    lastProxy = proxy;
0346:                } else {
0347:                    lastProxy.nextProxy = proxy;
0348:                    proxy.prevProxy = lastProxy;
0349:                    lastProxy = proxy;
0350:                }
0351:            }
0352:
0353:            /**
0354:             * Removes a proxy from this node. If the input proxy is null,
0355:             * or is not an existing proxy, this does nothing.
0356:             *
0357:             * @param proxy the <code>ElementNodeProxy</code> to remove.
0358:             *
0359:             * @see #addProxy
0360:             */
0361:            void removeProxy(final ElementNodeProxy proxy) {
0362:                if (proxy == null || firstProxy == null) {
0363:                    return;
0364:                }
0365:
0366:                // The proxy may be the first one, the last
0367:                // one, or in the middle
0368:                if (proxy == firstProxy) {
0369:                    firstProxy = proxy.nextProxy;
0370:                }
0371:                if (proxy == lastProxy) {
0372:                    lastProxy = proxy.prevProxy;
0373:                }
0374:                if (proxy.prevProxy != null) {
0375:                    proxy.prevProxy.nextProxy = proxy.nextProxy;
0376:                }
0377:                if (proxy.nextProxy != null) {
0378:                    proxy.nextProxy.prevProxy = proxy.prevProxy;
0379:                }
0380:            }
0381:
0382:            /**
0383:             * Used to notify the <code>UpdateListener</code>, if any, of
0384:             * an upcoming node modification
0385:             *
0386:             */
0387:            protected void modifyingNode() {
0388:                UpdateListener updateListener = getUpdateListener();
0389:                if (updateListener != null) {
0390:                    updateListener.modifyingNode(this );
0391:                }
0392:
0393:                // During progressive rendering, a proxy may be hooked into
0394:                // the tree while the referenced node is not. This is why we
0395:                // need to notify proxies even if the node is not hooked into 
0396:                // the tree yet.
0397:                ElementNodeProxy proxy = firstProxy;
0398:                while (proxy != null) {
0399:                    proxy.modifyingProxied();
0400:                    proxy = proxy.nextProxy;
0401:                }
0402:            }
0403:
0404:            /**
0405:             * Used to notify the <code>UpdateListener</code>, if any, of
0406:             * a completed node modification
0407:             *
0408:             */
0409:            protected void modifiedNode() {
0410:                UpdateListener updateListener = getUpdateListener();
0411:                if (updateListener != null) {
0412:                    updateListener.modifiedNode(this );
0413:                }
0414:
0415:                // See comment in #modifyingNode.
0416:                ElementNodeProxy proxy = firstProxy;
0417:                while (proxy != null) {
0418:                    proxy.modifiedProxied();
0419:                    proxy = proxy.nextProxy;
0420:                }
0421:            }
0422:
0423:            /**
0424:             * Appends an element at the end of the list
0425:             *
0426:             * @param element the node to add to this <tt>CompositeNode</tt>
0427:             * @throws NullPointerException if the input argument is null.
0428:             */
0429:            public void add(final ElementNode element) {
0430:                super .add(element);
0431:
0432:                ElementNodeProxy proxy = firstProxy;
0433:                while (proxy != null) {
0434:                    proxy.proxiedChildAdded(element);
0435:                    proxy = proxy.nextProxy;
0436:                }
0437:            }
0438:
0439:            /**
0440:             * @return an adequate <code>ElementNodeProxy</code> for this node.
0441:             */
0442:            ElementNodeProxy buildProxy() {
0443:                return new ElementNodeProxy(this );
0444:            }
0445:
0446:            /**
0447:             * @return an adequate <code>ElementNodeProxy</code> for this node and
0448:             *         makes sure the content is expanded before returning.
0449:             */
0450:            protected ElementNodeProxy buildExpandedProxy() {
0451:                if (buildingProxy) {
0452:                    // We ran into a circular reference.
0453:                    throw new IllegalStateException();
0454:                }
0455:                buildingProxy = true;
0456:                ElementNodeProxy proxy = buildProxy();
0457:                proxy.expand();
0458:                buildingProxy = false;
0459:                return proxy;
0460:            }
0461:
0462:            /**
0463:             * @return the node's identifier
0464:             */
0465:            public String getId() {
0466:                return id;
0467:            }
0468:
0469:            /**
0470:             * @param newId the node's identifier
0471:             *
0472:             * @throws DOMException - with error code NO_MODIFICATION_ALLOWED_ERR is
0473:             * raised if an attempt is made to change an existing Id.
0474:             * @throws DOMException - with error code INVALID_ACCESS_ERR is raised if
0475:             * the Id is not unique i.e. if this Id already exists in the document. 
0476:             * 
0477:             * @throws java.lang.NullPointerException - if Id is null.
0478:             */
0479:            public void setId(final String newId) {
0480:                // Null ids are disallowed.
0481:                if (newId == null) {
0482:                    throw new NullPointerException();
0483:                }
0484:
0485:                // If the id was already set, we cannot let it be modified.
0486:                if (id != null) {
0487:                    throw new DOMException(
0488:                            DOMException.NO_MODIFICATION_ALLOWED_ERR, Messages
0489:                                    .formatMessage(
0490:                                            Messages.ERROR_CANNOT_MODIFY_ID,
0491:                                            new String[] { newId, id,
0492:                                                    getLocalName(),
0493:                                                    getNamespaceURI() }));
0494:                }
0495:
0496:                // Now, check if there is any element with that id already.
0497:                if (ownerDocument.getElementByIdAll(newId) != null) {
0498:                    ElementNode duplicateElement = (ElementNode) ownerDocument
0499:                            .getElementByIdAll(newId);
0500:                    throw new DOMException(
0501:                            DOMException.INVALID_ACCESS_ERR,
0502:                            Messages
0503:                                    .formatMessage(
0504:                                            Messages.ERROR_DUPLICATE_ID_VALUE,
0505:                                            new String[] {
0506:                                                    newId,
0507:                                                    getLocalName(),
0508:                                                    getNamespaceURI(),
0509:                                                    duplicateElement
0510:                                                            .getLocalName(),
0511:                                                    duplicateElement
0512:                                                            .getNamespaceURI() }));
0513:                }
0514:
0515:                modifyingNode();
0516:                id = newId;
0517:
0518:                // We only declare the id in the global document
0519:                // scope, i.e., we only consider the id to be
0520:                // resolved, once the element is loaded, i.e., ready
0521:                // to render. If the element is not loaded, 
0522:                // see the buildComplete method: it adds the element
0523:                // to the list of identified nodes when loaded is
0524:                // set to true.
0525:                if (loaded && isInDocumentTree()) {
0526:                    ownerDocument.addIdentifiedNode(this );
0527:                } else {
0528:                    ownerDocument.reserveId(this );
0529:                }
0530:                modifiedNode();
0531:            }
0532:
0533:            /**
0534:             * When an Element is hooked into the document tree, it needs
0535:             * to register as an identified node if it does have an id.
0536:             */
0537:            void nodeHookedInDocumentTree() {
0538:                super .nodeHookedInDocumentTree();
0539:
0540:                if (id != null) {
0541:                    ownerDocument.addIdentifiedNode(this );
0542:                }
0543:            }
0544:
0545:            /**
0546:             * The node's URI base to use to resolve URI references
0547:             * If a URI base value was set on this node, then that value
0548:             * is returned. Otherwise, this method returns the parent's 
0549:             * URI base.
0550:             *
0551:             * @return the node's URI base to use to resolve relative URI references.
0552:             */
0553:            public String getURIBase() {
0554:                if (uriBase == null) {
0555:                    if (parent != null) {
0556:                        return parent.getURIBase();
0557:                    }
0558:                    return null;
0559:                } else {
0560:                    if (uriBase.indexOf(":") != -1 || parent == null) {
0561:                        // This is not a relative URI, we can return this
0562:                        // value
0563:                        // - or -
0564:                        // There is no parent, return this relative URI
0565:                        // as the baseURI
0566:                        return uriBase;
0567:                    } else {
0568:                        // There is no scheme in this node's uri base. 
0569:                        // We concatenate the uriBase to the one of the 
0570:                        // parent. 
0571:                        // This is done according to RFC 2396 
0572:                        // (http://www.faqs.org/rfcs/rfc2396.html)
0573:                        String parentURIBase = parent.getURIBase();
0574:                        if (parentURIBase != null) {
0575:                            int lastSlashIndex = parentURIBase.lastIndexOf('/');
0576:                            if (lastSlashIndex != -1) {
0577:                                parentURIBase = parentURIBase.substring(0,
0578:                                        lastSlashIndex);
0579:                            }
0580:                            return parentURIBase + '/' + uriBase;
0581:                        } else {
0582:                            return uriBase;
0583:                        }
0584:                    }
0585:                }
0586:            }
0587:
0588:            /**
0589:             * @param newUriBase the node's new URI base. The uriBase is used
0590:             *        to resolve relative URIs
0591:             */
0592:            public void setURIBase(final String newUriBase) {
0593:                if (equal(newUriBase, uriBase)) {
0594:                    return;
0595:                }
0596:                modifyingNode();
0597:                uriBase = newUriBase;
0598:                modifiedNode();
0599:            }
0600:
0601:            /**
0602:             * Controls how the node handles white spaces
0603:             *
0604:             * @param newXmlSpace should be one of XML_SPACE_DEFAULT, 
0605:             *        XML_SPACE_PRESERVE, or XML_SPACE_INHERIT. Otherwise, an 
0606:             *        IllegalArgumentException is thrown.
0607:             */
0608:            public void setXMLSpace(final int newXmlSpace) {
0609:                if (newXmlSpace == xmlSpace) {
0610:                    return;
0611:                }
0612:                switch (newXmlSpace) {
0613:                case XML_SPACE_DEFAULT:
0614:                case XML_SPACE_PRESERVE:
0615:                case XML_SPACE_INHERIT:
0616:                    modifyingNode();
0617:                    xmlSpace = newXmlSpace;
0618:                    modifiedNode();
0619:                    break;
0620:                default:
0621:                    throw new IllegalArgumentException();
0622:                }
0623:            }
0624:
0625:            /**
0626:             * Defines how the node handles white spaces. Note that
0627:             * if the value is set to null, the node should return 
0628:             * the value of its parent, as the xml:space attribute is
0629:             * inherited.
0630:             * 
0631:             * @return one of XML_SPACE_DEFAULT, XML_SPACE_PRESERVE
0632:             */
0633:            public int getXMLSpace() {
0634:                if (xmlSpace != XML_SPACE_INHERIT) {
0635:                    return xmlSpace;
0636:                } else {
0637:                    ModelNode ancestor = parent;
0638:                    while (ancestor != null) {
0639:                        if (ancestor instanceof  ElementNode) {
0640:                            return ((ElementNode) parent).getXMLSpace();
0641:                        }
0642:                        ancestor = ancestor.parent;
0643:                    }
0644:                    return XML_SPACE_DEFAULT;
0645:                }
0646:            }
0647:
0648:            /**
0649:             * Returns true if the condition at the given index is equal to the input 
0650:             * value.
0651:             */
0652:            final boolean conditionEquals(final int index,
0653:                    final String[] conditionValue) {
0654:                if (conditionValue == null) {
0655:                    return (conditionalAttributes == null)
0656:                            || (conditionalAttributes[index] == null);
0657:                } else {
0658:                    return (conditionalAttributes != null)
0659:                            && (equal(conditionalAttributes[index],
0660:                                    conditionValue));
0661:                }
0662:            }
0663:
0664:            /**
0665:             * The node will only render if the requiredFeatures string
0666:             * evaluates to true. A null value will evaluate to true.
0667:             *
0668:             * @param newRequiredFeatures the set of features required for rendering
0669:             *        this node.
0670:             */
0671:            public void setRequiredFeatures(final String[] newRequiredFeatures) {
0672:                setConditionalAttribute(REQUIRED_FEATURES_INDEX,
0673:                        newRequiredFeatures);
0674:            }
0675:
0676:            /**
0677:             * Sets the new value for the given conditional attribute.
0678:             *
0679:             * @param index the conditional attribute index.
0680:             * @param value the new conditional attribute value.
0681:             */
0682:            void setConditionalAttribute(final int index,
0683:                    final String[] newValue) {
0684:                if (conditionEquals(index, newValue)) {
0685:                    return;
0686:                }
0687:                modifyingNode();
0688:
0689:                if (newValue == null) {
0690:                    if (conditionalAttributes != null) {
0691:                        conditionalAttributes[index] = null;
0692:                    }
0693:                } else {
0694:                    if (conditionalAttributes == null) {
0695:                        conditionalAttributes = new String[CONDITIONAl_ATTRIBUTES_LENGTH][];
0696:                    }
0697:                    conditionalAttributes[index] = newValue;
0698:                }
0699:
0700:                switch (index) {
0701:                case REQUIRED_FEATURES_INDEX: {
0702:                    computeCanRenderRequiredFeaturesBit(newValue);
0703:                    ElementNodeProxy p = firstProxy;
0704:                    while (p != null) {
0705:                        p.computeCanRenderRequiredFeaturesBit(newValue);
0706:                        p = p.nextProxy;
0707:                    }
0708:                }
0709:                    break;
0710:                case REQUIRED_EXTENSIONS_INDEX: {
0711:                    computeCanRenderRequiredExtensionsBit(newValue);
0712:                    ElementNodeProxy p = firstProxy;
0713:                    while (p != null) {
0714:                        p.computeCanRenderRequiredExtensionsBit(newValue);
0715:                        p = p.nextProxy;
0716:                    }
0717:                }
0718:                    break;
0719:                default: {
0720:                    computeCanRenderSystemLanguageBit(newValue);
0721:                    ElementNodeProxy p = firstProxy;
0722:                    while (p != null) {
0723:                        p.computeCanRenderSystemLanguageBit(newValue);
0724:                        p = p.nextProxy;
0725:                    }
0726:                }
0727:                    break;
0728:                }
0729:
0730:                modifiedNode();
0731:            }
0732:
0733:            /**
0734:             * The node will only render if the required feature is 
0735:             * supported by Perseus.
0736:             * 
0737:             * @return the array of features required for this node to 
0738:             *         render.
0739:             * @see #setRequiredFeatures
0740:             */
0741:            public String[] getRequiredFeatures() {
0742:                return getConditionalAttribute(REQUIRED_FEATURES_INDEX);
0743:            }
0744:
0745:            /**
0746:             * Returns the value of the conditional attribute with the given 
0747:             * index.
0748:             *
0749:             * @param index the conditional attribute index.
0750:             * @return the conditional attribute value.
0751:             */
0752:            String[] getConditionalAttribute(final int index) {
0753:                if (conditionalAttributes != null) {
0754:                    return conditionalAttributes[index];
0755:                } else {
0756:                    return null;
0757:                }
0758:            }
0759:
0760:            /**
0761:             * The node will only render if the requiredExtensions string
0762:             * evaluates to true. A null value evaluates to true.
0763:             * 
0764:             * @param newRequiredExtensions the extensions which will be considered
0765:             *        a match for any document required extension.
0766:             * @see #getRequiredExtensions
0767:             */
0768:            public void setRequiredExtensions(
0769:                    final String[] newRequiredExtensions) {
0770:                setConditionalAttribute(REQUIRED_EXTENSIONS_INDEX,
0771:                        newRequiredExtensions);
0772:            }
0773:
0774:            /**
0775:             * The node will only render if the required extension is supported
0776:             * by Perseus.
0777:             *
0778:             * @return the extensions required to render this node
0779:             * @see #setRequiredExtensions
0780:             */
0781:            public String[] getRequiredExtensions() {
0782:                return getConditionalAttribute(REQUIRED_EXTENSIONS_INDEX);
0783:            }
0784:
0785:            /**
0786:             * The node will only render if the Perseus user language matches
0787:             * one of the values in this comma separated list. A null value is 
0788:             * a match.
0789:             *
0790:             * @param newSystemLanguage an array of languages which will be matched
0791:             *        against any document system language value
0792:             */
0793:            public void setSystemLanguage(final String[] newSystemLanguage) {
0794:                setConditionalAttribute(SYSTEM_LANGUAGE_INDEX,
0795:                        newSystemLanguage);
0796:            }
0797:
0798:            /**
0799:             * The node will only render if the Perseus user language matches
0800:             * one of the values in this comma separated list. A null value is a 
0801:             * match.
0802:             * @return the set of system languages.
0803:             * @see #setSystemLanguage
0804:             */
0805:            public String[] getSystemLanguage() {
0806:                return getConditionalAttribute(SYSTEM_LANGUAGE_INDEX);
0807:            }
0808:
0809:            /**
0810:             * @return true if the node needs to be fully loaded before it
0811:             *         can be painted
0812:             */
0813:            public boolean getPaintNeedsLoad() {
0814:                return paintNeedsLoad;
0815:            }
0816:
0817:            /**
0818:             * @param paintNeedsLoad if true, the node can only be painted after its
0819:             *        children have been loaded. This can be used by a renderer
0820:             *        implementing progressive rendering of an SVG document.
0821:             */
0822:            public void setPreferedPaintNeedsLoad(final boolean paintNeedsLoad) {
0823:                this .paintNeedsLoad = paintNeedsLoad;
0824:            }
0825:
0826:            /**
0827:             * @return the namespace URI of the Node. By default, this returns
0828:             * SVGConstants.SVG_NAMESPACE_URI.
0829:             */
0830:            public String getNamespaceURI() {
0831:                return SVGConstants.SVG_NAMESPACE_URI;
0832:            }
0833:
0834:            /**
0835:             * Returns the parent <code>Node</code> of this <code>Node</code>.
0836:             *
0837:             * @return the parent node or null if there is no parent (i.e. if a node has
0838:             * just been created and not yet added to the tree, or if it has been
0839:             * removed from the tree, this is null).
0840:             * @throws SecurityException if the application does not have the necessary
0841:             * privilege rights to access this (SVG) content.
0842:             */
0843:            public Node getParentNode() {
0844:                return (Node) parent;
0845:            }
0846:
0847:            /**
0848:             * Used by <code>DocumentNode</code> to create a new instance from
0849:             * a prototype <code>ElementNode</code>.
0850:             *
0851:             * @param doc the <code>DocumentNode</code> for which a new node is
0852:             *        should be created.
0853:             * @return a new <code>ElementNode</code> for the requested document.
0854:             */
0855:            public abstract ElementNode newInstance(final DocumentNode doc);
0856:
0857:            /**
0858:             * @return the first child element node of this element. <code>null</code>
0859:             * if this element has no child elements.
0860:             */
0861:            public Element getFirstElementChild() {
0862:                return (Element) firstChild;
0863:            }
0864:
0865:            /**
0866:             * @return the next sibling element node of this element. <code>null</code>
0867:             * if this element has no element sibling nodes that come after this one in
0868:             * the document tree.
0869:             */
0870:            public Element getNextElementSibling() {
0871:                // Casting is safe here because ElementNodes can only have ElementNode
0872:                // siblings.
0873:                return (Element) nextSibling;
0874:            }
0875:
0876:            /**
0877:             * @return the previous sibling element node of this element.  null if this
0878:             * element has no element sibling nodes that come before this one in the
0879:             * document tree.
0880:             */
0881:            public Element getPreviousElementSibling() {
0882:                // Casting is safe here because ElementNodes can only have ElementNode
0883:                // siblings.
0884:                return (Element) prevSibling;
0885:            }
0886:
0887:            /** 
0888:             * @return the last child element node of this element. null if this element
0889:             * has no child elements.
0890:             */
0891:            public Element getLastElementChild() {
0892:                return (Element) lastChild;
0893:            }
0894:
0895:            /**
0896:             * @param traitName the name of the trait which the element may support.
0897:             * @return true if this element supports the given trait in one of the
0898:             *         trait accessor methods (such as <code>getTrait</code> or 
0899:             *         <code>setFloatTrait</code>.
0900:             */
0901:            boolean supportsTrait(final String traitName) {
0902:                if (SVGConstants.SVG_ID_ATTRIBUTE == traitName
0903:                        || SVGConstants.SVG_REQUIRED_FEATURES_ATTRIBUTE == traitName
0904:                        || SVGConstants.SVG_REQUIRED_EXTENSIONS_ATTRIBUTE == traitName
0905:                        || SVGConstants.SVG_SYSTEM_LANGUAGE_ATTRIBUTE == traitName) {
0906:                    return true;
0907:                }
0908:
0909:                return false;
0910:            }
0911:
0912:            /**
0913:             * Checks if the input trait name is valid and throws a DOMException 
0914:             * with error code NOT_SUPPORTED_ERR if not.
0915:             *
0916:             * @param name the name whose syntax should be checked.
0917:             * @throws DOMException with error code NOT_SUPPORTED_ERR if the 
0918:             * trait name is syntactically incorrect (e.g., null or containing
0919:             * characters not conforming to the Namespaces in XML specification.
0920:             *
0921:             * @see http://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-NCName
0922:             */
0923:            final void checkNCName(final String name) throws DOMException {
0924:                if (name == null || name.length() == 0) {
0925:                    throw unsupportedTrait(name);
0926:                }
0927:
0928:                // We should really validate that the name has the conforming syntax
0929:                // But this slows down the load time considerably.
0930:                //
0931:                // NCName        ::=  (Letter | '_') (NCNameChar)*
0932:                // NCNameChar 	 ::=  Letter | Digit | '.' | '-' | '_' | CombiningChar 
0933:                //                      | Extender
0934:            }
0935:
0936:            /**
0937:             * @param traitNamespace the namespace of the trait for which a TraitAnim
0938:             *        is requested.
0939:             * @param traitName the trait for which there may be a TraitAnimation.
0940:             * @return the TraitAnim for the requested trait name.
0941:             */
0942:            TraitAnim getSafeTraitAnimNS(final String traitNamespace,
0943:                    final String traitName) {
0944:                TraitAnim traitAnim = getTraitAnimNS(traitNamespace, traitName);
0945:                if (traitAnim == null) {
0946:                    traitAnim = createTraitAnimNS(traitNamespace, traitName);
0947:                }
0948:
0949:                return traitAnim;
0950:            }
0951:
0952:            /**
0953:             * @param traitNamespace the namespace of the trait for which a TraitAnim
0954:             *        is requested.
0955:             * @param traitName the trait for which there may be a TraitAnimation.
0956:             * @return the TraitAnim for the requested trait name.
0957:             */
0958:            TraitAnim getTraitAnimNS(String traitNamespace,
0959:                    final String traitName) {
0960:                if (traitName == null) {
0961:                    throw new NullPointerException();
0962:                }
0963:
0964:                if (traitAnimsNS == null) {
0965:                    return null;
0966:                }
0967:
0968:                if (traitNamespace == null || traitNamespace.length() == 0) {
0969:                    traitNamespace = NULL_NS;
0970:                }
0971:
0972:                Hashtable nsTraitAnims = (Hashtable) traitAnimsNS
0973:                        .get(traitNamespace);
0974:                if (nsTraitAnims != null) {
0975:                    return (TraitAnim) nsTraitAnims.get(traitName);
0976:                }
0977:                return null;
0978:            }
0979:
0980:            /**
0981:             * @return an array of traits that are required by this element.
0982:             */
0983:            public String[] getRequiredTraits() {
0984:                return null;
0985:            }
0986:
0987:            /**
0988:             * @return an array of namespaceURI, localName trait pairs required by
0989:             *         this element.
0990:             */
0991:            public String[][] getRequiredTraitsNS() {
0992:                return null;
0993:            }
0994:
0995:            /**
0996:             * @return an array of trait default values, used if this element
0997:             *         requires that the default trait value be explicitly 
0998:             *         set through a setTrait call. This happens, for example,
0999:             *         with the begin trait value on animation elements.
1000:             */
1001:            public String[][] getDefaultTraits() {
1002:                return null;
1003:            }
1004:
1005:            /**
1006:             * @return an array of trait aliases. These are used when the 
1007:             * value of a trait can be used to set the value of another trait.
1008:             * For example, on a <rect>, if the rx trait is not specified in the 
1009:             * original XML document, the value fot eh ry trait should be used.
1010:             */
1011:            public String[][] getTraitAliases() {
1012:                return null;
1013:            }
1014:
1015:            /**
1016:             * Validates the input trait value.
1017:             *
1018:             * @param namespaceURI the trait's namespace URI.
1019:             * @param traitName the name of the trait to be validated.
1020:             * @param value the value to be validated
1021:             * @param reqNamespaceURI the namespace of the element requesting 
1022:             *        validation.
1023:             * @param reqLocalName the local name of the element requesting validation.
1024:             * @param reqTraitNamespace the namespace of the trait which has the values
1025:             *        value on the requesting element.
1026:             * @param reqTraitName the name of the trait which has the values value on 
1027:             *        the requesting element.
1028:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
1029:             * value is incompatible with the given trait.
1030:             *
1031:             * @return the computed trait value.
1032:             */
1033:            String validateTraitNS(final String namespaceURI,
1034:                    final String traitName, final String value,
1035:                    final String reqNamespaceURI, final String reqLocalName,
1036:                    final String reqTraitNamespace, final String reqTraitName)
1037:                    throws DOMException {
1038:                /* 
1039:                throw new InternalError(
1040:                        "Trying to validate unknown trait: " + 
1041:                        "namespaceURI : " + namespaceURI + "\n" +
1042:                        "traitName : " + traitName + "\n" +
1043:                        "value : " + value + "\n" +
1044:                        "reqNamespaceURI : " + reqNamespaceURI + "\n" +
1045:                        "reqLocalName : " + reqLocalName + "\n" +
1046:                        "reqTraitNamespace : " + reqTraitNamespace + "\n" +
1047:                        "reqTraitName : " + reqTraitName); 
1048:                 */
1049:                return value;
1050:            }
1051:
1052:            /**
1053:             * Validates the input trait value.
1054:             *
1055:             * @param traitName the name of the trait to be validated.
1056:             * @param value the value to be validated
1057:             * @param reqNamespaceURI the namespace of the element requesting 
1058:             *        validation.
1059:             * @param reqLocalName the local name of the element requesting validation.
1060:             * @param reqTraitNamespace the namespace of the trait which has the values
1061:             *        value on the requesting element.
1062:             * @param reqTraitName the name of the trait which has the values value on 
1063:             *        the requesting element.
1064:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
1065:             * value is incompatible with the given trait.
1066:             */
1067:            float[][] validateFloatArrayTrait(final String traitName,
1068:                    final String value, final String reqNamespaceURI,
1069:                    final String reqLocalName, final String reqTraitNamespace,
1070:                    final String reqTraitName) throws DOMException {
1071:                // Throw an error because this should _never_ happen, as a float
1072:                // array anim should only happen on a known trait. If validation is
1073:                // requested, the element implementation should know the trait.
1074:                throw new Error();
1075:            }
1076:
1077:            /**
1078:             * @param namespaceURI the trait's namespace URI.
1079:             * @param traitName the name of the trait which the element may support.
1080:             * @return true if this element supports the given trait in one of the
1081:             *         trait accessor methods.
1082:             */
1083:            boolean supportsTraitNS(final String namespaceURI,
1084:                    final String traitName) {
1085:                if (SVGConstants.PERSEUS_NAMESPACE_URI == namespaceURI
1086:                        && SVGConstants.PERSEUS_CHILDREN_REQUIRED_ATTRIBUTE == traitName) {
1087:                    return true;
1088:                } else if (SVGConstants.XML_NAMESPACE_URI == namespaceURI
1089:                        && (SVGConstants.XML_BASE_ATTRIBUTE_LOCAL_NAME == traitName || SVGConstants.XML_SPACE_ATTRIBUTE_LOCAL_NAME == traitName)) {
1090:                    return true;
1091:                }
1092:
1093:                if (namespaceURI == null) {
1094:                    return supportsTrait(traitName);
1095:                } else {
1096:                    return false;
1097:                }
1098:            }
1099:
1100:            /**
1101:             * The traits supported by default are: externalResourcesRequired,
1102:             * xml:base, xml:space, requiredFeatures, requiredExtensions and 
1103:             * systemLanguage.
1104:             *
1105:             * Returns the trait value as String. In SVG Tiny only certain traits can be
1106:             * obtained as a String value. Syntax of the returned String matches the
1107:             * syntax of the corresponding attribute. This element is exactly equivalent
1108:             * to {@link org.w3c.dom.svg.SVGElement#getTraitNS getTraitNS} with
1109:             * namespaceURI set to null.
1110:             *
1111:             * The method is meant to be overridden by derived classes. The 
1112:             * implementation pattern is that derived classes will override the method 
1113:             * and call their super class' implementation. If the ElementNode 
1114:             * implementation is called, it means that the trait is either not supported
1115:             * or that it cannot be seen as a String.
1116:             *
1117:             * @param name the requested trait name.
1118:             * @return the trait value.
1119:             *
1120:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1121:             * trait is not supported on this element or null.
1122:             * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1123:             * trait's computed value cannot be converted to a String (SVG Tiny only).
1124:             */
1125:            public final String getTrait(String traitName) throws DOMException {
1126:                traitName = intern(traitName);
1127:
1128:                if (!supportsTrait(traitName)) {
1129:                    throw unsupportedTrait(traitName);
1130:                }
1131:
1132:                TraitAnim anim = getTraitAnimNS(NULL_NS, traitName);
1133:                if (anim == null || !anim.active) {
1134:                    return getTraitImpl(traitName);
1135:                }
1136:
1137:                // Get the computed trait value from the trait animation.
1138:                return anim.getTrait(TRAIT_TYPE_STRING);
1139:            }
1140:
1141:            /**
1142:             * Returns the specified trait value as String. In SVG Tiny only certain
1143:             * traits can be obtained as a String value. Syntax of the returned String
1144:             * matches the syntax of the corresponding attribute. This element is
1145:             * exactly equivalent to {@link org.w3c.dom.svg.SVGElement#getTraitNS
1146:             * getTraitNS} with namespaceURI set to null.
1147:             *
1148:             * The method is meant to be overridden by derived classes. The 
1149:             * implementation pattern is that derived classes will override the method 
1150:             * and call their super class' implementation. If the ElementNode 
1151:             * implementation is called, it means that the trait is either not supported
1152:             * or that it cannot be seen as a String.
1153:             *
1154:             * @param traitNamespace the requested trait's namespace.
1155:             * @param traitName the requested trait name.
1156:             * @return the trait value.
1157:             *
1158:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1159:             * trait is not supported on this element or null.
1160:             * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1161:             * trait's computed value cannot be converted to a String (SVG Tiny only).
1162:             */
1163:            String getSpecifiedTraitNSImpl(final String traitNamespace,
1164:                    final String traitName) throws DOMException {
1165:                if (traitNamespace == null || traitNamespace == NULL_NS) {
1166:                    return getSpecifiedTraitImpl(traitName);
1167:                }
1168:
1169:                // Only xml:base behaves differently because the computed value
1170:                // may be different from the specified value.
1171:                if (SVGConstants.XML_NAMESPACE_URI == traitNamespace
1172:                        && SVGConstants.XML_BASE_ATTRIBUTE_LOCAL_NAME == traitName) {
1173:                    return uriBase;
1174:                }
1175:
1176:                return getTraitNSImpl(traitNamespace, traitName);
1177:            }
1178:
1179:            /**
1180:             * Returns the specified trait value as String. In SVG Tiny only certain
1181:             * traits can be obtained as a String value. Syntax of the returned String
1182:             * matches the syntax of the corresponding attribute. This element is
1183:             * exactly equivalent to {@link org.w3c.dom.svg.SVGElement#getTraitNS
1184:             * getTraitNS} with namespaceURI set to null.
1185:             *
1186:             * The method is meant to be overridden by derived classes. The 
1187:             * implementation pattern is that derived classes will override the method 
1188:             * and call their super class' implementation. If the ElementNode 
1189:             * implementation is called, it means that the trait is either not supported
1190:             * or that it cannot be seen as a String.
1191:             *
1192:             * @param traitName the requested trait name.
1193:             * @return the trait value.
1194:             *
1195:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1196:             * trait is not supported on this element or null.
1197:             * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1198:             * trait's computed value cannot be converted to a String (SVG Tiny only).
1199:             */
1200:            String getSpecifiedTraitImpl(final String traitName)
1201:                    throws DOMException {
1202:                return getTraitImpl(traitName);
1203:            }
1204:
1205:            /**
1206:             * The traits supported by default are: externalResourcesRequired,
1207:             * xml:base, xml:space, requiredFeatures, requiredExtensions and 
1208:             * systemLanguage.
1209:             *
1210:             * Returns the trait value as String. In SVG Tiny only certain traits can be
1211:             * obtained as a String value. Syntax of the returned String matches the
1212:             * syntax of the corresponding attribute. This element is exactly equivalent
1213:             * to {@link org.w3c.dom.svg.SVGElement#getTraitNS getTraitNS} with
1214:             * namespaceURI set to null.
1215:             *
1216:             * The method is meant to be overridden by derived classes. The 
1217:             * implementation pattern is that derived classes will override the method 
1218:             * and call their super class' implementation. If the ElementNode 
1219:             * implementation is called, it means that the trait is either not supported
1220:             * or that it cannot be seen as a String.
1221:             *
1222:             * @param name the requested trait name.
1223:             * @return the trait value.
1224:             *
1225:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1226:             * trait is not supported on this element or null.
1227:             * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1228:             * trait's computed value cannot be converted to a String (SVG Tiny only).
1229:             */
1230:            public String getTraitImpl(final String name) throws DOMException {
1231:                if (SVGConstants.SVG_ID_ATTRIBUTE == name) {
1232:                    return getId();
1233:                } else if (SVGConstants.SVG_REQUIRED_FEATURES_ATTRIBUTE == name) {
1234:                    return toStringTrait(getRequiredFeatures(), " ");
1235:                } else if (SVGConstants.SVG_REQUIRED_EXTENSIONS_ATTRIBUTE == name) {
1236:                    return toStringTrait(getRequiredExtensions(), " ");
1237:                } else if (SVGConstants.SVG_SYSTEM_LANGUAGE_ATTRIBUTE == name) {
1238:                    return toStringTrait(getSystemLanguage(), ",");
1239:                } else {
1240:                    if (!supportsTrait(name)) {
1241:                        if (name == null) {
1242:                            throw unsupportedTrait(name);
1243:                        }
1244:
1245:                        String unknownTraitValue = ownerDocument
1246:                                .getUnknownTraitsNS(this , NULL_NS, name);
1247:                        if (unknownTraitValue != null) {
1248:                            return unknownTraitValue;
1249:                        } else {
1250:                            return "";
1251:                        }
1252:                    } else {
1253:                        throw unsupportedTraitType(name, TRAIT_TYPE_STRING);
1254:                    }
1255:                }
1256:            }
1257:
1258:            /**
1259:             * Implementation method.
1260:             *
1261:             * Creates a TraitAnim for the requested trait. This method does not 
1262:             * check whether or not there is an existing TraitAnim for the trait.
1263:             * Instead, it creates a new TraitAnim and associates it with the 
1264:             * given trait. After this call, any call to getSafeTraitAnimNS or
1265:             * getTraitAnimNS will return this new object.
1266:             *
1267:             * @param traitName the trait name.
1268:             * @param traitNamespace the trait's namespace. Should not be null.
1269:             */
1270:            TraitAnim createTraitAnimNS(String traitNamespace,
1271:                    final String traitName) {
1272:                if (traitNamespace == null || traitNamespace.length() == 0) {
1273:                    traitNamespace = NULL_NS;
1274:                }
1275:
1276:                TraitAnim traitAnim = null;
1277:                if (NULL_NS == traitNamespace) {
1278:                    traitAnim = createTraitAnimImpl(traitName);
1279:                } else {
1280:                    traitAnim = createTraitAnimNSImpl(traitNamespace, traitName);
1281:                }
1282:
1283:                if (traitAnimsNS == null) {
1284:                    traitAnimsNS = new Hashtable();
1285:                }
1286:
1287:                Hashtable nsTraitAnims = (Hashtable) traitAnimsNS
1288:                        .get(traitNamespace);
1289:                if (nsTraitAnims == null) {
1290:                    nsTraitAnims = new Hashtable();
1291:                    traitAnimsNS.put(traitNamespace, nsTraitAnims);
1292:                }
1293:
1294:                nsTraitAnims.put(traitName, traitAnim);
1295:                return traitAnim;
1296:            }
1297:
1298:            /**
1299:             * To be overridden by derived classes. Should create the proper 
1300:             * TraitAnim type for the given trait in the anonymous namespace.
1301:             *
1302:             * @param traitName the trait name.
1303:             */
1304:            TraitAnim createTraitAnimImpl(final String traitName) {
1305:                //
1306:                // If the trait is supported but the element did not create
1307:                // a TraitAnim in its implementation of createTraitAnimImpl,
1308:                // it means the trait is not animatable.
1309:                //
1310:                if (supportsTrait(traitName)) {
1311:                    throw notAnimatable(null, traitName);
1312:                }
1313:
1314:                return new StringTraitAnim(this , NULL_NS, traitName);
1315:            }
1316:
1317:            /**
1318:             * To be overridden by derived classes. Should create the proper 
1319:             * TraitAnim type for the given trait in the desired namespace.
1320:             *
1321:             * @param traitName the trait name.
1322:             */
1323:            TraitAnim createTraitAnimNSImpl(final String traitNamespace,
1324:                    final String traitName) {
1325:                //
1326:                // If the trait is supported but the element did not create
1327:                // a TraitAnim in its implementation of createTraitAnimImpl,
1328:                // it means the trait is not animatable.
1329:                //
1330:                if (supportsTraitNS(traitNamespace, traitName)) {
1331:                    throw notAnimatable(traitNamespace, traitName);
1332:                }
1333:
1334:                return new StringTraitAnim(this , traitNamespace, traitName);
1335:            }
1336:
1337:            /**
1338:             * Same as {@link org.w3c.dom.svg.SVGElement#getTrait getTrait}, but for
1339:             * namespaced traits. Parameter name must be a non-qualified trait name,
1340:             * i.e. without prefix.
1341:             *
1342:             * @param namespaceURI the requested trait's namespace.
1343:             * @param name the requested trait's local name (un-prefixed, e.g, 'href')
1344:             *
1345:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1346:             * trait is not supported on this element or null.
1347:             * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1348:             * trait's computed value cannot be converted to a String (SVG Tiny only).
1349:             * @throws SecurityException if the application does not have the necessary
1350:             * privilege rights to access this (SVG) content.
1351:             */
1352:            public final String getTraitNS(String namespaceURI, String name)
1353:                    throws DOMException {
1354:                if (namespaceURI == null) {
1355:                    return getTrait(name);
1356:                }
1357:
1358:                name = intern(name);
1359:                namespaceURI = intern(namespaceURI);
1360:
1361:                if (!supportsTraitNS(namespaceURI, name)) {
1362:                    throw unsupportedTraitNS(name, namespaceURI);
1363:                }
1364:
1365:                StringTraitAnim anim = (StringTraitAnim) getTraitAnimNS(
1366:                        namespaceURI, name);
1367:                if (anim == null || !anim.active) {
1368:                    return getTraitNSImpl(namespaceURI, name);
1369:                }
1370:
1371:                return anim.getTrait(TRAIT_TYPE_STRING);
1372:            }
1373:
1374:            /**
1375:             * Same as {@link org.w3c.dom.svg.SVGElement#getTrait getTrait}, but for
1376:             * namespaced traits. Parameter name must be a non-qualified trait name,
1377:             * i.e. without prefix.
1378:             *
1379:             * @param namespaceURI the requested trait's namespace.
1380:             * @param name the requested trait's local name (un-prefixed, e.g, 'href')
1381:             *
1382:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1383:             * trait is not supported on this element or null.
1384:             * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1385:             * trait's computed value cannot be converted to a String (SVG Tiny only).
1386:             * @throws SecurityException if the application does not have the necessary
1387:             * privilege rights to access this (SVG) content.
1388:             */
1389:            String getTraitNSImpl(String namespaceURI, String name) {
1390:                if (SVGConstants.PERSEUS_NAMESPACE_URI == namespaceURI) {
1391:                    if (SVGConstants.PERSEUS_CHILDREN_REQUIRED_ATTRIBUTE == name) {
1392:                        if (paintNeedsLoad) {
1393:                            return SVGConstants.SVG_TRUE_VALUE;
1394:                        } else {
1395:                            return SVGConstants.SVG_FALSE_VALUE;
1396:                        }
1397:                    }
1398:                } else if (SVGConstants.XML_NAMESPACE_URI == namespaceURI) {
1399:                    if (SVGConstants.XML_BASE_ATTRIBUTE_LOCAL_NAME == name) {
1400:                        return getURIBase();
1401:                    } else if (SVGConstants.XML_SPACE_ATTRIBUTE_LOCAL_NAME == name) {
1402:                        switch (getXMLSpace()) {
1403:                        case XML_SPACE_DEFAULT:
1404:                            return SVGConstants.XML_DEFAULT_VALUE;
1405:                        case XML_SPACE_PRESERVE:
1406:                        default:
1407:                            return SVGConstants.XML_PRESERVE_VALUE;
1408:                        }
1409:                    }
1410:                }
1411:
1412:                if (!supportsTraitNS(namespaceURI, name)) {
1413:                    String unknownTraitValue = ownerDocument
1414:                            .getUnknownTraitsNS(this , namespaceURI, name);
1415:
1416:                    if (unknownTraitValue != null) {
1417:                        return unknownTraitValue;
1418:                    }
1419:
1420:                    return "";
1421:                } else {
1422:                    throw unsupportedTraitTypeNS(name, namespaceURI,
1423:                            TRAIT_TYPE_STRING);
1424:                }
1425:            }
1426:
1427:            /**
1428:             * @param name the requested trait's name.
1429:             * @return the trait value as float.
1430:             *
1431:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1432:             * trait is not supported on this element or null.
1433:             * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1434:             * trait's computed value cannot be converted to a float
1435:             */
1436:            public final float getFloatTrait(String name) throws DOMException {
1437:                name = intern(name);
1438:
1439:                if (!supportsTrait(name)) {
1440:                    throw unsupportedTrait(name);
1441:                }
1442:
1443:                TraitAnim anim = getTraitAnimNS(NULL_NS, name);
1444:                if (anim == null || !anim.active) {
1445:                    return getFloatTraitImpl(name);
1446:                }
1447:
1448:                // Get the computed value from the trait animation.
1449:                return parseFloatTrait(name, anim.getTrait(TRAIT_TYPE_FLOAT));
1450:            }
1451:
1452:            /**
1453:             * @param name the requested trait's name.
1454:             * @return the trait value as float.
1455:             *
1456:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1457:             * trait is not supported on this element or null.
1458:             * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1459:             * trait's computed value cannot be converted to a float
1460:             */
1461:            float getFloatTraitImpl(final String name) {
1462:                throw unsupportedTraitType(name, TRAIT_TYPE_FLOAT);
1463:            }
1464:
1465:            /**
1466:             * Returns the trait value as {@link org.w3c.dom.svg.SVGMatrix SVGMatrix}.
1467:             * The returned object is a copy of the actual trait value and will not
1468:             * change ifthe corresponding trait changes.
1469:             *
1470:             * @param name matrix trait name.
1471:             * @return the trait value corresponding to name as SVGMatrix.
1472:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1473:             * trait is not supported on this element or null.
1474:             * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1475:             * trait's computed value cannot be converted to {@link
1476:             * org.w3c.dom.svg.SVGMatrix SVGMatrix}
1477:             */
1478:            public final SVGMatrix getMatrixTrait(String name)
1479:                    throws DOMException {
1480:                name = intern(name);
1481:
1482:                if (!supportsTrait(name)) {
1483:                    throw unsupportedTrait(name);
1484:                }
1485:
1486:                TraitAnim anim = getTraitAnimNS(NULL_NS, name);
1487:                if (anim == null || !anim.active) {
1488:                    return getMatrixTraitImpl(name);
1489:                }
1490:
1491:                // Get the computed value from the trait animation
1492:                SVGMatrix m = parseTransformTrait(name, anim
1493:                        .getTrait(TRAIT_TYPE_SVG_MATRIX));
1494:
1495:                if (m == null) {
1496:                    m = new Transform(1, 0, 0, 1, 0, 0);
1497:                }
1498:
1499:                return m;
1500:            }
1501:
1502:            /**
1503:             * Returns the trait value as {@link org.w3c.dom.svg.SVGMatrix SVGMatrix}.
1504:             * The returned object is a copy of the actual trait value and will not
1505:             * change ifthe corresponding trait changes.
1506:             *
1507:             * @param name matrix trait name.
1508:             * @return the trait value corresponding to name as SVGMatrix.
1509:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1510:             * trait is not supported on this element or null.
1511:             * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1512:             * trait's computed value cannot be converted to {@link
1513:             * org.w3c.dom.svg.SVGMatrix SVGMatrix}
1514:             */
1515:            SVGMatrix getMatrixTraitImpl(final String name) throws DOMException {
1516:                throw unsupportedTraitType(name, TRAIT_TYPE_SVG_MATRIX);
1517:            }
1518:
1519:            /**
1520:             * @param name the trait's name.
1521:             * @return the trait value as {@link org.w3c.dom.svg.SVGRect SVGRect}. The
1522:             * returned object is a copy of the actual trait value and will not change
1523:             * if the corresponding trait changes.
1524:             *
1525:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1526:             * trait is not supported on this element or null.
1527:             * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1528:             * trait's computed value cannot be converted to {@link
1529:             * org.w3c.dom.svg.SVGRect SVGRect}
1530:             */
1531:            public final SVGRect getRectTrait(String name) throws DOMException {
1532:                name = intern(name);
1533:
1534:                if (!supportsTrait(name)) {
1535:                    throw unsupportedTrait(name);
1536:                }
1537:
1538:                TraitAnim anim = getTraitAnimNS(NULL_NS, name);
1539:                if (anim == null || !anim.active) {
1540:                    return getRectTraitImpl(name);
1541:                }
1542:
1543:                // Get the computed value from the trait animation.
1544:                return toSVGRect(toViewBox(name, anim
1545:                        .getTrait(TRAIT_TYPE_SVG_RECT)));
1546:            }
1547:
1548:            /**
1549:             * @param name the trait's name.
1550:             * @return the trait value as {@link org.w3c.dom.svg.SVGRect SVGRect}. The
1551:             * returned object is a copy of the actual trait value and will not change
1552:             * if the corresponding trait changes.
1553:             *
1554:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1555:             * trait is not supported on this element or null.
1556:             * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1557:             * trait's computed value cannot be converted to {@link
1558:             * org.w3c.dom.svg.SVGRect SVGRect}
1559:             */
1560:            SVGRect getRectTraitImpl(final String name) throws DOMException {
1561:                throw unsupportedTraitType(name, TRAIT_TYPE_SVG_RECT);
1562:            }
1563:
1564:            /**
1565:             * Returns the trait value as {@link org.w3c.dom.svg.SVGPath SVGPath}. The
1566:             * returned object is a copy of the actual trait value and will not change
1567:             * if the corresponding trait changes.
1568:             *
1569:             * @param name the trait's name.
1570:             * @return the trait's value, as an <code>SVGPath</code> object.
1571:             *
1572:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1573:             * trait is not supported on this element or null.
1574:             * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1575:             * trait's computed value cannot be converted to {@link
1576:             * org.w3c.dom.svg.SVGPath SVGPath}
1577:             */
1578:            public final SVGPath getPathTrait(String name) throws DOMException {
1579:                name = intern(name);
1580:
1581:                if (!supportsTrait(name)) {
1582:                    throw unsupportedTrait(name);
1583:                }
1584:
1585:                TraitAnim anim = getTraitAnimNS(NULL_NS, name);
1586:                if (anim == null || !anim.active) {
1587:                    return getPathTraitImpl(name);
1588:                }
1589:
1590:                // Get the computed value from the trait animation.
1591:                return parsePathTrait(name, anim.getTrait(TRAIT_TYPE_SVG_PATH));
1592:            }
1593:
1594:            /**
1595:             * Returns the trait value as {@link org.w3c.dom.svg.SVGPath SVGPath}. The
1596:             * returned object is a copy of the actual trait value and will not change
1597:             * if the corresponding trait changes.
1598:             *
1599:             * @param name the trait's name.
1600:             * @return the trait's value, as an <code>SVGPath</code> object.
1601:             *
1602:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1603:             * trait is not supported on this element or null.
1604:             * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1605:             * trait's computed value cannot be converted to {@link
1606:             * org.w3c.dom.svg.SVGPath SVGPath}
1607:             */
1608:            SVGPath getPathTraitImpl(final String name) throws DOMException {
1609:                throw unsupportedTraitType(name, TRAIT_TYPE_SVG_PATH);
1610:            }
1611:
1612:            /**
1613:             * Returns the trait value as {@link org.w3c.dom.svg.SVGRGBColor
1614:             * SVGRGBColor}. The returned object is a copy of the trait value and will
1615:             * not change if the corresponding trait changes. If the actual trait value
1616:             * is not an RGBColor (i.e. "none"), this method will return null.
1617:             *
1618:             * @param name the requested trait name.
1619:             * @return the trait value, as an <code>SVGRGBColor</code> object.
1620:             *
1621:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1622:             * trait is not supported on this element or null.
1623:             * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1624:             * trait's computed value cannot be converted to {@link
1625:             * org.w3c.dom.svg.SVGRGBColor SVGRGBColor}
1626:             */
1627:            public final SVGRGBColor getRGBColorTrait(String name)
1628:                    throws DOMException {
1629:                name = intern(name);
1630:
1631:                if (!supportsTrait(name)) {
1632:                    throw unsupportedTrait(name);
1633:                }
1634:
1635:                TraitAnim anim = getTraitAnimNS(NULL_NS, name);
1636:                if (anim == null || !anim.active) {
1637:                    return getRGBColorTraitImpl(name);
1638:                }
1639:
1640:                // Get the computed value from the trait animation
1641:                return toSVGRGBColor(name, parseColorTrait(name, anim
1642:                        .getTrait(TRAIT_TYPE_SVG_RGB_COLOR)));
1643:            }
1644:
1645:            /**
1646:             * Returns the trait value as {@link org.w3c.dom.svg.SVGRGBColor
1647:             * SVGRGBColor}. The returned object is a copy of the trait value and will
1648:             * not change if the corresponding trait changes. If the actual trait value
1649:             * is not an RGBColor (i.e. "none"), this method will return null.
1650:             *
1651:             * @param name the requested trait name.
1652:             * @return the trait value, as an <code>SVGRGBColor</code> object.
1653:             *
1654:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1655:             * trait is not supported on this element or null.
1656:             * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1657:             * trait's computed value cannot be converted to {@link
1658:             * org.w3c.dom.svg.SVGRGBColor SVGRGBColor}
1659:             */
1660:            SVGRGBColor getRGBColorTraitImpl(final String name)
1661:                    throws DOMException {
1662:                throw unsupportedTraitType(name, TRAIT_TYPE_SVG_RGB_COLOR);
1663:            }
1664:
1665:            /**
1666:             * Adds a new attribute. 
1667:             *
1668:             * @param name - the name of the attribute to add.
1669:             * @param value - the value to set.
1670:             * @throws DOMException INVALID_CHARACTER_ERR: Raised if the specified name
1671:             * contains an illegal character.  NO_MODIFICATION_ALLOWED_ERR: Raised if
1672:             * this node is readonly.
1673:             */
1674:            public final void setAttribute(String name, String value)
1675:                    throws DOMException {
1676:                checkNCName(name);
1677:
1678:                if (value == null) {
1679:                    throw illegalTraitValue(name, value);
1680:                }
1681:
1682:                name = name.intern();
1683:                setTraitImpl(name, value);
1684:            }
1685:
1686:            /**
1687:             * Returns the requested attribute. 
1688:             *
1689:             * @param name - the name of the attribute to add.
1690:             * @return the attribute value or empty string if the attribute is not 
1691:             *         specified.
1692:             * @throws DOMException INVALID_CHARACTER_ERR: Raised if the specified name
1693:             *         contains an illegal character.  
1694:             */
1695:            public final String getAttribute(String name) throws DOMException {
1696:                checkNCName(name);
1697:
1698:                name = name.intern();
1699:                return getTraitImpl(name);
1700:            }
1701:
1702:            /**
1703:             * The traits supported by default are: externalResourcesRequired,
1704:             * xml:base, xml:space, requiredFeatures, requiredExtensions and 
1705:             * systemLanguage.
1706:             *
1707:             * @param name the trait's name.
1708:             * @param value the trait's value.
1709:             *
1710:             * @throws DOMException with error code NOT_SUPPORTED_ERR if the requested
1711:             * trait is not supported on this element or null.
1712:             * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
1713:             * trait's value cannot be specified as a String
1714:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
1715:             * value is an invalid value for the given trait or null.
1716:             * @throws DOMException with error code NO_MODIFICATION_ALLOWED_ERR: if
1717:             * attempt is made to change readonly trait.
1718:             */
1719:            public final void setTrait(String name, String value)
1720:                    throws DOMException {
1721:                name = intern(name);
1722:
1723:                if (!supportsTrait(name)) {
1724:                    throw unsupportedTrait(name);
1725:                }
1726:
1727:                if (value == null) {
1728:                    throw illegalTraitValue(name, value);
1729:                }
1730:
1731:                TraitAnim anim = (TraitAnim) getTraitAnimNS(NULL_NS, name);
1732:
1733:                if (anim == null || !anim.active) {
1734:                    setTraitImpl(name, value);
1735:                } else {
1736:                    anim.setTrait(value, TRAIT_TYPE_STRING);
1737:                }
1738:            }
1739:
1740:            /**
1741:             * The traits supported by default are: externalResourcesRequired,
1742:             * xml:base, xml:space, requiredFeatures, requiredExtensions and 
1743:             * systemLanguage.
1744:             *
1745:             * @param name the trait's name.
1746:             * @param value the trait's value.
1747:             *
1748:             * @throws DOMException with error code NOT_SUPPORTED_ERR if the requested
1749:             * trait is not supported on this element or null.
1750:             * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
1751:             * trait's value cannot be specified as a String
1752:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
1753:             * value is an invalid value for the given trait or null.
1754:             * @throws DOMException with error code NO_MODIFICATION_ALLOWED_ERR: if
1755:             * attempt is made to change readonly trait.
1756:             */
1757:            public void setTraitImpl(final String name, final String value)
1758:                    throws DOMException {
1759:                if (SVGConstants.SVG_ID_ATTRIBUTE == name) {
1760:                    try {
1761:                        setId(value);
1762:                    } catch (IllegalArgumentException iae) {
1763:                        iae.printStackTrace();
1764:                        throw illegalTraitValue(name, value);
1765:                    }
1766:                } else if (SVGConstants.SVG_REQUIRED_FEATURES_ATTRIBUTE == name) {
1767:                    if (value == null) {
1768:                        throw illegalTraitValue(name, value);
1769:                    }
1770:                    setRequiredFeatures(parseStringArrayTrait(name, value, " "));
1771:                } else if (SVGConstants.SVG_REQUIRED_EXTENSIONS_ATTRIBUTE == name) {
1772:                    if (value == null) {
1773:                        throw illegalTraitValue(name, value);
1774:                    }
1775:                    setRequiredExtensions(parseStringArrayTrait(name, value,
1776:                            " "));
1777:                } else if (SVGConstants.SVG_SYSTEM_LANGUAGE_ATTRIBUTE == name) {
1778:                    if (value == null) {
1779:                        throw illegalTraitValue(name, value);
1780:                    }
1781:                    setSystemLanguage(parseStringArrayTrait(name, value, ","));
1782:                } else {
1783:                    // The trait is not handled by this element as a string.
1784:                    // There are two situations. If this trait is supported 
1785:                    // by the element, then it means that the String type is 
1786:                    // not supported for the trait, and the following throws an
1787:                    // exception. Otherwise, this means the trait is just unknown,
1788:                    // and it goes into the generic trait map.
1789:                    if (supportsTrait(name)) {
1790:                        throw unsupportedTraitType(name, TRAIT_TYPE_STRING);
1791:                    } else {
1792:                        if (name == null) {
1793:                            throw unsupportedTrait(name);
1794:                        }
1795:
1796:                        if (value == null) {
1797:                            throw illegalTraitValue(name, value);
1798:                        }
1799:
1800:                        ownerDocument.setUnknownTraitsNS(this , NULL_NS, name,
1801:                                value);
1802:                    }
1803:                }
1804:            }
1805:
1806:            /**
1807:             * Adds a new attribute. 
1808:             * 
1809:             * @param namespaceURI - the namespace URI of the attribute to create or 
1810:             *        alter.
1811:             * @param name - the local name of the attribute to create or alter.
1812:             * @param value - the value to set in string form.
1813:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
1814:             *         value is an invalid value for the given trait or null.
1815:             * @throws DOMException with error code NO_MODIFICATION_ALLOWED_ERR: if
1816:             *         attempt is made to change readonly trait.
1817:             */
1818:            public final void setAttributeNS(String namespaceURI, String name,
1819:                    String value) throws DOMException {
1820:                if (namespaceURI == null || namespaceURI.length() == 0) {
1821:                    setAttribute(name, value);
1822:                    return;
1823:                }
1824:
1825:                checkNCName(name);
1826:
1827:                if (value == null) {
1828:                    throw illegalTraitValue(name, namespaceURI, value);
1829:                }
1830:
1831:                namespaceURI = namespaceURI.intern();
1832:                name = name.intern();
1833:
1834:                setTraitNSImpl(namespaceURI, name, value);
1835:            }
1836:
1837:            /**
1838:             * Returns the requested attribute in the specified namespace.
1839:             * 
1840:             * @param namespaceURI - the namespace URI of the attribute to create or 
1841:             *        alter.
1842:             * @param name - the local name of the attribute to create or alter.
1843:             * @return the attribute value as a string, or the empty string if the 
1844:             *         attribute was not specified.
1845:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
1846:             *         value is an invalid value for the given trait or null.
1847:             */
1848:            public final String getAttributeNS(String namespaceURI, String name)
1849:                    throws DOMException {
1850:                if (namespaceURI == null || namespaceURI.length() == 0) {
1851:                    return getAttribute(name);
1852:                }
1853:
1854:                checkNCName(name);
1855:
1856:                namespaceURI = namespaceURI.intern();
1857:                name = name.intern();
1858:
1859:                return getTraitNSImpl(namespaceURI, name);
1860:            }
1861:
1862:            /*
1863:             * Same as {@link org.w3c.dom.svg.SVGElement#setTrait setTrait}, but for
1864:             * namespaced traits. Parameter name must be a non-qualified trait name,
1865:             * i.e. without prefix.
1866:             *
1867:             * @param namespaceURI the trait's namespace.
1868:             * @param name the trait's local name (un-prefixed).
1869:             * @param value the trait's value.
1870:             *
1871:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1872:             * trait is not supported on this element or null.
1873:             * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
1874:             * trait's value cannot be specified as a String
1875:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
1876:             * value is an invalid value for the given trait or null.
1877:             * @throws DOMException with error code NO_MODIFICATION_ALLOWED_ERR: if
1878:             * attempt is made to change readonly trait.
1879:             */
1880:
1881:            public final void setTraitNS(String namespaceURI, String name,
1882:                    String value) throws DOMException {
1883:                if (namespaceURI == null || namespaceURI.length() == 0) {
1884:                    setTrait(name, value);
1885:                    return;
1886:                }
1887:
1888:                namespaceURI = intern(namespaceURI);
1889:                name = intern(name);
1890:
1891:                if (!supportsTraitNS(namespaceURI, name)) {
1892:                    throw unsupportedTraitNS(name, namespaceURI);
1893:                }
1894:
1895:                StringTraitAnim anim = (StringTraitAnim) getTraitAnimNS(
1896:                        namespaceURI, name);
1897:
1898:                if (anim == null || !anim.active) {
1899:                    setTraitNSImpl(namespaceURI, name, value);
1900:                } else {
1901:                    anim.setTrait(value, TRAIT_TYPE_STRING);
1902:                }
1903:            }
1904:
1905:            /**
1906:             * Same as {@link org.w3c.dom.svg.SVGElement#setTrait setTrait}, but for
1907:             * namespaced traits. Parameter name must be a non-qualified trait name,
1908:             * i.e. without prefix.
1909:             *
1910:             * @param namespaceURI the trait's namespace.
1911:             * @param name the trait's local name (un-prefixed).
1912:             * @param value the trait's value.
1913:             *
1914:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1915:             * trait is not supported on this element or null.
1916:             * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
1917:             * trait's value cannot be specified as a String
1918:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
1919:             * value is an invalid value for the given trait or null.
1920:             * @throws DOMException with error code NO_MODIFICATION_ALLOWED_ERR: if
1921:             * attempt is made to change readonly trait.
1922:             */
1923:            public void setTraitNSImpl(final String namespaceURI,
1924:                    final String name, final String value) throws DOMException {
1925:                if (SVGConstants.PERSEUS_NAMESPACE_URI == namespaceURI) {
1926:                    if (SVGConstants.PERSEUS_CHILDREN_REQUIRED_ATTRIBUTE == name) {
1927:                        if (SVGConstants.SVG_TRUE_VALUE.equals(value)) {
1928:                            setPreferedPaintNeedsLoad(true);
1929:                            return;
1930:                        } else if (SVGConstants.SVG_FALSE_VALUE.equals(value)) {
1931:                            setPreferedPaintNeedsLoad(false);
1932:                            return;
1933:                        } else {
1934:                            throw illegalTraitValue(namespaceURI, name, value);
1935:                        }
1936:                    }
1937:                } else if (SVGConstants.XML_NAMESPACE_URI == namespaceURI) {
1938:                    if (SVGConstants.XML_BASE_ATTRIBUTE_LOCAL_NAME == name) {
1939:                        if (value == null) {
1940:                            throw illegalTraitValue(name, value);
1941:                        }
1942:                        setURIBase(value);
1943:                    } else if (SVGConstants.XML_SPACE_ATTRIBUTE_LOCAL_NAME == name) {
1944:                        if (SVGConstants.XML_DEFAULT_VALUE.equals(value)
1945:                                || (value != null && value.length() == 0)) {
1946:                            setXMLSpace(XML_SPACE_DEFAULT);
1947:                            return;
1948:                        } else if (SVGConstants.XML_PRESERVE_VALUE
1949:                                .equals(value)) {
1950:                            setXMLSpace(XML_SPACE_PRESERVE);
1951:                            return;
1952:                        } else {
1953:                            throw illegalTraitValue(name, value);
1954:                        }
1955:                    }
1956:                }
1957:
1958:                // The trait is not handled by this element as a string.
1959:                // There are two situations. If this trait is supported 
1960:                // by the element, then it means that the String type is 
1961:                // not supported for the trait which should never happen
1962:                // because all traits have to be supported as a string.
1963:                // So that causes an internal error.
1964:                // Otherwise, this means the trait is just unknown,
1965:                // and it goes into the generic trait map.
1966:                if (supportsTraitNS(name, value)) {
1967:                    throw new Error();
1968:                }
1969:
1970:                // Trait is unknown, treat as a generic string trait.
1971:                ownerDocument.setUnknownTraitsNS(this , namespaceURI, name,
1972:                        value);
1973:            }
1974:
1975:            /**
1976:             * Set the trait value as float.
1977:             *
1978:             * @param name the trait's name.
1979:             * @param value the trait's value.
1980:             *
1981:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1982:             * trait is not supported on this element.
1983:             * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
1984:             * trait's value cannot be specified as a float
1985:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
1986:             * value is an invalid value for the given trait.
1987:             */
1988:            public final void setFloatTrait(String name, float value)
1989:                    throws DOMException {
1990:                name = intern(name);
1991:
1992:                if (!supportsTrait(name)) {
1993:                    throw unsupportedTrait(name);
1994:                }
1995:
1996:                TraitAnim anim = (TraitAnim) getTraitAnimNS(NULL_NS, name);
1997:                if (anim == null || !anim.active) {
1998:                    setFloatTraitImpl(name, value);
1999:                } else {
2000:                    anim.setTrait(Float.toString(value), TRAIT_TYPE_FLOAT);
2001:                }
2002:            }
2003:
2004:            /**
2005:             * Converts the input float array value to a String value.
2006:             *
2007:             * @param traitName the name of the trait to convert.
2008:             * @param value the float trait value to convert.
2009:             */
2010:            String toStringTrait(final String traitName, final float[][] value) {
2011:                throw new Error(traitName);
2012:            }
2013:
2014:            /**
2015:             * Conversts the input PaintServer value to a String trait value.
2016:             *
2017:             * @param value the PaintServer value to convert.
2018:             */
2019:            String toString(final PaintServer paintServer) {
2020:                if (paintServer == null) {
2021:                    return SVGConstants.CSS_NONE_VALUE;
2022:                }
2023:
2024:                return paintServer.toString();
2025:            }
2026:
2027:            /**
2028:             * Set the trait value as float.
2029:             *
2030:             * @param name the trait's name.
2031:             * @param value the trait's value.
2032:             *
2033:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
2034:             * trait is not supported on this element.
2035:             * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
2036:             * trait's value cannot be specified as a float
2037:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2038:             * value is an invalid value for the given trait.
2039:             */
2040:            void setFloatArrayTrait(final String name, final float[][] value)
2041:                    throws DOMException {
2042:                throw new Error(name);
2043:            }
2044:
2045:            /**
2046:             * Set the trait value as a float.
2047:             * 
2048:             * @param name the trait's name.
2049:             * @param value the trait's value.
2050:             *
2051:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
2052:             * trait is not supported on this element.
2053:             * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
2054:             * trait's value cannot be specified as a float
2055:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2056:             * value is an invalid value for the given trait.
2057:             */
2058:            void setFloatTraitImpl(final String name, final float value) {
2059:                throw unsupportedTraitType(name, TRAIT_TYPE_FLOAT);
2060:            }
2061:
2062:            /**
2063:             * Set the trait value as {@link org.w3c.dom.svg.SVGMatrix SVGMatrix}.
2064:             * Values in SVGMarix are copied in the trait so subsequent changes to the
2065:             * givenSVGMatrix have no effect on the value of the trait.
2066:             *
2067:             * @param name name of trait to set
2068:             * @param matrix SVGMatrix value of trait
2069:             *
2070:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
2071:             * trait is not supported on this element or null.
2072:             * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
2073:             * trait's value cannot be specified as an {@link org.w3c.dom.svg.SVGMatrix
2074:             * SVGMatrix}
2075:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2076:             * value is an invalid value for the given trait or null.
2077:             * @throws DOMException with error code NO_MODIFICATION_ALLOWED_ERR: if
2078:             * attempt is made to change readonly trait.
2079:             */
2080:            public final void setMatrixTrait(String name, final SVGMatrix matrix)
2081:                    throws DOMException {
2082:                name = intern(name);
2083:
2084:                if (!supportsTrait(name)) {
2085:                    throw unsupportedTrait(name);
2086:                }
2087:
2088:                if (matrix == null) {
2089:                    throw illegalTraitValue(name, null);
2090:                }
2091:
2092:                TraitAnim anim = (TraitAnim) getTraitAnimNS(NULL_NS, name);
2093:                if (anim == null || !anim.active) {
2094:                    setMatrixTraitImpl(name, new Transform(matrix));
2095:                } else {
2096:                    anim.setTrait(toStringTrait((Transform) matrix),
2097:                            TRAIT_TYPE_SVG_MATRIX);
2098:                }
2099:            }
2100:
2101:            /**
2102:             * Set the trait value as {@link org.w3c.dom.svg.SVGMatrix SVGMatrix}.
2103:             * Values in SVGMarix are copied in the trait so subsequent changes to the
2104:             * givenSVGMatrix have no effect on the value of the trait.
2105:             *
2106:             * @param name name of trait to set
2107:             * @param matrix Transform value of trait
2108:             *
2109:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
2110:             * trait is not supported on this element or null.
2111:             * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
2112:             * trait's value cannot be specified as an {@link org.w3c.dom.svg.SVGMatrix
2113:             * SVGMatrix}
2114:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2115:             * value is an invalid value for the given trait or null.
2116:             * @throws DOMException with error code NO_MODIFICATION_ALLOWED_ERR: if
2117:             * attempt is made to change readonly trait.
2118:             */
2119:            void setMatrixTraitImpl(final String name, final Transform matrix)
2120:                    throws DOMException {
2121:                throw unsupportedTraitType(name, TRAIT_TYPE_SVG_MATRIX);
2122:            }
2123:
2124:            /**
2125:             * Set the trait value as {@link org.w3c.dom.svg.SVGRect SVGRect}. Values in
2126:             * SVGRect are copied in the trait so subsequent changes to the given
2127:             * SVGRect have no effect on the value of the trait.
2128:             *
2129:             * @param name the trait name.
2130:             * @param rect the trait value, as an <code>SVGRect</code> object.
2131:             *
2132:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
2133:             * trait is not supported on this element or null.
2134:             * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
2135:             * trait's value cannot be specified as an {@link org.w3c.dom.svg.SVGRect
2136:             * SVGRect}
2137:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2138:             * value is an invalid value for the given trait or null.  SVGRect is
2139:             * invalid if the width or height values are set to negative.
2140:             */
2141:            public final void setRectTrait(String name, final SVGRect rect)
2142:                    throws DOMException {
2143:                name = intern(name);
2144:
2145:                if (!supportsTrait(name)) {
2146:                    throw unsupportedTrait(name);
2147:                }
2148:
2149:                TraitAnim anim = (TraitAnim) getTraitAnimNS(NULL_NS, name);
2150:                if (anim == null || !anim.active) {
2151:                    setRectTraitImpl(name, rect);
2152:                } else {
2153:                    if (rect == null) {
2154:                        throw illegalTraitValue(name, null);
2155:                    }
2156:
2157:                    float[] vb = { rect.getX(), rect.getY(), rect.getWidth(),
2158:                            rect.getHeight() };
2159:
2160:                    anim.setTrait(toStringTrait(vb), TRAIT_TYPE_SVG_RECT);
2161:                }
2162:            }
2163:
2164:            /**
2165:             * Set the trait value as {@link org.w3c.dom.svg.SVGRect SVGRect}. Values in
2166:             * SVGRect are copied in the trait so subsequent changes to the given
2167:             * SVGRect have no effect on the value of the trait.
2168:             *
2169:             * @param name the trait name.
2170:             * @param rect the trait value, as an <code>SVGRect</code> object.
2171:             *
2172:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
2173:             * trait is not supported on this element or null.
2174:             * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
2175:             * trait's value cannot be specified as an {@link org.w3c.dom.svg.SVGRect
2176:             * SVGRect}
2177:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2178:             * value is an invalid value for the given trait or null.  SVGRect is
2179:             * invalid if the width or height values are set to negative.
2180:             */
2181:            public void setRectTraitImpl(final String name, final SVGRect rect)
2182:                    throws DOMException {
2183:                throw unsupportedTraitType(name, TRAIT_TYPE_SVG_RECT);
2184:            }
2185:
2186:            /**
2187:             * Set the trait value as {@link org.w3c.dom.svg.SVGPath SVGPath}. Values in
2188:             * SVGPath are copied in the trait so subsequent changes to the given
2189:             * SVGPath have no effect on the value of the trait.
2190:             *
2191:             * @param name the trait name.
2192:             * @param path the trait value, as an <code>SVGPath</code> object.
2193:             *
2194:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
2195:             * trait is not supported on this element or null.
2196:             * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
2197:             * trait's value cannot be specified as an {@link org.w3c.dom.svg.SVGPath
2198:             * SVGPath}
2199:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2200:             * value is an invalid value for the given trait or null.  SVGPath is
2201:             * invalid if it does not begin with a MOVE_TO segment.
2202:             */
2203:            public final void setPathTrait(String name, final SVGPath path)
2204:                    throws DOMException {
2205:                name = intern(name);
2206:
2207:                if (!supportsTrait(name)) {
2208:                    throw unsupportedTrait(name);
2209:                }
2210:
2211:                if (path == null) {
2212:                    throw illegalTraitValue(name, null);
2213:                }
2214:
2215:                TraitAnim anim = (TraitAnim) getTraitAnimNS(NULL_NS, name);
2216:                if (anim == null || !anim.active) {
2217:                    setPathTraitImpl(name, path);
2218:                } else {
2219:                    if (path == null) {
2220:                        throw illegalTraitValue(name, null);
2221:                    }
2222:                    anim
2223:                            .setTrait(((Path) path).toString(),
2224:                                    TRAIT_TYPE_SVG_PATH);
2225:                }
2226:            }
2227:
2228:            /**
2229:             * Set the trait value as {@link org.w3c.dom.svg.SVGPath SVGPath}. Values in
2230:             * SVGPath are copied in the trait so subsequent changes to the given
2231:             * SVGPath have no effect on the value of the trait.
2232:             *
2233:             * @param name the trait name.
2234:             * @param path the trait value, as an <code>SVGPath</code> object.
2235:             *
2236:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
2237:             * trait is not supported on this element or null.
2238:             * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
2239:             * trait's value cannot be specified as an {@link org.w3c.dom.svg.SVGPath
2240:             * SVGPath}
2241:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2242:             * value is an invalid value for the given trait or null.  SVGPath is
2243:             * invalid if it does not begin with a MOVE_TO segment.
2244:             */
2245:            void setPathTraitImpl(final String name, final SVGPath path)
2246:                    throws DOMException {
2247:                throw unsupportedTraitType(name, TRAIT_TYPE_SVG_PATH);
2248:            }
2249:
2250:            /**
2251:             * Set the trait value as {@link org.w3c.dom.svg.SVGRGBColor SVGRGBColor}.
2252:             *
2253:             * @param name the trait name.
2254:             * @param color the trait value, as a color.
2255:             *
2256:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
2257:             * trait is not supported on this element or null.
2258:             * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
2259:             * trait's value cannot be specified as an {@link
2260:             * org.w3c.dom.svg.SVGRGBColor SVGRGBColor}
2261:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2262:             * value is null.
2263:             */
2264:            public final void setRGBColorTrait(String name,
2265:                    final SVGRGBColor color) throws DOMException {
2266:                name = intern(name);
2267:
2268:                if (!supportsTrait(name)) {
2269:                    throw unsupportedTrait(name);
2270:                }
2271:
2272:                if (color == null) {
2273:                    throw illegalTraitValue(name, null);
2274:                }
2275:
2276:                TraitAnim anim = (TraitAnim) getTraitAnimNS(NULL_NS, name);
2277:                if (anim == null || !anim.active) {
2278:                    setRGBColorTraitImpl(name, color);
2279:                } else {
2280:                    anim.setTrait(color.toString(), TRAIT_TYPE_SVG_RGB_COLOR);
2281:                }
2282:
2283:            }
2284:
2285:            /**
2286:             * Set the trait value as {@link org.w3c.dom.svg.SVGRGBColor SVGRGBColor}.
2287:             *
2288:             * @param name the trait name.
2289:             * @param color the trait value, as a color.
2290:             *
2291:             * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
2292:             * trait is not supported on this element or null.
2293:             * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
2294:             * trait's value cannot be specified as an {@link
2295:             * org.w3c.dom.svg.SVGRGBColor SVGRGBColor}
2296:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2297:             * value is null.
2298:             */
2299:            void setRGBColorTraitImpl(final String name, final SVGRGBColor color)
2300:                    throws DOMException {
2301:                throw unsupportedTraitType(name, TRAIT_TYPE_SVG_RGB_COLOR);
2302:            }
2303:
2304:            /**
2305:             * Parses the input value and converts it to a String array.
2306:             *
2307:             * @param value the value to convert to a String array
2308:             * @param name the name of the trait being converted.
2309:             * @param seperators the string of characters which are seperators 
2310:             *        between array values.
2311:             */
2312:            protected final String[] parseStringArrayTrait(final String name,
2313:                    final String value, final String seperators)
2314:                    throws DOMException {
2315:                // Don't accept null trait values.
2316:                if (value == null) {
2317:                    throw illegalTraitValue(name, value);
2318:                }
2319:
2320:                SimpleTokenizer st = new SimpleTokenizer(value, seperators);
2321:                int n = st.countTokens();
2322:                String[] result = new String[n];
2323:                for (int i = 0; i < n; i++) {
2324:                    result[i] = st.nextToken().trim().intern();
2325:                }
2326:
2327:                return result;
2328:            }
2329:
2330:            /**
2331:             * Parses the input value and converts it to a float value.
2332:             *
2333:             * @param name the name of the trait to convert to a float.
2334:             * @param value the value to convert to a float.
2335:             * @return the value converted to a float value.
2336:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2337:             * value is an invalid float value or null.
2338:             */
2339:            protected final float parseFloatTrait(final String name,
2340:                    final String value) throws DOMException {
2341:                try {
2342:                    return ownerDocument.lengthParser.parseNumber(value);
2343:                } catch (IllegalArgumentException iae) {
2344:                    throw illegalTraitValue(name, value);
2345:                }
2346:            }
2347:
2348:            /**
2349:             * Parses the input value and converts it to a float array value.
2350:             *
2351:             * @param name the name of the trait to convert to a float array.
2352:             * @param value the value to convert to a float.
2353:             * @return the value converted to a float array value.
2354:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2355:             * value is an invalid float value or null.
2356:             */
2357:            protected final float[] parsePositiveFloatArrayTrait(
2358:                    final String name, final String value) throws DOMException {
2359:                try {
2360:                    SimpleTokenizer st = new SimpleTokenizer(value, ", ");
2361:                    float[] da = null;
2362:                    int n = st.countTokens();
2363:                    float totalLength = 0;
2364:
2365:                    if ((n % 2) == 0) {
2366:                        da = new float[n];
2367:                        for (int i = 0; i < da.length; i++) {
2368:                            da[i] = ownerDocument.lengthParser.parseNumber(st
2369:                                    .nextToken());
2370:
2371:                            if (Float.isNaN(da[i]) || da[i] < 0) {
2372:                                // The CSS number was invalid. 
2373:                                // Do not set the value
2374:                                throw new IllegalArgumentException();
2375:                            }
2376:
2377:                            totalLength += da[i];
2378:                        }
2379:                    } else {
2380:                        da = new float[2 * n];
2381:                        for (int i = 0; i < n; i++) {
2382:                            da[i] = ownerDocument.lengthParser.parseNumber(st
2383:                                    .nextToken());
2384:                            da[n + i] = da[i];
2385:
2386:                            if (Float.isNaN(da[i]) || da[i] < 0) {
2387:                                // The CSS number was invalid. 
2388:                                // Do not set the value
2389:                                throw new IllegalArgumentException();
2390:                            }
2391:
2392:                            totalLength += da[i];
2393:                        }
2394:                    }
2395:
2396:                    if (totalLength > 0) {
2397:                        return da;
2398:                    } else {
2399:                        return null;
2400:                    }
2401:                } catch (IllegalArgumentException iae) {
2402:                    throw illegalTraitValue(name, value);
2403:                } catch (NullPointerException iae) {
2404:                    throw illegalTraitValue(name, value);
2405:                }
2406:            }
2407:
2408:            /**
2409:             * Parses the input value and converts it to a positive float value.
2410:             *
2411:             * @param name the trait name.
2412:             * @param value the value to convert to a float.
2413:             * @return the value converted to a float value.
2414:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2415:             * value is an invalid positive float value or null.
2416:             */
2417:            protected final float parsePositiveFloatTrait(final String name,
2418:                    final String value) throws DOMException {
2419:                try {
2420:                    float v = ownerDocument.lengthParser.parseNumber(value);
2421:                    if (v < 0) {
2422:                        throw new IllegalArgumentException();
2423:                    }
2424:                    return v;
2425:                } catch (IllegalArgumentException iae) {
2426:                    throw illegalTraitValue(name, value);
2427:                }
2428:            }
2429:
2430:            /**
2431:             * Parses the input value and converts it to a float.
2432:             *
2433:             * @param name the trait name.
2434:             * @param value the value to convert to a float.
2435:             * @param isHorizontal controls whether this is a horizontal length or not.
2436:             * @return the value converted to a float.
2437:             * @throws DOMException if the trait value is invalid.
2438:             */
2439:            protected final float parseLengthTrait(final String name,
2440:                    final String value, boolean isHorizontal)
2441:                    throws DOMException {
2442:                try {
2443:                    Length l = ownerDocument.lengthParser.parseLength(value);
2444:                    switch (l.unit) {
2445:                    case Length.SVG_LENGTHTYPE_NUMBER:
2446:                        return l.value;
2447:                    case Length.SVG_LENGTHTYPE_IN:
2448:                        return (l.value * 25.4f / ownerDocument
2449:                                .getPixelMMSize());
2450:                    case Length.SVG_LENGTHTYPE_CM:
2451:                        return (l.value * 10f / ownerDocument.getPixelMMSize());
2452:                    case Length.SVG_LENGTHTYPE_MM:
2453:                        return (l.value / ownerDocument.getPixelMMSize());
2454:                    case Length.SVG_LENGTHTYPE_PT:
2455:                        return (l.value * 25.4f / (72f * ownerDocument
2456:                                .getPixelMMSize()));
2457:                    case Length.SVG_LENGTHTYPE_PC:
2458:                        return (l.value * 25.4f / (6f * ownerDocument
2459:                                .getPixelMMSize()));
2460:                    case Length.SVG_LENGTHTYPE_PERCENTAGE:
2461:                        if (isHorizontal) {
2462:                            return ownerDocument.width * l.value / 100f;
2463:                        } else {
2464:                            return ownerDocument.height * l.value / 100f;
2465:                        }
2466:                    default:
2467:                        // This should never happen.
2468:                        throw new Error();
2469:                    }
2470:                } catch (IllegalArgumentException iae) {
2471:                    throw illegalTraitValue(name, value);
2472:                }
2473:            }
2474:
2475:            /**
2476:             * Parses the input value and converts it to a float.
2477:             * @param name the trait name.
2478:             * @param value the value to convert to a float.
2479:             * @param isHorizontal controls whether this is a horizontal length or not.
2480:             * @return the value converted to a float.
2481:             * @throws DOMException if the trait value is invalid.
2482:             */
2483:            protected final float parsePositiveLengthTrait(final String name,
2484:                    final String value, final boolean isHorizontal)
2485:                    throws DOMException {
2486:                float v = parseLengthTrait(name, value, isHorizontal);
2487:                if (v < 0) {
2488:                    throw illegalTraitValue(name, value);
2489:                }
2490:                return v;
2491:            }
2492:
2493:            /**
2494:             * Parses the input value and converts it to a Path value.
2495:             *
2496:             * @param name the trait name.
2497:             * @param value the value to convert.
2498:             * @throws DOMException if the input value is invalid.
2499:             */
2500:            protected final Path parsePathTrait(final String name,
2501:                    final String value) throws DOMException {
2502:                try {
2503:                    return ownerDocument.pathParser.parsePath(value);
2504:                } catch (IllegalArgumentException iae) {
2505:                    DOMException de = illegalTraitValue(name, value);
2506:                    if (!loaded) {
2507:                        ownerDocument.setDelayedException(de);
2508:                        return ownerDocument.pathParser.getPath();
2509:                    } else {
2510:                        throw de;
2511:                    }
2512:                }
2513:            }
2514:
2515:            /**
2516:             * Parses the input points value and converts it to a Path value.
2517:             *
2518:             * @param name the trait name.
2519:             * @param value the value to convert.
2520:             * @throws DOMException if the input value is invalid.
2521:             */
2522:            protected final Path parsePointsTrait(final String name,
2523:                    final String value) throws DOMException {
2524:                try {
2525:                    return ownerDocument.pathParser.parsePoints(value);
2526:                } catch (IllegalArgumentException iae) {
2527:                    DOMException de = illegalTraitValue(name, value);
2528:                    if (!loaded) {
2529:                        ownerDocument.setDelayedException(de);
2530:                        return ownerDocument.pathParser.getPath();
2531:                    } else {
2532:                        throw de;
2533:                    }
2534:                }
2535:            }
2536:
2537:            /**
2538:             * Parses the input value and converts it to an Transform value.
2539:             *
2540:             * @param name the trait's name.
2541:             * @param value the value to convert to a transform.
2542:             * @return the value converted to an Transform object.
2543:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2544:             * value is an invalid transform trait value.
2545:             */
2546:            protected final Transform parseTransformTrait(final String name,
2547:                    final String value) throws DOMException {
2548:                try {
2549:                    return ownerDocument.transformListParser
2550:                            .parseTransformList(value);
2551:                } catch (IllegalArgumentException iae) {
2552:                    throw illegalTraitValue(name, value);
2553:                }
2554:            }
2555:
2556:            /**
2557:             * Parses the input value and converts it to an RGB value
2558:             *
2559:             * @param traitName the name of the color trait being parsed.
2560:             * @param value the value to convert to an RGB
2561:             * @return the value converted to a RGB object
2562:             *
2563:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2564:             * value is an invalid color trait value.
2565:             */
2566:            protected final RGB parseColorTrait(final String traitName,
2567:                    final String value) throws DOMException {
2568:                try {
2569:                    return ownerDocument.colorParser.parseColor(value);
2570:                } catch (IllegalArgumentException e) {
2571:                    throw illegalTraitValue(traitName, value);
2572:                }
2573:            }
2574:
2575:            /**
2576:             * Parses the input value and converts it to a Paint value
2577:             *
2578:             * @param traitName the name of the color trait being parsed.
2579:             * @param paintTarget the PaintTarget requesting the PaintServer.
2580:             * @param value the value to convert to a Paint
2581:             * @return the value converted to a Paint object
2582:             *
2583:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2584:             * value is an invalid color trait value.
2585:             */
2586:            protected final PaintServer parsePaintTrait(final String traitName,
2587:                    final PaintTarget paintTarget, final String value)
2588:                    throws DOMException {
2589:                if (value == null) {
2590:                    throw illegalTraitValue(traitName, value);
2591:                }
2592:
2593:                if (value.startsWith("url(#")) {
2594:                    if (value.length() < 7
2595:                            || value.charAt(value.length() - 1) != ')') {
2596:                        throw illegalTraitValue(traitName, value);
2597:                    }
2598:
2599:                    String idRef = value.substring(5, value.length() - 1);
2600:
2601:                    return PaintServerReference.resolve(ownerDocument,
2602:                            paintTarget, traitName, idRef);
2603:                } else {
2604:                    try {
2605:                        return ownerDocument.colorParser.parseColor(value);
2606:                    } catch (IllegalArgumentException e) {
2607:                        throw illegalTraitValue(traitName, value);
2608:                    }
2609:                }
2610:            }
2611:
2612:            /**
2613:             * Parses the input value and converts it to a Time value.
2614:             *
2615:             * @param traitName the name of the clock trait being parsed.
2616:             * @param value the value to convert to a Time instance.
2617:             * @return the value converted to a Time object.
2618:             * @throws DOMException if the input value is invalid.
2619:             */
2620:            protected final Time parseClockTrait(final String traitName,
2621:                    final String value) throws DOMException {
2622:                if (SVGConstants.SVG_INDEFINITE_VALUE.equals(value)) {
2623:                    return Time.INDEFINITE;
2624:                }
2625:
2626:                try {
2627:                    return new Time(ownerDocument.clockParser.parseClock(value));
2628:                } catch (IllegalArgumentException iae) {
2629:                    throw illegalTraitValue(traitName, value);
2630:                }
2631:            }
2632:
2633:            /**
2634:             * Parses the input value and converts it to a Time value. If there
2635:             * is a syntax error or if the value is invalid for the given usage
2636:             * (has to be [0, infinite[ for min, and ]0, infinite[ for max,
2637:             * then the default is used. For min, the default is 0. For max, the 
2638:             * default is 'indefinite'
2639:             *
2640:             * @param traitName the name of the clock trait being parsed.
2641:             * @param value the value to convert to a Time instance.
2642:             * @param isMin should 
2643:             * @return the value converted to a Time object.
2644:             * @throws DOMException if the input value is invalid.
2645:             */
2646:            protected final Time parseMinMaxClock(final String traitName,
2647:                    final String value, final boolean isMin)
2648:                    throws DOMException {
2649:                if (SVGConstants.SVG_INDEFINITE_VALUE.equals(value)) {
2650:                    return Time.INDEFINITE;
2651:                }
2652:
2653:                if (value == null) {
2654:                    throw illegalTraitValue(traitName, value);
2655:                }
2656:
2657:                try {
2658:                    long v = ownerDocument.clockParser.parseClock(value);
2659:                    if (v < 0) {
2660:                        throw new IllegalArgumentException();
2661:                    }
2662:
2663:                    if (v == 0 && !isMin) {
2664:                        throw new IllegalArgumentException();
2665:                    }
2666:
2667:                    return new Time(v);
2668:                } catch (IllegalArgumentException iae) {
2669:                    if (isMin) {
2670:                        return new Time(0);
2671:                    }
2672:                    return Time.INDEFINITE;
2673:                }
2674:            }
2675:
2676:            /**
2677:             * Utility method. This should be used for XML attribute values converted
2678:             * to float arrays.
2679:             *
2680:             * @param traitName the name of the trait to parse
2681:             * @param ctx the build context
2682:             * @return the attribute value, converted to float
2683:             * @throws DOMException if the value represents an invalid 
2684:             *         floating point array value.
2685:             */
2686:            public final float[] parseFloatArrayTrait(final String traitName,
2687:                    final String value) throws DOMException {
2688:                return parseFloatArrayTrait(traitName, value, ',');
2689:            }
2690:
2691:            /**
2692:             * Utility method. This should be used for XML attribute values converted
2693:             * to float arrays.
2694:             *
2695:             * @param traitName the name of the trait to parse
2696:             * @param value the value to parse
2697:             * @param sep the number separator in the input value list of numbers.
2698:             * @return the attribute value, converted to float
2699:             * @throws DOMException if the value represents an invalid 
2700:             *         floating point array value.
2701:             */
2702:            public final float[] parseFloatArrayTrait(final String traitName,
2703:                    final String value, final char sep) throws DOMException {
2704:                try {
2705:                    return ownerDocument.numberListParser.parseNumberList(
2706:                            value, sep);
2707:                } catch (IllegalArgumentException e) {
2708:                    e.printStackTrace();
2709:                    throw illegalTraitValue(traitName, value);
2710:                }
2711:            }
2712:
2713:            /**
2714:             * CSS 2 Specification (section 15.3.2) and SVG 1.1 specification
2715:             * (20.8.3):
2716:             *
2717:             * all | [ normal | italic | oblique ] [, [normal | italic | oblique] ]*
2718:             *
2719:             * @param name the name of the trait to parse
2720:             * @param value the trait value
2721:             * @return the font style in the FontFace.FONT_STYLE_XXX value set.
2722:             * @throws DOMException if the value is not a legal one for this trait.
2723:             */
2724:            public final int parseFontStylesTrait(final String name,
2725:                    final String value) {
2726:                if (value == null) {
2727:                    throw illegalTraitValue(name, value);
2728:                }
2729:
2730:                if (SVGConstants.CSS_ALL_VALUE.equals(value)) {
2731:                    return FontFace.FONT_STYLE_ALL;
2732:                }
2733:
2734:                SimpleTokenizer st = new SimpleTokenizer(value,
2735:                        SVGConstants.COMMA_STR);
2736:
2737:                if (st.countTokens() < 1) {
2738:                    throw illegalTraitValue(name, value);
2739:                }
2740:
2741:                int styles = 0;
2742:                while (st.hasMoreTokens()) {
2743:                    String t = st.nextToken().trim();
2744:                    if (SVGConstants.CSS_NORMAL_VALUE.equals(t)) {
2745:                        styles |= TextNode.FONT_STYLE_NORMAL;
2746:                    } else if (SVGConstants.CSS_ITALIC_VALUE.equals(t)) {
2747:                        styles |= TextNode.FONT_STYLE_ITALIC;
2748:                    } else if (SVGConstants.CSS_OBLIQUE_VALUE.equals(t)) {
2749:                        styles |= TextNode.FONT_STYLE_OBLIQUE;
2750:                    } else {
2751:                        throw illegalTraitValue(name, value);
2752:                    }
2753:                }
2754:
2755:                return styles;
2756:            }
2757:
2758:            /**
2759:             * CSS 2 specification ((section 15.3.2) and SVG 1.1 specification
2760:             * (20.8.3):
2761:             *
2762:             * all | [normal | bold |100 | 200 | 300 | 400 | 500 | 600 | 
2763:             * 700 | 800 | 900] [, [normal | bold |100 | 200 | 300 |
2764:             * 400 | 500 | 600 | 700 | 800 | 900]]*
2765:             *
2766:             * @param name the name of the trait to parse
2767:             * @param value the trait value.
2768:             * @return the font weight as an int value in the 
2769:             *         FontFace.FONT_WEIGHT_XXX set.
2770:             * @throws DOMException if the value is not a legal one for this trait.
2771:             */
2772:            protected final int parseFontWeightsTrait(final String name,
2773:                    final String value) {
2774:                if (value == null) {
2775:                    throw illegalTraitValue(name, value);
2776:                }
2777:
2778:                if (SVGConstants.CSS_ALL_VALUE.equals(value)) {
2779:                    return FontFace.FONT_WEIGHT_ALL;
2780:                }
2781:
2782:                SimpleTokenizer st = new SimpleTokenizer(value,
2783:                        SVGConstants.COMMA_STR);
2784:
2785:                if (st.countTokens() < 1) {
2786:                    throw illegalTraitValue(name, value);
2787:                }
2788:
2789:                int weights = 0;
2790:                while (st.hasMoreTokens()) {
2791:                    String t = st.nextToken().trim();
2792:                    if (SVGConstants.CSS_NORMAL_VALUE.equals(t)) {
2793:                        weights |= TextNode.FONT_WEIGHT_NORMAL;
2794:                    } else if (SVGConstants.CSS_BOLD_VALUE.equals(t)) {
2795:                        weights |= TextNode.FONT_WEIGHT_BOLD;
2796:                    } else if (SVGConstants.CSS_100_VALUE.equals(t)) {
2797:                        weights |= TextNode.FONT_WEIGHT_100;
2798:                    } else if (SVGConstants.CSS_200_VALUE.equals(t)) {
2799:                        weights |= TextNode.FONT_WEIGHT_200;
2800:                    } else if (SVGConstants.CSS_300_VALUE.equals(t)) {
2801:                        weights |= TextNode.FONT_WEIGHT_300;
2802:                    } else if (SVGConstants.CSS_400_VALUE.equals(t)) {
2803:                        weights |= TextNode.FONT_WEIGHT_400;
2804:                    } else if (SVGConstants.CSS_500_VALUE.equals(t)) {
2805:                        weights |= TextNode.FONT_WEIGHT_500;
2806:                    } else if (SVGConstants.CSS_600_VALUE.equals(t)) {
2807:                        weights |= TextNode.FONT_WEIGHT_600;
2808:                    } else if (SVGConstants.CSS_700_VALUE.equals(t)) {
2809:                        weights |= TextNode.FONT_WEIGHT_700;
2810:                    } else if (SVGConstants.CSS_800_VALUE.equals(t)) {
2811:                        weights |= TextNode.FONT_WEIGHT_800;
2812:                    } else if (SVGConstants.CSS_900_VALUE.equals(t)) {
2813:                        weights |= TextNode.FONT_WEIGHT_900;
2814:                    } else {
2815:                        throw illegalTraitValue(name, value);
2816:                    }
2817:                }
2818:
2819:                return weights;
2820:            }
2821:
2822:            /**
2823:             * Parses the input value assuming it has the folloing syntax:
2824:             * Value:   [ <family-name> | <generic-family> ] [, [<family-name> |
2825:             *          <generic-family> ]]*
2826:             * @param name the name of the trait being parsed.
2827:             * @param value the font family value to be parsed. Should not be null.
2828:             * @return an array of font-family strings
2829:             */
2830:            public String[] parseFontFamilyTrait(final String name,
2831:                    final String value) {
2832:                if (value == null) {
2833:                    throw illegalTraitValue(name, value);
2834:                }
2835:
2836:                SimpleTokenizer st = new SimpleTokenizer(value,
2837:                        SVGConstants.COMMA_STR);
2838:                String[] fontFamily = new String[st.countTokens()];
2839:                int i = 0;
2840:                while (st.hasMoreTokens()) {
2841:                    fontFamily[i] = st.nextToken();
2842:
2843:                    // Remove leading and trailing white spaces
2844:                    fontFamily[i] = fontFamily[i].trim();
2845:
2846:                    //
2847:                    // Now, take care of quotes
2848:                    //
2849:
2850:                    // <!> NOTE
2851:                    //
2852:                    // According to the CSS spec., if font family values are not 
2853:                    // quoted, then the spaces should be consolidated. The following
2854:                    // code does not do that. 
2855:                    //
2856:                    if (fontFamily[i].length() > 0) {
2857:                        if (fontFamily[i].charAt(0) == '\'') {
2858:                            // If there is a trailing quote, remove the quotes
2859:                            if (fontFamily[i]
2860:                                    .charAt(fontFamily[i].length() - 1) == '\'') {
2861:                                fontFamily[i] = fontFamily[i].substring(1,
2862:                                        fontFamily[i].length() - 1);
2863:                            }
2864:                        }
2865:                    }
2866:                    i++;
2867:                }
2868:
2869:                return fontFamily;
2870:            }
2871:
2872:            /**
2873:             * Parses the input value, assuming a unicode range syntax, as for the
2874:             * <code>&lt;hkern&gt;</code> element's u1 and u2 attributes.
2875:             *
2876:             * @param name the trait name.
2877:             * @param value the trait value.
2878:             * @return an array of unicode range pairs, as integer pairs.
2879:             * @throws DOMException if the input trait value is invalid.
2880:             */
2881:            protected final int[][] parseUnicodeRangeTrait(final String name,
2882:                    final String value) throws DOMException {
2883:                try {
2884:                    return ownerDocument.unicodeParser.parseUnicode(value);
2885:                } catch (IllegalArgumentException iae) {
2886:                    throw illegalTraitValue(name, value);
2887:                }
2888:            }
2889:
2890:            /**
2891:             * Throws a DOMException if the element is not loading, i.e., if
2892:             * its loaded field is set to true.
2893:             *
2894:             * @param name the name of the trait that is accessed.
2895:             */
2896:            protected void checkWriteLoading(final String name)
2897:                    throws DOMException {
2898:                if (loaded && isInDocumentTree()) {
2899:                    throw readOnlyTraitError(name);
2900:                }
2901:            }
2902:
2903:            /**
2904:             * Throws a DOMException if the input float trait value is
2905:             * strictly negative.
2906:             *
2907:             * @param name the trait name.
2908:             * @param value the trait float value.
2909:             */
2910:            protected void checkPositive(final String name, final float value) {
2911:                if (value < 0) {
2912:                    throw illegalTraitValue(name, Float.toString(value));
2913:                }
2914:            }
2915:
2916:            /**
2917:             * @param name the trait name.
2918:             * @return a DOMException describing the type mismatch error.
2919:             */
2920:            protected DOMException unsupportedTraitType(final String name,
2921:                    final String type) {
2922:                if (name == null) {
2923:                    return unsupportedTrait(name);
2924:                }
2925:
2926:                return new DOMException(DOMException.TYPE_MISMATCH_ERR,
2927:                        Messages.formatMessage(
2928:                                Messages.ERROR_TRAIT_TYPE_MISMATCH,
2929:                                new String[] { name, type, getLocalName(),
2930:                                        getNamespaceURI() }));
2931:            }
2932:
2933:            /**
2934:             * @param name the trait name.
2935:             * @return a DOMException describing the type mismatch error.
2936:             */
2937:            protected DOMException unsupportedTraitTypeNS(final String name,
2938:                    final String namespaceURI, final String type) {
2939:                return new DOMException(DOMException.TYPE_MISMATCH_ERR,
2940:                        Messages.formatMessage(
2941:                                Messages.ERROR_TRAIT_TYPE_NS_MISMATCH,
2942:                                new String[] { name, namespaceURI, type,
2943:                                        getLocalName(), getNamespaceURI() }));
2944:            }
2945:
2946:            /**
2947:             * @param name the trait name
2948:             * @return a DOMException describing the unsupported trait error.
2949:             */
2950:            protected DOMException unsupportedTrait(final String name) {
2951:                return new DOMException(DOMException.NOT_SUPPORTED_ERR,
2952:                        Messages.formatMessage(
2953:                                Messages.ERROR_UNSUPPORTED_TRAIT, new String[] {
2954:                                        name, null, getLocalName(),
2955:                                        getNamespaceURI() }));
2956:            }
2957:
2958:            /**
2959:             * @param name the trait name
2960:             * @param namespaceURI the trait's namespace URI.
2961:             * @return a DOMException describing the unsupported trait error.
2962:             */
2963:            protected DOMException unsupportedTraitNS(final String name,
2964:                    final String namespaceURI) {
2965:                return new DOMException(DOMException.NOT_SUPPORTED_ERR,
2966:                        Messages.formatMessage(
2967:                                Messages.ERROR_UNSUPPORTED_TRAIT, new String[] {
2968:                                        name, namespaceURI, getLocalName(),
2969:                                        getNamespaceURI() }));
2970:            }
2971:
2972:            /**
2973:             * @param name the name of the trait
2974:             * @param value the illegal value.
2975:             * @return a DOMException describing an illegal trait value
2976:             */
2977:            DOMException illegalTraitValue(final String name, final String value) {
2978:                return new DOMException(DOMException.INVALID_ACCESS_ERR,
2979:                        Messages.formatMessage(
2980:                                Messages.ERROR_INVALID_TRAIT_VALUE,
2981:                                new String[] { name, value,
2982:                                        getLocalName() + "(" + getId() + ")",
2983:                                        getNamespaceURI() }));
2984:            }
2985:
2986:            /**
2987:             * @param name the name of the trait
2988:             * @param value the illegal value.
2989:             * @return a DOMException describing an illegal trait value
2990:             */
2991:            DOMException notAnimatable(final String traitNamespace,
2992:                    final String traitName) {
2993:                return new DOMException(DOMException.NOT_SUPPORTED_ERR,
2994:                        Messages.formatMessage(
2995:                                Messages.ERROR_TRAIT_NOT_ANIMATABLE,
2996:                                new String[] { traitNamespace, traitName,
2997:                                        getLocalName(), getNamespaceURI() }));
2998:            }
2999:
3000:            /**
3001:             * @param targetId the target element's id (may be null)
3002:             * @param traitNamespace the animated trait's namespace.
3003:             * @param traitName the animated trait's name.
3004:             * @param targetNamespace the target element's namespace.
3005:             * @param targetName the target element's name
3006:             * @param animationId the animation id (may be null)
3007:             * @param animationNamespace the animation's namespace
3008:             * @param animationLocalName the animation's local name.
3009:             * @param errorDescription the animation error's description.
3010:             */
3011:            protected DOMException animationError(final String targetId,
3012:                    final String traitNamespace, final String traitName,
3013:                    final String targetNamespace, final String targetName,
3014:                    final String animationId, final String animationNamespace,
3015:                    final String animationLocalName,
3016:                    final String errorDescription) {
3017:                return new DOMException(DOMException.INVALID_STATE_ERR,
3018:                        Messages.formatMessage(
3019:                                Messages.ERROR_INVALID_ANIMATION_CONFIGURATION,
3020:                                new String[] { targetId, traitNamespace,
3021:                                        traitName, targetNamespace, targetName,
3022:                                        animationId, animationNamespace,
3023:                                        animationLocalName, animationLocalName,
3024:                                        errorDescription }));
3025:            }
3026:
3027:            /**
3028:             * @param name the name of the trait
3029:             * @param namespaceURI the trait's namespace URI.
3030:             * @param value the illegal value.
3031:             * @return a DOMException describing an illegal trait value
3032:             */
3033:            protected DOMException illegalTraitValue(final String name,
3034:                    final String namespaceURI, final String value) {
3035:                return illegalTraitValue(name + "(" + namespaceURI + ")", value);
3036:            }
3037:
3038:            /**
3039:             * @param name the trait name.
3040:             * @return DOMException describing the write error on a read-only attribute.
3041:             */
3042:            protected DOMException readOnlyTraitError(final String name) {
3043:                return new DOMException(
3044:                        DOMException.NO_MODIFICATION_ALLOWED_ERR, Messages
3045:                                .formatMessage(Messages.ERROR_READ_ONLY_TRAIT,
3046:                                        new String[] { name, getLocalName(),
3047:                                                getNamespaceURI() }));
3048:            }
3049:
3050:            /**
3051:             * Converts an animated float[][] value into an AWT color value.
3052:             *
3053:             * @param name the trait's name.
3054:             * @param value the float[][] to convert.
3055:             * @return the color converted to an AWT <code>Color</code> object.
3056:             */
3057:            protected RGB toRGB(final String name, final float[][] v)
3058:                    throws DOMException {
3059:                if (v != null) {
3060:                    return new RGB((int) v[0][0], (int) v[0][1], (int) v[0][2]);
3061:                } else {
3062:                    return null;
3063:                }
3064:            }
3065:
3066:            /**
3067:             * Converts an animated float[][] value into an String rgb value.
3068:             *
3069:             * @param name the trait's name.
3070:             * @param value the float[][] to convert.
3071:             * @return the color converted to a string.
3072:             */
3073:            protected String toRGBString(final String name, final float[][] v)
3074:                    throws DOMException {
3075:                if (v != null) {
3076:                    return "rgb(" + ((int) v[0][0]) + "," + ((int) v[0][1])
3077:                            + "," + ((int) v[0][2]) + ")";
3078:                } else {
3079:                    return "none";
3080:                }
3081:            }
3082:
3083:            /**
3084:             * Converts an J2D RGB to an SVG DOM RGBColor
3085:             *
3086:             * @param traitName the name of the trait whose value is convereted.
3087:             * @param paint the PaintServer to convert. Should not be null.
3088:             * @return the color, converted to an <code>SVGRGBColor</code> instance.
3089:             *
3090:             * @throws DOMException with error code TYPE_MISMATCH_ERR if the 
3091:             *         paint is not an instance of Colorl
3092:             */
3093:            protected SVGRGBColor toSVGRGBColor(final String traitName,
3094:                    final PaintServer paint) {
3095:                if (paint == null) {
3096:                    return null;
3097:                }
3098:
3099:                if (!(paint instanceof  SVGRGBColor)) {
3100:                    throw unsupportedTraitType(traitName,
3101:                            TRAIT_TYPE_SVG_RGB_COLOR);
3102:                }
3103:
3104:                return (SVGRGBColor) paint;
3105:            }
3106:
3107:            /**
3108:             * Converts a viewBox array to an SVGRect value.
3109:             *
3110:             * @param name the name of the trait.
3111:             * @param viewBox the viewbox value to convet.
3112:             */
3113:            protected SVGRect toSVGRect(final float[][] viewBox) {
3114:                if (viewBox == null) {
3115:                    return null;
3116:                }
3117:
3118:                SVGRect r = new Box(viewBox[0][0], viewBox[0][1],
3119:                        viewBox[1][0], viewBox[2][0]);
3120:
3121:                return r;
3122:            }
3123:
3124:            /**
3125:             * Converts an comma seperated list of floats to a viewBox array
3126:             *
3127:             * @param name the trait name
3128:             * @param value the trait value to be converted to an SVGRect. 
3129:             *        The expected syntax is 
3130:             *        "float comma-wsp float comma-wsp float comma-wsp float comma-wsp"
3131:             * @return an array of four floats.
3132:             *
3133:             * @throws DOMException with error code INVALID_ACCESS_ERR if the input
3134:             * value is an invalid value for the given trait or null.
3135:             */
3136:            protected float[][] toViewBox(final String name, final String value)
3137:                    throws DOMException {
3138:                if (value == null) {
3139:                    throw illegalTraitValue(name, value);
3140:                }
3141:
3142:                try {
3143:                    return ownerDocument.viewBoxParser.parseViewBox(value);
3144:                } catch (IllegalArgumentException iae) {
3145:                    throw illegalTraitValue(name, value);
3146:                }
3147:            }
3148:
3149:            /**
3150:             * Converts a Java String array to a trait string array with the format:
3151:             * "str1, str2, .., strN"
3152:             *
3153:             * @param array the string array to be converted.
3154:             * @return a string with the value "" if the array is null or 
3155:             *         "float1,float2,..,floatN"
3156:             */
3157:            protected String toStringTrait(final String[] array) {
3158:                return toStringTrait(array, ",");
3159:            }
3160:
3161:            /**
3162:             * Converts a Java String array to a trait string array with the format:
3163:             * "str1, str2, .., strN"
3164:             *
3165:             * @param array the string array to be converted.
3166:             * @param sep seperator to use in the output string array.
3167:             *
3168:             * @return a string with the value "" if the array is null or 
3169:             *         "float1,float2,..,floatN"
3170:             */
3171:            protected String toStringTrait(final String[] array,
3172:                    final String sep) {
3173:                if (array == null || array.length < 1) {
3174:                    return "";
3175:                }
3176:
3177:                StringBuffer sb = new StringBuffer();
3178:
3179:                for (int i = 0; i < array.length - 1; i++) {
3180:                    sb.append(array[i]);
3181:                    sb.append(sep);
3182:                }
3183:
3184:                sb.append(array[array.length - 1]);
3185:                return sb.toString();
3186:            }
3187:
3188:            /**
3189:             * Converts a Java String array to a trait string array with the format:
3190:             * "str1, str2, .., strN". In addition, the string values are put inside
3191:             * single quotes if there are spaces in the string values. This is needed
3192:             * for values such as the CSS 2 font-family attribute.
3193:             *
3194:             * @param array the string array to be converted.
3195:             *
3196:             * @return a string with the value "" if the array is null or 
3197:             *         "float1,float2,..,floatN"
3198:             */
3199:            protected String toStringTraitQuote(final String[] array) {
3200:                if (array == null || array.length < 1) {
3201:                    return "";
3202:                }
3203:
3204:                StringBuffer sb = new StringBuffer();
3205:
3206:                for (int i = 0; i < array.length - 1; i++) {
3207:                    if (array[i].indexOf(' ') != -1) {
3208:                        sb.append('\'');
3209:                        sb.append(array[i]);
3210:                        sb.append('\'');
3211:                    } else {
3212:                        sb.append(array[i]);
3213:                    }
3214:                    sb.append(',');
3215:                }
3216:
3217:                if (array[array.length - 1].indexOf(' ') != -1) {
3218:                    sb.append('\'');
3219:                    sb.append(array[array.length - 1]);
3220:                    sb.append('\'');
3221:                } else {
3222:                    sb.append(array[array.length - 1]);
3223:                }
3224:
3225:                return sb.toString();
3226:            }
3227:
3228:            /**
3229:             * Helper method. Converts the input array value to a string trait value.
3230:             *
3231:             * @param array the float array to be converted.
3232:             * @return a string with the value "none" if the array is null or 
3233:             *         "float1,float2,..,floatN"
3234:             */
3235:            protected String toStringTrait(final float[] array) {
3236:                return toStringTrait(array, ',');
3237:            }
3238:
3239:            /**
3240:             * Helper method. Converts the input array value to a string trait value.
3241:             *
3242:             * @param array the float array to be converted.
3243:             * @return a string with the value "none" if the array is null or 
3244:             *         "float1,float2,..,floatN"
3245:             */
3246:            protected String toStringTrait(final float[] array, final char sep) {
3247:                if (array == null) {
3248:                    return SVGConstants.CSS_NONE_VALUE;
3249:                }
3250:
3251:                StringBuffer sb = new StringBuffer();
3252:
3253:                for (int i = 0; i < array.length - 1; i++) {
3254:                    sb.append(array[i]);
3255:                    sb.append(sep);
3256:                }
3257:
3258:                sb.append(array[array.length - 1]);
3259:                return sb.toString();
3260:            }
3261:
3262:            /**
3263:             * Helper method. Convertst the input array of float arrays into a 
3264:             * string trait value.
3265:             *
3266:             * @param array the array of float arrays to convert.
3267:             * @return a string the the value "" if the array is null or 
3268:             *         "f01 f02 f03 f04; f11 f12 f13 f14; ...;fn1 fn2 fn3 fn4"
3269:             * @throws NullPointerException if one of the array values is null
3270:             * @throws ArrayIndexOutOfBoundsException if one of the array values is of
3271:             *         length 0.
3272:             */
3273:            protected String toStringTrait(final float[][] array) {
3274:                if (array == null || array.length == 0) {
3275:                    return "";
3276:                }
3277:
3278:                StringBuffer sb = new StringBuffer();
3279:
3280:                for (int i = 0; i < array.length; i++) {
3281:                    for (int j = 0; j < array[i].length - 1; j++) {
3282:                        sb.append(array[i][j]);
3283:                        sb.append(SVGConstants.COMMA);
3284:                    }
3285:                    sb.append(array[i][array[i].length - 1]);
3286:                    sb.append(SVGConstants.SEMI_COLON);
3287:                }
3288:
3289:                String value = sb.toString();
3290:
3291:                // Trim trailing ';'
3292:                return value.substring(0, value.length() - 1);
3293:            }
3294:
3295:            /**
3296:             * Helper method. Converts the input <code>Transform</code>
3297:             * to an SVGMatrix trait value.
3298:             *
3299:             * @param transform the transform to convert.
3300:             * @return the SVGMatrix equivalent value.
3301:             */
3302:            protected SVGMatrix toSVGMatrixTrait(final Transform transform) {
3303:                if (transform == null) {
3304:                    return new Transform(1, 0, 0, 1, 0, 0);
3305:                } else {
3306:                    return new Transform(transform);
3307:                }
3308:            }
3309:
3310:            /**
3311:             * Converts an align value to a preserveAspectRatio string trait
3312:             * value.
3313:             * 
3314:             * @param align one of StructureNode.ALIGN_NONE, 
3315:             *        StructureNode.ALIGN_XMIDYMID
3316:             */
3317:            protected static String alignToStringTrait(final int align) {
3318:                switch (align) {
3319:                case StructureNode.ALIGN_XMIDYMID:
3320:                    return SVGConstants.SVG_IMAGE_PRESERVE_ASPECT_RATIO_DEFAULT_VALUE;
3321:                default:
3322:                    return SVGConstants.SVG_NONE_VALUE;
3323:                }
3324:            }
3325:
3326:            /**
3327:             * Converts a FontFace's font-styles to a String trait.
3328:             *
3329:             * @param styles the FontFace type styles value.
3330:             */
3331:            protected String fontStylesToStringTrait(final int styles) {
3332:                if (styles == FontFace.FONT_STYLE_ALL) {
3333:                    return SVGConstants.CSS_ALL_VALUE;
3334:                }
3335:
3336:                StringBuffer sb = new StringBuffer();
3337:
3338:                if ((styles & TextNode.FONT_STYLE_NORMAL) != 0) {
3339:                    sb.append(SVGConstants.CSS_NORMAL_VALUE);
3340:                    sb.append(SVGConstants.COMMA);
3341:                }
3342:
3343:                if ((styles & TextNode.FONT_STYLE_ITALIC) != 0) {
3344:                    sb.append(SVGConstants.CSS_ITALIC_VALUE);
3345:                    sb.append(SVGConstants.COMMA);
3346:                }
3347:
3348:                if ((styles & TextNode.FONT_STYLE_OBLIQUE) != 0) {
3349:                    sb.append(SVGConstants.CSS_OBLIQUE_VALUE);
3350:                    sb.append(SVGConstants.COMMA);
3351:                }
3352:
3353:                if (sb.length() > 0) {
3354:                    return sb.toString().substring(0, sb.length() - 1);
3355:                }
3356:
3357:                return sb.toString();
3358:            }
3359:
3360:            /**
3361:             * Converts an FontFace's font-weights to a String trait.
3362:             *
3363:             * @param weight the FontFace type' weights value.
3364:             */
3365:            protected String fontWeightsToStringTrait(final int weight) {
3366:                if (weight == FontFace.FONT_WEIGHT_ALL) {
3367:                    return SVGConstants.CSS_ALL_VALUE;
3368:                }
3369:
3370:                StringBuffer sb = new StringBuffer();
3371:                if ((weight & TextNode.FONT_WEIGHT_100) != 0) {
3372:                    sb.append(SVGConstants.CSS_100_VALUE);
3373:                    sb.append(SVGConstants.COMMA);
3374:                }
3375:
3376:                if ((weight & TextNode.FONT_WEIGHT_200) != 0) {
3377:                    sb.append(SVGConstants.CSS_200_VALUE);
3378:                    sb.append(SVGConstants.COMMA);
3379:                }
3380:
3381:                if ((weight & TextNode.FONT_WEIGHT_300) != 0) {
3382:                    sb.append(SVGConstants.CSS_300_VALUE);
3383:                    sb.append(SVGConstants.COMMA);
3384:                }
3385:
3386:                if ((weight & TextNode.FONT_WEIGHT_400) != 0) {
3387:                    sb.append(SVGConstants.CSS_400_VALUE);
3388:                    sb.append(SVGConstants.COMMA);
3389:                }
3390:
3391:                if ((weight & TextNode.FONT_WEIGHT_500) != 0) {
3392:                    sb.append(SVGConstants.CSS_500_VALUE);
3393:                    sb.append(SVGConstants.COMMA);
3394:                }
3395:
3396:                if ((weight & TextNode.FONT_WEIGHT_600) != 0) {
3397:                    sb.append(SVGConstants.CSS_600_VALUE);
3398:                    sb.append(SVGConstants.COMMA);
3399:                }
3400:
3401:                if ((weight & TextNode.FONT_WEIGHT_700) != 0) {
3402:                    sb.append(SVGConstants.CSS_700_VALUE);
3403:                    sb.append(SVGConstants.COMMA);
3404:                }
3405:
3406:                if ((weight & TextNode.FONT_WEIGHT_800) != 0) {
3407:                    sb.append(SVGConstants.CSS_800_VALUE);
3408:                    sb.append(SVGConstants.COMMA);
3409:                }
3410:
3411:                if ((weight & TextNode.FONT_WEIGHT_900) != 0) {
3412:                    sb.append(SVGConstants.CSS_900_VALUE);
3413:                    sb.append(SVGConstants.COMMA);
3414:                }
3415:
3416:                if (sb.length() > 0) {
3417:                    return sb.toString().substring(0, sb.length() - 1);
3418:                }
3419:
3420:                return sb.toString();
3421:            }
3422:
3423:            /**
3424:             * Helper method. Converts the input <code>Transform</code>
3425:             * to a string trait value.
3426:             *
3427:             * @param transform the transform to convert.
3428:             * @return the string trait value.
3429:             */
3430:            protected static String toStringTrait(final Transform transform) {
3431:                if (transform == null) {
3432:                    return Transformable.IDENTITY_TRANSFORM_TRAIT;
3433:                } else {
3434:                    StringBuffer sb = new StringBuffer();
3435:                    sb.append("matrix(");
3436:                    sb.append(transform.getComponent(0));
3437:                    sb.append(",");
3438:                    sb.append(transform.getComponent(1));
3439:                    sb.append(",");
3440:                    sb.append(transform.getComponent(2));
3441:                    sb.append(",");
3442:                    sb.append(transform.getComponent(3));
3443:                    sb.append(",");
3444:                    sb.append(transform.getComponent(4));
3445:                    sb.append(",");
3446:                    sb.append(transform.getComponent(5));
3447:                    sb.append(")");
3448:                    return sb.toString();
3449:                }
3450:            }
3451:
3452:            /**
3453:             * Helper method. Converts the input unicode range into a String
3454:             * trait, with the following syntax:
3455:             * "U+b1-e1,U+b2-e2,...,U+bn-en"
3456:             *
3457:             * @param u the unicode range to convert.
3458:             * @return the string value with the unicode range syntax.
3459:             */
3460:            protected String unicodeRangeToStringTrait(final int[][] u) {
3461:                if (u == null) {
3462:                    return null;
3463:                }
3464:
3465:                if (u.length == 0) {
3466:                    return SVGConstants.EMPTY;
3467:                }
3468:
3469:                StringBuffer sb = new StringBuffer();
3470:                for (int i = 0; i < u.length - 1; i++) {
3471:                    if (u[i] == null || u[i].length != 2) {
3472:                        throw new IllegalArgumentException();
3473:                    }
3474:                    sb.append("U+");
3475:                    sb.append(Integer.toHexString(u[i][0]));
3476:                    sb.append('-');
3477:                    sb.append(Integer.toHexString(u[i][1]));
3478:                    sb.append(',');
3479:                }
3480:
3481:                if (u[u.length - 1] == null || u[u.length - 1].length != 2) {
3482:                    throw new IllegalArgumentException();
3483:                }
3484:                sb.append("U+");
3485:                sb.append(Integer.toHexString(u[u.length - 1][0]));
3486:                sb.append('-');
3487:                sb.append(Integer.toHexString(u[u.length - 1][1]));
3488:
3489:                return sb.toString();
3490:            }
3491:
3492:            /**
3493:             * Converts the input float value to an animated float array trait.
3494:             *
3495:             * @param v the float value to wrap in a float[][] array.
3496:             * @return the wrapped value.
3497:             */
3498:            float[][] toAnimatedFloatArray(final float v) {
3499:                return new float[][] { { v } };
3500:            }
3501:
3502:            /**
3503:             * Converts the input float[] array to an animated float array trait.
3504:             *
3505:             * @param a the float array to wrap in a float[][] array. Should not
3506:             *        be null.
3507:             * @return the wrapped value.
3508:             */
3509:            float[][] toAnimatedFloatArray(final float[] a) {
3510:                float[][] v = new float[a.length][];
3511:                // This assumes that each value in the input array are separate
3512:                // components.
3513:                for (int i = 0; i < a.length; i++) {
3514:                    v[i] = new float[] { a[i] };
3515:                }
3516:                return v;
3517:            }
3518:
3519:            /**
3520:             * Utility method to convert a Path to an animatable float array.
3521:             *
3522:             * @param p the path to convert
3523:             * @return the converted value.
3524:             */
3525:            float[][] toAnimatedFloatArray(final Path path) {
3526:                return new float[][] { path.getData() };
3527:            }
3528:
3529:            /**
3530:             * Converts an animated float array to a trait float array value.
3531:             * This is used for multi-component trait values, such as 
3532:             * stroke-dasharray, or the text's x, y or rotate values.
3533:             *
3534:             * @param value the animated value to convert.
3535:             * @return an float array trait value.
3536:             */
3537:            float[] toTraitFloatArray(final float[][] value) {
3538:                float[] v = new float[value.length];
3539:                for (int i = 0; i < v.length; i++) {
3540:                    v[i] = value[i][0];
3541:                }
3542:
3543:                return v;
3544:            }
3545:
3546:            /**
3547:             * @return a text description of this node including the node
3548:             *         ID if one was set.
3549:             */
3550:            public String toString() {
3551:                if (getId() != null && getId().length() > 0) {
3552:                    return "ElementNode[" + getId() + "] [" + super .toString()
3553:                            + "]";
3554:                } else {
3555:                    return super .toString();
3556:                }
3557:            }
3558:
3559:            // =========================================================================
3560:            // Type comparison utilities.
3561:            //
3562:
3563:            /**
3564:             * @param objA first object to compare.
3565:             * @param objB second object to compare. 
3566:             * @return true if the objects are both null or if they are Object.equals()
3567:             */
3568:            public static boolean equal(final Object objA, final Object objB) {
3569:                if (objA == objB) {
3570:                    return true;
3571:                }
3572:
3573:                if (objA == null || objB == null) {
3574:                    return false;
3575:                }
3576:
3577:                return objA.equals(objB);
3578:            }
3579:
3580:            /**
3581:             * @param faa first float array to compare
3582:             * @param faab second float array to compare
3583:             * @return true if the objects are both null or if they are equal
3584:             */
3585:            public static boolean equal(final float[] faa, final float[] fab) {
3586:                if (faa == fab) {
3587:                    return true;
3588:                }
3589:
3590:                if (faa == null || fab == null || faa.length != fab.length) {
3591:                    return false;
3592:                }
3593:
3594:                int n = faa.length;
3595:                for (int i = 0; i < n; i++) {
3596:                    if (faa[i] != fab[i]) {
3597:                        return false;
3598:                    }
3599:                }
3600:
3601:                return true;
3602:            }
3603:
3604:            /**
3605:             * @param saa first string array to compare
3606:             * @param sab second string array to compare
3607:             * @return true if the objects are both null or if they are equal
3608:             */
3609:            public static boolean equal(final String[] saa, final String[] sab) {
3610:                if (saa == sab) {
3611:                    return true;
3612:                }
3613:
3614:                if (saa == null || sab == null || saa.length != sab.length) {
3615:                    return false;
3616:                }
3617:
3618:                int n = saa.length;
3619:                for (int i = 0; i < n; i++) {
3620:                    if (!equal(saa[i], sab[i])) {
3621:                        return false;
3622:                    }
3623:                }
3624:
3625:                return true;
3626:            }
3627:
3628:            /**
3629:             * @param iaa first int array to compare
3630:             * @param iab second int array to compare
3631:             * @return true if the objects are both null or if they are equal
3632:             */
3633:            public static boolean equal(final int[][] iaa, final int[][] iab) {
3634:                if (iaa == iab) {
3635:                    return true;
3636:                }
3637:
3638:                if (iaa == null || iab == null || iaa.length != iab.length) {
3639:                    return false;
3640:                }
3641:
3642:                int n = iaa.length;
3643:                for (int i = 0; i < n; i++) {
3644:                    if (iaa[i] != iab[i]) {
3645:                        if (iaa[i] == null || iab[i] == null
3646:                                || iaa[i].length != iab[i].length) {
3647:                            return false;
3648:                        }
3649:
3650:                        int m = iaa[i].length;
3651:                        for (int j = 0; j < m; j++) {
3652:                            if (iaa[i][j] != iab[i][j]) {
3653:                                return false;
3654:                            }
3655:                        }
3656:                    }
3657:                }
3658:
3659:                return true;
3660:            }
3661:
3662:            /**
3663:             * @param faa first float array to compare
3664:             * @param fab second float array to compare
3665:             * @return true if the objects are both null or if they are equal
3666:             */
3667:            public static boolean equal(final float[][] faa, final float[][] fab) {
3668:                if (faa == fab) {
3669:                    return true;
3670:                }
3671:
3672:                if (faa == null || fab == null || faa.length != fab.length) {
3673:                    return false;
3674:                }
3675:
3676:                int n = faa.length;
3677:                for (int i = 0; i < n; i++) {
3678:                    if (faa[i] != fab[i]) {
3679:                        if (faa[i] == null || fab[i] == null
3680:                                || faa[i].length != fab[i].length) {
3681:                            return false;
3682:                        }
3683:
3684:                        int m = faa[i].length;
3685:                        for (int j = 0; j < m; j++) {
3686:                            if (faa[i][j] != fab[i][j]) {
3687:                                return false;
3688:                            }
3689:                        }
3690:                    }
3691:                }
3692:
3693:                return true;
3694:            }
3695:
3696:            /**
3697:             * Utility method.
3698:             *
3699:             * @param str the String object to intern.
3700:             * @return null if the input string is null. The interned string otherwise.
3701:             */
3702:            public static String intern(final String str) {
3703:                if (str == null) {
3704:                    return null;
3705:                }
3706:
3707:                return str.intern();
3708:            }
3709:
3710:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.