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.util.Vector;
0044:
0045: import org.mozilla.javascript.*;
0046: import org.mozilla.javascript.xml.*;
0047:
0048: import org.apache.xmlbeans.XmlCursor;
0049:
0050: class XMLList extends XMLObjectImpl implements Function {
0051: static final long serialVersionUID = -4543618751670781135L;
0052:
0053: static class AnnotationList {
0054: private Vector v;
0055:
0056: AnnotationList() {
0057: v = new Vector();
0058: }
0059:
0060: void add(XML.XScriptAnnotation n) {
0061: v.add(n);
0062: }
0063:
0064: XML.XScriptAnnotation item(int index) {
0065: return (XML.XScriptAnnotation) (v.get(index));
0066: }
0067:
0068: void remove(int index) {
0069: v.remove(index);
0070: }
0071:
0072: int length() {
0073: return v.size();
0074: }
0075: };
0076:
0077: // Fields
0078: private AnnotationList _annos;
0079:
0080: private XMLObjectImpl targetObject = null;
0081: private javax.xml.namespace.QName targetProperty = null;
0082:
0083: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0084: //
0085: // Constructors
0086: //
0087: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0088:
0089: /**
0090: *
0091: */
0092: XMLList(XMLLibImpl lib) {
0093: super (lib, lib.xmlListPrototype);
0094: _annos = new AnnotationList();
0095: }
0096:
0097: /**
0098: *
0099: * @param inputObject
0100: */
0101: XMLList(XMLLibImpl lib, Object inputObject) {
0102: super (lib, lib.xmlListPrototype);
0103: String frag;
0104:
0105: if (inputObject == null || inputObject instanceof Undefined) {
0106: frag = "";
0107: } else if (inputObject instanceof XML) {
0108: XML xml = (XML) inputObject;
0109:
0110: _annos = new AnnotationList();
0111: _annos.add(xml.getAnnotation());
0112: } else if (inputObject instanceof XMLList) {
0113: XMLList xmll = (XMLList) inputObject;
0114:
0115: _annos = new AnnotationList();
0116:
0117: for (int i = 0; i < xmll._annos.length(); i++) {
0118: _annos.add(xmll._annos.item(i));
0119: }
0120: } else {
0121: frag = ScriptRuntime.toString(inputObject).trim();
0122:
0123: if (!frag.startsWith("<>")) {
0124: frag = "<>" + frag + "</>";
0125: }
0126:
0127: frag = "<fragment>" + frag.substring(2);
0128: if (!frag.endsWith("</>")) {
0129: throw ScriptRuntime
0130: .typeError("XML with anonymous tag missing end anonymous tag");
0131: }
0132:
0133: frag = frag.substring(0, frag.length() - 3) + "</fragment>";
0134:
0135: XML orgXML = XML.createFromJS(lib, frag);
0136:
0137: // Now orphan the children and add them to our XMLList.
0138: XMLList children = orgXML.children();
0139:
0140: _annos = new AnnotationList();
0141:
0142: for (int i = 0; i < children._annos.length(); i++) {
0143: // Copy here is so that they'll be orphaned (parent() will be undefined)
0144: _annos.add(((XML) children.item(i).copy())
0145: .getAnnotation());
0146: }
0147: }
0148: }
0149:
0150: //
0151: //
0152: // TargetObject/Property accessors
0153: //
0154: //
0155:
0156: /**
0157: *
0158: * @param object
0159: * @param property
0160: */
0161: void setTargets(XMLObjectImpl object,
0162: javax.xml.namespace.QName property) {
0163: targetObject = object;
0164: targetProperty = property;
0165: }
0166:
0167: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0168: //
0169: // Private functions
0170: //
0171: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0172:
0173: /**
0174: *
0175: * @param index
0176: * @return
0177: */
0178: XML getXmlFromAnnotation(int index) {
0179: XML retVal;
0180:
0181: if (index >= 0 && index < length()) {
0182: XML.XScriptAnnotation anno = _annos.item(index);
0183: retVal = XML.getFromAnnotation(lib, anno);
0184: } else {
0185: retVal = null;
0186: }
0187:
0188: return retVal;
0189: }
0190:
0191: /**
0192: *
0193: * @param index
0194: */
0195: private void internalRemoveFromList(int index) {
0196: _annos.remove(index);
0197: }
0198:
0199: /**
0200: *
0201: * @param index
0202: * @param xml
0203: */
0204: void replace(int index, XML xml) {
0205: if (index < length()) {
0206: AnnotationList newAnnoList = new AnnotationList();
0207:
0208: // Copy upto item to replace.
0209: for (int i = 0; i < index; i++) {
0210: newAnnoList.add(_annos.item(i));
0211: }
0212:
0213: newAnnoList.add(xml.getAnnotation());
0214:
0215: // Skip over old item we're going to replace we've already add new item on above line.
0216: for (int i = index + 1; i < length(); i++) {
0217: newAnnoList.add(_annos.item(i));
0218: }
0219:
0220: _annos = newAnnoList;
0221: }
0222: }
0223:
0224: /**
0225: *
0226: * @param index
0227: * @param xml
0228: */
0229: private void insert(int index, XML xml) {
0230: if (index < length()) {
0231: AnnotationList newAnnoList = new AnnotationList();
0232:
0233: // Copy upto item to insert.
0234: for (int i = 0; i < index; i++) {
0235: newAnnoList.add(_annos.item(i));
0236: }
0237:
0238: newAnnoList.add(xml.getAnnotation());
0239:
0240: for (int i = index; i < length(); i++) {
0241: newAnnoList.add(_annos.item(i));
0242: }
0243:
0244: _annos = newAnnoList;
0245: }
0246: }
0247:
0248: //
0249: //
0250: // methods overriding ScriptableObject
0251: //
0252: //
0253:
0254: public String getClassName() {
0255: return "XMLList";
0256: }
0257:
0258: //
0259: //
0260: // methods overriding IdScriptableObject
0261: //
0262: //
0263:
0264: /**
0265: *
0266: * @param index
0267: * @param start
0268: * @return
0269: */
0270: public Object get(int index, Scriptable start) {
0271: //Log("get index: " + index);
0272:
0273: if (index >= 0 && index < length()) {
0274: return getXmlFromAnnotation(index);
0275: } else {
0276: return Scriptable.NOT_FOUND;
0277: }
0278: }
0279:
0280: /**
0281: *
0282: * @param name
0283: * @param start
0284: * @return
0285: */
0286: boolean hasXMLProperty(XMLName xmlName) {
0287: boolean result = false;
0288:
0289: // Has now should return true if the property would have results > 0 or
0290: // if it's a method name
0291: String name = xmlName.localName();
0292: if ((getPropertyList(xmlName).length() > 0)
0293: || (getMethod(name) != NOT_FOUND)) {
0294: result = true;
0295: }
0296:
0297: return result;
0298: }
0299:
0300: /**
0301: *
0302: * @param index
0303: * @param start
0304: * @return
0305: */
0306: public boolean has(int index, Scriptable start) {
0307: return 0 <= index && index < length();
0308: }
0309:
0310: /**
0311: *
0312: * @param name
0313: * @param value
0314: */
0315: void putXMLProperty(XMLName xmlName, Object value) {
0316: //Log("put property: " + name);
0317:
0318: // Special-case checks for undefined and null
0319: if (value == null) {
0320: value = "null";
0321: } else if (value instanceof Undefined) {
0322: value = "undefined";
0323: }
0324:
0325: if (length() > 1) {
0326: throw ScriptRuntime
0327: .typeError("Assignment to lists with more that one item is not supported");
0328: } else if (length() == 0) {
0329: // Secret sauce for super-expandos.
0330: // We set an element here, and then add ourselves to our target.
0331: if (targetObject != null && targetProperty != null
0332: && !targetProperty.getLocalPart().equals("*")) {
0333: // Add an empty element with our targetProperty name and then set it.
0334: XML xmlValue = XML.createTextElement(lib,
0335: targetProperty, "");
0336: addToList(xmlValue);
0337:
0338: if (xmlName.isAttributeName()) {
0339: setAttribute(xmlName, value);
0340: } else {
0341: XML xml = item(0);
0342: xml.putXMLProperty(xmlName, value);
0343:
0344: // Update the list with the new item at location 0.
0345: replace(0, item(0));
0346: }
0347:
0348: // Now add us to our parent
0349: XMLName name2 = XMLName.formProperty(targetProperty
0350: .getNamespaceURI(), targetProperty
0351: .getLocalPart());
0352: targetObject.putXMLProperty(name2, this );
0353: } else {
0354: throw ScriptRuntime
0355: .typeError("Assignment to empty XMLList without targets not supported");
0356: }
0357: } else if (xmlName.isAttributeName()) {
0358: setAttribute(xmlName, value);
0359: } else {
0360: XML xml = item(0);
0361: xml.putXMLProperty(xmlName, value);
0362:
0363: // Update the list with the new item at location 0.
0364: replace(0, item(0));
0365: }
0366: }
0367:
0368: /**
0369: *
0370: * @param name
0371: * @return
0372: */
0373: Object getXMLProperty(XMLName name) {
0374: return getPropertyList(name);
0375: }
0376:
0377: /**
0378: *
0379: * @param index
0380: * @param value
0381: */
0382: public void put(int index, Scriptable start, Object value) {
0383: Object parent = Undefined.instance;
0384: // Convert text into XML if needed.
0385: XMLObject xmlValue;
0386:
0387: // Special-case checks for undefined and null
0388: if (value == null) {
0389: value = "null";
0390: } else if (value instanceof Undefined) {
0391: value = "undefined";
0392: }
0393:
0394: if (value instanceof XMLObject) {
0395: xmlValue = (XMLObject) value;
0396: } else {
0397: if (targetProperty == null) {
0398: xmlValue = XML.createFromJS(lib, value.toString());
0399: } else {
0400: xmlValue = XML.createTextElement(lib, targetProperty,
0401: value.toString());
0402: }
0403: }
0404:
0405: // Find the parent
0406: if (index < length()) {
0407: parent = item(index).parent();
0408: } else {
0409: // Appending
0410: parent = parent();
0411: }
0412:
0413: if (parent instanceof XML) {
0414: // found parent, alter doc
0415: XML xmlParent = (XML) parent;
0416:
0417: if (index < length()) {
0418: // We're replacing the the node.
0419: XML xmlNode = getXmlFromAnnotation(index);
0420:
0421: if (xmlValue instanceof XML) {
0422: xmlNode.replaceAll((XML) xmlValue);
0423: replace(index, xmlNode);
0424: } else if (xmlValue instanceof XMLList) {
0425: // Replace the first one, and add the rest on the list.
0426: XMLList list = (XMLList) xmlValue;
0427:
0428: if (list.length() > 0) {
0429: int lastIndexAdded = xmlNode.childIndex();
0430: xmlNode.replaceAll(list.item(0));
0431: replace(index, list.item(0));
0432:
0433: for (int i = 1; i < list.length(); i++) {
0434: xmlParent.insertChildAfter(xmlParent
0435: .getXmlChild(lastIndexAdded), list
0436: .item(i));
0437: lastIndexAdded++;
0438: insert(index + i, list.item(i));
0439: }
0440: }
0441: }
0442: } else {
0443: // Appending
0444: xmlParent.appendChild(xmlValue);
0445: addToList(xmlParent.getXmlChild(index));
0446: }
0447: } else {
0448: // Don't all have same parent, no underlying doc to alter
0449: if (index < length()) {
0450: XML xmlNode = XML.getFromAnnotation(lib, _annos
0451: .item(index));
0452:
0453: if (xmlValue instanceof XML) {
0454: xmlNode.replaceAll((XML) xmlValue);
0455: replace(index, xmlNode);
0456: } else if (xmlValue instanceof XMLList) {
0457: // Replace the first one, and add the rest on the list.
0458: XMLList list = (XMLList) xmlValue;
0459:
0460: if (list.length() > 0) {
0461: xmlNode.replaceAll(list.item(0));
0462: replace(index, list.item(0));
0463:
0464: for (int i = 1; i < list.length(); i++) {
0465: insert(index + i, list.item(i));
0466: }
0467: }
0468: }
0469: } else {
0470: addToList(xmlValue);
0471: }
0472: }
0473: }
0474:
0475: /**
0476: *
0477: * @param name
0478: */
0479: void deleteXMLProperty(XMLName name) {
0480: for (int i = 0; i < length(); i++) {
0481: XML xml = getXmlFromAnnotation(i);
0482:
0483: if (xml.tokenType() == XmlCursor.TokenType.START) {
0484: xml.deleteXMLProperty(name);
0485: }
0486: }
0487: }
0488:
0489: /**
0490: *
0491: * @param index
0492: */
0493: public void delete(int index) {
0494: if (index >= 0 && index < length()) {
0495: XML xml = getXmlFromAnnotation(index);
0496:
0497: xml.remove();
0498:
0499: internalRemoveFromList(index);
0500: }
0501: }
0502:
0503: /**
0504: *
0505: * @return
0506: */
0507: public Object[] getIds() {
0508: Object enumObjs[];
0509:
0510: if (prototypeFlag) {
0511: enumObjs = new Object[0];
0512: } else {
0513: enumObjs = new Object[length()];
0514:
0515: for (int i = 0; i < enumObjs.length; i++) {
0516: enumObjs[i] = new Integer(i);
0517: }
0518: }
0519:
0520: return enumObjs;
0521: }
0522:
0523: /**
0524: *
0525: * @return
0526: */
0527: public Object[] getIdsForDebug() {
0528: return getIds();
0529: }
0530:
0531: // XMLList will remove will delete all items in the list (a set delete) this differs from the XMLList delete operator.
0532: void remove() {
0533: int nLen = length();
0534: for (int i = nLen - 1; i >= 0; i--) {
0535: XML xml = getXmlFromAnnotation(i);
0536: if (xml != null) {
0537: xml.remove();
0538: internalRemoveFromList(i);
0539: }
0540: }
0541: }
0542:
0543: /**
0544: *
0545: * @param index
0546: * @return
0547: */
0548: XML item(int index) {
0549: return _annos != null ? getXmlFromAnnotation(index) : XML
0550: .createEmptyXML(lib);
0551: }
0552:
0553: /**
0554: *
0555: * @param name
0556: * @param value
0557: */
0558: private void setAttribute(XMLName xmlName, Object value) {
0559: for (int i = 0; i < length(); i++) {
0560: XML xml = getXmlFromAnnotation(i);
0561: xml.setAttribute(xmlName, value);
0562: }
0563: }
0564:
0565: /**
0566: *
0567: * @param toAdd
0568: */
0569: void addToList(Object toAdd) {
0570: if (toAdd instanceof Undefined) {
0571: // Missing argument do nothing...
0572: return;
0573: }
0574:
0575: if (toAdd instanceof XMLList) {
0576: XMLList xmlSrc = (XMLList) toAdd;
0577: for (int i = 0; i < xmlSrc.length(); i++) {
0578: _annos.add((xmlSrc.item(i)).getAnnotation());
0579: }
0580: } else if (toAdd instanceof XML) {
0581: _annos.add(((XML) (toAdd)).getAnnotation());
0582: } else if (toAdd instanceof XML.XScriptAnnotation) {
0583: _annos.add((XML.XScriptAnnotation) toAdd);
0584: }
0585: }
0586:
0587: //
0588: //
0589: // Methods from section 12.4.4 in the spec
0590: //
0591: //
0592:
0593: /**
0594: *
0595: * @param toAdd
0596: */
0597: XML addNamespace(Namespace ns) {
0598: if (length() == 1) {
0599: return getXmlFromAnnotation(0).addNamespace(ns);
0600: } else {
0601: throw ScriptRuntime
0602: .typeError("The addNamespace method works only on lists containing one item");
0603: }
0604: }
0605:
0606: /**
0607: *
0608: * @param xml
0609: * @return
0610: */
0611: XML appendChild(Object xml) {
0612: if (length() == 1) {
0613: return getXmlFromAnnotation(0).appendChild(xml);
0614: } else {
0615: throw ScriptRuntime
0616: .typeError("The appendChild method works only on lists containing one item");
0617: }
0618: }
0619:
0620: /**
0621: *
0622: * @param attr
0623: * @return
0624: */
0625: XMLList attribute(XMLName xmlName) {
0626: XMLList result = new XMLList(lib);
0627:
0628: for (int i = 0; i < length(); i++) {
0629: XML xml = getXmlFromAnnotation(i);
0630: result.addToList(xml.attribute(xmlName));
0631: }
0632:
0633: return result;
0634: }
0635:
0636: /**
0637: *
0638: * @return
0639: */
0640: XMLList attributes() {
0641: XMLList result = new XMLList(lib);
0642:
0643: for (int i = 0; i < length(); i++) {
0644: XML xml = getXmlFromAnnotation(i);
0645: result.addToList(xml.attributes());
0646: }
0647:
0648: return result;
0649: }
0650:
0651: XMLList child(long index) {
0652: XMLList result = new XMLList(lib);
0653:
0654: for (int i = 0; i < length(); i++) {
0655: result.addToList(getXmlFromAnnotation(i).child(index));
0656: }
0657:
0658: return result;
0659: }
0660:
0661: XMLList child(XMLName xmlName) {
0662: XMLList result = new XMLList(lib);
0663:
0664: for (int i = 0; i < length(); i++) {
0665: result.addToList(getXmlFromAnnotation(i).child(xmlName));
0666: }
0667:
0668: return result;
0669: }
0670:
0671: /**
0672: *
0673: * @return
0674: */
0675: int childIndex() {
0676: if (length() == 1) {
0677: return getXmlFromAnnotation(0).childIndex();
0678: } else {
0679: throw ScriptRuntime
0680: .typeError("The childIndex method works only on lists containing one item");
0681: }
0682: }
0683:
0684: /**
0685: *
0686: * @return
0687: */
0688: XMLList children() {
0689: Vector v = new Vector();
0690:
0691: for (int i = 0; i < length(); i++) {
0692: XML xml = getXmlFromAnnotation(i);
0693:
0694: if (xml != null) {
0695: Object o = xml.children();
0696: if (o instanceof XMLList) {
0697: XMLList childList = (XMLList) o;
0698:
0699: int cChildren = childList.length();
0700: for (int j = 0; j < cChildren; j++) {
0701: v.addElement(childList.item(j));
0702: }
0703: }
0704: }
0705: }
0706:
0707: XMLList allChildren = new XMLList(lib);
0708: int sz = v.size();
0709:
0710: for (int i = 0; i < sz; i++) {
0711: allChildren.addToList(v.get(i));
0712: }
0713:
0714: return allChildren;
0715: }
0716:
0717: /**
0718: *
0719: * @return
0720: */
0721: XMLList comments() {
0722: XMLList result = new XMLList(lib);
0723:
0724: for (int i = 0; i < length(); i++) {
0725: XML xml = getXmlFromAnnotation(i);
0726:
0727: result.addToList(xml.comments());
0728: }
0729:
0730: return result;
0731: }
0732:
0733: /**
0734: *
0735: * @param xml
0736: * @return
0737: */
0738: boolean contains(Object xml) {
0739: boolean result = false;
0740:
0741: for (int i = 0; i < length(); i++) {
0742: XML member = getXmlFromAnnotation(i);
0743:
0744: if (member.equivalentXml(xml)) {
0745: result = true;
0746: break;
0747: }
0748: }
0749:
0750: return result;
0751: }
0752:
0753: /**
0754: *
0755: * @return
0756: */
0757: Object copy() {
0758: XMLList result = new XMLList(lib);
0759:
0760: for (int i = 0; i < length(); i++) {
0761: XML xml = getXmlFromAnnotation(i);
0762: result.addToList(xml.copy());
0763: }
0764:
0765: return result;
0766: }
0767:
0768: /**
0769: *
0770: * @return
0771: */
0772: XMLList descendants(XMLName xmlName) {
0773: XMLList result = new XMLList(lib);
0774:
0775: for (int i = 0; i < length(); i++) {
0776: XML xml = getXmlFromAnnotation(i);
0777: result.addToList(xml.descendants(xmlName));
0778: }
0779:
0780: return result;
0781: }
0782:
0783: /**
0784: *
0785: * @return
0786: */
0787: Object[] inScopeNamespaces() {
0788: if (length() == 1) {
0789: return getXmlFromAnnotation(0).inScopeNamespaces();
0790: } else {
0791: throw ScriptRuntime
0792: .typeError("The inScopeNamespaces method works only on lists containing one item");
0793: }
0794: }
0795:
0796: /**
0797: *
0798: * @param child
0799: * @param xml
0800: */
0801: XML insertChildAfter(Object child, Object xml) {
0802: if (length() == 1) {
0803: return getXmlFromAnnotation(0).insertChildAfter(child, xml);
0804: } else {
0805: throw ScriptRuntime
0806: .typeError("The insertChildAfter method works only on lists containing one item");
0807: }
0808: }
0809:
0810: /**
0811: *
0812: * @param child
0813: * @param xml
0814: */
0815: XML insertChildBefore(Object child, Object xml) {
0816: if (length() == 1) {
0817: return getXmlFromAnnotation(0).insertChildAfter(child, xml);
0818: } else {
0819: throw ScriptRuntime
0820: .typeError("The insertChildBefore method works only on lists containing one item");
0821: }
0822: }
0823:
0824: /**
0825: *
0826: * @return
0827: */
0828: boolean hasOwnProperty(XMLName xmlName) {
0829: boolean hasProperty = false;
0830:
0831: if (prototypeFlag) {
0832: String property = xmlName.localName();
0833: hasProperty = (0 != findPrototypeId(property));
0834: } else {
0835: hasProperty = (getPropertyList(xmlName).length() > 0);
0836: }
0837:
0838: return hasProperty;
0839: }
0840:
0841: /**
0842: *
0843: * @return
0844: */
0845: boolean hasComplexContent() {
0846: boolean complexContent;
0847: int length = length();
0848:
0849: if (length == 0) {
0850: complexContent = false;
0851: } else if (length == 1) {
0852: complexContent = getXmlFromAnnotation(0)
0853: .hasComplexContent();
0854: } else {
0855: complexContent = false;
0856:
0857: for (int i = 0; i < length; i++) {
0858: XML nextElement = getXmlFromAnnotation(i);
0859: if (nextElement.tokenType() == XmlCursor.TokenType.START) {
0860: complexContent = true;
0861: break;
0862: }
0863: }
0864: }
0865:
0866: return complexContent;
0867: }
0868:
0869: /**
0870: *
0871: * @return
0872: */
0873: boolean hasSimpleContent() {
0874: boolean simpleContent;
0875: int length = length();
0876:
0877: if (length == 0) {
0878: simpleContent = true;
0879: } else if (length == 1) {
0880: simpleContent = getXmlFromAnnotation(0).hasSimpleContent();
0881: } else {
0882: simpleContent = true;
0883:
0884: for (int i = 0; i < length; i++) {
0885: XML nextElement = getXmlFromAnnotation(i);
0886: if (nextElement.tokenType() == XmlCursor.TokenType.START) {
0887: simpleContent = false;
0888: break;
0889: }
0890: }
0891: }
0892:
0893: return simpleContent;
0894: }
0895:
0896: /**
0897: *
0898: * @return
0899: */
0900: int length() {
0901: int result = 0;
0902:
0903: if (_annos != null) {
0904: result = _annos.length();
0905: }
0906:
0907: return result;
0908: }
0909:
0910: /**
0911: *
0912: * @return
0913: */
0914: String localName() {
0915: if (length() == 1) {
0916: return name().localName();
0917: } else {
0918: throw ScriptRuntime
0919: .typeError("The localName method works only on lists containing one item");
0920: }
0921: }
0922:
0923: /**
0924: *
0925: * @return
0926: */
0927: QName name() {
0928: if (length() == 1) {
0929: return getXmlFromAnnotation(0).name();
0930: } else {
0931: throw ScriptRuntime
0932: .typeError("The name method works only on lists containing one item");
0933: }
0934: }
0935:
0936: /**
0937: *
0938: * @param prefix
0939: * @return
0940: */
0941: Object namespace(String prefix) {
0942: if (length() == 1) {
0943: return getXmlFromAnnotation(0).namespace(prefix);
0944: } else {
0945: throw ScriptRuntime
0946: .typeError("The namespace method works only on lists containing one item");
0947: }
0948: }
0949:
0950: /**
0951: *
0952: * @return
0953: */
0954: Object[] namespaceDeclarations() {
0955: if (length() == 1) {
0956: return getXmlFromAnnotation(0).namespaceDeclarations();
0957: } else {
0958: throw ScriptRuntime
0959: .typeError("The namespaceDeclarations method works only on lists containing one item");
0960: }
0961: }
0962:
0963: /**
0964: *
0965: * @return
0966: */
0967: Object nodeKind() {
0968: if (length() == 1) {
0969: return getXmlFromAnnotation(0).nodeKind();
0970: } else {
0971: throw ScriptRuntime
0972: .typeError("The nodeKind method works only on lists containing one item");
0973: }
0974: }
0975:
0976: /**
0977: *
0978: */
0979: void normalize() {
0980: for (int i = 0; i < length(); i++) {
0981: getXmlFromAnnotation(i).normalize();
0982: }
0983: }
0984:
0985: /**
0986: * If list is empty, return undefined, if elements have different parents return undefined,
0987: * If they all have the same parent, return that parent.
0988: *
0989: * @return
0990: */
0991: Object parent() {
0992: Object sameParent = Undefined.instance;
0993:
0994: if ((length() == 0) && (targetObject != null)
0995: && (targetObject instanceof XML)) {
0996: sameParent = targetObject;
0997: } else {
0998: for (int i = 0; i < length(); i++) {
0999: Object currParent = getXmlFromAnnotation(i).parent();
1000:
1001: if (i == 0) {
1002: // Set the first for the rest to compare to.
1003: sameParent = currParent;
1004: } else if (sameParent != currParent) {
1005: sameParent = Undefined.instance;
1006: break;
1007: }
1008: }
1009: }
1010:
1011: // If everything in the list is the sameParent then return that as the parent.
1012: return sameParent;
1013: }
1014:
1015: /**
1016: *
1017: * @param xml
1018: * @return
1019: */
1020: XML prependChild(Object xml) {
1021: if (length() == 1) {
1022: return getXmlFromAnnotation(0).prependChild(xml);
1023: } else {
1024: throw ScriptRuntime
1025: .typeError("The prependChild method works only on lists containing one item");
1026: }
1027: }
1028:
1029: /**
1030: *
1031: * @return
1032: */
1033: Object processingInstructions(XMLName xmlName) {
1034: XMLList result = new XMLList(lib);
1035:
1036: for (int i = 0; i < length(); i++) {
1037: XML xml = getXmlFromAnnotation(i);
1038:
1039: result.addToList(xml.processingInstructions(xmlName));
1040: }
1041:
1042: return result;
1043: }
1044:
1045: /**
1046: *
1047: * @param name
1048: * @return
1049: */
1050: boolean propertyIsEnumerable(Object name) {
1051: long index;
1052: if (name instanceof Integer) {
1053: index = ((Integer) name).intValue();
1054: } else if (name instanceof Number) {
1055: double x = ((Number) name).doubleValue();
1056: index = (long) x;
1057: if (index != x) {
1058: return false;
1059: }
1060: if (index == 0 && 1.0 / x < 0) {
1061: // Negative 0
1062: return false;
1063: }
1064: } else {
1065: String s = ScriptRuntime.toString(name);
1066: index = ScriptRuntime.testUint32String(s);
1067: }
1068: return (0 <= index && index < length());
1069: }
1070:
1071: /**
1072: *
1073: * @param ns
1074: */
1075: XML removeNamespace(Namespace ns) {
1076: if (length() == 1) {
1077: return getXmlFromAnnotation(0).removeNamespace(ns);
1078: } else {
1079: throw ScriptRuntime
1080: .typeError("The removeNamespace method works only on lists containing one item");
1081: }
1082: }
1083:
1084: XML replace(long index, Object xml) {
1085: if (length() == 1) {
1086: return getXmlFromAnnotation(0).replace(index, xml);
1087: } else {
1088: throw ScriptRuntime
1089: .typeError("The replace method works only on lists containing one item");
1090: }
1091: }
1092:
1093: /**
1094: *
1095: * @param propertyName
1096: * @param xml
1097: * @return
1098: */
1099: XML replace(XMLName xmlName, Object xml) {
1100: if (length() == 1) {
1101: return getXmlFromAnnotation(0).replace(xmlName, xml);
1102: } else {
1103: throw ScriptRuntime
1104: .typeError("The replace method works only on lists containing one item");
1105: }
1106: }
1107:
1108: /**
1109: *
1110: * @param xml
1111: */
1112: XML setChildren(Object xml) {
1113: if (length() == 1) {
1114: return getXmlFromAnnotation(0).setChildren(xml);
1115: } else {
1116: throw ScriptRuntime
1117: .typeError("The setChildren method works only on lists containing one item");
1118: }
1119: }
1120:
1121: /**
1122: *
1123: * @param name
1124: */
1125: void setLocalName(String localName) {
1126: if (length() == 1) {
1127: getXmlFromAnnotation(0).setLocalName(localName);
1128: } else {
1129: throw ScriptRuntime
1130: .typeError("The setLocalName method works only on lists containing one item");
1131: }
1132: }
1133:
1134: /**
1135: *
1136: * @param name
1137: */
1138: void setName(QName qname) {
1139: if (length() == 1) {
1140: getXmlFromAnnotation(0).setName(qname);
1141: } else {
1142: throw ScriptRuntime
1143: .typeError("The setName method works only on lists containing one item");
1144: }
1145: }
1146:
1147: /**
1148: *
1149: * @param ns
1150: */
1151: void setNamespace(Namespace ns) {
1152: if (length() == 1) {
1153: getXmlFromAnnotation(0).setNamespace(ns);
1154: } else {
1155: throw ScriptRuntime
1156: .typeError("The setNamespace method works only on lists containing one item");
1157: }
1158: }
1159:
1160: /**
1161: *
1162: * * @return
1163: */
1164: XMLList text() {
1165: XMLList result = new XMLList(lib);
1166:
1167: for (int i = 0; i < length(); i++) {
1168: result.addToList(getXmlFromAnnotation(i).text());
1169: }
1170:
1171: return result;
1172: }
1173:
1174: /**
1175: *
1176: * @return
1177: */
1178: public String toString() {
1179: if (hasSimpleContent()) {
1180: StringBuffer sb = new StringBuffer();
1181:
1182: for (int i = 0; i < length(); i++) {
1183: XML next = getXmlFromAnnotation(i);
1184: sb.append(next.toString());
1185: }
1186:
1187: return sb.toString();
1188: } else {
1189: return toXMLString(0);
1190: }
1191: }
1192:
1193: String toSource(int indent) {
1194: // XXX indent is ignored
1195: return "<>" + toXMLString(0) + "</>";
1196: }
1197:
1198: /**
1199: *
1200: * @return
1201: */
1202: String toXMLString(int indent) {
1203: StringBuffer sb = new StringBuffer();
1204:
1205: for (int i = 0; i < length(); i++) {
1206: if (i > 0) {
1207: sb.append('\n');
1208: }
1209:
1210: sb.append(getXmlFromAnnotation(i).toXMLString(indent));
1211: }
1212:
1213: return sb.toString();
1214: }
1215:
1216: /**
1217: *
1218: * @return
1219: */
1220: Object valueOf() {
1221: return this ;
1222: }
1223:
1224: //
1225: // Other public Functions from XMLObject
1226: //
1227:
1228: /**
1229: *
1230: * @param target
1231: * @return
1232: */
1233: boolean equivalentXml(Object target) {
1234: boolean result = false;
1235:
1236: // Zero length list should equate to undefined
1237: if (target instanceof Undefined && length() == 0) {
1238: result = true;
1239: } else if (length() == 1) {
1240: result = getXmlFromAnnotation(0).equivalentXml(target);
1241: } else if (target instanceof XMLList) {
1242: XMLList otherList = (XMLList) target;
1243:
1244: if (otherList.length() == length()) {
1245: result = true;
1246:
1247: for (int i = 0; i < length(); i++) {
1248: if (!getXmlFromAnnotation(i).equivalentXml(
1249: otherList.getXmlFromAnnotation(i))) {
1250: result = false;
1251: break;
1252: }
1253: }
1254: }
1255: }
1256:
1257: return result;
1258: }
1259:
1260: /**
1261: *
1262: * @param name
1263: * @param start
1264: * @return
1265: */
1266: private XMLList getPropertyList(XMLName name) {
1267: XMLList propertyList = new XMLList(lib);
1268: javax.xml.namespace.QName qname = null;
1269:
1270: if (!name.isDescendants() && !name.isAttributeName()) {
1271: // Only set the targetProperty if this is a regular child get
1272: // and not a descendant or attribute get
1273: qname = new javax.xml.namespace.QName(name.uri(), name
1274: .localName());
1275: }
1276:
1277: propertyList.setTargets(this , qname);
1278:
1279: for (int i = 0; i < length(); i++) {
1280: propertyList.addToList(getXmlFromAnnotation(i)
1281: .getPropertyList(name));
1282: }
1283:
1284: return propertyList;
1285: }
1286:
1287: private Object applyOrCall(boolean isApply, Context cx,
1288: Scriptable scope, Scriptable this Obj, Object[] args) {
1289: String methodName = isApply ? "apply" : "call";
1290: if (!(this Obj instanceof XMLList)
1291: || ((XMLList) this Obj).targetProperty == null)
1292: throw ScriptRuntime.typeError1("msg.isnt.function",
1293: methodName);
1294:
1295: return ScriptRuntime.applyOrCall(isApply, cx, scope, this Obj,
1296: args);
1297: }
1298:
1299: protected Object jsConstructor(Context cx, boolean inNewExpr,
1300: Object[] args) {
1301: if (args.length == 0) {
1302: return new XMLList(lib);
1303: } else {
1304: Object arg0 = args[0];
1305: if (!inNewExpr && arg0 instanceof XMLList) {
1306: // XMLList(XMLList) returns the same object.
1307: return arg0;
1308: }
1309: return new XMLList(lib, arg0);
1310: }
1311: }
1312:
1313: org.apache.xmlbeans.XmlObject getXmlObject() {
1314: if (length() == 1) {
1315: return getXmlFromAnnotation(0).getXmlObject();
1316: } else {
1317: throw ScriptRuntime
1318: .typeError("getXmlObject method works only on lists containing one item");
1319: }
1320: }
1321:
1322: /**
1323: * See ECMA 357, 11_2_2_1, Semantics, 3_e.
1324: */
1325: public Scriptable getExtraMethodSource(Context cx) {
1326: if (length() == 1) {
1327: return getXmlFromAnnotation(0);
1328: }
1329: return null;
1330: }
1331:
1332: public Object call(Context cx, Scriptable scope,
1333: Scriptable this Obj, Object[] args) {
1334: // This XMLList is being called as a Function.
1335: // Let's find the real Function object.
1336: if (targetProperty == null)
1337: throw ScriptRuntime.notFunctionError(this );
1338:
1339: String methodName = targetProperty.getLocalPart();
1340:
1341: boolean isApply = methodName.equals("apply");
1342: if (isApply || methodName.equals("call"))
1343: return applyOrCall(isApply, cx, scope, this Obj, args);
1344:
1345: Callable method = ScriptRuntime.getElemFunctionAndThis(this ,
1346: methodName, cx);
1347: // Call lastStoredScriptable to clear stored thisObj
1348: // but ignore the result as the method should use the supplied
1349: // thisObj, not one from redirected call
1350: ScriptRuntime.lastStoredScriptable(cx);
1351: return method.call(cx, scope, this Obj, args);
1352: }
1353:
1354: public Scriptable construct(Context cx, Scriptable scope,
1355: Object[] args) {
1356: throw ScriptRuntime.typeError1("msg.not.ctor", "XMLList");
1357: }
1358: }
|