001: /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
002: *
003: * ***** BEGIN LICENSE BLOCK *****
004: * Version: MPL 1.1/GPL 2.0
005: *
006: * The contents of this file are subject to the Mozilla Public License Version
007: * 1.1 (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: * http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the
014: * License.
015: *
016: * The Original Code is Rhino code, released
017: * May 6, 1999.
018: *
019: * The Initial Developer of the Original Code is
020: * Netscape Communications Corporation.
021: * Portions created by the Initial Developer are Copyright (C) 1997-2000
022: * the Initial Developer. All Rights Reserved.
023: *
024: * Contributor(s):
025: * Ethan Hugg
026: * Terry Lucas
027: * Milen Nankov
028: *
029: * Alternatively, the contents of this file may be used under the terms of
030: * the GNU General Public License Version 2 or later (the "GPL"), in which
031: * case the provisions of the GPL are applicable instead of those above. If
032: * you wish to allow use of your version of this file only under the terms of
033: * the GPL and not to allow others to use your version of this file under the
034: * MPL, indicate your decision by deleting the provisions above and replacing
035: * them with the notice and other provisions required by the GPL. If you do
036: * not delete the provisions above, a recipient may use your version of this
037: * file under either the MPL or the GPL.
038: *
039: * ***** END LICENSE BLOCK ***** */
040:
041: package org.mozilla.javascript.xmlimpl;
042:
043: import org.mozilla.javascript.*;
044:
045: /**
046: * Class QName
047: *
048: */
049: final class QName extends IdScriptableObject {
050: static final long serialVersionUID = 416745167693026750L;
051:
052: private static final Object QNAME_TAG = new Object();
053:
054: private XMLLibImpl lib;
055:
056: private QName prototype;
057:
058: private XmlNode.QName delegate;
059:
060: private QName() {
061: }
062:
063: static QName create(XMLLibImpl lib, Scriptable scope,
064: QName prototype, XmlNode.QName delegate) {
065: QName rv = new QName();
066: rv.lib = lib;
067: rv.setParentScope(scope);
068: rv.prototype = prototype;
069: rv.setPrototype(prototype);
070: rv.delegate = delegate;
071: return rv;
072: }
073:
074: // /** @deprecated */
075: // static QName create(XMLLibImpl lib, XmlNode.QName nodeQname) {
076: // return create(lib, lib.globalScope(), lib.qnamePrototype(), nodeQname);
077: // }
078:
079: void exportAsJSClass(boolean sealed) {
080: exportAsJSClass(MAX_PROTOTYPE_ID, getParentScope(), sealed);
081: }
082:
083: public String toString() {
084: // ECMA357 13.3.4.2
085: if (delegate.getNamespace() == null) {
086: return "*::" + localName();
087: } else if (delegate.getNamespace().isGlobal()) {
088: // leave as empty
089: return localName();
090: } else {
091: return uri() + "::" + localName();
092: }
093: }
094:
095: public String localName() {
096: if (delegate.getLocalName() == null)
097: return "*";
098: return delegate.getLocalName();
099: }
100:
101: /**
102: @deprecated
103:
104: This property is supposed to be invisible and I think we can make it private at some point, though Namespace
105: might need it
106: */
107: String prefix() {
108: if (delegate.getNamespace() == null)
109: return null;
110: return delegate.getNamespace().getPrefix();
111: }
112:
113: String uri() {
114: if (delegate.getNamespace() == null)
115: return null;
116: return delegate.getNamespace().getUri();
117: }
118:
119: /** @deprecated */
120: final XmlNode.QName toNodeQname() {
121: return delegate;
122: }
123:
124: final XmlNode.QName getDelegate() {
125: return delegate;
126: }
127:
128: public boolean equals(Object obj) {
129: if (!(obj instanceof QName))
130: return false;
131: return equals((QName) obj);
132: }
133:
134: protected Object equivalentValues(Object value) {
135: if (!(value instanceof QName))
136: return Scriptable.NOT_FOUND;
137: boolean result = equals((QName) value);
138: return result ? Boolean.TRUE : Boolean.FALSE;
139: }
140:
141: private boolean equals(QName q) {
142: return this .delegate.isEqualTo(q.delegate);
143: }
144:
145: public String getClassName() {
146: return "QName";
147: }
148:
149: public Object getDefaultValue(Class hint) {
150: return toString();
151: }
152:
153: // #string_id_map#
154: private static final int Id_localName = 1, Id_uri = 2,
155: MAX_INSTANCE_ID = 2;
156:
157: protected int getMaxInstanceId() {
158: return super .getMaxInstanceId() + MAX_INSTANCE_ID;
159: }
160:
161: protected int findInstanceIdInfo(String s) {
162: int id;
163: // #generated# Last update: 2007-08-20 08:21:41 EDT
164: L0: {
165: id = 0;
166: String X = null;
167: int s_length = s.length();
168: if (s_length == 3) {
169: X = "uri";
170: id = Id_uri;
171: } else if (s_length == 9) {
172: X = "localName";
173: id = Id_localName;
174: }
175: if (X != null && X != s && !X.equals(s))
176: id = 0;
177: break L0;
178: }
179: // #/generated#
180:
181: if (id == 0)
182: return super .findInstanceIdInfo(s);
183:
184: int attr;
185: switch (id) {
186: case Id_localName:
187: case Id_uri:
188: attr = PERMANENT | READONLY;
189: break;
190: default:
191: throw new IllegalStateException();
192: }
193: return instanceIdInfo(attr, super .getMaxInstanceId() + id);
194: }
195:
196: // #/string_id_map#
197:
198: protected String getInstanceIdName(int id) {
199: switch (id - super .getMaxInstanceId()) {
200: case Id_localName:
201: return "localName";
202: case Id_uri:
203: return "uri";
204: }
205: return super .getInstanceIdName(id);
206: }
207:
208: protected Object getInstanceIdValue(int id) {
209: switch (id - super .getMaxInstanceId()) {
210: case Id_localName:
211: return localName();
212: case Id_uri:
213: return uri();
214: }
215: return super .getInstanceIdValue(id);
216: }
217:
218: // #string_id_map#
219: private static final int Id_constructor = 1, Id_toString = 2,
220: Id_toSource = 3, MAX_PROTOTYPE_ID = 3;
221:
222: protected int findPrototypeId(String s) {
223: int id;
224: // #generated# Last update: 2007-08-20 08:21:41 EDT
225: L0: {
226: id = 0;
227: String X = null;
228: int c;
229: int s_length = s.length();
230: if (s_length == 8) {
231: c = s.charAt(3);
232: if (c == 'o') {
233: X = "toSource";
234: id = Id_toSource;
235: } else if (c == 't') {
236: X = "toString";
237: id = Id_toString;
238: }
239: } else if (s_length == 11) {
240: X = "constructor";
241: id = Id_constructor;
242: }
243: if (X != null && X != s && !X.equals(s))
244: id = 0;
245: break L0;
246: }
247: // #/generated#
248: return id;
249: }
250:
251: // #/string_id_map#
252:
253: protected void initPrototypeId(int id) {
254: String s;
255: int arity;
256: switch (id) {
257: case Id_constructor:
258: arity = 2;
259: s = "constructor";
260: break;
261: case Id_toString:
262: arity = 0;
263: s = "toString";
264: break;
265: case Id_toSource:
266: arity = 0;
267: s = "toSource";
268: break;
269: default:
270: throw new IllegalArgumentException(String.valueOf(id));
271: }
272: initPrototypeMethod(QNAME_TAG, id, s, arity);
273: }
274:
275: public Object execIdCall(IdFunctionObject f, Context cx,
276: Scriptable scope, Scriptable this Obj, Object[] args) {
277: if (!f.hasTag(QNAME_TAG)) {
278: return super .execIdCall(f, cx, scope, this Obj, args);
279: }
280: int id = f.methodId();
281: switch (id) {
282: case Id_constructor:
283: return jsConstructor(cx, (this Obj == null), args);
284: case Id_toString:
285: return realThis(this Obj, f).toString();
286: case Id_toSource:
287: return realThis(this Obj, f).js_toSource();
288: }
289: throw new IllegalArgumentException(String.valueOf(id));
290: }
291:
292: private QName realThis(Scriptable this Obj, IdFunctionObject f) {
293: if (!(this Obj instanceof QName))
294: throw incompatibleCallError(f);
295: return (QName) this Obj;
296: }
297:
298: QName newQName(XMLLibImpl lib, String q_uri, String q_localName,
299: String q_prefix) {
300: QName prototype = this .prototype;
301: if (prototype == null) {
302: prototype = this ;
303: }
304: XmlNode.Namespace ns = null;
305: if (q_prefix != null) {
306: ns = XmlNode.Namespace.create(q_uri, q_prefix);
307: } else if (q_uri != null) {
308: ns = XmlNode.Namespace.create(q_uri);
309: } else {
310: ns = null;
311: }
312: if (q_localName != null && q_localName.equals("*"))
313: q_localName = null;
314: return create(lib, this .getParentScope(), prototype,
315: XmlNode.QName.create(ns, q_localName));
316: }
317:
318: // See ECMA357 13.3.2
319: QName constructQName(XMLLibImpl lib, Context cx, Object namespace,
320: Object name) {
321: String nameString = null;
322: if (name instanceof QName) {
323: if (namespace == Undefined.instance) {
324: return (QName) name;
325: } else {
326: nameString = ((QName) name).localName();
327: }
328: }
329: if (name == Undefined.instance) {
330: nameString = "";
331: } else {
332: nameString = ScriptRuntime.toString(name);
333: }
334:
335: if (namespace == Undefined.instance) {
336: if ("*".equals(nameString)) {
337: namespace = null;
338: } else {
339: namespace = lib.getDefaultNamespace(cx);
340: }
341: }
342: Namespace namespaceNamespace = null;
343: if (namespace == null) {
344: // leave as null
345: } else if (namespace instanceof Namespace) {
346: namespaceNamespace = (Namespace) namespace;
347: } else {
348: namespaceNamespace = lib.newNamespace(ScriptRuntime
349: .toString(namespace));
350: }
351: String q_localName = nameString;
352: String q_uri;
353: String q_prefix;
354: if (namespace == null) {
355: q_uri = null;
356: q_prefix = null; // corresponds to undefined; see QName class
357: } else {
358: q_uri = namespaceNamespace.uri();
359: q_prefix = namespaceNamespace.prefix();
360: }
361: return newQName(lib, q_uri, q_localName, q_prefix);
362: }
363:
364: QName constructQName(XMLLibImpl lib, Context cx, Object nameValue) {
365: return constructQName(lib, cx, Undefined.instance, nameValue);
366: }
367:
368: QName castToQName(XMLLibImpl lib, Context cx, Object qnameValue) {
369: if (qnameValue instanceof QName) {
370: return (QName) qnameValue;
371: }
372: return constructQName(lib, cx, qnameValue);
373: }
374:
375: private Object jsConstructor(Context cx, boolean inNewExpr,
376: Object[] args) {
377: // See ECMA357 13.3.2
378: if (!inNewExpr && args.length == 1) {
379: return castToQName(lib, cx, args[0]);
380: }
381: if (args.length == 0) {
382: return constructQName(lib, cx, Undefined.instance);
383: } else if (args.length == 1) {
384: return constructQName(lib, cx, args[0]);
385: } else {
386: return constructQName(lib, cx, args[0], args[1]);
387: }
388: }
389:
390: private String js_toSource() {
391: StringBuffer sb = new StringBuffer();
392: sb.append('(');
393: toSourceImpl(uri(), localName(), prefix(), sb);
394: sb.append(')');
395: return sb.toString();
396: }
397:
398: private static void toSourceImpl(String uri, String localName,
399: String prefix, StringBuffer sb) {
400: sb.append("new QName(");
401: if (uri == null && prefix == null) {
402: if (!"*".equals(localName)) {
403: sb.append("null, ");
404: }
405: } else {
406: Namespace.toSourceImpl(prefix, uri, sb);
407: sb.append(", ");
408: }
409: sb.append('\'');
410: sb.append(ScriptRuntime.escapeString(localName, '\''));
411: sb.append("')");
412: }
413: }
|