Source Code Cross Referenced for XML.java in  » Scripting » rhino » org » mozilla » javascript » xml » impl » xmlbeans » 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 » Scripting » rhino » org.mozilla.javascript.xml.impl.xmlbeans 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
0002:         *
0003:         * ***** BEGIN LICENSE BLOCK *****
0004:         * Version: MPL 1.1/GPL 2.0
0005:         *
0006:         * The contents of this file are subject to the Mozilla Public License Version
0007:         * 1.1 (the "License"); you may not use this file except in compliance with
0008:         * the License. You may obtain a copy of the License at
0009:         * http://www.mozilla.org/MPL/
0010:         *
0011:         * Software distributed under the License is distributed on an "AS IS" basis,
0012:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0013:         * for the specific language governing rights and limitations under the
0014:         * License.
0015:         *
0016:         * The Original Code is Rhino code, released
0017:         * May 6, 1999.
0018:         *
0019:         * The Initial Developer of the Original Code is
0020:         * Netscape Communications Corporation.
0021:         * Portions created by the Initial Developer are Copyright (C) 1997-2000
0022:         * the Initial Developer. All Rights Reserved.
0023:         *
0024:         * Contributor(s):
0025:         *   Ethan Hugg
0026:         *   Terry Lucas
0027:         *   Milen Nankov
0028:         *
0029:         * Alternatively, the contents of this file may be used under the terms of
0030:         * the GNU General Public License Version 2 or later (the "GPL"), in which
0031:         * case the provisions of the GPL are applicable instead of those above. If
0032:         * you wish to allow use of your version of this file only under the terms of
0033:         * the GPL and not to allow others to use your version of this file under the
0034:         * MPL, indicate your decision by deleting the provisions above and replacing
0035:         * them with the notice and other provisions required by the GPL. If you do
0036:         * not delete the provisions above, a recipient may use your version of this
0037:         * file under either the MPL or the GPL.
0038:         *
0039:         * ***** END LICENSE BLOCK ***** */
0040:
0041:        package org.mozilla.javascript.xml.impl.xmlbeans;
0042:
0043:        import java.io.Serializable;
0044:        import java.util.*;
0045:
0046:        import org.mozilla.javascript.*;
0047:
0048:        import org.apache.xmlbeans.XmlCursor;
0049:        import org.apache.xmlbeans.XmlCursor.XmlBookmark;
0050:        import org.apache.xmlbeans.XmlCursor.TokenType;
0051:        import org.apache.xmlbeans.XmlException;
0052:        import org.apache.xmlbeans.XmlObject;
0053:        import org.apache.xmlbeans.XmlOptions;
0054:
0055:        class XML extends XMLObjectImpl {
0056:            static final long serialVersionUID = -630969919086449092L;
0057:
0058:            final static class XScriptAnnotation extends XmlBookmark implements 
0059:                    Serializable {
0060:                private static final long serialVersionUID = 1L;
0061:
0062:                javax.xml.namespace.QName _name;
0063:                XML _xScriptXML;
0064:
0065:                ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0066:                //
0067:                //  Constructurs
0068:                //
0069:                ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0070:
0071:                XScriptAnnotation(XmlCursor curs) {
0072:                    _name = curs.getName();
0073:                }
0074:
0075:            }
0076:
0077:            /**
0078:             *
0079:             */
0080:            final static class NamespaceDeclarations {
0081:                private int _prefixIdx;
0082:                private StringBuffer _namespaceDecls;
0083:                private String _defaultNSURI;
0084:
0085:                NamespaceDeclarations(XmlCursor curs) {
0086:                    _prefixIdx = 0;
0087:                    _namespaceDecls = new StringBuffer();
0088:
0089:                    skipNonElements(curs);
0090:                    _defaultNSURI = curs.namespaceForPrefix("");
0091:
0092:                    if (isAnyDefaultNamespace()) {
0093:                        addDecl("", _defaultNSURI);
0094:                    }
0095:                }
0096:
0097:                private void addDecl(String prefix, String ns) {
0098:                    _namespaceDecls
0099:                            .append((prefix.length() > 0 ? "declare namespace "
0100:                                    + prefix : "default element namespace")
0101:                                    + " = \"" + ns + "\"" + "\n");
0102:                }
0103:
0104:                String getNextPrefix(String ns) {
0105:                    String prefix = "NS" + _prefixIdx++;
0106:
0107:                    _namespaceDecls.append("declare namespace " + prefix
0108:                            + " = " + "\"" + ns + "\"" + "\n");
0109:
0110:                    return prefix;
0111:                }
0112:
0113:                boolean isAnyDefaultNamespace() {
0114:                    return _defaultNSURI != null ? _defaultNSURI.length() > 0
0115:                            : false;
0116:                }
0117:
0118:                String getDeclarations() {
0119:                    return _namespaceDecls.toString();
0120:                }
0121:            }
0122:
0123:            // Fields
0124:            //static final XML prototype = new XML();
0125:            private XScriptAnnotation _anno;
0126:
0127:            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0128:            //
0129:            //  Constructors
0130:            //
0131:            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0132:
0133:            /**
0134:             *
0135:             * @param anno
0136:             */
0137:            private XML(XMLLibImpl lib, XScriptAnnotation anno) {
0138:                super (lib, lib.xmlPrototype);
0139:                _anno = anno;
0140:                _anno._xScriptXML = this ;
0141:            }
0142:
0143:            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0144:            //
0145:            //  Public factories for creating a XScript XML object given an XBean cursor.
0146:            //
0147:            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0148:
0149:            static XML createEmptyXML(XMLLibImpl lib) {
0150:                XScriptAnnotation anno;
0151:
0152:                XmlObject xo = XmlObject.Factory.newInstance();
0153:                XmlCursor curs = xo.newCursor();
0154:                try {
0155:                    anno = new XScriptAnnotation(curs);
0156:                    curs.setBookmark(anno);
0157:                } finally {
0158:                    curs.dispose();
0159:                }
0160:
0161:                return new XML(lib, anno);
0162:            }
0163:
0164:            private static XML createXML(XMLLibImpl lib, XmlCursor curs) {
0165:                if (curs.currentTokenType().isStartdoc()) {
0166:                    curs.toFirstContentToken();
0167:                }
0168:
0169:                XScriptAnnotation anno = findAnnotation(curs);
0170:
0171:                return new XML(lib, anno);
0172:            }
0173:
0174:            /**
0175:             * Special constructor for making an attribute
0176:             *
0177:             */
0178:            private static XML createAttributeXML(XMLLibImpl lib,
0179:                    XmlCursor cursor) {
0180:                if (!cursor.isAttr())
0181:                    throw new IllegalArgumentException();
0182:
0183:                XScriptAnnotation anno = new XScriptAnnotation(cursor);
0184:                cursor.setBookmark(anno);
0185:
0186:                return new XML(lib, anno);
0187:            }
0188:
0189:            /**
0190:             *
0191:             * @param qname
0192:             * @param value
0193:             * @return
0194:             */
0195:            static XML createTextElement(XMLLibImpl lib,
0196:                    javax.xml.namespace.QName qname, String value) {
0197:                XScriptAnnotation anno;
0198:
0199:                XmlObject xo = XmlObject.Factory.newInstance();
0200:                XmlCursor cursor = xo.newCursor();
0201:                try {
0202:                    cursor.toNextToken();
0203:
0204:                    cursor.beginElement(qname.getLocalPart(), qname
0205:                            .getNamespaceURI());
0206:                    //if(namespace.length() > 0)
0207:                    //    cursor.insertNamespace("", namespace);
0208:                    cursor.insertChars(value);
0209:
0210:                    cursor.toStartDoc();
0211:                    cursor.toNextToken();
0212:                    anno = new XScriptAnnotation(cursor);
0213:                    cursor.setBookmark(anno);
0214:                } finally {
0215:                    cursor.dispose();
0216:                }
0217:
0218:                return new XML(lib, anno);
0219:            }
0220:
0221:            static XML createFromXmlObject(XMLLibImpl lib, XmlObject xo) {
0222:                XScriptAnnotation anno;
0223:                XmlCursor curs = xo.newCursor();
0224:                if (curs.currentTokenType().isStartdoc()) {
0225:                    curs.toFirstContentToken();
0226:                }
0227:                try {
0228:                    anno = new XScriptAnnotation(curs);
0229:                    curs.setBookmark(anno);
0230:                } finally {
0231:                    curs.dispose();
0232:                }
0233:                return new XML(lib, anno);
0234:            }
0235:
0236:            static XML createFromJS(XMLLibImpl lib, Object inputObject) {
0237:                XmlObject xo;
0238:                boolean isText = false;
0239:                String frag;
0240:
0241:                if (inputObject == null || inputObject == Undefined.instance) {
0242:                    frag = "";
0243:                } else if (inputObject instanceof  XMLObjectImpl) {
0244:                    // todo: faster way for XMLObjects?
0245:                    frag = ((XMLObjectImpl) inputObject).toXMLString(0);
0246:                } else {
0247:                    if (inputObject instanceof  Wrapper) {
0248:                        Object wrapped = ((Wrapper) inputObject).unwrap();
0249:                        if (wrapped instanceof  XmlObject) {
0250:                            return createFromXmlObject(lib, (XmlObject) wrapped);
0251:                        }
0252:                    }
0253:                    frag = ScriptRuntime.toString(inputObject);
0254:                }
0255:
0256:                if (frag.trim().startsWith("<>")) {
0257:                    throw ScriptRuntime
0258:                            .typeError("Invalid use of XML object anonymous tags <></>.");
0259:                }
0260:
0261:                if (frag.indexOf("<") == -1) {
0262:                    // Must be solo text node, wrap in XML fragment
0263:                    isText = true;
0264:                    frag = "<textFragment>" + frag + "</textFragment>";
0265:                }
0266:
0267:                XmlOptions options = new XmlOptions();
0268:
0269:                if (lib.ignoreComments) {
0270:                    options.put(XmlOptions.LOAD_STRIP_COMMENTS);
0271:                }
0272:
0273:                if (lib.ignoreProcessingInstructions) {
0274:                    options.put(XmlOptions.LOAD_STRIP_PROCINSTS);
0275:                }
0276:
0277:                if (lib.ignoreWhitespace) {
0278:                    options.put(XmlOptions.LOAD_STRIP_WHITESPACE);
0279:                }
0280:
0281:                try {
0282:                    xo = XmlObject.Factory.parse(frag, options);
0283:
0284:                    // Apply the default namespace
0285:                    Context cx = Context.getCurrentContext();
0286:                    String defaultURI = lib.getDefaultNamespaceURI(cx);
0287:
0288:                    if (defaultURI.length() > 0) {
0289:                        XmlCursor cursor = xo.newCursor();
0290:                        boolean isRoot = true;
0291:                        while (!cursor.toNextToken().isEnddoc()) {
0292:                            if (!cursor.isStart())
0293:                                continue;
0294:
0295:                            // Check if this element explicitly sets the
0296:                            // default namespace
0297:                            boolean defaultNSDeclared = false;
0298:                            cursor.push();
0299:                            while (cursor.toNextToken().isAnyAttr()) {
0300:                                if (cursor.isNamespace()) {
0301:                                    if (cursor.getName().getLocalPart()
0302:                                            .length() == 0) {
0303:                                        defaultNSDeclared = true;
0304:                                        break;
0305:                                    }
0306:                                }
0307:                            }
0308:                            cursor.pop();
0309:                            if (defaultNSDeclared) {
0310:                                cursor.toEndToken();
0311:                                continue;
0312:                            }
0313:
0314:                            // Check if this element's name is in no namespace
0315:                            javax.xml.namespace.QName qname = cursor.getName();
0316:                            if (qname.getNamespaceURI().length() == 0) {
0317:                                // Change the namespace
0318:                                qname = new javax.xml.namespace.QName(
0319:                                        defaultURI, qname.getLocalPart());
0320:                                cursor.setName(qname);
0321:                            }
0322:
0323:                            if (isRoot) {
0324:                                // Declare the default namespace
0325:                                cursor.push();
0326:                                cursor.toNextToken();
0327:                                cursor.insertNamespace("", defaultURI);
0328:                                cursor.pop();
0329:
0330:                                isRoot = false;
0331:                            }
0332:                        }
0333:                        cursor.dispose();
0334:                    }
0335:                } catch (XmlException xe) {
0336:                    /*
0337:                     todo need to handle namespace prefix not found in XML look for namespace type in the scope change.
0338:
0339:                     String errorMsg = "Use of undefined namespace prefix: ";
0340:                     String msg = xe.getError().getMessage();
0341:                     if (msg.startsWith(errorMsg))
0342:                     {
0343:                     String prefix = msg.substring(errorMsg.length());
0344:                     }
0345:                     */
0346:                    String errMsg = xe.getMessage();
0347:                    if (errMsg
0348:                            .equals("error: Unexpected end of file after null")) {
0349:                        // Create an empty document.
0350:                        xo = XmlObject.Factory.newInstance();
0351:                    } else {
0352:                        throw ScriptRuntime.typeError(xe.getMessage());
0353:                    }
0354:                } catch (Throwable e) {
0355:                    // todo: TLL Catch specific exceptions during parse.
0356:                    throw ScriptRuntime.typeError("Not Parsable as XML");
0357:                }
0358:
0359:                XmlCursor curs = xo.newCursor();
0360:                if (curs.currentTokenType().isStartdoc()) {
0361:                    curs.toFirstContentToken();
0362:                }
0363:
0364:                if (isText) {
0365:                    // Move it to point to the text node
0366:                    curs.toFirstContentToken();
0367:                }
0368:
0369:                XScriptAnnotation anno;
0370:                try {
0371:                    anno = new XScriptAnnotation(curs);
0372:                    curs.setBookmark(anno);
0373:                } finally {
0374:                    curs.dispose();
0375:                }
0376:
0377:                return new XML(lib, anno);
0378:            }
0379:
0380:            static XML getFromAnnotation(XMLLibImpl lib, XScriptAnnotation anno) {
0381:                if (anno._xScriptXML == null) {
0382:                    anno._xScriptXML = new XML(lib, anno);
0383:                }
0384:
0385:                return anno._xScriptXML;
0386:            }
0387:
0388:            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0389:            //
0390:            //  Private functions:
0391:            //
0392:            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0393:
0394:            /**
0395:             *
0396:             * @param curs
0397:             * @return
0398:             */
0399:            private static TokenType skipNonElements(XmlCursor curs) {
0400:                TokenType tt = curs.currentTokenType();
0401:                while (tt.isComment() || tt.isProcinst()) {
0402:                    tt = curs.toNextToken();
0403:                }
0404:
0405:                return tt;
0406:            }
0407:
0408:            /**
0409:             *
0410:             * @param curs
0411:             * @return
0412:             */
0413:            protected static XScriptAnnotation findAnnotation(XmlCursor curs) {
0414:                XmlBookmark anno = curs.getBookmark(XScriptAnnotation.class);
0415:                if (anno == null) {
0416:                    anno = new XScriptAnnotation(curs);
0417:                    curs.setBookmark(anno);
0418:                }
0419:
0420:                return (XScriptAnnotation) anno;
0421:            }
0422:
0423:            /**
0424:             *
0425:             * @return
0426:             */
0427:            private XmlOptions getOptions() {
0428:                XmlOptions options = new XmlOptions();
0429:
0430:                if (lib.ignoreComments) {
0431:                    options.put(XmlOptions.LOAD_STRIP_COMMENTS);
0432:                }
0433:
0434:                if (lib.ignoreProcessingInstructions) {
0435:                    options.put(XmlOptions.LOAD_STRIP_PROCINSTS);
0436:                }
0437:
0438:                if (lib.ignoreWhitespace) {
0439:                    options.put(XmlOptions.LOAD_STRIP_WHITESPACE);
0440:                }
0441:
0442:                if (lib.prettyPrinting) {
0443:                    options.put(XmlOptions.SAVE_PRETTY_PRINT, null);
0444:                    options.put(XmlOptions.SAVE_PRETTY_PRINT_INDENT,
0445:                            new Integer(lib.prettyIndent));
0446:                }
0447:
0448:                return options;
0449:            }
0450:
0451:            /**
0452:             *
0453:             * @param cursor
0454:             * @param opts
0455:             * @return
0456:             */
0457:            private static String dumpNode(XmlCursor cursor, XmlOptions opts) {
0458:                if (cursor.isText())
0459:                    return cursor.getChars();
0460:
0461:                if (cursor.isFinish())
0462:                    return "";
0463:
0464:                cursor.push();
0465:                boolean wanRawText = cursor.isStartdoc()
0466:                        && !cursor.toFirstChild();
0467:                cursor.pop();
0468:
0469:                return wanRawText ? cursor.getTextValue() : cursor
0470:                        .xmlText(opts);
0471:            }
0472:
0473:            /**
0474:             *
0475:             * @return
0476:             */
0477:            private XmlCursor newCursor() {
0478:                XmlCursor curs;
0479:
0480:                if (_anno != null) {
0481:                    curs = _anno.createCursor();
0482:                    if (curs == null) {
0483:                        // Orphaned case.
0484:                        XmlObject doc = XmlObject.Factory.newInstance();
0485:                        curs = doc.newCursor();
0486:
0487:                        if (_anno._name != null) {
0488:                            curs.toNextToken();
0489:                            curs.insertElement(_anno._name);
0490:                            curs.toPrevSibling();
0491:                        }
0492:
0493:                        curs.setBookmark(_anno);
0494:                    }
0495:                } else {
0496:                    XmlObject doc = XmlObject.Factory.newInstance();
0497:                    curs = doc.newCursor();
0498:                }
0499:
0500:                return curs;
0501:            }
0502:
0503:            /*
0504:             * fUseStartDoc used by child(int index) the index is at startDoc is the element at the top-level
0505:             *              otherwise we always want to drill in.
0506:             */
0507:            private boolean moveToChild(XmlCursor curs, long index,
0508:                    boolean fFirstChild, boolean fUseStartDoc) {
0509:                if (index < 0)
0510:                    throw new IllegalArgumentException();
0511:
0512:                long idxChild = 0;
0513:
0514:                if (!fUseStartDoc && curs.currentTokenType().isStartdoc()) {
0515:                    // We always move to the children of the top node.
0516:                    // todo:  This assumes that we want have multiple top-level nodes.  Which we should be able tohave.
0517:                    curs.toFirstContentToken();
0518:                }
0519:
0520:                TokenType tt = curs.toFirstContentToken();
0521:                if (!tt.isNone() && !tt.isEnd()) {
0522:                    while (true) {
0523:                        if (index == idxChild) {
0524:                            return true;
0525:                        }
0526:
0527:                        tt = curs.currentTokenType();
0528:                        if (tt.isText()) {
0529:                            curs.toNextToken();
0530:                        } else if (tt.isStart()) {
0531:                            // Need to do this we want to be pointing at the text if that after the end token.
0532:                            curs.toEndToken();
0533:                            curs.toNextToken();
0534:                        } else if (tt.isComment() || tt.isProcinst()) {
0535:                            continue;
0536:                        } else {
0537:                            break;
0538:                        }
0539:
0540:                        idxChild++;
0541:                    }
0542:                } else if (fFirstChild && index == 0) {
0543:                    // Drill into where first child would be.
0544:                    //            curs.toFirstContentToken();
0545:                    return true;
0546:                }
0547:
0548:                return false;
0549:            }
0550:
0551:            /**
0552:             *
0553:             * @return
0554:             */
0555:            XmlCursor.TokenType tokenType() {
0556:                XmlCursor.TokenType result;
0557:
0558:                XmlCursor curs = newCursor();
0559:
0560:                if (curs.isStartdoc()) {
0561:                    curs.toFirstContentToken();
0562:                }
0563:
0564:                result = curs.currentTokenType();
0565:
0566:                curs.dispose();
0567:
0568:                return result;
0569:            }
0570:
0571:            /**
0572:             *
0573:             * @param srcCurs
0574:             * @param destCurs
0575:             * @param fDontMoveIfSame
0576:             * @return
0577:             */
0578:            private boolean moveSrcToDest(XmlCursor srcCurs,
0579:                    XmlCursor destCurs, boolean fDontMoveIfSame) {
0580:                boolean fMovedSomething = true;
0581:                TokenType tt;
0582:                do {
0583:                    if (fDontMoveIfSame && srcCurs.isInSameDocument(destCurs)
0584:                            && (srcCurs.comparePosition(destCurs) == 0)) {
0585:                        // If the source and destination are pointing at the same place then there's nothing to move.
0586:                        fMovedSomething = false;
0587:                        break;
0588:                    }
0589:
0590:                    // todo ***TLL*** Use replaceContents (when added) and eliminate children removes (see above todo).
0591:                    if (destCurs.currentTokenType().isStartdoc()) {
0592:                        destCurs.toNextToken();
0593:                    }
0594:
0595:                    // todo ***TLL*** Can Eric support notion of copy instead of me copying then moving???
0596:                    XmlCursor copyCurs = copy(srcCurs);
0597:
0598:                    copyCurs.moveXml(destCurs);
0599:
0600:                    copyCurs.dispose();
0601:
0602:                    tt = srcCurs.currentTokenType();
0603:                } while (!tt.isStart() && !tt.isEnd() && !tt.isEnddoc());
0604:
0605:                return fMovedSomething;
0606:            }
0607:
0608:            /**
0609:             *
0610:             * @param cursToCopy
0611:             * @return
0612:             */
0613:            private XmlCursor copy(XmlCursor cursToCopy) {
0614:                XmlObject xo = XmlObject.Factory.newInstance();
0615:
0616:                XmlCursor copyCurs = null;
0617:
0618:                if (cursToCopy.currentTokenType().isText()) {
0619:                    try {
0620:                        // Try just as a textnode, to do that we need to wrap the text in a special fragment tag
0621:                        // that is not visible from the XmlCursor.
0622:                        copyCurs = XmlObject.Factory.parse(
0623:                                "<x:fragment xmlns:x=\"http://www.openuri.org/fragment\">"
0624:                                        + cursToCopy.getChars()
0625:                                        + "</x:fragment>").newCursor();
0626:                        if (!cursToCopy.toNextSibling()) {
0627:                            if (cursToCopy.currentTokenType().isText()) {
0628:                                cursToCopy.toNextToken(); // It's not an element it's text so skip it.
0629:                            }
0630:                        }
0631:                    } catch (Exception ex) {
0632:                        throw ScriptRuntime.typeError(ex.getMessage());
0633:                    }
0634:                } else {
0635:                    copyCurs = xo.newCursor();
0636:                    copyCurs.toFirstContentToken();
0637:                    if (cursToCopy.currentTokenType() == XmlCursor.TokenType.STARTDOC) {
0638:                        cursToCopy.toNextToken();
0639:                    }
0640:
0641:                    cursToCopy.copyXml(copyCurs);
0642:                    if (!cursToCopy.toNextSibling()) // If element skip element.
0643:                    {
0644:                        if (cursToCopy.currentTokenType().isText()) {
0645:                            cursToCopy.toNextToken(); // It's not an element it's text so skip it.
0646:                        }
0647:                    }
0648:
0649:                }
0650:
0651:                copyCurs.toStartDoc();
0652:                copyCurs.toFirstContentToken();
0653:
0654:                return copyCurs;
0655:            }
0656:
0657:            private static final int APPEND_CHILD = 1;
0658:            private static final int PREPEND_CHILD = 2;
0659:
0660:            /**
0661:             *
0662:             * @param curs
0663:             * @param xmlToInsert
0664:             */
0665:            private void insertChild(XmlCursor curs, Object xmlToInsert) {
0666:                if (xmlToInsert == null || xmlToInsert instanceof  Undefined) {
0667:                    // Do nothing
0668:                } else if (xmlToInsert instanceof  XmlCursor) {
0669:                    moveSrcToDest((XmlCursor) xmlToInsert, curs, true);
0670:                } else if (xmlToInsert instanceof  XML) {
0671:                    XML xmlValue = (XML) xmlToInsert;
0672:
0673:                    // If it's an attribute, then change to text node
0674:                    if (xmlValue.tokenType() == XmlCursor.TokenType.ATTR) {
0675:                        insertChild(curs, xmlValue.toString());
0676:                    } else {
0677:                        XmlCursor cursToInsert = ((XML) xmlToInsert)
0678:                                .newCursor();
0679:
0680:                        moveSrcToDest(cursToInsert, curs, true);
0681:
0682:                        cursToInsert.dispose();
0683:                    }
0684:                } else if (xmlToInsert instanceof  XMLList) {
0685:                    XMLList list = (XMLList) xmlToInsert;
0686:
0687:                    for (int i = 0; i < list.length(); i++) {
0688:                        insertChild(curs, list.item(i));
0689:                    }
0690:                } else {
0691:                    // Convert to string and make XML out of it
0692:                    String xmlStr = ScriptRuntime.toString(xmlToInsert);
0693:                    XmlObject xo = XmlObject.Factory.newInstance(); // Create an empty document.
0694:
0695:                    XmlCursor sourceCurs = xo.newCursor();
0696:                    sourceCurs.toNextToken();
0697:
0698:                    // To hold the text.
0699:                    sourceCurs.insertChars(xmlStr);
0700:
0701:                    sourceCurs.toPrevToken();
0702:
0703:                    // Call us again with the cursor.
0704:                    moveSrcToDest(sourceCurs, curs, true);
0705:                }
0706:            }
0707:
0708:            /**
0709:             *
0710:             * @param childToMatch
0711:             * @param xmlToInsert
0712:             * @param addToType
0713:             */
0714:            private void insertChild(XML childToMatch, Object xmlToInsert,
0715:                    int addToType) {
0716:                XmlCursor curs = newCursor();
0717:                TokenType tt = curs.currentTokenType();
0718:                XmlCursor xmlChildCursor = childToMatch.newCursor();
0719:
0720:                if (tt.isStartdoc()) {
0721:                    tt = curs.toFirstContentToken();
0722:                }
0723:
0724:                if (tt.isContainer()) {
0725:                    tt = curs.toNextToken();
0726:
0727:                    while (!tt.isEnd()) {
0728:                        if (tt.isStart()) {
0729:                            // See if this child is the same as the one thep passed in
0730:                            if (curs.comparePosition(xmlChildCursor) == 0) {
0731:                                // Found it
0732:                                if (addToType == APPEND_CHILD) {
0733:                                    // Move the cursor to just past the end of this element
0734:                                    curs.toEndToken();
0735:                                    curs.toNextToken();
0736:                                }
0737:
0738:                                insertChild(curs, xmlToInsert);
0739:                                break;
0740:                            }
0741:                        }
0742:
0743:                        // Skip over child elements
0744:                        if (tt.isStart()) {
0745:                            tt = curs.toEndToken();
0746:                        }
0747:
0748:                        tt = curs.toNextToken();
0749:                    }
0750:
0751:                }
0752:
0753:                xmlChildCursor.dispose();
0754:                curs.dispose();
0755:            }
0756:
0757:            /**
0758:             *
0759:             * @param curs
0760:             */
0761:            protected void removeToken(XmlCursor curs) {
0762:                XmlObject xo = XmlObject.Factory.newInstance();
0763:
0764:                // Don't delete anything move to another document so it gets orphaned nicely.
0765:                XmlCursor tmpCurs = xo.newCursor();
0766:                tmpCurs.toFirstContentToken();
0767:
0768:                curs.moveXml(tmpCurs);
0769:
0770:                tmpCurs.dispose();
0771:            }
0772:
0773:            /**
0774:             *
0775:             * @param index
0776:             */
0777:            protected void removeChild(long index) {
0778:                XmlCursor curs = newCursor();
0779:
0780:                if (moveToChild(curs, index, false, false)) {
0781:                    removeToken(curs);
0782:                }
0783:
0784:                curs.dispose();
0785:            }
0786:
0787:            /**
0788:             *
0789:             * @param name
0790:             * @return
0791:             */
0792:            protected static javax.xml.namespace.QName computeQName(Object name) {
0793:                if (name instanceof  String) {
0794:                    String ns = null;
0795:                    String localName = null;
0796:
0797:                    String fullName = (String) name;
0798:                    localName = fullName;
0799:                    if (fullName.startsWith("\"")) {
0800:                        int idx = fullName.indexOf(":");
0801:                        if (idx != -1) {
0802:                            ns = fullName.substring(1, idx - 1); // Don't include the "" around the namespace
0803:                            localName = fullName.substring(idx + 1);
0804:                        }
0805:                    }
0806:
0807:                    if (ns == null) {
0808:                        return new javax.xml.namespace.QName(localName);
0809:                    } else {
0810:                        return new javax.xml.namespace.QName(ns, localName);
0811:                    }
0812:                }
0813:
0814:                return null;
0815:            }
0816:
0817:            /**
0818:             *
0819:             * @param destCurs
0820:             * @param newValue
0821:             */
0822:            private void replace(XmlCursor destCurs, XML newValue) {
0823:                if (destCurs.isStartdoc()) {
0824:                    // Can't overwrite a whole document (user really wants to overwrite the contents of).
0825:                    destCurs.toFirstContentToken();
0826:                }
0827:
0828:                // Orphan the token -- don't delete it outright on the XmlCursor.
0829:                removeToken(destCurs);
0830:
0831:                XmlCursor srcCurs = newValue.newCursor();
0832:                if (srcCurs.currentTokenType().isStartdoc()) {
0833:                    // Cann't append a whole document (user really wants to append the contents of).
0834:                    srcCurs.toFirstContentToken();
0835:                }
0836:
0837:                moveSrcToDest(srcCurs, destCurs, false);
0838:
0839:                // Re-link a new annotation to this cursor -- we just deleted the previous annotation on entrance to replace.
0840:                if (!destCurs.toPrevSibling()) {
0841:                    destCurs.toPrevToken();
0842:                }
0843:                destCurs.setBookmark(new XScriptAnnotation(destCurs));
0844:
0845:                // todo would be nice if destCurs.toNextSibling went to where the next token if the cursor was pointing at the last token in the stream.
0846:                destCurs.toEndToken();
0847:                destCurs.toNextToken();
0848:
0849:                srcCurs.dispose();
0850:            }
0851:
0852:            /**
0853:             *
0854:             * @param currXMLNode
0855:             * @param xmlValue
0856:             * @return
0857:             */
0858:            private boolean doPut(XMLName name, XML currXMLNode,
0859:                    XMLObjectImpl xmlValue) {
0860:                boolean result = false;
0861:                XmlCursor curs = currXMLNode.newCursor();
0862:
0863:                try {
0864:                    // Replace the node with this new xml value.
0865:                    XML xml;
0866:
0867:                    int toAssignLen = xmlValue.length();
0868:
0869:                    for (int i = 0; i < toAssignLen; i++) {
0870:                        if (xmlValue instanceof  XMLList) {
0871:                            xml = ((XMLList) xmlValue).item(i);
0872:                        } else {
0873:                            xml = (XML) xmlValue;
0874:                        }
0875:
0876:                        // If it's an attribute or text node, make text node.
0877:                        XmlCursor.TokenType tt = xml.tokenType();
0878:                        if (tt == XmlCursor.TokenType.ATTR
0879:                                || tt == XmlCursor.TokenType.TEXT) {
0880:                            xml = makeXmlFromString(lib, name, xml.toString());
0881:                        }
0882:
0883:                        if (i == 0) {
0884:                            // 1st assignment is replaceChild all others are appendChild
0885:                            replace(curs, xml);
0886:                        } else {
0887:                            insertChild(curs, xml);
0888:                        }
0889:                    }
0890:
0891:                    // We're done we've blown away the node because the rvalue was XML...
0892:                    result = true;
0893:                } catch (Exception ex) {
0894:                    ex.printStackTrace();
0895:                    throw ScriptRuntime.typeError(ex.getMessage());
0896:                } finally {
0897:                    curs.dispose();
0898:                }
0899:
0900:                return result;
0901:            }
0902:
0903:            /**
0904:             * Make a text node element with this element name and text value.
0905:             *
0906:             * @param name
0907:             * @param value
0908:             * @return
0909:             */
0910:            private XML makeXmlFromString(XMLLibImpl lib, XMLName name,
0911:                    String value) {
0912:                XML result;
0913:
0914:                javax.xml.namespace.QName qname;
0915:
0916:                try {
0917:                    qname = new javax.xml.namespace.QName(name.uri(), name
0918:                            .localName());
0919:                } catch (Exception e) {
0920:                    throw ScriptRuntime.typeError(e.getMessage());
0921:                }
0922:
0923:                result = createTextElement(lib, qname, value);
0924:
0925:                return result;
0926:            }
0927:
0928:            /**
0929:             *
0930:             * @param name
0931:             * @return
0932:             */
0933:            private XMLList matchAttributes(XMLName xmlName) {
0934:                XMLList result = new XMLList(lib);
0935:                XmlCursor curs = newCursor();
0936:
0937:                if (curs.currentTokenType().isStartdoc()) {
0938:                    curs.toFirstContentToken();
0939:                }
0940:
0941:                if (curs.isStart()) {
0942:                    if (curs.toFirstAttribute()) {
0943:                        do {
0944:                            if (qnameMatches(xmlName, curs.getName())) {
0945:                                result.addToList(createAttributeObject(curs));
0946:                            }
0947:                        } while (curs.toNextAttribute());
0948:                    }
0949:                }
0950:
0951:                curs.dispose();
0952:
0953:                return result;
0954:            }
0955:
0956:            /**
0957:             *
0958:             * @param attrCurs
0959:             * @return
0960:             */
0961:            private XML createAttributeObject(XmlCursor attrCurs) {
0962:                XML result = null;
0963:
0964:                if (attrCurs.currentTokenType().isAttr()) {
0965:                    result = createAttributeXML(lib, attrCurs);
0966:                }
0967:
0968:                return result;
0969:            }
0970:
0971:            //
0972:            //
0973:            //  methods overriding ScriptableObject
0974:            //
0975:            //
0976:
0977:            public String getClassName() {
0978:                return "XML";
0979:            }
0980:
0981:            //
0982:            //
0983:            //  methods overriding IdScriptableObject
0984:            //
0985:            //
0986:
0987:            /**
0988:             * XML[0] should return this, all other indexes are Undefined
0989:             *
0990:             * @param index
0991:             * @param start
0992:             * @return
0993:             */
0994:            public Object get(int index, Scriptable start) {
0995:                //Log("get index: " + index);
0996:
0997:                if (index == 0) {
0998:                    return this ;
0999:                } else {
1000:                    return Scriptable.NOT_FOUND;
1001:                }
1002:            }
1003:
1004:            /**
1005:             * Does the named property exist
1006:             *
1007:             * @param name
1008:             * @param start
1009:             * @return
1010:             */
1011:            boolean hasXMLProperty(XMLName xmlName) {
1012:                boolean result = false;
1013:
1014:                if (prototypeFlag) {
1015:                    String name = xmlName.localName();
1016:
1017:                    if (getMethod(name) != NOT_FOUND) {
1018:                        result = true;
1019:                    }
1020:                } else {
1021:                    // Has now should return true if the property would have results > 0 or
1022:                    // if it's a method name
1023:                    String name = xmlName.localName();
1024:                    if ((getPropertyList(xmlName).length() > 0)
1025:                            || (getMethod(name) != NOT_FOUND)) {
1026:                        result = true;
1027:                    }
1028:                }
1029:
1030:                return result;
1031:            }
1032:
1033:            /**
1034:             *
1035:             * @param index
1036:             * @param start
1037:             * @return
1038:             */
1039:            public boolean has(int index, Scriptable start) {
1040:                return (index == 0);
1041:            }
1042:
1043:            /**
1044:             *
1045:             * @return
1046:             */
1047:            public Object[] getIds() {
1048:                Object[] enumObjs;
1049:
1050:                if (prototypeFlag) {
1051:                    enumObjs = new Object[0];
1052:                } else {
1053:                    enumObjs = new Object[1];
1054:
1055:                    enumObjs[0] = new Integer(0);
1056:                }
1057:
1058:                return enumObjs;
1059:            }
1060:
1061:            /**
1062:             *
1063:             * @return
1064:             */
1065:            public Object[] getIdsForDebug() {
1066:                return getIds();
1067:            }
1068:
1069:            /**
1070:             *
1071:             * @param name
1072:             * @param start
1073:             * @return
1074:             */
1075:            Object getXMLProperty(XMLName xmlName) {
1076:                Object result = NOT_FOUND;
1077:
1078:                if (prototypeFlag) {
1079:                    String name = xmlName.localName();
1080:
1081:                    result = getMethod(name);
1082:                } else {
1083:                    result = getPropertyList(xmlName);
1084:                }
1085:
1086:                return result;
1087:            }
1088:
1089:            /**
1090:             *
1091:             * @param name
1092:             * @param start
1093:             * @param value
1094:             */
1095:            void putXMLProperty(XMLName xmlName, Object value) {
1096:                //Log("put property: " + name + " value: " + value.getClass());
1097:
1098:                if (prototypeFlag) {
1099:                } else {
1100:                    // Special-case checks for undefined and null
1101:                    if (value == null) {
1102:                        value = "null";
1103:                    } else if (value instanceof  Undefined) {
1104:                        value = "undefined";
1105:                    }
1106:
1107:                    // Get the named property
1108:                    if (xmlName.isAttributeName()) {
1109:                        setAttribute(xmlName, value);
1110:                    } else if (xmlName.uri() == null
1111:                            && xmlName.localName().equals("*")) {
1112:                        setChildren(value);
1113:                    } else {
1114:                        // Convert text into XML if needed.
1115:                        XMLObjectImpl xmlValue = null;
1116:
1117:                        if (value instanceof  XMLObjectImpl) {
1118:                            xmlValue = (XMLObjectImpl) value;
1119:
1120:                            // Check for attribute type and convert to textNode
1121:                            if (xmlValue instanceof  XML) {
1122:                                if (((XML) xmlValue).tokenType() == XmlCursor.TokenType.ATTR) {
1123:                                    xmlValue = makeXmlFromString(lib, xmlName,
1124:                                            xmlValue.toString());
1125:                                }
1126:                            }
1127:
1128:                            if (xmlValue instanceof  XMLList) {
1129:                                for (int i = 0; i < xmlValue.length(); i++) {
1130:                                    XML xml = ((XMLList) xmlValue).item(i);
1131:
1132:                                    if (xml.tokenType() == XmlCursor.TokenType.ATTR) {
1133:                                        ((XMLList) xmlValue).replace(i,
1134:                                                makeXmlFromString(lib, xmlName,
1135:                                                        xml.toString()));
1136:                                    }
1137:                                }
1138:                            }
1139:                        } else {
1140:                            xmlValue = makeXmlFromString(lib, xmlName,
1141:                                    ScriptRuntime.toString(value));
1142:                        }
1143:
1144:                        XMLList matches = getPropertyList(xmlName);
1145:
1146:                        if (matches.length() == 0) {
1147:                            appendChild(xmlValue);
1148:                        } else {
1149:                            // Remove all other matches
1150:                            for (int i = 1; i < matches.length(); i++) {
1151:                                removeChild(matches.item(i).childIndex());
1152:                            }
1153:
1154:                            // Replace first match with new value.
1155:                            doPut(xmlName, matches.item(0), xmlValue);
1156:                        }
1157:                    }
1158:                }
1159:            }
1160:
1161:            /**
1162:             *
1163:             * @param index
1164:             * @param start
1165:             * @param value
1166:             */
1167:            public void put(int index, Scriptable start, Object value) {
1168:                // Spec says assignment to indexed XML object should return type error
1169:                throw ScriptRuntime
1170:                        .typeError("Assignment to indexed XML is not allowed");
1171:            }
1172:
1173:            /**
1174:             *
1175:             * @param name
1176:             */
1177:            void deleteXMLProperty(XMLName name) {
1178:                if (!name.isDescendants() && name.isAttributeName()) {
1179:                    XmlCursor curs = newCursor();
1180:
1181:                    // TODO: Cover the case *::name
1182:                    if (name.localName().equals("*")) {
1183:                        // Delete all attributes.
1184:                        if (curs.toFirstAttribute()) {
1185:                            while (curs.currentTokenType().isAttr()) {
1186:                                curs.removeXml();
1187:                            }
1188:                        }
1189:                    } else {
1190:                        // Delete an attribute.
1191:                        javax.xml.namespace.QName qname = new javax.xml.namespace.QName(
1192:                                name.uri(), name.localName());
1193:                        curs.removeAttribute(qname);
1194:                    }
1195:
1196:                    curs.dispose();
1197:                } else {
1198:                    XMLList matches = getPropertyList(name);
1199:
1200:                    matches.remove();
1201:                }
1202:            }
1203:
1204:            /**
1205:             *
1206:             * @param index
1207:             */
1208:            public void delete(int index) {
1209:                if (index == 0) {
1210:                    remove();
1211:                }
1212:            }
1213:
1214:            //
1215:            //
1216:            //  package utility functions:
1217:            //
1218:            //
1219:
1220:            protected XScriptAnnotation getAnnotation() {
1221:                return _anno;
1222:            }
1223:
1224:            protected void changeNS(String oldURI, String newURI) {
1225:                XmlCursor curs = newCursor();
1226:                while (curs.toParent()) {
1227:                    /* Goto the top of the document */
1228:                }
1229:
1230:                TokenType tt = curs.currentTokenType();
1231:                if (tt.isStartdoc()) {
1232:                    tt = curs.toFirstContentToken();
1233:                }
1234:
1235:                if (tt.isStart()) {
1236:                    do {
1237:                        if (tt.isStart() || tt.isAttr() || tt.isNamespace()) {
1238:                            javax.xml.namespace.QName currQName = curs
1239:                                    .getName();
1240:                            if (oldURI.equals(currQName.getNamespaceURI())) {
1241:                                curs.setName(new javax.xml.namespace.QName(
1242:                                        newURI, currQName.getLocalPart()));
1243:                            }
1244:                        }
1245:
1246:                        tt = curs.toNextToken();
1247:                    } while (!tt.isEnddoc() && !tt.isNone());
1248:                }
1249:
1250:                curs.dispose();
1251:            }
1252:
1253:            /**
1254:             *
1255:             */
1256:            void remove() {
1257:                XmlCursor childCurs = newCursor();
1258:
1259:                if (childCurs.currentTokenType().isStartdoc()) {
1260:                    // Remove on the document removes all children.
1261:                    TokenType tt = childCurs.toFirstContentToken();
1262:                    while (!tt.isEnd() && !tt.isEnddoc()) {
1263:                        removeToken(childCurs);
1264:                        tt = childCurs.currentTokenType(); // Now see where we're pointing after the delete -- next token.
1265:                    }
1266:                } else {
1267:                    removeToken(childCurs);
1268:                }
1269:
1270:                childCurs.dispose();
1271:            }
1272:
1273:            /**
1274:             *
1275:             * @param value
1276:             */
1277:            void replaceAll(XML value) {
1278:                XmlCursor curs = newCursor();
1279:
1280:                replace(curs, value);
1281:                _anno = value._anno;
1282:
1283:                curs.dispose();
1284:            }
1285:
1286:            /**
1287:             *
1288:             * @param attrName
1289:             * @param value
1290:             */
1291:            void setAttribute(XMLName xmlName, Object value) {
1292:                if (xmlName.uri() == null && xmlName.localName().equals("*")) {
1293:                    throw ScriptRuntime
1294:                            .typeError("@* assignment not supported.");
1295:                }
1296:
1297:                XmlCursor curs = newCursor();
1298:
1299:                String strValue = ScriptRuntime.toString(value);
1300:                if (curs.currentTokenType().isStartdoc()) {
1301:                    curs.toFirstContentToken();
1302:                }
1303:
1304:                javax.xml.namespace.QName qName;
1305:
1306:                try {
1307:                    qName = new javax.xml.namespace.QName(xmlName.uri(),
1308:                            xmlName.localName());
1309:                } catch (Exception e) {
1310:                    throw ScriptRuntime.typeError(e.getMessage());
1311:                }
1312:
1313:                if (!curs.setAttributeText(qName, strValue)) {
1314:                    if (curs.currentTokenType().isStart()) {
1315:                        // Can only add attributes inside of a start.
1316:                        curs.toNextToken();
1317:                    }
1318:                    curs.insertAttributeWithValue(qName, strValue);
1319:                }
1320:
1321:                curs.dispose();
1322:            }
1323:
1324:            /**
1325:             *
1326:             * @param namespace
1327:             * @return
1328:             */
1329:            private XMLList allChildNodes(String namespace) {
1330:                XMLList result = new XMLList(lib);
1331:                XmlCursor curs = newCursor();
1332:                TokenType tt = curs.currentTokenType();
1333:                javax.xml.namespace.QName targetProperty = new javax.xml.namespace.QName(
1334:                        namespace, "*");
1335:
1336:                if (tt.isStartdoc()) {
1337:                    tt = curs.toFirstContentToken();
1338:                }
1339:
1340:                if (tt.isContainer()) {
1341:                    tt = curs.toFirstContentToken();
1342:
1343:                    while (!tt.isEnd()) {
1344:                        if (!tt.isStart()) {
1345:                            // Not an element
1346:                            result.addToList(findAnnotation(curs));
1347:
1348:                            // Reset target property to null in this case
1349:                            targetProperty = null;
1350:                        } else {
1351:                            // Match namespace as well if specified
1352:                            if (namespace == null
1353:                                    || namespace.length() == 0
1354:                                    || namespace.equals("*")
1355:                                    || curs.getName().getNamespaceURI().equals(
1356:                                            namespace)) {
1357:                                // Add it to the list
1358:                                result.addToList(findAnnotation(curs));
1359:
1360:                                // Set target property if target name is "*",
1361:                                // Otherwise if target property does not match current, then
1362:                                // set to null
1363:                                if (targetProperty != null) {
1364:                                    if (targetProperty.getLocalPart().equals(
1365:                                            "*")) {
1366:                                        targetProperty = curs.getName();
1367:                                    } else if (!targetProperty.getLocalPart()
1368:                                            .equals(
1369:                                                    curs.getName()
1370:                                                            .getLocalPart())) {
1371:                                        // Not a match, unset target property
1372:                                        targetProperty = null;
1373:                                    }
1374:                                }
1375:                            }
1376:                        }
1377:
1378:                        // Skip over child elements
1379:                        if (tt.isStart()) {
1380:                            tt = curs.toEndToken();
1381:                        }
1382:
1383:                        tt = curs.toNextToken();
1384:                    }
1385:                }
1386:
1387:                curs.dispose();
1388:
1389:                // Set the targets for this XMLList.
1390:                result.setTargets(this , targetProperty);
1391:
1392:                return result;
1393:            }
1394:
1395:            /**
1396:             *
1397:             * @return
1398:             */
1399:            private XMLList matchDescendantAttributes(XMLName xmlName) {
1400:                XMLList result = new XMLList(lib);
1401:                XmlCursor curs = newCursor();
1402:                TokenType tt = curs.currentTokenType();
1403:
1404:                // Set the targets for this XMLList.
1405:                result.setTargets(this , null);
1406:
1407:                if (tt.isStartdoc()) {
1408:                    tt = curs.toFirstContentToken();
1409:                }
1410:
1411:                if (tt.isContainer()) {
1412:                    int nestLevel = 1;
1413:
1414:                    while (nestLevel > 0) {
1415:                        tt = curs.toNextToken();
1416:
1417:                        // Only try to match names for attributes
1418:                        if (tt.isAttr()) {
1419:                            if (qnameMatches(xmlName, curs.getName())) {
1420:                                result.addToList(findAnnotation(curs));
1421:                            }
1422:                        }
1423:
1424:                        if (tt.isStart()) {
1425:                            nestLevel++;
1426:                        } else if (tt.isEnd()) {
1427:                            nestLevel--;
1428:                        } else if (tt.isEnddoc()) {
1429:                            // Shouldn't get here, but just in case.
1430:                            break;
1431:                        }
1432:                    }
1433:                }
1434:
1435:                curs.dispose();
1436:
1437:                return result;
1438:            }
1439:
1440:            /**
1441:             *
1442:             * @return
1443:             */
1444:            private XMLList matchDescendantChildren(XMLName xmlName) {
1445:                XMLList result = new XMLList(lib);
1446:                XmlCursor curs = newCursor();
1447:                TokenType tt = curs.currentTokenType();
1448:
1449:                // Set the targets for this XMLList.
1450:                result.setTargets(this , null);
1451:
1452:                if (tt.isStartdoc()) {
1453:                    tt = curs.toFirstContentToken();
1454:                }
1455:
1456:                if (tt.isContainer()) {
1457:                    int nestLevel = 1;
1458:
1459:                    while (nestLevel > 0) {
1460:                        tt = curs.toNextToken();
1461:
1462:                        if (!tt.isAttr() && !tt.isEnd() && !tt.isEnddoc()) {
1463:                            // Only try to match names for elements or processing instructions.
1464:                            if (!tt.isStart() && !tt.isProcinst()) {
1465:                                // Not an element or procinst, only add if qname is all
1466:                                if (xmlName.localName().equals("*")) {
1467:                                    result.addToList(findAnnotation(curs));
1468:                                }
1469:                            } else {
1470:                                if (qnameMatches(xmlName, curs.getName())) {
1471:                                    result.addToList(findAnnotation(curs));
1472:                                }
1473:                            }
1474:                        }
1475:
1476:                        if (tt.isStart()) {
1477:                            nestLevel++;
1478:                        } else if (tt.isEnd()) {
1479:                            nestLevel--;
1480:                        } else if (tt.isEnddoc()) {
1481:                            // Shouldn't get here, but just in case.
1482:                            break;
1483:                        }
1484:                    }
1485:                }
1486:
1487:                curs.dispose();
1488:
1489:                return result;
1490:            }
1491:
1492:            /**
1493:             *
1494:             * @param tokenType
1495:             * @return
1496:             */
1497:            private XMLList matchChildren(XmlCursor.TokenType tokenType) {
1498:                return matchChildren(tokenType, XMLName.formStar());
1499:            }
1500:
1501:            /**
1502:             *
1503:             * @return
1504:             */
1505:            private XMLList matchChildren(XmlCursor.TokenType tokenType,
1506:                    XMLName name) {
1507:                XMLList result = new XMLList(lib);
1508:                XmlCursor curs = newCursor();
1509:                TokenType tt = curs.currentTokenType();
1510:                javax.xml.namespace.QName qname = new javax.xml.namespace.QName(
1511:                        name.uri(), name.localName());
1512:                javax.xml.namespace.QName targetProperty = qname;
1513:
1514:                if (tt.isStartdoc()) {
1515:                    tt = curs.toFirstContentToken();
1516:                }
1517:
1518:                if (tt.isContainer()) {
1519:                    tt = curs.toFirstContentToken();
1520:
1521:                    while (!tt.isEnd()) {
1522:                        if (tt == tokenType) {
1523:                            // Only try to match names for elements or processing instructions.
1524:                            if (!tt.isStart() && !tt.isProcinst()) {
1525:                                // Not an element or no name specified.
1526:                                result.addToList(findAnnotation(curs));
1527:
1528:                                // Reset target property to null in this case
1529:                                targetProperty = null;
1530:                            } else {
1531:                                // Match names as well
1532:                                if (qnameMatches(name, curs.getName())) {
1533:                                    // Add it to the list
1534:                                    result.addToList(findAnnotation(curs));
1535:
1536:                                    // Set target property if target name is "*",
1537:                                    // Otherwise if target property does not match current, then
1538:                                    // set to null
1539:                                    if (targetProperty != null) {
1540:                                        if (targetProperty.getLocalPart()
1541:                                                .equals("*")) {
1542:                                            targetProperty = curs.getName();
1543:                                        } else if (!targetProperty
1544:                                                .getLocalPart()
1545:                                                .equals(
1546:                                                        curs.getName()
1547:                                                                .getLocalPart())) {
1548:                                            // Not a match, unset target property
1549:                                            targetProperty = null;
1550:                                        }
1551:                                    }
1552:                                }
1553:                            }
1554:                        }
1555:
1556:                        // Skip over child elements
1557:                        if (tt.isStart()) {
1558:                            tt = curs.toEndToken();
1559:                        }
1560:
1561:                        tt = curs.toNextToken();
1562:                    }
1563:                }
1564:
1565:                curs.dispose();
1566:
1567:                if (tokenType == XmlCursor.TokenType.START) {
1568:                    // Set the targets for this XMLList.
1569:                    result.setTargets(this , targetProperty);
1570:                }
1571:
1572:                return result;
1573:
1574:            }
1575:
1576:            /**
1577:             *
1578:             * @param template
1579:             * @param match
1580:             * @return
1581:             */
1582:            private boolean qnameMatches(XMLName template,
1583:                    javax.xml.namespace.QName match) {
1584:                boolean matches = false;
1585:
1586:                if (template.uri() == null
1587:                        || template.uri().equals(match.getNamespaceURI())) {
1588:                    // URI OK, test name
1589:                    if (template.localName().equals("*")
1590:                            || template.localName()
1591:                                    .equals(match.getLocalPart())) {
1592:                        matches = true;
1593:                    }
1594:                }
1595:
1596:                return matches;
1597:            }
1598:
1599:            //
1600:            //
1601:            // Methods from section 12.4.4 in the spec
1602:            //
1603:            //
1604:
1605:            /**
1606:             * The addNamespace method adds a namespace declaration to the in scope
1607:             * namespaces for this XML object and returns this XML object.
1608:             *
1609:             * @param toAdd
1610:             */
1611:            XML addNamespace(Namespace ns) {
1612:                // When a namespace is used it will be added automatically
1613:                // to the inScopeNamespaces set. There is no need to add
1614:                // Namespaces with undefined prefixes.
1615:                String nsPrefix = ns.prefix();
1616:                if (nsPrefix == null)
1617:                    return this ;
1618:
1619:                XmlCursor cursor = newCursor();
1620:
1621:                try {
1622:                    if (!cursor.isContainer())
1623:                        return this ;
1624:
1625:                    javax.xml.namespace.QName qname = cursor.getName();
1626:                    // Don't add a default namespace declarations to containers
1627:                    // with QNames in no namespace.
1628:                    if (qname.getNamespaceURI().equals("")
1629:                            && nsPrefix.equals(""))
1630:                        return this ;
1631:
1632:                    // Get all declared namespaces that are in scope
1633:                    Map prefixToURI = NamespaceHelper.getAllNamespaces(lib,
1634:                            cursor);
1635:
1636:                    String uri = (String) prefixToURI.get(nsPrefix);
1637:                    if (uri != null) {
1638:                        // Check if the Namespace is not already in scope
1639:                        if (uri.equals(ns.uri()))
1640:                            return this ;
1641:
1642:                        cursor.push();
1643:
1644:                        // Let's see if we have to delete a namespace declaration
1645:                        while (cursor.toNextToken().isAnyAttr()) {
1646:                            if (cursor.isNamespace()) {
1647:                                qname = cursor.getName();
1648:                                String prefix = qname.getLocalPart();
1649:                                if (prefix.equals(nsPrefix)) {
1650:                                    // Delete the current Namespace declaration
1651:                                    cursor.removeXml();
1652:                                    break;
1653:                                }
1654:                            }
1655:                        }
1656:
1657:                        cursor.pop();
1658:                    }
1659:
1660:                    cursor.toNextToken();
1661:                    cursor.insertNamespace(nsPrefix, ns.uri());
1662:                } finally {
1663:                    cursor.dispose();
1664:                }
1665:
1666:                return this ;
1667:            }
1668:
1669:            /**
1670:             *
1671:             * @param xml
1672:             * @return
1673:             */
1674:            XML appendChild(Object xml) {
1675:                XmlCursor curs = newCursor();
1676:
1677:                if (curs.isStartdoc()) {
1678:                    curs.toFirstContentToken();
1679:                }
1680:
1681:                // Move the cursor to the end of this element
1682:                if (curs.isStart()) {
1683:                    curs.toEndToken();
1684:                }
1685:
1686:                insertChild(curs, xml);
1687:
1688:                curs.dispose();
1689:
1690:                return this ;
1691:            }
1692:
1693:            /**
1694:             *
1695:             * @param name
1696:             * @return
1697:             */
1698:            XMLList attribute(XMLName xmlName) {
1699:                return matchAttributes(xmlName);
1700:            }
1701:
1702:            /**
1703:             *
1704:             * @return
1705:             */
1706:            XMLList attributes() {
1707:                XMLName xmlName = XMLName.formStar();
1708:                return matchAttributes(xmlName);
1709:            }
1710:
1711:            XMLList child(long index) {
1712:                XMLList result = new XMLList(lib);
1713:                result.setTargets(this , null);
1714:                result.addToList(getXmlChild(index));
1715:                return result;
1716:            }
1717:
1718:            XMLList child(XMLName xmlName) {
1719:                if (xmlName == null)
1720:                    return new XMLList(lib);
1721:
1722:                XMLList result;
1723:                if (xmlName.localName().equals("*")) {
1724:                    result = allChildNodes(xmlName.uri());
1725:                } else {
1726:                    result = matchChildren(XmlCursor.TokenType.START, xmlName);
1727:                }
1728:
1729:                return result;
1730:            }
1731:
1732:            /**
1733:             *
1734:             * @param index
1735:             * @return
1736:             */
1737:            XML getXmlChild(long index) {
1738:                XML result = null;
1739:                XmlCursor curs = newCursor();
1740:
1741:                if (moveToChild(curs, index, false, true)) {
1742:                    result = createXML(lib, curs);
1743:                }
1744:
1745:                curs.dispose();
1746:
1747:                return result;
1748:            }
1749:
1750:            /**
1751:             *
1752:             * @return
1753:             */
1754:            int childIndex() {
1755:                int index = 0;
1756:
1757:                XmlCursor curs = newCursor();
1758:
1759:                TokenType tt = curs.currentTokenType();
1760:                while (true) {
1761:                    if (tt.isText()) {
1762:                        index++;
1763:                        if (!curs.toPrevSibling()) {
1764:                            break;
1765:                        }
1766:                    } else if (tt.isStart()) {
1767:                        tt = curs.toPrevToken();
1768:                        if (tt.isEnd()) {
1769:                            curs.toNextToken();
1770:                            if (!curs.toPrevSibling()) {
1771:                                break;
1772:                            }
1773:
1774:                            index++;
1775:                        } else {
1776:                            // Hit the parent start tag so get out we're down counting children.
1777:                            break;
1778:                        }
1779:                    } else if (tt.isComment() || tt.isProcinst()) {
1780:                        curs.toPrevToken();
1781:                    } else {
1782:                        break;
1783:                    }
1784:
1785:                    tt = curs.currentTokenType();
1786:                }
1787:
1788:                index = curs.currentTokenType().isStartdoc() ? -1 : index;
1789:
1790:                curs.dispose();
1791:
1792:                return index;
1793:            }
1794:
1795:            /**
1796:             *
1797:             * @return
1798:             */
1799:            XMLList children() {
1800:                return allChildNodes(null);
1801:            }
1802:
1803:            /**
1804:             *
1805:             * @return
1806:             */
1807:            XMLList comments() {
1808:                return matchChildren(XmlCursor.TokenType.COMMENT);
1809:            }
1810:
1811:            /**
1812:             *
1813:             * @param xml
1814:             * @return
1815:             */
1816:            boolean contains(Object xml) {
1817:                boolean result = false;
1818:
1819:                if (xml instanceof  XML) {
1820:                    result = equivalentXml(xml);
1821:                }
1822:
1823:                return result;
1824:            }
1825:
1826:            /**
1827:             *
1828:             * @return
1829:             */
1830:            Object copy() {
1831:                XmlCursor srcCurs = newCursor();
1832:
1833:                if (srcCurs.isStartdoc()) {
1834:                    srcCurs.toFirstContentToken();
1835:                }
1836:
1837:                XML xml = createEmptyXML(lib);
1838:
1839:                XmlCursor destCurs = xml.newCursor();
1840:                destCurs.toFirstContentToken();
1841:
1842:                srcCurs.copyXml(destCurs);
1843:
1844:                destCurs.dispose();
1845:                srcCurs.dispose();
1846:
1847:                return xml;
1848:            }
1849:
1850:            /**
1851:             *
1852:             * @param name
1853:             * @return
1854:             */
1855:            XMLList descendants(XMLName xmlName) {
1856:                XMLList result;
1857:                if (xmlName.isAttributeName()) {
1858:                    result = matchDescendantAttributes(xmlName);
1859:                } else {
1860:                    result = matchDescendantChildren(xmlName);
1861:                }
1862:
1863:                return result;
1864:            }
1865:
1866:            /**
1867:             * The inScopeNamespaces method returns an Array of Namespace objects
1868:             * representing the namespaces in scope for this XML object in the
1869:             * context of its parent.
1870:             *
1871:             * @return Array of all Namespaces in scope for this XML Object.
1872:             */
1873:            Object[] inScopeNamespaces() {
1874:                XmlCursor cursor = newCursor();
1875:                Object[] namespaces = NamespaceHelper.inScopeNamespaces(lib,
1876:                        cursor);
1877:                cursor.dispose();
1878:                return namespaces;
1879:            }
1880:
1881:            /**
1882:             *
1883:             * @param child
1884:             * @param xml
1885:             */
1886:            XML insertChildAfter(Object child, Object xml) {
1887:                if (child == null) {
1888:                    // Spec says inserting after nothing is the same as prepending
1889:                    prependChild(xml);
1890:                } else if (child instanceof  XML) {
1891:                    insertChild((XML) child, xml, APPEND_CHILD);
1892:                }
1893:
1894:                return this ;
1895:            }
1896:
1897:            /**
1898:             *
1899:             * @param child
1900:             * @param xml
1901:             */
1902:            XML insertChildBefore(Object child, Object xml) {
1903:                if (child == null) {
1904:                    // Spec says inserting before nothing is the same as appending
1905:                    appendChild(xml);
1906:                } else if (child instanceof  XML) {
1907:                    insertChild((XML) child, xml, PREPEND_CHILD);
1908:                }
1909:
1910:                return this ;
1911:            }
1912:
1913:            /**
1914:             *
1915:             * @return
1916:             */
1917:            boolean hasOwnProperty(XMLName xmlName) {
1918:                boolean hasProperty = false;
1919:
1920:                if (prototypeFlag) {
1921:                    String property = xmlName.localName();
1922:                    hasProperty = (0 != findPrototypeId(property));
1923:                } else {
1924:                    hasProperty = (getPropertyList(xmlName).length() > 0);
1925:                }
1926:
1927:                return hasProperty;
1928:            }
1929:
1930:            /**
1931:             *
1932:             * @return
1933:             */
1934:            boolean hasComplexContent() {
1935:                return !hasSimpleContent();
1936:            }
1937:
1938:            /**
1939:             *
1940:             * @return
1941:             */
1942:            boolean hasSimpleContent() {
1943:                boolean simpleContent = false;
1944:
1945:                XmlCursor curs = newCursor();
1946:
1947:                if (curs.isAttr() || curs.isText()) {
1948:                    return true;
1949:                }
1950:
1951:                if (curs.isStartdoc()) {
1952:                    curs.toFirstContentToken();
1953:                }
1954:
1955:                simpleContent = !(curs.toFirstChild());
1956:
1957:                curs.dispose();
1958:
1959:                return simpleContent;
1960:            }
1961:
1962:            /**
1963:             * Length of an XML object is always 1, it's a list of XML objects of size 1.
1964:             *
1965:             * @return
1966:             */
1967:            int length() {
1968:                return 1;
1969:            }
1970:
1971:            /**
1972:             *
1973:             * @return
1974:             */
1975:            String localName() {
1976:                XmlCursor cursor = newCursor();
1977:                if (cursor.isStartdoc())
1978:                    cursor.toFirstContentToken();
1979:
1980:                String name = null;
1981:
1982:                if (cursor.isStart() || cursor.isAttr() || cursor.isProcinst()) {
1983:                    javax.xml.namespace.QName qname = cursor.getName();
1984:                    name = qname.getLocalPart();
1985:                }
1986:                cursor.dispose();
1987:
1988:                return name;
1989:            }
1990:
1991:            /**
1992:             * The name method returns the qualified name associated with this XML object.
1993:             *
1994:             * @return The qualified name associated with this XML object.
1995:             */
1996:            QName name() {
1997:                XmlCursor cursor = newCursor();
1998:                if (cursor.isStartdoc())
1999:                    cursor.toFirstContentToken();
2000:
2001:                QName name = null;
2002:
2003:                if (cursor.isStart() || cursor.isAttr() || cursor.isProcinst()) {
2004:                    javax.xml.namespace.QName qname = cursor.getName();
2005:                    if (cursor.isProcinst()) {
2006:                        name = new QName(lib, "", qname.getLocalPart(), "");
2007:                    } else {
2008:                        String uri = qname.getNamespaceURI();
2009:                        String prefix = qname.getPrefix();
2010:                        name = new QName(lib, uri, qname.getLocalPart(), prefix);
2011:                    }
2012:                }
2013:
2014:                cursor.dispose();
2015:
2016:                return name;
2017:            }
2018:
2019:            /**
2020:             *
2021:             * @param prefix
2022:             * @return
2023:             */
2024:            Object namespace(String prefix) {
2025:                XmlCursor cursor = newCursor();
2026:                if (cursor.isStartdoc()) {
2027:                    cursor.toFirstContentToken();
2028:                }
2029:
2030:                Object result = null;
2031:
2032:                if (prefix == null) {
2033:                    if (cursor.isStart() || cursor.isAttr()) {
2034:                        Object[] inScopeNS = NamespaceHelper.inScopeNamespaces(
2035:                                lib, cursor);
2036:                        // XXX Is it reaaly necessary to create the second cursor?
2037:                        XmlCursor cursor2 = newCursor();
2038:                        if (cursor2.isStartdoc())
2039:                            cursor2.toFirstContentToken();
2040:
2041:                        result = NamespaceHelper.getNamespace(lib, cursor2,
2042:                                inScopeNS);
2043:
2044:                        cursor2.dispose();
2045:                    }
2046:                } else {
2047:                    Map prefixToURI = NamespaceHelper.getAllNamespaces(lib,
2048:                            cursor);
2049:                    String uri = (String) prefixToURI.get(prefix);
2050:                    result = (uri == null) ? Undefined.instance
2051:                            : new Namespace(lib, prefix, uri);
2052:                }
2053:
2054:                cursor.dispose();
2055:
2056:                return result;
2057:            }
2058:
2059:            /**
2060:             *
2061:             * @return
2062:             */
2063:            Object[] namespaceDeclarations() {
2064:                XmlCursor cursor = newCursor();
2065:                Object[] namespaces = NamespaceHelper.namespaceDeclarations(
2066:                        lib, cursor);
2067:                cursor.dispose();
2068:                return namespaces;
2069:            }
2070:
2071:            /**
2072:             *
2073:             * @return
2074:             */
2075:            Object nodeKind() {
2076:                String result;
2077:                XmlCursor.TokenType tt = tokenType();
2078:
2079:                if (tt == XmlCursor.TokenType.ATTR) {
2080:                    result = "attribute";
2081:                } else if (tt == XmlCursor.TokenType.TEXT) {
2082:                    result = "text";
2083:                } else if (tt == XmlCursor.TokenType.COMMENT) {
2084:                    result = "comment";
2085:                } else if (tt == XmlCursor.TokenType.PROCINST) {
2086:                    result = "processing-instruction";
2087:                } else if (tt == XmlCursor.TokenType.START) {
2088:                    result = "element";
2089:                } else {
2090:                    // A non-existant node has the nodeKind() of text
2091:                    result = "text";
2092:                }
2093:
2094:                return result;
2095:            }
2096:
2097:            /**
2098:             *
2099:             */
2100:            void normalize() {
2101:                XmlCursor curs = newCursor();
2102:                TokenType tt = curs.currentTokenType();
2103:
2104:                // Walk through the tokens removing empty text nodes and merging adjacent text nodes.
2105:                if (tt.isStartdoc()) {
2106:                    tt = curs.toFirstContentToken();
2107:                }
2108:
2109:                if (tt.isContainer()) {
2110:                    int nestLevel = 1;
2111:                    String previousText = null;
2112:
2113:                    while (nestLevel > 0) {
2114:                        tt = curs.toNextToken();
2115:
2116:                        if (tt == XmlCursor.TokenType.TEXT) {
2117:                            String currentText = curs.getChars().trim();
2118:
2119:                            if (currentText.trim().length() == 0) {
2120:                                // Empty text node, remove.
2121:                                removeToken(curs);
2122:                                curs.toPrevToken();
2123:                            } else if (previousText == null) {
2124:                                // No previous text node, reset to trimmed version
2125:                                previousText = currentText;
2126:                            } else {
2127:                                // It appears that this case never happens with XBeans.
2128:                                // Previous text node exists, concatenate
2129:                                String newText = previousText + currentText;
2130:
2131:                                curs.toPrevToken();
2132:                                removeToken(curs);
2133:                                removeToken(curs);
2134:                                curs.insertChars(newText);
2135:                            }
2136:                        } else {
2137:                            previousText = null;
2138:                        }
2139:
2140:                        if (tt.isStart()) {
2141:                            nestLevel++;
2142:                        } else if (tt.isEnd()) {
2143:                            nestLevel--;
2144:                        } else if (tt.isEnddoc()) {
2145:                            // Shouldn't get here, but just in case.
2146:                            break;
2147:                        }
2148:                    }
2149:                }
2150:
2151:                curs.dispose();
2152:            }
2153:
2154:            /**
2155:             *
2156:             * @return
2157:             */
2158:            Object parent() {
2159:                Object parent;
2160:
2161:                XmlCursor curs = newCursor();
2162:
2163:                if (curs.isStartdoc()) {
2164:                    // At doc level - no parent
2165:                    parent = Undefined.instance;
2166:                } else {
2167:                    if (curs.toParent()) {
2168:                        if (curs.isStartdoc()) {
2169:                            // Was top-level - no parent
2170:                            parent = Undefined.instance;
2171:                        } else {
2172:                            parent = getFromAnnotation(lib,
2173:                                    findAnnotation(curs));
2174:                        }
2175:                    } else {
2176:                        // No parent
2177:                        parent = Undefined.instance;
2178:                    }
2179:                }
2180:
2181:                curs.dispose();
2182:
2183:                return parent;
2184:            }
2185:
2186:            /**
2187:             *
2188:             * @param xml
2189:             * @return
2190:             */
2191:            XML prependChild(Object xml) {
2192:                XmlCursor curs = newCursor();
2193:
2194:                if (curs.isStartdoc()) {
2195:                    curs.toFirstContentToken();
2196:                }
2197:
2198:                // Move the cursor to the first content token
2199:                curs.toFirstContentToken();
2200:
2201:                insertChild(curs, xml);
2202:
2203:                curs.dispose();
2204:
2205:                return this ;
2206:            }
2207:
2208:            /**
2209:             *
2210:             * @return
2211:             */
2212:            Object processingInstructions(XMLName xmlName) {
2213:                return matchChildren(XmlCursor.TokenType.PROCINST, xmlName);
2214:            }
2215:
2216:            /**
2217:             *
2218:             * @param name
2219:             * @return
2220:             */
2221:            boolean propertyIsEnumerable(Object name) {
2222:                boolean result;
2223:                if (name instanceof  Integer) {
2224:                    result = (((Integer) name).intValue() == 0);
2225:                } else if (name instanceof  Number) {
2226:                    double x = ((Number) name).doubleValue();
2227:                    // Check that number is posotive 0
2228:                    result = (x == 0.0 && 1.0 / x > 0);
2229:                } else {
2230:                    result = ScriptRuntime.toString(name).equals("0");
2231:                }
2232:                return result;
2233:            }
2234:
2235:            /**
2236:             *
2237:             * @param namespace
2238:             */
2239:            XML removeNamespace(Namespace ns) {
2240:                XmlCursor cursor = newCursor();
2241:
2242:                try {
2243:                    if (cursor.isStartdoc())
2244:                        cursor.toFirstContentToken();
2245:                    if (!cursor.isStart())
2246:                        return this ;
2247:
2248:                    String nsPrefix = ns.prefix();
2249:                    String nsURI = ns.uri();
2250:                    Map prefixToURI = new HashMap();
2251:                    int depth = 1;
2252:
2253:                    while (!(cursor.isEnd() && depth == 0)) {
2254:                        if (cursor.isStart()) {
2255:                            // Get the namespaces declared in this element.
2256:                            // The ones with undefined prefixes are not candidates
2257:                            // for removal because they are used.
2258:                            prefixToURI.clear();
2259:                            NamespaceHelper.getNamespaces(cursor, prefixToURI);
2260:                            ObjArray inScopeNSBag = new ObjArray();
2261:                            Iterator i = prefixToURI.entrySet().iterator();
2262:                            while (i.hasNext()) {
2263:                                Map.Entry entry = (Map.Entry) i.next();
2264:                                ns = new Namespace(lib,
2265:                                        (String) entry.getKey(), (String) entry
2266:                                                .getValue());
2267:                                inScopeNSBag.add(ns);
2268:                            }
2269:
2270:                            // Add the URI we are looking for to avoid matching
2271:                            // non-existing Namespaces.
2272:                            ns = new Namespace(lib, nsURI);
2273:                            inScopeNSBag.add(ns);
2274:
2275:                            Object[] inScopeNS = inScopeNSBag.toArray();
2276:
2277:                            // Check the element name
2278:                            Namespace n = NamespaceHelper.getNamespace(lib,
2279:                                    cursor, inScopeNS);
2280:                            if (nsURI.equals(n.uri())
2281:                                    && (nsPrefix == null || nsPrefix.equals(n
2282:                                            .prefix()))) {
2283:                                // This namespace is used
2284:                                return this ;
2285:                            }
2286:
2287:                            // Check the attributes
2288:                            cursor.push();
2289:                            boolean hasNext = cursor.toFirstAttribute();
2290:                            while (hasNext) {
2291:                                n = NamespaceHelper.getNamespace(lib, cursor,
2292:                                        inScopeNS);
2293:                                if (nsURI.equals(n.uri())
2294:                                        && (nsPrefix == null || nsPrefix
2295:                                                .equals(n.prefix()))) {
2296:                                    // This namespace is used
2297:                                    return this ;
2298:                                }
2299:
2300:                                hasNext = cursor.toNextAttribute();
2301:                            }
2302:                            cursor.pop();
2303:
2304:                            if (nsPrefix == null) {
2305:                                // Remove all namespaces declarations that match nsURI
2306:                                i = prefixToURI.entrySet().iterator();
2307:                                while (i.hasNext()) {
2308:                                    Map.Entry entry = (Map.Entry) i.next();
2309:                                    if (entry.getValue().equals(nsURI))
2310:                                        NamespaceHelper.removeNamespace(cursor,
2311:                                                (String) entry.getKey());
2312:                                }
2313:                            } else if (nsURI.equals(prefixToURI.get(nsPrefix))) {
2314:                                // Remove the namespace declaration that matches nsPrefix
2315:                                NamespaceHelper.removeNamespace(cursor, String
2316:                                        .valueOf(nsPrefix));
2317:                            }
2318:                        }
2319:
2320:                        switch (cursor.toNextToken().intValue()) {
2321:                        case XmlCursor.TokenType.INT_START:
2322:                            depth++;
2323:                            break;
2324:                        case XmlCursor.TokenType.INT_END:
2325:                            depth--;
2326:                            break;
2327:                        }
2328:                    }
2329:                } finally {
2330:                    cursor.dispose();
2331:                }
2332:
2333:                return this ;
2334:            }
2335:
2336:            XML replace(long index, Object xml) {
2337:                XMLList xlChildToReplace = child(index);
2338:                if (xlChildToReplace.length() > 0) {
2339:                    // One exists an that index
2340:                    XML childToReplace = xlChildToReplace.item(0);
2341:                    insertChildAfter(childToReplace, xml);
2342:                    removeChild(index);
2343:                }
2344:                return this ;
2345:            }
2346:
2347:            /**
2348:             *
2349:             * @param propertyName
2350:             * @param xml
2351:             * @return
2352:             */
2353:            XML replace(XMLName xmlName, Object xml) {
2354:                putXMLProperty(xmlName, xml);
2355:                return this ;
2356:            }
2357:
2358:            /**
2359:             *
2360:             * @param xml
2361:             */
2362:            XML setChildren(Object xml) {
2363:                // remove all children
2364:                XMLName xmlName = XMLName.formStar();
2365:                XMLList matches = getPropertyList(xmlName);
2366:                matches.remove();
2367:
2368:                // append new children
2369:                appendChild(xml);
2370:
2371:                return this ;
2372:            }
2373:
2374:            /**
2375:             *
2376:             * @param name
2377:             */
2378:            void setLocalName(String localName) {
2379:                XmlCursor cursor = newCursor();
2380:
2381:                try {
2382:                    if (cursor.isStartdoc())
2383:                        cursor.toFirstContentToken();
2384:
2385:                    if (cursor.isText() || cursor.isComment())
2386:                        return;
2387:
2388:                    javax.xml.namespace.QName qname = cursor.getName();
2389:                    cursor.setName(new javax.xml.namespace.QName(qname
2390:                            .getNamespaceURI(), localName, qname.getPrefix()));
2391:                } finally {
2392:                    cursor.dispose();
2393:                }
2394:            }
2395:
2396:            /**
2397:             *
2398:             * @param name
2399:             */
2400:            void setName(QName qname) {
2401:                XmlCursor cursor = newCursor();
2402:
2403:                try {
2404:                    if (cursor.isStartdoc())
2405:                        cursor.toFirstContentToken();
2406:
2407:                    if (cursor.isText() || cursor.isComment())
2408:                        return;
2409:
2410:                    if (cursor.isProcinst()) {
2411:                        String localName = qname.localName();
2412:                        cursor
2413:                                .setName(new javax.xml.namespace.QName(
2414:                                        localName));
2415:                    } else {
2416:                        String prefix = qname.prefix();
2417:                        if (prefix == null) {
2418:                            prefix = "";
2419:                        }
2420:                        cursor.setName(new javax.xml.namespace.QName(qname
2421:                                .uri(), qname.localName(), prefix));
2422:                    }
2423:                } finally {
2424:                    cursor.dispose();
2425:                }
2426:            }
2427:
2428:            /**
2429:             *
2430:             * @param ns
2431:             */
2432:            void setNamespace(Namespace ns) {
2433:                XmlCursor cursor = newCursor();
2434:
2435:                try {
2436:                    if (cursor.isStartdoc())
2437:                        cursor.toFirstContentToken();
2438:
2439:                    if (cursor.isText() || cursor.isComment()
2440:                            || cursor.isProcinst())
2441:                        return;
2442:
2443:                    String prefix = ns.prefix();
2444:                    if (prefix == null) {
2445:                        prefix = "";
2446:                    }
2447:                    cursor.setName(new javax.xml.namespace.QName(ns.uri(),
2448:                            localName(), prefix));
2449:                } finally {
2450:                    cursor.dispose();
2451:                }
2452:            }
2453:
2454:            /**
2455:             *
2456:             * @return
2457:             */
2458:            XMLList text() {
2459:                return matchChildren(XmlCursor.TokenType.TEXT);
2460:            }
2461:
2462:            /**
2463:             *
2464:             * @return
2465:             */
2466:            public String toString() {
2467:                String result;
2468:                XmlCursor curs = newCursor();
2469:
2470:                if (curs.isStartdoc()) {
2471:                    curs.toFirstContentToken();
2472:                }
2473:
2474:                if (curs.isText()) {
2475:                    result = curs.getChars();
2476:                } else if (curs.isStart() && hasSimpleContent()) {
2477:                    result = curs.getTextValue();
2478:                } else {
2479:                    result = toXMLString(0);
2480:                }
2481:
2482:                return result;
2483:            }
2484:
2485:            String toSource(int indent) {
2486:                // XXX Does toXMLString always return valid XML literal?
2487:                return toXMLString(indent);
2488:            }
2489:
2490:            /**
2491:             *
2492:             * @return
2493:             */
2494:            String toXMLString(int indent) {
2495:                // XXX indent is ignored
2496:
2497:                String result;
2498:
2499:                XmlCursor curs = newCursor();
2500:
2501:                if (curs.isStartdoc()) {
2502:                    curs.toFirstContentToken();
2503:                }
2504:
2505:                try {
2506:                    if (curs.isText()) {
2507:                        result = curs.getChars();
2508:                    } else if (curs.isAttr()) {
2509:                        result = curs.getTextValue();
2510:                    } else if (curs.isComment() || curs.isProcinst()) {
2511:                        result = XML.dumpNode(curs, getOptions());
2512:
2513:                        // todo: XBeans-dependent hack here
2514:                        // If it's a comment or PI, take off the xml-frament stuff
2515:                        String start = "<xml-fragment>";
2516:                        String end = "</xml-fragment>";
2517:
2518:                        if (result.startsWith(start)) {
2519:                            result = result.substring(start.length());
2520:                        }
2521:
2522:                        if (result.endsWith(end)) {
2523:                            result = result.substring(0, result.length()
2524:                                    - end.length());
2525:                        }
2526:                    } else {
2527:                        result = XML.dumpNode(curs, getOptions());
2528:                    }
2529:                } finally {
2530:                    curs.dispose();
2531:                }
2532:
2533:                return result;
2534:            }
2535:
2536:            /**
2537:             *
2538:             * @return
2539:             */
2540:            Object valueOf() {
2541:                return this ;
2542:            }
2543:
2544:            //
2545:            // Other public Functions from XMLObject
2546:            //
2547:
2548:            /**
2549:             *
2550:             * @param target
2551:             * @return
2552:             */
2553:            boolean equivalentXml(Object target) {
2554:                boolean result = false;
2555:
2556:                if (target instanceof  XML) {
2557:                    XML otherXml = (XML) target;
2558:
2559:                    // Compare with toString() if either side is text node or attribute
2560:                    // otherwise compare as XML
2561:                    XmlCursor.TokenType this TT = tokenType();
2562:                    XmlCursor.TokenType otherTT = otherXml.tokenType();
2563:                    if (this TT == XmlCursor.TokenType.ATTR
2564:                            || otherTT == XmlCursor.TokenType.ATTR
2565:                            || this TT == XmlCursor.TokenType.TEXT
2566:                            || otherTT == XmlCursor.TokenType.TEXT) {
2567:                        result = toString().equals(otherXml.toString());
2568:                    } else {
2569:                        XmlCursor cursOne = newCursor();
2570:                        XmlCursor cursTwo = otherXml.newCursor();
2571:
2572:                        result = LogicalEquality.nodesEqual(cursOne, cursTwo);
2573:
2574:                        cursOne.dispose();
2575:                        cursTwo.dispose();
2576:
2577:                        // Old way of comparing by string.
2578:                        //                boolean orgPrettyPrinting = prototype.prettyPrinting;
2579:                        //                prototype.prettyPrinting = true;
2580:                        //                result = toXMLString(0).equals(otherXml.toXMLString(0));
2581:                        //                prototype.prettyPrinting = orgPrettyPrinting;
2582:                    }
2583:                } else if (target instanceof  XMLList) {
2584:                    XMLList otherList = (XMLList) target;
2585:
2586:                    if (otherList.length() == 1) {
2587:                        result = equivalentXml(otherList
2588:                                .getXmlFromAnnotation(0));
2589:                    }
2590:                } else if (hasSimpleContent()) {
2591:                    String otherStr = ScriptRuntime.toString(target);
2592:
2593:                    result = toString().equals(otherStr);
2594:                }
2595:
2596:                return result;
2597:            }
2598:
2599:            /**
2600:             *
2601:             * @param name
2602:             * @param start
2603:             * @return
2604:             */
2605:            XMLList getPropertyList(XMLName name) {
2606:                XMLList result;
2607:
2608:                // Get the named property
2609:                if (name.isDescendants()) {
2610:                    result = descendants(name);
2611:                } else if (name.isAttributeName()) {
2612:                    result = attribute(name);
2613:                } else {
2614:                    result = child(name);
2615:                }
2616:
2617:                return result;
2618:            }
2619:
2620:            protected Object jsConstructor(Context cx, boolean inNewExpr,
2621:                    Object[] args) {
2622:                if (args.length == 0) {
2623:                    return createFromJS(lib, "");
2624:                } else {
2625:                    Object arg0 = args[0];
2626:                    if (!inNewExpr && arg0 instanceof  XML) {
2627:                        // XML(XML) returns the same object.
2628:                        return arg0;
2629:                    }
2630:                    return createFromJS(lib, arg0);
2631:                }
2632:            }
2633:
2634:            /**
2635:             * See ECMA 357, 11_2_2_1, Semantics, 3_f.
2636:             */
2637:            public Scriptable getExtraMethodSource(Context cx) {
2638:                if (hasSimpleContent()) {
2639:                    String src = toString();
2640:                    return ScriptRuntime.toObjectOrNull(cx, src);
2641:                }
2642:                return null;
2643:            }
2644:
2645:            XmlObject getXmlObject() {
2646:                XmlObject xo;
2647:                XmlCursor cursor = newCursor();
2648:                try {
2649:                    xo = cursor.getObject();
2650:                } finally {
2651:                    cursor.dispose();
2652:                }
2653:                return xo;
2654:            }
2655:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.