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: * Igor Bukanov
0026: * Ethan Hugg
0027: * Terry Lucas
0028: * Milen Nankov
0029: * David P. Caldwell <inonit@inonit.com>
0030: *
0031: * Alternatively, the contents of this file may be used under the terms of
0032: * the GNU General Public License Version 2 or later (the "GPL"), in which
0033: * case the provisions of the GPL are applicable instead of those above. If
0034: * you wish to allow use of your version of this file only under the terms of
0035: * the GPL and not to allow others to use your version of this file under the
0036: * MPL, indicate your decision by deleting the provisions above and replacing
0037: * them with the notice and other provisions required by the GPL. If you do
0038: * not delete the provisions above, a recipient may use your version of this
0039: * file under either the MPL or the GPL.
0040: *
0041: * ***** END LICENSE BLOCK ***** */
0042:
0043: package org.mozilla.javascript.xmlimpl;
0044:
0045: import org.mozilla.javascript.*;
0046: import org.mozilla.javascript.xml.*;
0047:
0048: /**
0049: * This abstract class describes what all XML objects (XML, XMLList) should
0050: * have in common.
0051: *
0052: * @see XML
0053: */
0054: abstract class XMLObjectImpl extends XMLObject {
0055: private static final Object XMLOBJECT_TAG = new Object();
0056: private XMLLibImpl lib;
0057: private boolean prototypeFlag;
0058:
0059: protected XMLObjectImpl(XMLLibImpl lib, Scriptable scope,
0060: XMLObject prototype) {
0061: initialize(lib, scope, prototype);
0062: }
0063:
0064: final void initialize(XMLLibImpl lib, Scriptable scope,
0065: XMLObject prototype) {
0066: setParentScope(scope);
0067: setPrototype(prototype);
0068: prototypeFlag = (prototype == null);
0069: this .lib = lib;
0070: }
0071:
0072: final boolean isPrototype() {
0073: return prototypeFlag;
0074: }
0075:
0076: XMLLibImpl getLib() {
0077: return lib;
0078: }
0079:
0080: final XML newXML(XmlNode node) {
0081: return lib.newXML(node);
0082: }
0083:
0084: XML xmlFromNode(XmlNode node) {
0085: if (node.getXml() == null) {
0086: node.setXml(newXML(node));
0087: }
0088: return node.getXml();
0089: }
0090:
0091: final XMLList newXMLList() {
0092: return lib.newXMLList();
0093: }
0094:
0095: final XMLList newXMLListFrom(Object o) {
0096: return lib.newXMLListFrom(o);
0097: }
0098:
0099: final XmlProcessor getProcessor() {
0100: return lib.getProcessor();
0101: }
0102:
0103: final QName newQName(String uri, String localName, String prefix) {
0104: return lib.newQName(uri, localName, prefix);
0105: }
0106:
0107: final QName newQName(XmlNode.QName name) {
0108: return lib.newQName(name);
0109: }
0110:
0111: final Namespace createNamespace(XmlNode.Namespace declaration) {
0112: if (declaration == null)
0113: return null;
0114: return lib
0115: .createNamespaces(new XmlNode.Namespace[] { declaration })[0];
0116: }
0117:
0118: final Namespace[] createNamespaces(XmlNode.Namespace[] declarations) {
0119: return lib.createNamespaces(declarations);
0120: }
0121:
0122: //
0123: // Scriptable
0124: //
0125:
0126: public final Object get(String name, Scriptable start) {
0127: return super .get(name, start);
0128: }
0129:
0130: public final boolean has(String name, Scriptable start) {
0131: return super .has(name, start);
0132: }
0133:
0134: public final void put(String name, Scriptable start, Object value) {
0135: super .put(name, start, value);
0136: }
0137:
0138: public final void delete(String name) {
0139: // TODO I am not sure about this, but this is how I found it. DPC
0140: throw new IllegalArgumentException("String: [" + name + "]");
0141: }
0142:
0143: public final Scriptable getPrototype() {
0144: return super .getPrototype();
0145: }
0146:
0147: public final void setPrototype(Scriptable prototype) {
0148: super .setPrototype(prototype);
0149: }
0150:
0151: public final Scriptable getParentScope() {
0152: return super .getParentScope();
0153: }
0154:
0155: public final void setParentScope(Scriptable parent) {
0156: super .setParentScope(parent);
0157: }
0158:
0159: public final Object getDefaultValue(Class hint) {
0160: return this .toString();
0161: }
0162:
0163: public final boolean hasInstance(Scriptable scriptable) {
0164: return super .hasInstance(scriptable);
0165: }
0166:
0167: /**
0168: * ecmaHas(cx, id) calls this after resolving when id to XMLName
0169: * and checking it is not Uint32 index.
0170: */
0171: abstract boolean hasXMLProperty(XMLName name);
0172:
0173: /**
0174: * ecmaGet(cx, id) calls this after resolving when id to XMLName
0175: * and checking it is not Uint32 index.
0176: */
0177: abstract Object getXMLProperty(XMLName name);
0178:
0179: /**
0180: * ecmaPut(cx, id, value) calls this after resolving when id to XMLName
0181: * and checking it is not Uint32 index.
0182: */
0183: abstract void putXMLProperty(XMLName name, Object value);
0184:
0185: /**
0186: * ecmaDelete(cx, id) calls this after resolving when id to XMLName
0187: * and checking it is not Uint32 index.
0188: */
0189: abstract void deleteXMLProperty(XMLName name);
0190:
0191: /**
0192: * Test XML equality with target the target.
0193: */
0194: abstract boolean equivalentXml(Object target);
0195:
0196: abstract void addMatches(XMLList rv, XMLName name);
0197:
0198: private XMLList getMatches(XMLName name) {
0199: XMLList rv = newXMLList();
0200: addMatches(rv, name);
0201: return rv;
0202: }
0203:
0204: abstract XML getXML();
0205:
0206: // Methods from section 12.4.4 in the spec
0207: abstract XMLList child(int index);
0208:
0209: abstract XMLList child(XMLName xmlName);
0210:
0211: abstract XMLList children();
0212:
0213: abstract XMLList comments();
0214:
0215: abstract boolean contains(Object xml);
0216:
0217: abstract XMLObjectImpl copy();
0218:
0219: abstract XMLList elements(XMLName xmlName);
0220:
0221: abstract boolean hasOwnProperty(XMLName xmlName);
0222:
0223: abstract boolean hasComplexContent();
0224:
0225: abstract boolean hasSimpleContent();
0226:
0227: abstract int length();
0228:
0229: abstract void normalize();
0230:
0231: abstract Object parent();
0232:
0233: abstract XMLList processingInstructions(XMLName xmlName);
0234:
0235: abstract boolean propertyIsEnumerable(Object member);
0236:
0237: abstract XMLList text();
0238:
0239: public abstract String toString();
0240:
0241: abstract String toXMLString();
0242:
0243: abstract Object valueOf();
0244:
0245: protected abstract Object jsConstructor(Context cx,
0246: boolean inNewExpr, Object[] args);
0247:
0248: final Object getMethod(String id) {
0249: return super .get(id, this );
0250: }
0251:
0252: //
0253: //
0254: // Methods overriding ScriptableObject
0255: //
0256: //
0257:
0258: /**
0259: * XMLObject always compare with any value and equivalentValues
0260: * never returns {@link Scriptable#NOT_FOUND} for them but rather
0261: * calls equivalentXml(value) and wrap the result as Boolean.
0262: */
0263: protected final Object equivalentValues(Object value) {
0264: boolean result = equivalentXml(value);
0265: return result ? Boolean.TRUE : Boolean.FALSE;
0266: }
0267:
0268: //
0269: //
0270: // Methods overriding XMLObject
0271: //
0272: //
0273:
0274: /**
0275: * Implementation of ECMAScript [[Has]]
0276: */
0277: public final boolean ecmaHas(Context cx, Object id) {
0278: if (cx == null)
0279: cx = Context.getCurrentContext();
0280: XMLName xmlName = lib.toXMLNameOrIndex(cx, id);
0281: if (xmlName == null) {
0282: long index = ScriptRuntime.lastUint32Result(cx);
0283: // XXX Fix this cast
0284: return has((int) index, this );
0285: }
0286: return hasXMLProperty(xmlName);
0287: }
0288:
0289: /**
0290: * Implementation of ECMAScript [[Get]]
0291: */
0292: public final Object ecmaGet(Context cx, Object id) {
0293: if (cx == null)
0294: cx = Context.getCurrentContext();
0295: XMLName xmlName = lib.toXMLNameOrIndex(cx, id);
0296: if (xmlName == null) {
0297: long index = ScriptRuntime.lastUint32Result(cx);
0298: // XXX Fix this cast
0299: Object result = get((int) index, this );
0300: if (result == Scriptable.NOT_FOUND) {
0301: result = Undefined.instance;
0302: }
0303: return result;
0304: }
0305: return getXMLProperty(xmlName);
0306: }
0307:
0308: /**
0309: * Implementation of ECMAScript [[Put]]
0310: */
0311: public final void ecmaPut(Context cx, Object id, Object value) {
0312: if (cx == null)
0313: cx = Context.getCurrentContext();
0314: XMLName xmlName = lib.toXMLNameOrIndex(cx, id);
0315: if (xmlName == null) {
0316: long index = ScriptRuntime.lastUint32Result(cx);
0317: // XXX Fix this cast
0318: put((int) index, this , value);
0319: return;
0320: }
0321: putXMLProperty(xmlName, value);
0322: }
0323:
0324: /**
0325: * Implementation of ECMAScript [[Delete]].
0326: */
0327: public final boolean ecmaDelete(Context cx, Object id) {
0328: if (cx == null)
0329: cx = Context.getCurrentContext();
0330: XMLName xmlName = lib.toXMLNameOrIndex(cx, id);
0331: if (xmlName == null) {
0332: long index = ScriptRuntime.lastUint32Result(cx);
0333: // XXX Fix this
0334: delete((int) index);
0335: return true;
0336: }
0337: deleteXMLProperty(xmlName);
0338: return true;
0339: }
0340:
0341: // TODO Can this be made more strongly typed?
0342: public Ref memberRef(Context cx, Object elem, int memberTypeFlags) {
0343: boolean attribute = (memberTypeFlags & Node.ATTRIBUTE_FLAG) != 0;
0344: boolean descendants = (memberTypeFlags & Node.DESCENDANTS_FLAG) != 0;
0345: if (!attribute && !descendants) {
0346: // Code generation would use ecma(Get|Has|Delete|Set) for
0347: // normal name identifiers so one ATTRIBUTE_FLAG
0348: // or DESCENDANTS_FLAG has to be set
0349: throw Kit.codeBug();
0350: }
0351: XmlNode.QName qname = lib.toNodeQName(cx, elem, attribute);
0352: XMLName rv = XMLName.create(qname, attribute, descendants);
0353: rv.initXMLObject(this );
0354: return rv;
0355: }
0356:
0357: /**
0358: * Generic reference to implement x::ns, x.@ns::y, x..@ns::y etc.
0359: */
0360: public Ref memberRef(Context cx, Object namespace, Object elem,
0361: int memberTypeFlags) {
0362: boolean attribute = (memberTypeFlags & Node.ATTRIBUTE_FLAG) != 0;
0363: boolean descendants = (memberTypeFlags & Node.DESCENDANTS_FLAG) != 0;
0364: XMLName rv = XMLName.create(lib
0365: .toNodeQName(cx, namespace, elem), attribute,
0366: descendants);
0367: rv.initXMLObject(this );
0368: return rv;
0369: }
0370:
0371: public NativeWith enterWith(Scriptable scope) {
0372: return new XMLWithScope(lib, scope, this );
0373: }
0374:
0375: public NativeWith enterDotQuery(Scriptable scope) {
0376: XMLWithScope xws = new XMLWithScope(lib, scope, this );
0377: xws.initAsDotQuery();
0378: return xws;
0379: }
0380:
0381: public final Object addValues(Context cx, boolean this IsLeft,
0382: Object value) {
0383: if (value instanceof XMLObject) {
0384: XMLObject v1, v2;
0385: if (this IsLeft) {
0386: v1 = this ;
0387: v2 = (XMLObject) value;
0388: } else {
0389: v1 = (XMLObject) value;
0390: v2 = this ;
0391: }
0392: return lib.addXMLObjects(cx, v1, v2);
0393: }
0394: if (value == Undefined.instance) {
0395: // both "xml + undefined" and "undefined + xml" gives String(xml)
0396: return ScriptRuntime.toString(this );
0397: }
0398:
0399: return super .addValues(cx, this IsLeft, value);
0400: }
0401:
0402: //
0403: //
0404: // IdScriptableObject machinery
0405: //
0406: //
0407:
0408: final void exportAsJSClass(boolean sealed) {
0409: prototypeFlag = true;
0410: exportAsJSClass(MAX_PROTOTYPE_ID, getParentScope(), sealed);
0411: }
0412:
0413: // #string_id_map#
0414: private final static int Id_constructor = 1,
0415:
0416: Id_addNamespace = 2, Id_appendChild = 3, Id_attribute = 4,
0417: Id_attributes = 5, Id_child = 6, Id_childIndex = 7,
0418: Id_children = 8, Id_comments = 9, Id_contains = 10,
0419: Id_copy = 11, Id_descendants = 12, Id_elements = 13,
0420: Id_inScopeNamespaces = 14, Id_insertChildAfter = 15,
0421: Id_insertChildBefore = 16, Id_hasOwnProperty = 17,
0422: Id_hasComplexContent = 18, Id_hasSimpleContent = 19,
0423: Id_length = 20, Id_localName = 21, Id_name = 22,
0424: Id_namespace = 23, Id_namespaceDeclarations = 24,
0425: Id_nodeKind = 25, Id_normalize = 26, Id_parent = 27,
0426: Id_prependChild = 28, Id_processingInstructions = 29,
0427: Id_propertyIsEnumerable = 30, Id_removeNamespace = 31,
0428: Id_replace = 32, Id_setChildren = 33, Id_setLocalName = 34,
0429: Id_setName = 35, Id_setNamespace = 36, Id_text = 37,
0430: Id_toString = 38, Id_toXMLString = 39, Id_valueOf = 40,
0431:
0432: MAX_PROTOTYPE_ID = 40;
0433:
0434: protected int findPrototypeId(String s) {
0435: int id;
0436: // #generated# Last update: 2007-08-20 09:04:06 EDT
0437: L0: {
0438: id = 0;
0439: String X = null;
0440: int c;
0441: L: switch (s.length()) {
0442: case 4:
0443: c = s.charAt(0);
0444: if (c == 'c') {
0445: X = "copy";
0446: id = Id_copy;
0447: } else if (c == 'n') {
0448: X = "name";
0449: id = Id_name;
0450: } else if (c == 't') {
0451: X = "text";
0452: id = Id_text;
0453: }
0454: break L;
0455: case 5:
0456: X = "child";
0457: id = Id_child;
0458: break L;
0459: case 6:
0460: c = s.charAt(0);
0461: if (c == 'l') {
0462: X = "length";
0463: id = Id_length;
0464: } else if (c == 'p') {
0465: X = "parent";
0466: id = Id_parent;
0467: }
0468: break L;
0469: case 7:
0470: c = s.charAt(0);
0471: if (c == 'r') {
0472: X = "replace";
0473: id = Id_replace;
0474: } else if (c == 's') {
0475: X = "setName";
0476: id = Id_setName;
0477: } else if (c == 'v') {
0478: X = "valueOf";
0479: id = Id_valueOf;
0480: }
0481: break L;
0482: case 8:
0483: switch (s.charAt(2)) {
0484: case 'S':
0485: X = "toString";
0486: id = Id_toString;
0487: break L;
0488: case 'd':
0489: X = "nodeKind";
0490: id = Id_nodeKind;
0491: break L;
0492: case 'e':
0493: X = "elements";
0494: id = Id_elements;
0495: break L;
0496: case 'i':
0497: X = "children";
0498: id = Id_children;
0499: break L;
0500: case 'm':
0501: X = "comments";
0502: id = Id_comments;
0503: break L;
0504: case 'n':
0505: X = "contains";
0506: id = Id_contains;
0507: break L;
0508: }
0509: break L;
0510: case 9:
0511: switch (s.charAt(2)) {
0512: case 'c':
0513: X = "localName";
0514: id = Id_localName;
0515: break L;
0516: case 'm':
0517: X = "namespace";
0518: id = Id_namespace;
0519: break L;
0520: case 'r':
0521: X = "normalize";
0522: id = Id_normalize;
0523: break L;
0524: case 't':
0525: X = "attribute";
0526: id = Id_attribute;
0527: break L;
0528: }
0529: break L;
0530: case 10:
0531: c = s.charAt(0);
0532: if (c == 'a') {
0533: X = "attributes";
0534: id = Id_attributes;
0535: } else if (c == 'c') {
0536: X = "childIndex";
0537: id = Id_childIndex;
0538: }
0539: break L;
0540: case 11:
0541: switch (s.charAt(0)) {
0542: case 'a':
0543: X = "appendChild";
0544: id = Id_appendChild;
0545: break L;
0546: case 'c':
0547: X = "constructor";
0548: id = Id_constructor;
0549: break L;
0550: case 'd':
0551: X = "descendants";
0552: id = Id_descendants;
0553: break L;
0554: case 's':
0555: X = "setChildren";
0556: id = Id_setChildren;
0557: break L;
0558: case 't':
0559: X = "toXMLString";
0560: id = Id_toXMLString;
0561: break L;
0562: }
0563: break L;
0564: case 12:
0565: c = s.charAt(0);
0566: if (c == 'a') {
0567: X = "addNamespace";
0568: id = Id_addNamespace;
0569: } else if (c == 'p') {
0570: X = "prependChild";
0571: id = Id_prependChild;
0572: } else if (c == 's') {
0573: c = s.charAt(3);
0574: if (c == 'L') {
0575: X = "setLocalName";
0576: id = Id_setLocalName;
0577: } else if (c == 'N') {
0578: X = "setNamespace";
0579: id = Id_setNamespace;
0580: }
0581: }
0582: break L;
0583: case 14:
0584: X = "hasOwnProperty";
0585: id = Id_hasOwnProperty;
0586: break L;
0587: case 15:
0588: X = "removeNamespace";
0589: id = Id_removeNamespace;
0590: break L;
0591: case 16:
0592: c = s.charAt(0);
0593: if (c == 'h') {
0594: X = "hasSimpleContent";
0595: id = Id_hasSimpleContent;
0596: } else if (c == 'i') {
0597: X = "insertChildAfter";
0598: id = Id_insertChildAfter;
0599: }
0600: break L;
0601: case 17:
0602: c = s.charAt(3);
0603: if (c == 'C') {
0604: X = "hasComplexContent";
0605: id = Id_hasComplexContent;
0606: } else if (c == 'c') {
0607: X = "inScopeNamespaces";
0608: id = Id_inScopeNamespaces;
0609: } else if (c == 'e') {
0610: X = "insertChildBefore";
0611: id = Id_insertChildBefore;
0612: }
0613: break L;
0614: case 20:
0615: X = "propertyIsEnumerable";
0616: id = Id_propertyIsEnumerable;
0617: break L;
0618: case 21:
0619: X = "namespaceDeclarations";
0620: id = Id_namespaceDeclarations;
0621: break L;
0622: case 22:
0623: X = "processingInstructions";
0624: id = Id_processingInstructions;
0625: break L;
0626: }
0627: if (X != null && X != s && !X.equals(s))
0628: id = 0;
0629: break L0;
0630: }
0631: // #/generated#
0632: return id;
0633: }
0634:
0635: // #/string_id_map#
0636:
0637: protected void initPrototypeId(int id) {
0638: String s;
0639: int arity;
0640: switch (id) {
0641: case Id_constructor: {
0642: IdFunctionObject ctor;
0643: if (this instanceof XML) {
0644: ctor = new XMLCtor((XML) this , XMLOBJECT_TAG, id, 1);
0645: } else {
0646: ctor = new IdFunctionObject(this , XMLOBJECT_TAG, id, 1);
0647: }
0648: initPrototypeConstructor(ctor);
0649: return;
0650: }
0651:
0652: case Id_addNamespace:
0653: arity = 1;
0654: s = "addNamespace";
0655: break;
0656: case Id_appendChild:
0657: arity = 1;
0658: s = "appendChild";
0659: break;
0660: case Id_attribute:
0661: arity = 1;
0662: s = "attribute";
0663: break;
0664: case Id_attributes:
0665: arity = 0;
0666: s = "attributes";
0667: break;
0668: case Id_child:
0669: arity = 1;
0670: s = "child";
0671: break;
0672: case Id_childIndex:
0673: arity = 0;
0674: s = "childIndex";
0675: break;
0676: case Id_children:
0677: arity = 0;
0678: s = "children";
0679: break;
0680: case Id_comments:
0681: arity = 0;
0682: s = "comments";
0683: break;
0684: case Id_contains:
0685: arity = 1;
0686: s = "contains";
0687: break;
0688: case Id_copy:
0689: arity = 0;
0690: s = "copy";
0691: break;
0692: case Id_descendants:
0693: arity = 1;
0694: s = "descendants";
0695: break;
0696: case Id_elements:
0697: arity = 1;
0698: s = "elements";
0699: break;
0700: case Id_hasComplexContent:
0701: arity = 0;
0702: s = "hasComplexContent";
0703: break;
0704: case Id_hasOwnProperty:
0705: arity = 1;
0706: s = "hasOwnProperty";
0707: break;
0708: case Id_hasSimpleContent:
0709: arity = 0;
0710: s = "hasSimpleContent";
0711: break;
0712: case Id_inScopeNamespaces:
0713: arity = 0;
0714: s = "inScopeNamespaces";
0715: break;
0716: case Id_insertChildAfter:
0717: arity = 2;
0718: s = "insertChildAfter";
0719: break;
0720: case Id_insertChildBefore:
0721: arity = 2;
0722: s = "insertChildBefore";
0723: break;
0724: case Id_length:
0725: arity = 0;
0726: s = "length";
0727: break;
0728: case Id_localName:
0729: arity = 0;
0730: s = "localName";
0731: break;
0732: case Id_name:
0733: arity = 0;
0734: s = "name";
0735: break;
0736: case Id_namespace:
0737: arity = 1;
0738: s = "namespace";
0739: break;
0740: case Id_namespaceDeclarations:
0741: arity = 0;
0742: s = "namespaceDeclarations";
0743: break;
0744: case Id_nodeKind:
0745: arity = 0;
0746: s = "nodeKind";
0747: break;
0748: case Id_normalize:
0749: arity = 0;
0750: s = "normalize";
0751: break;
0752: case Id_parent:
0753: arity = 0;
0754: s = "parent";
0755: break;
0756: case Id_prependChild:
0757: arity = 1;
0758: s = "prependChild";
0759: break;
0760: case Id_processingInstructions:
0761: arity = 1;
0762: s = "processingInstructions";
0763: break;
0764: case Id_propertyIsEnumerable:
0765: arity = 1;
0766: s = "propertyIsEnumerable";
0767: break;
0768: case Id_removeNamespace:
0769: arity = 1;
0770: s = "removeNamespace";
0771: break;
0772: case Id_replace:
0773: arity = 2;
0774: s = "replace";
0775: break;
0776: case Id_setChildren:
0777: arity = 1;
0778: s = "setChildren";
0779: break;
0780: case Id_setLocalName:
0781: arity = 1;
0782: s = "setLocalName";
0783: break;
0784: case Id_setName:
0785: arity = 1;
0786: s = "setName";
0787: break;
0788: case Id_setNamespace:
0789: arity = 1;
0790: s = "setNamespace";
0791: break;
0792: case Id_text:
0793: arity = 0;
0794: s = "text";
0795: break;
0796: case Id_toString:
0797: arity = 0;
0798: s = "toString";
0799: break;
0800: case Id_toXMLString:
0801: arity = 1;
0802: s = "toXMLString";
0803: break;
0804: case Id_valueOf:
0805: arity = 0;
0806: s = "valueOf";
0807: break;
0808:
0809: default:
0810: throw new IllegalArgumentException(String.valueOf(id));
0811: }
0812: initPrototypeMethod(XMLOBJECT_TAG, id, s, arity);
0813: }
0814:
0815: private Object[] toObjectArray(Object[] typed) {
0816: Object[] rv = new Object[typed.length];
0817: for (int i = 0; i < rv.length; i++) {
0818: rv[i] = typed[i];
0819: }
0820: return rv;
0821: }
0822:
0823: private void xmlMethodNotFound(Object object, String name) {
0824: throw ScriptRuntime.notFunctionError(object, name);
0825: }
0826:
0827: public Object execIdCall(IdFunctionObject f, Context cx,
0828: Scriptable scope, Scriptable this Obj, Object[] args) {
0829: if (!f.hasTag(XMLOBJECT_TAG)) {
0830: return super .execIdCall(f, cx, scope, this Obj, args);
0831: }
0832: int id = f.methodId();
0833: if (id == Id_constructor) {
0834: return jsConstructor(cx, this Obj == null, args);
0835: }
0836:
0837: // All (XML|XMLList).prototype methods require thisObj to be XML
0838: if (!(this Obj instanceof XMLObjectImpl))
0839: throw incompatibleCallError(f);
0840: XMLObjectImpl realThis = (XMLObjectImpl) this Obj;
0841:
0842: XML xml = realThis.getXML();
0843: switch (id) {
0844: case Id_appendChild: {
0845: if (xml == null)
0846: xmlMethodNotFound(realThis, "appendChild");
0847: return xml.appendChild(arg(args, 0));
0848: }
0849: case Id_addNamespace: {
0850: if (xml == null)
0851: xmlMethodNotFound(realThis, "addNamespace");
0852: Namespace ns = lib.castToNamespace(cx, arg(args, 0));
0853: return xml.addNamespace(ns);
0854: }
0855: case Id_childIndex: {
0856: if (xml == null)
0857: xmlMethodNotFound(realThis, "childIndex");
0858: return ScriptRuntime.wrapInt(xml.childIndex());
0859: }
0860: case Id_inScopeNamespaces: {
0861: if (xml == null)
0862: xmlMethodNotFound(realThis, "inScopeNamespaces");
0863: return cx.newArray(scope, toObjectArray(xml
0864: .inScopeNamespaces()));
0865: }
0866: case Id_insertChildAfter: {
0867: if (xml == null)
0868: xmlMethodNotFound(realThis, "insertChildAfter");
0869: Object arg0 = arg(args, 0);
0870: if (arg0 == null || arg0 instanceof XML) {
0871: return xml.insertChildAfter((XML) arg0, arg(args, 1));
0872: }
0873: return Undefined.instance;
0874: }
0875: case Id_insertChildBefore: {
0876: if (xml == null)
0877: xmlMethodNotFound(realThis, "insertChildBefore");
0878: Object arg0 = arg(args, 0);
0879: if (arg0 == null || arg0 instanceof XML) {
0880: return xml.insertChildBefore((XML) arg0, arg(args, 1));
0881: }
0882: return Undefined.instance;
0883: }
0884: case Id_localName: {
0885: if (xml == null)
0886: xmlMethodNotFound(realThis, "localName");
0887: return xml.localName();
0888: }
0889: case Id_name: {
0890: if (xml == null)
0891: xmlMethodNotFound(realThis, "name");
0892: return xml.name();
0893: }
0894: case Id_namespace: {
0895: if (xml == null)
0896: xmlMethodNotFound(realThis, "namespace");
0897: String prefix = (args.length > 0) ? ScriptRuntime
0898: .toString(args[0]) : null;
0899: Namespace rv = xml.namespace(prefix);
0900: if (rv == null) {
0901: return Undefined.instance;
0902: } else {
0903: return rv;
0904: }
0905: }
0906: case Id_namespaceDeclarations: {
0907: if (xml == null)
0908: xmlMethodNotFound(realThis, "namespaceDeclarations");
0909: Namespace[] array = xml.namespaceDeclarations();
0910: return cx.newArray(scope, toObjectArray(array));
0911: }
0912: case Id_nodeKind: {
0913: if (xml == null)
0914: xmlMethodNotFound(realThis, "nodeKind");
0915: return xml.nodeKind();
0916: }
0917: case Id_prependChild: {
0918: if (xml == null)
0919: xmlMethodNotFound(realThis, "prependChild");
0920: return xml.prependChild(arg(args, 0));
0921: }
0922: case Id_removeNamespace: {
0923: if (xml == null)
0924: xmlMethodNotFound(realThis, "removeNamespace");
0925: Namespace ns = lib.castToNamespace(cx, arg(args, 0));
0926: return xml.removeNamespace(ns);
0927: }
0928: case Id_replace: {
0929: if (xml == null)
0930: xmlMethodNotFound(realThis, "replace");
0931: XMLName xmlName = lib.toXMLNameOrIndex(cx, arg(args, 0));
0932: Object arg1 = arg(args, 1);
0933: if (xmlName == null) {
0934: // I refuse to believe that this number will exceed 2^31
0935: int index = (int) ScriptRuntime.lastUint32Result(cx);
0936: return xml.replace(index, arg1);
0937: } else {
0938: return xml.replace(xmlName, arg1);
0939: }
0940: }
0941: case Id_setChildren: {
0942: if (xml == null)
0943: xmlMethodNotFound(realThis, "setChildren");
0944: return xml.setChildren(arg(args, 0));
0945: }
0946: case Id_setLocalName: {
0947: if (xml == null)
0948: xmlMethodNotFound(realThis, "setLocalName");
0949: String localName;
0950: Object arg = arg(args, 0);
0951: if (arg instanceof QName) {
0952: localName = ((QName) arg).localName();
0953: } else {
0954: localName = ScriptRuntime.toString(arg);
0955: }
0956: xml.setLocalName(localName);
0957: return Undefined.instance;
0958: }
0959: case Id_setName: {
0960: if (xml == null)
0961: xmlMethodNotFound(realThis, "setName");
0962: Object arg = (args.length != 0) ? args[0]
0963: : Undefined.instance;
0964: QName qname = lib.constructQName(cx, arg);
0965: xml.setName(qname);
0966: return Undefined.instance;
0967: }
0968: case Id_setNamespace: {
0969: if (xml == null)
0970: xmlMethodNotFound(realThis, "setNamespace");
0971: Namespace ns = lib.castToNamespace(cx, arg(args, 0));
0972: xml.setNamespace(ns);
0973: return Undefined.instance;
0974: }
0975:
0976: case Id_attribute: {
0977: XMLName xmlName = XMLName.create(lib.toNodeQName(cx, arg(
0978: args, 0), true), true, false);
0979: return realThis.getMatches(xmlName);
0980: }
0981: case Id_attributes:
0982: return realThis.getMatches(XMLName.create(XmlNode.QName
0983: .create(null, null), true, false));
0984: case Id_child: {
0985: XMLName xmlName = lib.toXMLNameOrIndex(cx, arg(args, 0));
0986: if (xmlName == null) {
0987: // Two billion or so is a fine upper limit, so we cast to int
0988: int index = (int) ScriptRuntime.lastUint32Result(cx);
0989: return realThis.child(index);
0990: } else {
0991: return realThis.child(xmlName);
0992: }
0993: }
0994: case Id_children:
0995: return realThis.children();
0996: case Id_comments:
0997: return realThis.comments();
0998: case Id_contains:
0999: return ScriptRuntime.wrapBoolean(realThis.contains(arg(
1000: args, 0)));
1001: case Id_copy:
1002: return realThis.copy();
1003: case Id_descendants: {
1004: XmlNode.QName qname = (args.length == 0) ? XmlNode.QName
1005: .create(null, null) : lib.toNodeQName(cx, args[0],
1006: false);
1007: return realThis.getMatches(XMLName.create(qname, false,
1008: true));
1009: }
1010: case Id_elements: {
1011: XMLName xmlName = (args.length == 0) ? XMLName.formStar()
1012: : lib.toXMLName(cx, args[0]);
1013: return realThis.elements(xmlName);
1014: }
1015: case Id_hasOwnProperty: {
1016: XMLName xmlName = lib.toXMLName(cx, arg(args, 0));
1017: return ScriptRuntime.wrapBoolean(realThis
1018: .hasOwnProperty(xmlName));
1019: }
1020: case Id_hasComplexContent:
1021: return ScriptRuntime.wrapBoolean(realThis
1022: .hasComplexContent());
1023: case Id_hasSimpleContent:
1024: return ScriptRuntime.wrapBoolean(realThis
1025: .hasSimpleContent());
1026: case Id_length:
1027: return ScriptRuntime.wrapInt(realThis.length());
1028: case Id_normalize:
1029: realThis.normalize();
1030: return Undefined.instance;
1031: case Id_parent:
1032: return realThis.parent();
1033: case Id_processingInstructions: {
1034: XMLName xmlName = (args.length > 0) ? lib.toXMLName(cx,
1035: args[0]) : XMLName.formStar();
1036: return realThis.processingInstructions(xmlName);
1037: }
1038: case Id_propertyIsEnumerable: {
1039: return ScriptRuntime.wrapBoolean(realThis
1040: .propertyIsEnumerable(arg(args, 0)));
1041: }
1042: case Id_text:
1043: return realThis.text();
1044: case Id_toString:
1045: return realThis.toString();
1046: case Id_toXMLString: {
1047: return realThis.toXMLString();
1048: }
1049: case Id_valueOf:
1050: return realThis.valueOf();
1051: }
1052: throw new IllegalArgumentException(String.valueOf(id));
1053: }
1054:
1055: private static Object arg(Object[] args, int i) {
1056: return (i < args.length) ? args[i] : Undefined.instance;
1057: }
1058:
1059: final XML newTextElementXML(XmlNode reference, XmlNode.QName qname,
1060: String value) {
1061: return lib.newTextElementXML(reference, qname, value);
1062: }
1063:
1064: /** @deprecated Hopefully this can be replaced with ecmaToXml below. */
1065: final XML newXMLFromJs(Object inputObject) {
1066: return lib.newXMLFromJs(inputObject);
1067: }
1068:
1069: final XML ecmaToXml(Object object) {
1070: return lib.ecmaToXml(object);
1071: }
1072:
1073: final String ecmaEscapeAttributeValue(String s) {
1074: // TODO Check this
1075: String quoted = lib.escapeAttributeValue(s);
1076: return quoted.substring(1, quoted.length() - 1);
1077: }
1078:
1079: final XML createEmptyXML() {
1080: return newXML(XmlNode.createEmpty(getProcessor()));
1081: }
1082: }
|