diff options
Diffstat (limited to 'trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript')
14 files changed, 8284 insertions, 0 deletions
diff --git a/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/ClassDefinitionException.java b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/ClassDefinitionException.java new file mode 100644 index 0000000..2197063 --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/ClassDefinitionException.java @@ -0,0 +1,53 @@ + +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ +// API class + +package org.mozilla.javascript; + +/** + * @deprecated The exception is no longer thrown by Rhino runtime as + * {@link EvaluatorException} is used instead. + */ +public class ClassDefinitionException extends RuntimeException +{ + static final long serialVersionUID = -5637830967241712746L; + + public ClassDefinitionException(String detail) { + super(detail); + } +} diff --git a/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/NotAFunctionException.java b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/NotAFunctionException.java new file mode 100644 index 0000000..3de53a8 --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/NotAFunctionException.java @@ -0,0 +1,52 @@ + +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Igor Bukanov + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ +// API class + +package org.mozilla.javascript; + +/** + * @deprecated The exception is no longer thrown by Rhino runtime as + * {@link EvaluatorException} is used instead. + */ +public class NotAFunctionException extends RuntimeException +{ + static final long serialVersionUID = 6461524852170711724L; + + public NotAFunctionException() { } +} diff --git a/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/PropertyException.java b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/PropertyException.java new file mode 100644 index 0000000..8d786c7 --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/PropertyException.java @@ -0,0 +1,54 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Norris Boyd + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ + +// API class + +package org.mozilla.javascript; + +/** + * @deprecated This exception is no longer thrown by Rhino runtime. + */ +public class PropertyException extends RuntimeException +{ + static final long serialVersionUID = -8221564865490676219L; + + public PropertyException(String detail) { + super(detail); + } + +} diff --git a/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/LogicalEquality.java b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/LogicalEquality.java new file mode 100644 index 0000000..b525aff --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/LogicalEquality.java @@ -0,0 +1,367 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Ethan Hugg + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.javascript.xml.impl.xmlbeans; + +import org.apache.xmlbeans.XmlCursor; + +import java.util.*; + + +public class LogicalEquality +{ + public static boolean nodesEqual(XmlCursor xmlOne, XmlCursor xmlTwo) + { + boolean result = false; + + if (xmlOne.isStartdoc()) + { + xmlOne.toFirstContentToken(); + } + + if (xmlTwo.isStartdoc()) + { + xmlTwo.toFirstContentToken(); + } + + if (xmlOne.currentTokenType() == xmlTwo.currentTokenType()) + { + if (xmlOne.isEnddoc()) + { + // Both empty + result = true; + } + else if (xmlOne.isAttr()) + { + result = attributesEqual(xmlOne, xmlTwo); + } + else if (xmlOne.isText()) + { + result = textNodesEqual(xmlOne, xmlTwo); + } + else if (xmlOne.isComment()) + { + result = commentsEqual(xmlOne, xmlTwo); + } + else if (xmlOne.isProcinst()) + { + result = processingInstructionsEqual(xmlOne, xmlTwo); + } + else if (xmlOne.isStart()) + { + // Compare root elements + result = elementsEqual(xmlOne, xmlTwo); + } + } + + return result; + } + + private static boolean elementsEqual(XmlCursor xmlOne, XmlCursor xmlTwo) + { + boolean result = true; + + if (!qnamesEqual(xmlOne.getName(), xmlTwo.getName())) + { + result = false; + } + else + { + // These filter out empty text nodes. + nextToken(xmlOne); + nextToken(xmlTwo); + + do + { + if (xmlOne.currentTokenType() != xmlTwo.currentTokenType()) + { + // Not same token + result = false; + break; + } + else if (xmlOne.isEnd()) + { + // Done with this element, step over end + break; + } + else if (xmlOne.isEnddoc()) + { + // Shouldn't get here + break; + } + else if (xmlOne.isAttr()) + { + // This one will move us to the first non-attr token. + result = attributeListsEqual(xmlOne, xmlTwo); + } + else + { + if (xmlOne.isText()) + { + result = textNodesEqual(xmlOne, xmlTwo); + } + else if (xmlOne.isComment()) + { + result = commentsEqual(xmlOne, xmlTwo); + } + else if (xmlOne.isProcinst()) + { + result = processingInstructionsEqual(xmlOne, xmlTwo); + } + else if (xmlOne.isStart()) + { + result = elementsEqual(xmlOne, xmlTwo); + } + else + { + //XML.log("Unknown token type" + xmlOne.currentTokenType()); + } + + // These filter out empty text nodes. + nextToken(xmlOne); + nextToken(xmlTwo); + } + } + while(result); + } + + return result; + } + + /** + * + * @param xmlOne + * @param xmlTwo + * @return + */ + private static boolean attributeListsEqual(XmlCursor xmlOne, XmlCursor xmlTwo) + { + boolean result = true; + TreeMap mapOne = loadAttributeMap(xmlOne); + TreeMap mapTwo = loadAttributeMap(xmlTwo); + + if (mapOne.size() != mapTwo.size()) + { + result = false; + } + else + { + Set keysOne = mapOne.keySet(); + Set keysTwo = mapTwo.keySet(); + Iterator itOne = keysOne.iterator(); + Iterator itTwo = keysTwo.iterator(); + + while (result && itOne.hasNext()) + { + String valueOne = (String) itOne.next(); + String valueTwo = (String) itTwo.next(); + + if (!valueOne.equals(valueTwo)) + { + result = false; + } + else + { + javax.xml.namespace.QName qnameOne = (javax.xml.namespace.QName) mapOne.get(valueOne); + javax.xml.namespace.QName qnameTwo = (javax.xml.namespace.QName) mapTwo.get(valueTwo); + + if (!qnamesEqual(qnameOne, qnameTwo)) + { + result = false; + } + } + } + } + + return result; + } + + /** + * + * @param xml + * @return + */ + private static TreeMap loadAttributeMap(XmlCursor xml) + { + TreeMap result = new TreeMap(); + + while (xml.isAttr()) + { + result.put(xml.getTextValue(), xml.getName()); + nextToken(xml); + } + + return result; + } + + /** + * + * @param xmlOne + * @param xmlTwo + * @return + */ + private static boolean attributesEqual(XmlCursor xmlOne, XmlCursor xmlTwo) + { + boolean result = false; + + if (xmlOne.isAttr() && xmlTwo.isAttr()) + { + if (qnamesEqual(xmlOne.getName(), xmlTwo.getName())) + { + if (xmlOne.getTextValue().equals(xmlTwo.getTextValue())) + { + result = true; + } + } + } + + return result; + } + + /** + * + * @param xmlOne + * @param xmlTwo + * @return + */ + private static boolean textNodesEqual(XmlCursor xmlOne, XmlCursor xmlTwo) + { + boolean result = false; + + if (xmlOne.isText() && xmlTwo.isText()) + { + if (xmlOne.getChars().equals(xmlTwo.getChars())) + { + result = true; + } + } + + return result; + } + + /** + * + * @param xmlOne + * @param xmlTwo + * @return + */ + private static boolean commentsEqual(XmlCursor xmlOne, XmlCursor xmlTwo) + { + boolean result = false; + + if (xmlOne.isComment() && xmlTwo.isComment()) + { + if (xmlOne.getTextValue().equals(xmlTwo.getTextValue())) + { + result = true; + } + } + + return result; + } + + /** + * + * @param xmlOne + * @param xmlTwo + * @return + */ + private static boolean processingInstructionsEqual(XmlCursor xmlOne, XmlCursor xmlTwo) + { + boolean result = false; + + if (xmlOne.isProcinst() && xmlTwo.isProcinst()) + { + if (qnamesEqual(xmlOne.getName(), xmlTwo.getName())) + { + if (xmlOne.getTextValue().equals(xmlTwo.getTextValue())) + { + result = true; + } + } + } + + return result; + } + + /** + * + * @param qnameOne + * @param qnameTwo + * @return + */ + private static boolean qnamesEqual(javax.xml.namespace.QName qnameOne, javax.xml.namespace.QName qnameTwo) + { + boolean result = false; + + if (qnameOne.getNamespaceURI().equals(qnameTwo.getNamespaceURI())) + { + if (qnameOne.getLocalPart().equals(qnameTwo.getLocalPart())) + { + return true; + } + } + + return result; + } + + /** + * filter out empty textNodes here + * + * @param xml + */ + private static void nextToken(XmlCursor xml) + { + do + { + xml.toNextToken(); + + if (!xml.isText()) + { + // Not a text node + break; + } + else if (xml.getChars().trim().length() > 0) + { + // Text node is not empty + break; + } + } + while (true); + } +} diff --git a/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/Namespace.java b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/Namespace.java new file mode 100644 index 0000000..3a16320 --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/Namespace.java @@ -0,0 +1,335 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Ethan Hugg + * Terry Lucas + * Milen Nankov + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.javascript.xml.impl.xmlbeans; + +import org.mozilla.javascript.*; + +/** + * Class Namespace + * + */ +class Namespace extends IdScriptableObject +{ + static final long serialVersionUID = -5765755238131301744L; + + private static final Object NAMESPACE_TAG = new Object(); + + private XMLLibImpl lib; + private String prefix; + private String uri; + + public Namespace(XMLLibImpl lib, String uri) + { + super(lib.globalScope(), lib.namespacePrototype); + + if (uri == null) + throw new IllegalArgumentException(); + + this.lib = lib; + this.prefix = (uri.length() == 0) ? "" : null; + this.uri = uri; + } + + + public Namespace(XMLLibImpl lib, String prefix, String uri) + { + super(lib.globalScope(), lib.namespacePrototype); + + if (uri == null) + throw new IllegalArgumentException(); + if (uri.length() == 0) { + // prefix should be "" for empty uri + if (prefix == null) + throw new IllegalArgumentException(); + if (prefix.length() != 0) + throw new IllegalArgumentException(); + } + + this.lib = lib; + this.prefix = prefix; + this.uri = uri; + } + + public void exportAsJSClass(boolean sealed) + { + exportAsJSClass(MAX_PROTOTYPE_ID, lib.globalScope(), sealed); + } + + /** + * + * @return + */ + public String uri() + { + return uri; + } + + /** + * + * @return + */ + public String prefix() + { + return prefix; + } + + /** + * + * @return + */ + public String toString () + { + return uri(); + } + + /** + * + * @return + */ + public String toLocaleString () + { + return toString(); + } + + public boolean equals(Object obj) + { + if (!(obj instanceof Namespace)) return false; + return equals((Namespace)obj); + } + + protected Object equivalentValues(Object value) + { + if (!(value instanceof Namespace)) return Scriptable.NOT_FOUND; + boolean result = equals((Namespace)value); + return result ? Boolean.TRUE : Boolean.FALSE; + } + + private boolean equals(Namespace n) + { + return uri().equals(n.uri()); + } + + /** + * + * @return + */ + public String getClassName () + { + return "Namespace"; + } + + /** + * + * @param hint + * @return + */ + public Object getDefaultValue (Class hint) + { + return uri(); + } + +// #string_id_map# + private static final int + Id_prefix = 1, + Id_uri = 2, + MAX_INSTANCE_ID = 2; + + protected int getMaxInstanceId() + { + return super.getMaxInstanceId() + MAX_INSTANCE_ID; + } + + protected int findInstanceIdInfo(String s) + { + int id; +// #generated# Last update: 2004-07-20 19:50:50 CEST + L0: { id = 0; String X = null; + int s_length = s.length(); + if (s_length==3) { X="uri";id=Id_uri; } + else if (s_length==6) { X="prefix";id=Id_prefix; } + if (X!=null && X!=s && !X.equals(s)) id = 0; + } +// #/generated# + + if (id == 0) return super.findInstanceIdInfo(s); + + int attr; + switch (id) { + case Id_prefix: + case Id_uri: + attr = PERMANENT | READONLY; + break; + default: throw new IllegalStateException(); + } + return instanceIdInfo(attr, super.getMaxInstanceId() + id); + } +// #/string_id_map# + + protected String getInstanceIdName(int id) + { + switch (id - super.getMaxInstanceId()) { + case Id_prefix: return "prefix"; + case Id_uri: return "uri"; + } + return super.getInstanceIdName(id); + } + + protected Object getInstanceIdValue(int id) + { + switch (id - super.getMaxInstanceId()) { + case Id_prefix: + if (prefix == null) return Undefined.instance; + return prefix; + case Id_uri: + return uri; + } + return super.getInstanceIdValue(id); + } + + +// #string_id_map# + private static final int + Id_constructor = 1, + Id_toString = 2, + Id_toSource = 3, + MAX_PROTOTYPE_ID = 3; + + protected int findPrototypeId(String s) + { + int id; +// #generated# Last update: 2004-08-21 12:07:01 CEST + L0: { id = 0; String X = null; int c; + int s_length = s.length(); + if (s_length==8) { + c=s.charAt(3); + if (c=='o') { X="toSource";id=Id_toSource; } + else if (c=='t') { X="toString";id=Id_toString; } + } + else if (s_length==11) { X="constructor";id=Id_constructor; } + if (X!=null && X!=s && !X.equals(s)) id = 0; + } +// #/generated# + return id; + } +// #/string_id_map# + + protected void initPrototypeId(int id) + { + String s; + int arity; + switch (id) { + case Id_constructor: arity=2; s="constructor"; break; + case Id_toString: arity=0; s="toString"; break; + case Id_toSource: arity=0; s="toSource"; break; + default: throw new IllegalArgumentException(String.valueOf(id)); + } + initPrototypeMethod(NAMESPACE_TAG, id, s, arity); + } + + public Object execIdCall(IdFunctionObject f, + Context cx, + Scriptable scope, + Scriptable thisObj, + Object[] args) + { + if (!f.hasTag(NAMESPACE_TAG)) { + return super.execIdCall(f, cx, scope, thisObj, args); + } + int id = f.methodId(); + switch (id) { + case Id_constructor: + return jsConstructor(cx, (thisObj == null), args); + case Id_toString: + return realThis(thisObj, f).toString(); + case Id_toSource: + return realThis(thisObj, f).js_toSource(); + } + throw new IllegalArgumentException(String.valueOf(id)); + } + + private Namespace realThis(Scriptable thisObj, IdFunctionObject f) + { + if(!(thisObj instanceof Namespace)) + throw incompatibleCallError(f); + return (Namespace)thisObj; + } + + private Object jsConstructor(Context cx, boolean inNewExpr, Object[] args) + { + if (!inNewExpr && args.length == 1) { + return lib.castToNamespace(cx, args[0]); + } + + if (args.length == 0) { + return lib.constructNamespace(cx); + } else if (args.length == 1) { + return lib.constructNamespace(cx, args[0]); + } else { + return lib.constructNamespace(cx, args[0], args[1]); + } + } + + private String js_toSource() + { + StringBuffer sb = new StringBuffer(); + sb.append('('); + toSourceImpl(prefix, uri, sb); + sb.append(')'); + return sb.toString(); + } + + static void toSourceImpl(String prefix, String uri, StringBuffer sb) + { + sb.append("new Namespace("); + if (uri.length() == 0) { + if (!"".equals(prefix)) throw new IllegalArgumentException(prefix); + } else { + sb.append('\''); + if (prefix != null) { + sb.append(ScriptRuntime.escapeString(prefix, '\'')); + sb.append("', '"); + } + sb.append(ScriptRuntime.escapeString(uri, '\'')); + sb.append('\''); + } + sb.append(')'); + } +} diff --git a/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/NamespaceHelper.java b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/NamespaceHelper.java new file mode 100644 index 0000000..fc99c7e --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/NamespaceHelper.java @@ -0,0 +1,350 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Milen Nankov + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.javascript.xml.impl.xmlbeans; + +import java.util.*; +import org.apache.xmlbeans.XmlCursor; + +import org.mozilla.javascript.*; + +class NamespaceHelper +{ + private XMLLibImpl lib; + private final Map prefixToURI = new HashMap(); + private final Map uriToPrefix = new HashMap(); + // A set of URIs that are used without explicit namespace declaration in scope. + private final Set undeclared = new HashSet(); + + private NamespaceHelper(XMLLibImpl lib) + { + this.lib = lib; + // Insert the default namespace + prefixToURI.put("", ""); + Set prefixes = new HashSet(); + prefixes.add(""); + uriToPrefix.put("", prefixes); + } + + /** + * Declared a new namespace + * + * @param prefix + * @param uri + * @param declarations + */ + private void declareNamespace(String prefix, String uri, ObjArray declarations) + { + Set prefixes = (Set)uriToPrefix.get(uri); + if(prefixes == null) + { + prefixes = new HashSet(); + uriToPrefix.put(uri, prefixes); + } + + if(!prefixes.contains(prefix)) + { + String oldURI = (String)prefixToURI.get(prefix); + + // Add the new mapping + prefixes.add(prefix); + prefixToURI.put(prefix, uri); + if(declarations != null) + declarations.add(new Namespace(lib, prefix, uri)); + + if(oldURI != null) + { + // Update the existing mapping + prefixes = (Set)uriToPrefix.get(oldURI); + prefixes.remove(prefix); + } + } + } + + /** + * Updates the internal state of this NamespaceHelper to reflect the + * existance of the XML token pointed to by the cursor. + */ + private void processName(XmlCursor cursor, ObjArray declarations) + { + javax.xml.namespace.QName qname = cursor.getName(); + String uri = qname.getNamespaceURI(); + Set prefixes = (Set)uriToPrefix.get(uri); + if(prefixes == null || prefixes.size() == 0) + { + undeclared.add(uri); + if(declarations != null) + declarations.add(new Namespace(lib, uri)); + } + } + + /** + * Updates the internal state of this NamespaceHelper with the + * namespace information of the element pointed to by the cursor. + */ + private void update(XmlCursor cursor, ObjArray declarations) + { + // Process the Namespace declarations + cursor.push(); + while(cursor.toNextToken().isAnyAttr()) + { + if(cursor.isNamespace()) + { + javax.xml.namespace.QName name = cursor.getName(); + String prefix = name.getLocalPart(); + String uri = name.getNamespaceURI(); + + declareNamespace(prefix, uri, declarations); + } + } + cursor.pop(); + + // Process the element + processName(cursor, declarations); + + // Process the attributes + cursor.push(); + boolean hasNext = cursor.toFirstAttribute(); + while(hasNext) + { + processName(cursor, declarations); + hasNext = cursor.toNextAttribute(); + } + cursor.pop(); + } + + /** + * @return Object[] array of Namespace objects in scope at the cursor. + */ + public static Object[] inScopeNamespaces(XMLLibImpl lib, XmlCursor cursor) + { + ObjArray namespaces = new ObjArray(); + NamespaceHelper helper = new NamespaceHelper(lib); + + cursor.push(); + + int depth = 0; + while(cursor.hasPrevToken()) + { + if(cursor.isContainer()) + { + cursor.push(); + depth++; + } + + cursor.toParent(); + } + + for(int i = 0; i < depth; i++) + { + cursor.pop(); + helper.update(cursor, null); + } + + Iterator i = helper.prefixToURI.entrySet().iterator(); + while(i.hasNext()) + { + Map.Entry entry = (Map.Entry)i.next(); + Namespace ns = new Namespace(lib, (String)entry.getKey(), + (String)entry.getValue()); + namespaces.add(ns); + } + + i = helper.undeclared.iterator(); + while(i.hasNext()) + { + Namespace ns = new Namespace(lib, (String)i.next()); + namespaces.add(ns); + } + + cursor.pop(); + + return namespaces.toArray(); + } + + static Namespace getNamespace(XMLLibImpl lib, XmlCursor cursor, + Object[] inScopeNamespaces) + { + String uri; + String prefix; + + if (cursor.isProcinst()) { + uri = ""; + prefix = ""; + } else { + javax.xml.namespace.QName qname = cursor.getName(); + uri = qname.getNamespaceURI(); + prefix = qname.getPrefix(); + } + + if (inScopeNamespaces == null) + return new Namespace(lib, prefix, uri); + + Namespace result = null; + for (int i = 0; i != inScopeNamespaces.length; ++i) { + Namespace ns = (Namespace)inScopeNamespaces[i]; + if(ns == null) continue; + + String nsURI = ns.uri(); + if(nsURI.equals(uri)) + { + if(prefix.equals(ns.prefix())) + { + result = ns; + break; + } + + if(result == null || + (result.prefix() == null && + ns.prefix() != null)) + result = ns; + } + } + + if(result == null) + result = new Namespace(lib, prefix, uri); + + return result; + } + + /** + * @return List of Namespace objects that are declared in the container pointed to by the cursor. + */ + public static Object[] namespaceDeclarations(XMLLibImpl lib, XmlCursor cursor) + { + ObjArray declarations = new ObjArray(); + NamespaceHelper helper = new NamespaceHelper(lib); + + cursor.push(); + + int depth = 0; + while(cursor.hasPrevToken()) + { + if(cursor.isContainer()) + { + cursor.push(); + depth++; + } + + cursor.toParent(); + } + + for(int i = 0; i < depth - 1; i++) + { + cursor.pop(); + helper.update(cursor, null); + } + + if(depth > 0) + { + cursor.pop(); + helper.update(cursor, declarations); + } + + cursor.pop(); + + return declarations.toArray(); + } + + /** + * @return Prefix to URI map of all namespaces in scope at the cursor. + */ + public static Map getAllNamespaces(XMLLibImpl lib, XmlCursor cursor) + { + NamespaceHelper helper = new NamespaceHelper(lib); + + cursor.push(); + + int depth = 0; + while(cursor.hasPrevToken()) + { + if(cursor.isContainer()) + { + cursor.push(); + depth++; + } + + cursor.toParent(); + } + + for(int i = 0; i < depth; i++) + { + cursor.pop(); + helper.update(cursor, null); + } + + cursor.pop(); + + return helper.prefixToURI; + } + + public static void getNamespaces(XmlCursor cursor, Map prefixToURI) + { + cursor.push(); + while(cursor.toNextToken().isAnyAttr()) + { + if(cursor.isNamespace()) + { + javax.xml.namespace.QName name = cursor.getName(); + String prefix = name.getLocalPart(); + String uri = name.getNamespaceURI(); + + prefixToURI.put(prefix, uri); + } + } + cursor.pop(); + } + + public static void removeNamespace(XmlCursor cursor, String prefix) + { + cursor.push(); + while(cursor.toNextToken().isAnyAttr()) + { + if(cursor.isNamespace()) + { + javax.xml.namespace.QName name = cursor.getName(); + if(name.getLocalPart().equals(prefix)) + { + cursor.removeXml(); + break; + } + } + } + cursor.pop(); + } +}
\ No newline at end of file diff --git a/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/QName.java b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/QName.java new file mode 100644 index 0000000..247da19 --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/QName.java @@ -0,0 +1,321 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Ethan Hugg + * Terry Lucas + * Milen Nankov + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.javascript.xml.impl.xmlbeans; + +import org.mozilla.javascript.*; + +/** + * Class QName + * + */ +final class QName extends IdScriptableObject +{ + static final long serialVersionUID = 416745167693026750L; + + private static final Object QNAME_TAG = new Object(); + + XMLLibImpl lib; + private String prefix; + private String localName; + private String uri; + + QName(XMLLibImpl lib, String uri, String localName, String prefix) + { + super(lib.globalScope(), lib.qnamePrototype); + if (localName == null) throw new IllegalArgumentException(); + this.lib = lib; + this.uri = uri; + this.prefix = prefix; + this.localName = localName; + } + + void exportAsJSClass(boolean sealed) + { + exportAsJSClass(MAX_PROTOTYPE_ID, lib.globalScope(), sealed); + } + + /** + * + * @return + */ + public String toString() + { + String result; + + if (uri == null) + { + result = "*::".concat(localName); + } + else if(uri.length() == 0) + { + result = localName; + } + else + { + result = uri + "::" + localName; + } + + return result; + } + + public String localName() + { + return localName; + } + + String prefix() + { + return (prefix == null) ? prefix : ""; + } + + String uri() + { + return uri; + } + + public boolean equals(Object obj) + { + if(!(obj instanceof QName)) return false; + return equals((QName)obj); + } + + protected Object equivalentValues(Object value) + { + if(!(value instanceof QName)) return Scriptable.NOT_FOUND; + boolean result = equals((QName)value); + return result ? Boolean.TRUE : Boolean.FALSE; + } + + private boolean equals(QName q) + { + boolean result; + + if (uri == null) { + result = q.uri == null && localName.equals(q.localName); + } else { + result = uri.equals(q.uri) && localName.equals(q.localName); + } + + return result; + } + + /** + * + * @return + */ + public String getClassName () + { + return "QName"; + } + + /** + * + * @param hint + * @return + */ + public Object getDefaultValue (Class hint) + { + return toString(); + } + +// #string_id_map# + private static final int + Id_localName = 1, + Id_uri = 2, + MAX_INSTANCE_ID = 2; + + protected int getMaxInstanceId() + { + return super.getMaxInstanceId() + MAX_INSTANCE_ID; + } + + protected int findInstanceIdInfo(String s) + { + int id; +// #generated# Last update: 2004-07-18 12:32:51 CEST + L0: { id = 0; String X = null; + int s_length = s.length(); + if (s_length==3) { X="uri";id=Id_uri; } + else if (s_length==9) { X="localName";id=Id_localName; } + if (X!=null && X!=s && !X.equals(s)) id = 0; + } +// #/generated# + + if (id == 0) return super.findInstanceIdInfo(s); + + int attr; + switch (id) { + case Id_localName: + case Id_uri: + attr = PERMANENT | READONLY; + break; + default: throw new IllegalStateException(); + } + return instanceIdInfo(attr, super.getMaxInstanceId() + id); + } +// #/string_id_map# + + protected String getInstanceIdName(int id) + { + switch (id - super.getMaxInstanceId()) { + case Id_localName: return "localName"; + case Id_uri: return "uri"; + } + return super.getInstanceIdName(id); + } + + protected Object getInstanceIdValue(int id) + { + switch (id - super.getMaxInstanceId()) { + case Id_localName: return localName; + case Id_uri: return uri; + } + return super.getInstanceIdValue(id); + } + +// #string_id_map# + private static final int + Id_constructor = 1, + Id_toString = 2, + Id_toSource = 3, + MAX_PROTOTYPE_ID = 3; + + protected int findPrototypeId(String s) + { + int id; +// #generated# Last update: 2004-08-21 12:45:13 CEST + L0: { id = 0; String X = null; int c; + int s_length = s.length(); + if (s_length==8) { + c=s.charAt(3); + if (c=='o') { X="toSource";id=Id_toSource; } + else if (c=='t') { X="toString";id=Id_toString; } + } + else if (s_length==11) { X="constructor";id=Id_constructor; } + if (X!=null && X!=s && !X.equals(s)) id = 0; + } +// #/generated# + return id; + } +// #/string_id_map# + + protected void initPrototypeId(int id) + { + String s; + int arity; + switch (id) { + case Id_constructor: arity=2; s="constructor"; break; + case Id_toString: arity=0; s="toString"; break; + case Id_toSource: arity=0; s="toSource"; break; + default: throw new IllegalArgumentException(String.valueOf(id)); + } + initPrototypeMethod(QNAME_TAG, id, s, arity); + } + + public Object execIdCall(IdFunctionObject f, + Context cx, + Scriptable scope, + Scriptable thisObj, + Object[] args) + { + if (!f.hasTag(QNAME_TAG)) { + return super.execIdCall(f, cx, scope, thisObj, args); + } + int id = f.methodId(); + switch (id) { + case Id_constructor: + return jsConstructor(cx, (thisObj == null), args); + case Id_toString: + return realThis(thisObj, f).toString(); + case Id_toSource: + return realThis(thisObj, f).js_toSource(); + } + throw new IllegalArgumentException(String.valueOf(id)); + } + + private QName realThis(Scriptable thisObj, IdFunctionObject f) + { + if(!(thisObj instanceof QName)) + throw incompatibleCallError(f); + return (QName)thisObj; + } + + private Object jsConstructor(Context cx, boolean inNewExpr, Object[] args) + { + if (!inNewExpr && args.length == 1) { + return lib.castToQName(cx, args[0]); + } + if (args.length == 0) { + return lib.constructQName(cx, Undefined.instance); + } else if (args.length == 1) { + return lib.constructQName(cx, args[0]); + } else { + return lib.constructQName(cx, args[0], args[1]); + } + } + + private String js_toSource() + { + StringBuffer sb = new StringBuffer(); + sb.append('('); + toSourceImpl(uri, localName, prefix, sb); + sb.append(')'); + return sb.toString(); + } + + private static void toSourceImpl(String uri, String localName, + String prefix, StringBuffer sb) + { + sb.append("new QName("); + if (uri == null && prefix == null) { + if (!"*".equals(localName)) { + sb.append("null, "); + } + } else { + Namespace.toSourceImpl(prefix, uri, sb); + sb.append(", "); + } + sb.append('\''); + sb.append(ScriptRuntime.escapeString(localName, '\'')); + sb.append("')"); + } + +} diff --git a/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XML.java b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XML.java new file mode 100644 index 0000000..c8818a5 --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XML.java @@ -0,0 +1,3092 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Ethan Hugg + * Terry Lucas + * Milen Nankov + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.javascript.xml.impl.xmlbeans; + +import java.io.Serializable; +import java.util.*; + +import org.mozilla.javascript.*; + +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlCursor.XmlBookmark; +import org.apache.xmlbeans.XmlCursor.TokenType; +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlObject; +import org.apache.xmlbeans.XmlOptions; + +class XML extends XMLObjectImpl +{ + static final long serialVersionUID = -630969919086449092L; + + final static class XScriptAnnotation extends XmlBookmark implements Serializable + { + private static final long serialVersionUID = 1L; + + javax.xml.namespace.QName _name; + XML _xScriptXML; + + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Constructurs + // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + XScriptAnnotation (XmlCursor curs) + { + _name = curs.getName(); + } + + } + + /** + * + */ + final static class NamespaceDeclarations + { + private int _prefixIdx; + private StringBuffer _namespaceDecls; + private String _defaultNSURI; + + + NamespaceDeclarations (XmlCursor curs) + { + _prefixIdx = 0; + _namespaceDecls = new StringBuffer(); + + skipNonElements(curs); + _defaultNSURI = curs.namespaceForPrefix(""); + + if (isAnyDefaultNamespace()) + { + addDecl("", _defaultNSURI); + } + } + + + private void addDecl (String prefix, String ns) + { + _namespaceDecls.append((prefix.length() > 0 ? + "declare namespace " + prefix : + "default element namespace") + + " = \"" + ns + "\"" + "\n"); + } + + + String getNextPrefix (String ns) + { + String prefix = "NS" + _prefixIdx++; + + _namespaceDecls.append("declare namespace " + prefix + " = " + "\"" + ns + "\"" + "\n"); + + return prefix; + } + + + boolean isAnyDefaultNamespace () + { + return _defaultNSURI != null ?_defaultNSURI.length() > 0 : false; + } + + + String getDeclarations() + { + return _namespaceDecls.toString(); + } + } + + // Fields + //static final XML prototype = new XML(); + private XScriptAnnotation _anno; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Constructors + // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * + * @param anno + */ + private XML(XMLLibImpl lib, XScriptAnnotation anno) + { + super(lib, lib.xmlPrototype); + _anno = anno; + _anno._xScriptXML = this; + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Public factories for creating a XScript XML object given an XBean cursor. + // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + static XML createEmptyXML(XMLLibImpl lib) + { + XScriptAnnotation anno; + + XmlObject xo = XmlObject.Factory.newInstance(); + XmlCursor curs = xo.newCursor(); + try { + anno = new XScriptAnnotation(curs); + curs.setBookmark(anno); + } finally { + curs.dispose(); + } + + return new XML(lib, anno); + } + + private static XML createXML (XMLLibImpl lib, XmlCursor curs) + { + if (curs.currentTokenType().isStartdoc()) + { + curs.toFirstContentToken(); + } + + XScriptAnnotation anno = findAnnotation(curs); + + return new XML(lib, anno); + } + + /** + * Special constructor for making an attribute + * + */ + private static XML createAttributeXML(XMLLibImpl lib, XmlCursor cursor) + { + if (!cursor.isAttr()) + throw new IllegalArgumentException(); + + XScriptAnnotation anno = new XScriptAnnotation(cursor); + cursor.setBookmark(anno); + + return new XML(lib, anno); + } + + + /** + * + * @param qname + * @param value + * @return + */ + static XML createTextElement(XMLLibImpl lib, javax.xml.namespace.QName qname, String value) + { + XScriptAnnotation anno; + + XmlObject xo = XmlObject.Factory.newInstance(); + XmlCursor cursor = xo.newCursor(); + try { + cursor.toNextToken(); + + cursor.beginElement(qname.getLocalPart(), qname.getNamespaceURI()); + //if(namespace.length() > 0) + // cursor.insertNamespace("", namespace); + cursor.insertChars(value); + + cursor.toStartDoc(); + cursor.toNextToken(); + anno = new XScriptAnnotation(cursor); + cursor.setBookmark(anno); + } finally { + cursor.dispose(); + } + + return new XML(lib, anno); + } + + static XML createFromXmlObject(XMLLibImpl lib, XmlObject xo) + { + XScriptAnnotation anno; + XmlCursor curs = xo.newCursor(); + if (curs.currentTokenType().isStartdoc()) + { + curs.toFirstContentToken(); + } + try { + anno = new XScriptAnnotation(curs); + curs.setBookmark(anno); + } finally { + curs.dispose(); + } + return new XML(lib, anno); + } + + static XML createFromJS(XMLLibImpl lib, Object inputObject) + { + XmlObject xo; + boolean isText = false; + String frag; + + if (inputObject == null || inputObject == Undefined.instance) { + frag = ""; + } else if (inputObject instanceof XMLObjectImpl) { + // todo: faster way for XMLObjects? + frag = ((XMLObjectImpl) inputObject).toXMLString(0); + } else { + if (inputObject instanceof Wrapper) { + Object wrapped = ((Wrapper)inputObject).unwrap(); + if (wrapped instanceof XmlObject) { + return createFromXmlObject(lib, (XmlObject)wrapped); + } + } + frag = ScriptRuntime.toString(inputObject); + } + + if (frag.trim().startsWith("<>")) + { + throw ScriptRuntime.typeError("Invalid use of XML object anonymous tags <></>."); + } + + if (frag.indexOf("<") == -1) + { + // Must be solo text node, wrap in XML fragment + isText = true; + frag = "<textFragment>" + frag + "</textFragment>"; + } + + XmlOptions options = new XmlOptions(); + + if (lib.ignoreComments) + { + options.put(XmlOptions.LOAD_STRIP_COMMENTS); + } + + if (lib.ignoreProcessingInstructions) + { + options.put(XmlOptions.LOAD_STRIP_PROCINSTS); + } + + if (lib.ignoreWhitespace) + { + options.put(XmlOptions.LOAD_STRIP_WHITESPACE); + } + + try + { + xo = XmlObject.Factory.parse(frag, options); + + // Apply the default namespace + Context cx = Context.getCurrentContext(); + String defaultURI = lib.getDefaultNamespaceURI(cx); + + if(defaultURI.length() > 0) + { + XmlCursor cursor = xo.newCursor(); + boolean isRoot = true; + while(!cursor.toNextToken().isEnddoc()) + { + if(!cursor.isStart()) continue; + + // Check if this element explicitly sets the + // default namespace + boolean defaultNSDeclared = false; + cursor.push(); + while(cursor.toNextToken().isAnyAttr()) + { + if(cursor.isNamespace()) + { + if(cursor.getName().getLocalPart().length() == 0) + { + defaultNSDeclared = true; + break; + } + } + } + cursor.pop(); + if(defaultNSDeclared) + { + cursor.toEndToken(); + continue; + } + + // Check if this element's name is in no namespace + javax.xml.namespace.QName qname = cursor.getName(); + if(qname.getNamespaceURI().length() == 0) + { + // Change the namespace + qname = new javax.xml.namespace.QName(defaultURI, + qname.getLocalPart()); + cursor.setName(qname); + } + + if(isRoot) + { + // Declare the default namespace + cursor.push(); + cursor.toNextToken(); + cursor.insertNamespace("", defaultURI); + cursor.pop(); + + isRoot = false; + } + } + cursor.dispose(); + } + } + catch (XmlException xe) + { +/* +todo need to handle namespace prefix not found in XML look for namespace type in the scope change. + + String errorMsg = "Use of undefined namespace prefix: "; + String msg = xe.getError().getMessage(); + if (msg.startsWith(errorMsg)) + { + String prefix = msg.substring(errorMsg.length()); + } +*/ + String errMsg = xe.getMessage(); + if (errMsg.equals("error: Unexpected end of file after null")) + { + // Create an empty document. + xo = XmlObject.Factory.newInstance(); + } + else + { + throw ScriptRuntime.typeError(xe.getMessage()); + } + } + catch (Throwable e) + { + // todo: TLL Catch specific exceptions during parse. + throw ScriptRuntime.typeError("Not Parsable as XML"); + } + + XmlCursor curs = xo.newCursor(); + if (curs.currentTokenType().isStartdoc()) + { + curs.toFirstContentToken(); + } + + if (isText) + { + // Move it to point to the text node + curs.toFirstContentToken(); + } + + XScriptAnnotation anno; + try + { + anno = new XScriptAnnotation(curs); + curs.setBookmark(anno); + } + finally + { + curs.dispose(); + } + + return new XML(lib, anno); + } + + static XML getFromAnnotation(XMLLibImpl lib, XScriptAnnotation anno) + { + if (anno._xScriptXML == null) + { + anno._xScriptXML = new XML(lib, anno); + } + + return anno._xScriptXML; + } + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Private functions: + // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * + * @param curs + * @return + */ + private static TokenType skipNonElements (XmlCursor curs) + { + TokenType tt = curs.currentTokenType(); + while (tt.isComment() || tt.isProcinst()) + { + tt = curs.toNextToken(); + } + + return tt; + } + + /** + * + * @param curs + * @return + */ + protected static XScriptAnnotation findAnnotation(XmlCursor curs) + { + XmlBookmark anno = curs.getBookmark(XScriptAnnotation.class); + if (anno == null) + { + anno = new XScriptAnnotation(curs); + curs.setBookmark(anno); + } + + return (XScriptAnnotation)anno; + } + + /** + * + * @return + */ + private XmlOptions getOptions() + { + XmlOptions options = new XmlOptions(); + + if (lib.ignoreComments) + { + options.put(XmlOptions.LOAD_STRIP_COMMENTS); + } + + if (lib.ignoreProcessingInstructions) + { + options.put(XmlOptions.LOAD_STRIP_PROCINSTS); + } + + if (lib.ignoreWhitespace) + { + options.put(XmlOptions.LOAD_STRIP_WHITESPACE); + } + + if (lib.prettyPrinting) + { + options.put(XmlOptions.SAVE_PRETTY_PRINT, null); + options.put(XmlOptions.SAVE_PRETTY_PRINT_INDENT, new Integer(lib.prettyIndent)); + } + + return options; + } + + + /** + * + * @param cursor + * @param opts + * @return + */ + private static String dumpNode(XmlCursor cursor, XmlOptions opts) + { + if (cursor.isText()) + return cursor.getChars(); + + if (cursor.isFinish()) + return ""; + + cursor.push(); + boolean wanRawText = cursor.isStartdoc() && !cursor.toFirstChild(); + cursor.pop(); + + return wanRawText ? cursor.getTextValue() : cursor.xmlText( opts ); + } + + /** + * + * @return + */ + private XmlCursor newCursor () + { + XmlCursor curs; + + if (_anno != null) + { + curs = _anno.createCursor(); + if (curs == null) + { + // Orphaned case. + XmlObject doc = XmlObject.Factory.newInstance(); + curs = doc.newCursor(); + + if (_anno._name != null) + { + curs.toNextToken(); + curs.insertElement(_anno._name); + curs.toPrevSibling(); + } + + curs.setBookmark(_anno); + } + } + else + { + XmlObject doc = XmlObject.Factory.newInstance(); + curs = doc.newCursor(); + } + + return curs; + } + + /* + * fUseStartDoc used by child(int index) the index is at startDoc is the element at the top-level + * otherwise we always want to drill in. + */ + private boolean moveToChild(XmlCursor curs, long index, boolean fFirstChild, boolean fUseStartDoc) + { + if (index < 0) + throw new IllegalArgumentException(); + + long idxChild = 0; + + if (!fUseStartDoc && curs.currentTokenType().isStartdoc()) + { + // We always move to the children of the top node. + // todo: This assumes that we want have multiple top-level nodes. Which we should be able tohave. + curs.toFirstContentToken(); + } + + TokenType tt = curs.toFirstContentToken(); + if (!tt.isNone() && !tt.isEnd()) + { + while (true) + { + if (index == idxChild) + { + return true; + } + + tt = curs.currentTokenType(); + if (tt.isText()) + { + curs.toNextToken(); + } + else if (tt.isStart()) + { + // Need to do this we want to be pointing at the text if that after the end token. + curs.toEndToken(); + curs.toNextToken(); + } + else if (tt.isComment() || tt.isProcinst()) + { + continue; + } + else + { + break; + } + + idxChild++; + } + } + else if (fFirstChild && index == 0) + { + // Drill into where first child would be. +// curs.toFirstContentToken(); + return true; + } + + return false; + } + + /** + * + * @return + */ + XmlCursor.TokenType tokenType() + { + XmlCursor.TokenType result; + + XmlCursor curs = newCursor(); + + if (curs.isStartdoc()) + { + curs.toFirstContentToken(); + } + + result = curs.currentTokenType(); + + curs.dispose(); + + return result; + } + /** + * + * @param srcCurs + * @param destCurs + * @param fDontMoveIfSame + * @return + */ + private boolean moveSrcToDest (XmlCursor srcCurs, XmlCursor destCurs, boolean fDontMoveIfSame) + { + boolean fMovedSomething = true; + TokenType tt; + do + { + if (fDontMoveIfSame && srcCurs.isInSameDocument(destCurs) && (srcCurs.comparePosition(destCurs) == 0)) + { + // If the source and destination are pointing at the same place then there's nothing to move. + fMovedSomething = false; + break; + } + + // todo ***TLL*** Use replaceContents (when added) and eliminate children removes (see above todo). + if (destCurs.currentTokenType().isStartdoc()) + { + destCurs.toNextToken(); + } + + // todo ***TLL*** Can Eric support notion of copy instead of me copying then moving??? + XmlCursor copyCurs = copy(srcCurs); + + copyCurs.moveXml(destCurs); + + copyCurs.dispose(); + + tt = srcCurs.currentTokenType(); + } while (!tt.isStart() && !tt.isEnd() && !tt.isEnddoc()); + + return fMovedSomething; + } + + /** + * + * @param cursToCopy + * @return + */ + private XmlCursor copy (XmlCursor cursToCopy) + { + XmlObject xo = XmlObject.Factory.newInstance(); + + XmlCursor copyCurs = null; + + if (cursToCopy.currentTokenType().isText()) + { + try + { + // Try just as a textnode, to do that we need to wrap the text in a special fragment tag + // that is not visible from the XmlCursor. + copyCurs = XmlObject.Factory.parse("<x:fragment xmlns:x=\"http://www.openuri.org/fragment\">" + + cursToCopy.getChars() + + "</x:fragment>").newCursor(); + if (!cursToCopy.toNextSibling()) + { + if (cursToCopy.currentTokenType().isText()) + { + cursToCopy.toNextToken(); // It's not an element it's text so skip it. + } + } + } + catch (Exception ex) + { + throw ScriptRuntime.typeError(ex.getMessage()); + } + } + else + { + copyCurs = xo.newCursor(); + copyCurs.toFirstContentToken(); + if (cursToCopy.currentTokenType() == XmlCursor.TokenType.STARTDOC) + { + cursToCopy.toNextToken(); + } + + cursToCopy.copyXml(copyCurs); + if (!cursToCopy.toNextSibling()) // If element skip element. + { + if (cursToCopy.currentTokenType().isText()) + { + cursToCopy.toNextToken(); // It's not an element it's text so skip it. + } + } + + } + + copyCurs.toStartDoc(); + copyCurs.toFirstContentToken(); + + return copyCurs; + } + + private static final int APPEND_CHILD = 1; + private static final int PREPEND_CHILD = 2; + + /** + * + * @param curs + * @param xmlToInsert + */ + private void insertChild(XmlCursor curs, Object xmlToInsert) + { + if (xmlToInsert == null || xmlToInsert instanceof Undefined) + { + // Do nothing + } + else if (xmlToInsert instanceof XmlCursor) + { + moveSrcToDest((XmlCursor)xmlToInsert, curs, true); + } + else if (xmlToInsert instanceof XML) + { + XML xmlValue = (XML) xmlToInsert; + + // If it's an attribute, then change to text node + if (xmlValue.tokenType() == XmlCursor.TokenType.ATTR) + { + insertChild(curs, xmlValue.toString()); + } + else + { + XmlCursor cursToInsert = ((XML) xmlToInsert).newCursor(); + + moveSrcToDest(cursToInsert, curs, true); + + cursToInsert.dispose(); + } + } + else if (xmlToInsert instanceof XMLList) + { + XMLList list = (XMLList) xmlToInsert; + + for (int i = 0; i < list.length(); i++) + { + insertChild(curs, list.item(i)); + } + } + else + { + // Convert to string and make XML out of it + String xmlStr = ScriptRuntime.toString(xmlToInsert); + XmlObject xo = XmlObject.Factory.newInstance(); // Create an empty document. + + XmlCursor sourceCurs = xo.newCursor(); + sourceCurs.toNextToken(); + + // To hold the text. + sourceCurs.insertChars(xmlStr); + + sourceCurs.toPrevToken(); + + // Call us again with the cursor. + moveSrcToDest(sourceCurs, curs, true); + } + } + + /** + * + * @param childToMatch + * @param xmlToInsert + * @param addToType + */ + private void insertChild(XML childToMatch, Object xmlToInsert, int addToType) + { + XmlCursor curs = newCursor(); + TokenType tt = curs.currentTokenType(); + XmlCursor xmlChildCursor = childToMatch.newCursor(); + + if (tt.isStartdoc()) + { + tt = curs.toFirstContentToken(); + } + + if (tt.isContainer()) + { + tt = curs.toNextToken(); + + while (!tt.isEnd()) + { + if (tt.isStart()) + { + // See if this child is the same as the one thep passed in + if (curs.comparePosition(xmlChildCursor) == 0) + { + // Found it + if (addToType == APPEND_CHILD) + { + // Move the cursor to just past the end of this element + curs.toEndToken(); + curs.toNextToken(); + } + + insertChild(curs, xmlToInsert); + break; + } + } + + // Skip over child elements + if (tt.isStart()) + { + tt = curs.toEndToken(); + } + + tt = curs.toNextToken(); + } + + } + + xmlChildCursor.dispose(); + curs.dispose(); + } + + /** + * + * @param curs + */ + protected void removeToken (XmlCursor curs) + { + XmlObject xo = XmlObject.Factory.newInstance(); + + // Don't delete anything move to another document so it gets orphaned nicely. + XmlCursor tmpCurs = xo.newCursor(); + tmpCurs.toFirstContentToken(); + + + curs.moveXml(tmpCurs); + + tmpCurs.dispose(); + } + + /** + * + * @param index + */ + protected void removeChild(long index) + { + XmlCursor curs = newCursor(); + + if (moveToChild(curs, index, false, false)) + { + removeToken(curs); + } + + curs.dispose(); + } + + /** + * + * @param name + * @return + */ + protected static javax.xml.namespace.QName computeQName (Object name) + { + if (name instanceof String) + { + String ns = null; + String localName = null; + + String fullName = (String)name; + localName = fullName; + if (fullName.startsWith("\"")) + { + int idx = fullName.indexOf(":"); + if (idx != -1) + { + ns = fullName.substring(1, idx - 1); // Don't include the "" around the namespace + localName = fullName.substring(idx + 1); + } + } + + if (ns == null) + { + return new javax.xml.namespace.QName(localName); + } + else + { + return new javax.xml.namespace.QName(ns, localName); + } + } + + return null; + } + + /** + * + * @param destCurs + * @param newValue + */ + private void replace(XmlCursor destCurs, XML newValue) + { + if (destCurs.isStartdoc()) + { + // Can't overwrite a whole document (user really wants to overwrite the contents of). + destCurs.toFirstContentToken(); + } + + // Orphan the token -- don't delete it outright on the XmlCursor. + removeToken(destCurs); + + XmlCursor srcCurs = newValue.newCursor(); + if (srcCurs.currentTokenType().isStartdoc()) + { + // Cann't append a whole document (user really wants to append the contents of). + srcCurs.toFirstContentToken(); + } + + moveSrcToDest(srcCurs, destCurs, false); + + // Re-link a new annotation to this cursor -- we just deleted the previous annotation on entrance to replace. + if (!destCurs.toPrevSibling()) + { + destCurs.toPrevToken(); + } + destCurs.setBookmark(new XScriptAnnotation(destCurs)); + + // 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. + destCurs.toEndToken(); + destCurs.toNextToken(); + + srcCurs.dispose(); + } + + /** + * + * @param currXMLNode + * @param xmlValue + * @return + */ + private boolean doPut(XMLName name, XML currXMLNode, XMLObjectImpl xmlValue) + { + boolean result = false; + XmlCursor curs = currXMLNode.newCursor(); + + try + { + // Replace the node with this new xml value. + XML xml; + + int toAssignLen = xmlValue.length(); + + for (int i = 0; i < toAssignLen; i++) + { + if (xmlValue instanceof XMLList) + { + xml = ((XMLList) xmlValue).item(i); + } + else + { + xml = (XML) xmlValue; + } + + // If it's an attribute or text node, make text node. + XmlCursor.TokenType tt = xml.tokenType(); + if (tt == XmlCursor.TokenType.ATTR || tt == XmlCursor.TokenType.TEXT) + { + xml = makeXmlFromString(lib, name, xml.toString()); + } + + if (i == 0) + { + // 1st assignment is replaceChild all others are appendChild + replace(curs, xml); + } + else + { + insertChild(curs, xml); + } + } + + // We're done we've blown away the node because the rvalue was XML... + result = true; + } + catch (Exception ex) + { + ex.printStackTrace(); + throw ScriptRuntime.typeError(ex.getMessage()); + } + finally + { + curs.dispose(); + } + + return result; + } + + /** + * Make a text node element with this element name and text value. + * + * @param name + * @param value + * @return + */ + private XML makeXmlFromString(XMLLibImpl lib, XMLName name, + String value) + { + XML result; + + javax.xml.namespace.QName qname; + + try + { + qname = new javax.xml.namespace.QName(name.uri(), name.localName()); + } + catch(Exception e) + { + throw ScriptRuntime.typeError(e.getMessage()); + } + + result = createTextElement(lib, qname, value); + + return result; + } + + /** + * + * @param name + * @return + */ + private XMLList matchAttributes(XMLName xmlName) + { + XMLList result = new XMLList(lib); + XmlCursor curs = newCursor(); + + if (curs.currentTokenType().isStartdoc()) + { + curs.toFirstContentToken(); + } + + if (curs.isStart()) + { + if (curs.toFirstAttribute()) + { + do + { + if (qnameMatches(xmlName, curs.getName())) + { + result.addToList(createAttributeObject(curs)); + } + } while (curs.toNextAttribute()); + } + } + + curs.dispose(); + + return result; + } + + /** + * + * @param attrCurs + * @return + */ + private XML createAttributeObject (XmlCursor attrCurs) + { + XML result = null; + + if (attrCurs.currentTokenType().isAttr()) + { + result = createAttributeXML(lib, attrCurs); + } + + return result; + } + + // + // + // methods overriding ScriptableObject + // + // + + public String getClassName () + { + return "XML"; + } + + // + // + // methods overriding IdScriptableObject + // + // + + /** + * XML[0] should return this, all other indexes are Undefined + * + * @param index + * @param start + * @return + */ + public Object get(int index, Scriptable start) + { + //Log("get index: " + index); + + if (index == 0) + { + return this; + } + else + { + return Scriptable.NOT_FOUND; + } + } + + /** + * Does the named property exist + * + * @param name + * @param start + * @return + */ + boolean hasXMLProperty(XMLName xmlName) + { + boolean result = false; + + if (prototypeFlag) + { + String name = xmlName.localName(); + + if (getMethod(name) != NOT_FOUND) + { + result = true; + } + } + else + { + // Has now should return true if the property would have results > 0 or + // if it's a method name + String name = xmlName.localName(); + if ((getPropertyList(xmlName).length() > 0) || + (getMethod(name) != NOT_FOUND)) + { + result = true; + } + } + + return result; + } + + + /** + * + * @param index + * @param start + * @return + */ + public boolean has(int index, Scriptable start) + { + return (index == 0); + } + + /** + * + * @return + */ + public Object[] getIds() + { + Object[] enumObjs; + + if (prototypeFlag) + { + enumObjs = new Object[0]; + } + else + { + enumObjs = new Object[1]; + + enumObjs[0] = new Integer(0); + } + + return enumObjs; + } + + + /** + * + * @return + */ + public Object [] getIdsForDebug() + { + return getIds(); + } + + /** + * + * @param name + * @param start + * @return + */ + Object getXMLProperty(XMLName xmlName) + { + Object result = NOT_FOUND; + + if (prototypeFlag) + { + String name = xmlName.localName(); + + result = getMethod(name); + } + else + { + result = getPropertyList(xmlName); + } + + return result; + } + + /** + * + * @param name + * @param start + * @param value + */ + void putXMLProperty(XMLName xmlName, Object value) + { + //Log("put property: " + name + " value: " + value.getClass()); + + if (prototypeFlag) + { + } + else + { + // Special-case checks for undefined and null + if (value == null) + { + value = "null"; + } + else if (value instanceof Undefined) + { + value = "undefined"; + } + + // Get the named property + if (xmlName.isAttributeName()) + { + setAttribute(xmlName, value); + } + else if (xmlName.uri() == null && + xmlName.localName().equals("*")) + { + setChildren(value); + } + else + { + // Convert text into XML if needed. + XMLObjectImpl xmlValue = null; + + if (value instanceof XMLObjectImpl) + { + xmlValue = (XMLObjectImpl) value; + + // Check for attribute type and convert to textNode + if (xmlValue instanceof XML) + { + if (((XML) xmlValue).tokenType() == XmlCursor.TokenType.ATTR) + { + xmlValue = makeXmlFromString(lib, xmlName, xmlValue.toString()); + } + } + + if (xmlValue instanceof XMLList) + { + for (int i = 0; i < xmlValue.length(); i++) + { + XML xml = ((XMLList) xmlValue).item(i); + + if (xml.tokenType() == XmlCursor.TokenType.ATTR) + { + ((XMLList) xmlValue).replace(i, makeXmlFromString(lib, xmlName, xml.toString())); + } + } + } + } + else + { + xmlValue = makeXmlFromString(lib, xmlName, ScriptRuntime.toString(value)); + } + + XMLList matches = getPropertyList(xmlName); + + if (matches.length() == 0) + { + appendChild(xmlValue); + } + else + { + // Remove all other matches + for (int i = 1; i < matches.length(); i++) + { + removeChild(matches.item(i).childIndex()); + } + + // Replace first match with new value. + doPut(xmlName, matches.item(0), xmlValue); + } + } + } + } + + + /** + * + * @param index + * @param start + * @param value + */ + public void put(int index, Scriptable start, Object value) + { + // Spec says assignment to indexed XML object should return type error + throw ScriptRuntime.typeError("Assignment to indexed XML is not allowed"); + } + + + /** + * + * @param name + */ + void deleteXMLProperty(XMLName name) + { + if (!name.isDescendants() && name.isAttributeName()) + { + XmlCursor curs = newCursor(); + + // TODO: Cover the case *::name + if (name.localName().equals("*")) + { + // Delete all attributes. + if (curs.toFirstAttribute()) + { + while (curs.currentTokenType().isAttr()) + { + curs.removeXml(); + } + } + } + else + { + // Delete an attribute. + javax.xml.namespace.QName qname = new javax.xml.namespace.QName( + name.uri(), name.localName()); + curs.removeAttribute(qname); + } + + curs.dispose(); + } + else + { + XMLList matches = getPropertyList(name); + + matches.remove(); + } + } + + + /** + * + * @param index + */ + public void delete(int index) + { + if (index == 0) + { + remove(); + } + } + + // + // + // package utility functions: + // + // + + protected XScriptAnnotation getAnnotation () + { return _anno; } + + + protected void changeNS (String oldURI, String newURI) + { + XmlCursor curs = newCursor(); + while (curs.toParent()) { + /* Goto the top of the document */ + } + + TokenType tt = curs.currentTokenType(); + if (tt.isStartdoc()) + { + tt = curs.toFirstContentToken(); + } + + if (tt.isStart()) + { + do + { + if (tt.isStart() || tt.isAttr() || tt.isNamespace()) + { + javax.xml.namespace.QName currQName = curs.getName(); + if (oldURI.equals(currQName.getNamespaceURI())) + { + curs.setName(new javax.xml.namespace.QName(newURI, currQName.getLocalPart())); + } + } + + tt = curs.toNextToken(); + } while (!tt.isEnddoc() && !tt.isNone()); + } + + curs.dispose(); + } + + + /** + * + */ + void remove () + { + XmlCursor childCurs = newCursor(); + + if (childCurs.currentTokenType().isStartdoc()) + { + // Remove on the document removes all children. + TokenType tt = childCurs.toFirstContentToken(); + while (!tt.isEnd() && !tt.isEnddoc()) + { + removeToken(childCurs); + tt = childCurs.currentTokenType(); // Now see where we're pointing after the delete -- next token. + } + } + else + { + removeToken(childCurs); + } + + childCurs.dispose(); + } + + + /** + * + * @param value + */ + void replaceAll(XML value) + { + XmlCursor curs = newCursor(); + + replace(curs, value); + _anno = value._anno; + + curs.dispose(); + } + + + /** + * + * @param attrName + * @param value + */ + void setAttribute(XMLName xmlName, Object value) + { + if (xmlName.uri() == null && + xmlName.localName().equals("*")) + { + throw ScriptRuntime.typeError("@* assignment not supported."); + } + + XmlCursor curs = newCursor(); + + String strValue = ScriptRuntime.toString(value); + if (curs.currentTokenType().isStartdoc()) + { + curs.toFirstContentToken(); + } + + javax.xml.namespace.QName qName; + + try + { + qName = new javax.xml.namespace.QName(xmlName.uri(), xmlName.localName()); + } + catch(Exception e) + { + throw ScriptRuntime.typeError(e.getMessage()); + } + + if (!curs.setAttributeText(qName, strValue)) + { + if (curs.currentTokenType().isStart()) + { + // Can only add attributes inside of a start. + curs.toNextToken(); + } + curs.insertAttributeWithValue(qName, strValue); + } + + curs.dispose(); + } + + /** + * + * @param namespace + * @return + */ + private XMLList allChildNodes(String namespace) + { + XMLList result = new XMLList(lib); + XmlCursor curs = newCursor(); + TokenType tt = curs.currentTokenType(); + javax.xml.namespace.QName targetProperty = new javax.xml.namespace.QName(namespace, "*"); + + if (tt.isStartdoc()) + { + tt = curs.toFirstContentToken(); + } + + if (tt.isContainer()) + { + tt = curs.toFirstContentToken(); + + while (!tt.isEnd()) + { + if (!tt.isStart()) + { + // Not an element + result.addToList(findAnnotation(curs)); + + // Reset target property to null in this case + targetProperty = null; + } + else + { + // Match namespace as well if specified + if (namespace == null || + namespace.length() == 0 || + namespace.equals("*") || + curs.getName().getNamespaceURI().equals(namespace)) + { + // Add it to the list + result.addToList(findAnnotation(curs)); + + // Set target property if target name is "*", + // Otherwise if target property does not match current, then + // set to null + if (targetProperty != null) + { + if (targetProperty.getLocalPart().equals("*")) + { + targetProperty = curs.getName(); + } + else if (!targetProperty.getLocalPart().equals(curs.getName().getLocalPart())) + { + // Not a match, unset target property + targetProperty = null; + } + } + } + } + + // Skip over child elements + if (tt.isStart()) + { + tt = curs.toEndToken(); + } + + tt = curs.toNextToken(); + } + } + + curs.dispose(); + + // Set the targets for this XMLList. + result.setTargets(this, targetProperty); + + return result; + } + + /** + * + * @return + */ + private XMLList matchDescendantAttributes(XMLName xmlName) + { + XMLList result = new XMLList(lib); + XmlCursor curs = newCursor(); + TokenType tt = curs.currentTokenType(); + + // Set the targets for this XMLList. + result.setTargets(this, null); + + if (tt.isStartdoc()) + { + tt = curs.toFirstContentToken(); + } + + if (tt.isContainer()) + { + int nestLevel = 1; + + while (nestLevel > 0) + { + tt = curs.toNextToken(); + + // Only try to match names for attributes + if (tt.isAttr()) + { + if (qnameMatches(xmlName, curs.getName())) + { + result.addToList(findAnnotation(curs)); + } + } + + if (tt.isStart()) + { + nestLevel++; + } + else if (tt.isEnd()) + { + nestLevel--; + } + else if (tt.isEnddoc()) + { + // Shouldn't get here, but just in case. + break; + } + } + } + + curs.dispose(); + + return result; + } + + /** + * + * @return + */ + private XMLList matchDescendantChildren(XMLName xmlName) + { + XMLList result = new XMLList(lib); + XmlCursor curs = newCursor(); + TokenType tt = curs.currentTokenType(); + + // Set the targets for this XMLList. + result.setTargets(this, null); + + if (tt.isStartdoc()) + { + tt = curs.toFirstContentToken(); + } + + if (tt.isContainer()) + { + int nestLevel = 1; + + while (nestLevel > 0) + { + tt = curs.toNextToken(); + + if (!tt.isAttr() && !tt.isEnd() && !tt.isEnddoc()) + { + // Only try to match names for elements or processing instructions. + if (!tt.isStart() && !tt.isProcinst()) + { + // Not an element or procinst, only add if qname is all + if (xmlName.localName().equals("*")) + { + result.addToList(findAnnotation(curs)); + } + } + else + { + if (qnameMatches(xmlName, curs.getName())) + { + result.addToList(findAnnotation(curs)); + } + } + } + + if (tt.isStart()) + { + nestLevel++; + } + else if (tt.isEnd()) + { + nestLevel--; + } + else if (tt.isEnddoc()) + { + // Shouldn't get here, but just in case. + break; + } + } + } + + curs.dispose(); + + return result; + } + + /** + * + * @param tokenType + * @return + */ + private XMLList matchChildren(XmlCursor.TokenType tokenType) + { + return matchChildren(tokenType, XMLName.formStar()); + } + + /** + * + * @return + */ + private XMLList matchChildren(XmlCursor.TokenType tokenType, XMLName name) + { + XMLList result = new XMLList(lib); + XmlCursor curs = newCursor(); + TokenType tt = curs.currentTokenType(); + javax.xml.namespace.QName qname = new javax.xml.namespace.QName(name.uri(), name.localName()); + javax.xml.namespace.QName targetProperty = qname; + + if (tt.isStartdoc()) + { + tt = curs.toFirstContentToken(); + } + + if (tt.isContainer()) + { + tt = curs.toFirstContentToken(); + + while (!tt.isEnd()) + { + if (tt == tokenType) + { + // Only try to match names for elements or processing instructions. + if (!tt.isStart() && !tt.isProcinst()) + { + // Not an element or no name specified. + result.addToList(findAnnotation(curs)); + + // Reset target property to null in this case + targetProperty = null; + } + else + { + // Match names as well + if (qnameMatches(name, curs.getName())) + { + // Add it to the list + result.addToList(findAnnotation(curs)); + + // Set target property if target name is "*", + // Otherwise if target property does not match current, then + // set to null + if (targetProperty != null) + { + if (targetProperty.getLocalPart().equals("*")) + { + targetProperty = curs.getName(); + } + else if (!targetProperty.getLocalPart().equals(curs.getName().getLocalPart())) + { + // Not a match, unset target property + targetProperty = null; + } + } + } + } + } + + // Skip over child elements + if (tt.isStart()) + { + tt = curs.toEndToken(); + } + + tt = curs.toNextToken(); + } + } + + curs.dispose(); + + if (tokenType == XmlCursor.TokenType.START) + { + // Set the targets for this XMLList. + result.setTargets(this, targetProperty); + } + + return result; + + } + + /** + * + * @param template + * @param match + * @return + */ + private boolean qnameMatches(XMLName template, javax.xml.namespace.QName match) + { + boolean matches = false; + + if (template.uri() == null || + template.uri().equals(match.getNamespaceURI())) + { + // URI OK, test name + if (template.localName().equals("*") || + template.localName().equals(match.getLocalPart())) + { + matches = true; + } + } + + return matches; + } + + // + // + // Methods from section 12.4.4 in the spec + // + // + + /** + * The addNamespace method adds a namespace declaration to the in scope + * namespaces for this XML object and returns this XML object. + * + * @param toAdd + */ + XML addNamespace(Namespace ns) + { + // When a namespace is used it will be added automatically + // to the inScopeNamespaces set. There is no need to add + // Namespaces with undefined prefixes. + String nsPrefix = ns.prefix(); + if (nsPrefix == null) return this; + + XmlCursor cursor = newCursor(); + + try + { + if(!cursor.isContainer()) return this; + + javax.xml.namespace.QName qname = cursor.getName(); + // Don't add a default namespace declarations to containers + // with QNames in no namespace. + if(qname.getNamespaceURI().equals("") && + nsPrefix.equals("")) return this; + + // Get all declared namespaces that are in scope + Map prefixToURI = NamespaceHelper.getAllNamespaces(lib, cursor); + + String uri = (String)prefixToURI.get(nsPrefix); + if(uri != null) + { + // Check if the Namespace is not already in scope + if(uri.equals(ns.uri())) return this; + + cursor.push(); + + // Let's see if we have to delete a namespace declaration + while(cursor.toNextToken().isAnyAttr()) + { + if(cursor.isNamespace()) + { + qname = cursor.getName(); + String prefix = qname.getLocalPart(); + if(prefix.equals(nsPrefix)) + { + // Delete the current Namespace declaration + cursor.removeXml(); + break; + } + } + } + + cursor.pop(); + } + + cursor.toNextToken(); + cursor.insertNamespace(nsPrefix, ns.uri()); + } + finally + { + cursor.dispose(); + } + + return this; + } + + /** + * + * @param xml + * @return + */ + XML appendChild(Object xml) + { + XmlCursor curs = newCursor(); + + if (curs.isStartdoc()) + { + curs.toFirstContentToken(); + } + + // Move the cursor to the end of this element + if (curs.isStart()) + { + curs.toEndToken(); + } + + insertChild(curs, xml); + + curs.dispose(); + + return this; + } + + /** + * + * @param name + * @return + */ + XMLList attribute(XMLName xmlName) + { + return matchAttributes(xmlName); + } + + /** + * + * @return + */ + XMLList attributes() + { + XMLName xmlName = XMLName.formStar(); + return matchAttributes(xmlName); + } + + XMLList child(long index) + { + XMLList result = new XMLList(lib); + result.setTargets(this, null); + result.addToList(getXmlChild(index)); + return result; + } + + XMLList child(XMLName xmlName) + { + if (xmlName == null) + return new XMLList(lib); + + XMLList result; + if (xmlName.localName().equals("*")) + { + result = allChildNodes(xmlName.uri()); + } + else + { + result = matchChildren(XmlCursor.TokenType.START, xmlName); + } + + return result; + } + + /** + * + * @param index + * @return + */ + XML getXmlChild(long index) + { + XML result = null; + XmlCursor curs = newCursor(); + + if (moveToChild(curs, index, false, true)) + { + result = createXML(lib, curs); + } + + curs.dispose(); + + return result; + } + + /** + * + * @return + */ + int childIndex() + { + int index = 0; + + XmlCursor curs = newCursor(); + + TokenType tt = curs.currentTokenType(); + while (true) + { + if (tt.isText()) + { + index++; + if (!curs.toPrevSibling()) + { + break; + } + } + else if (tt.isStart()) + { + tt = curs.toPrevToken(); + if (tt.isEnd()) + { + curs.toNextToken(); + if (!curs.toPrevSibling()) + { + break; + } + + index++; + } + else + { + // Hit the parent start tag so get out we're down counting children. + break; + } + } + else if (tt.isComment() || tt.isProcinst()) + { + curs.toPrevToken(); + } + else + { + break; + } + + tt = curs.currentTokenType(); + } + + index = curs.currentTokenType().isStartdoc() ? -1 : index; + + curs.dispose(); + + return index; + } + + /** + * + * @return + */ + XMLList children() + { + return allChildNodes(null); + } + + /** + * + * @return + */ + XMLList comments() + { + return matchChildren(XmlCursor.TokenType.COMMENT); + } + + /** + * + * @param xml + * @return + */ + boolean contains(Object xml) + { + boolean result = false; + + if (xml instanceof XML) + { + result = equivalentXml(xml); + } + + return result; + } + + /** + * + * @return + */ + Object copy() + { + XmlCursor srcCurs = newCursor(); + + if (srcCurs.isStartdoc()) + { + srcCurs.toFirstContentToken(); + } + + XML xml = createEmptyXML(lib); + + XmlCursor destCurs = xml.newCursor(); + destCurs.toFirstContentToken(); + + srcCurs.copyXml(destCurs); + + destCurs.dispose(); + srcCurs.dispose(); + + return xml; + } + + /** + * + * @param name + * @return + */ + XMLList descendants(XMLName xmlName) + { + XMLList result; + if (xmlName.isAttributeName()) + { + result = matchDescendantAttributes(xmlName); + } + else + { + result = matchDescendantChildren(xmlName); + } + + return result; + } + + /** + * The inScopeNamespaces method returns an Array of Namespace objects + * representing the namespaces in scope for this XML object in the + * context of its parent. + * + * @return Array of all Namespaces in scope for this XML Object. + */ + Object[] inScopeNamespaces() + { + XmlCursor cursor = newCursor(); + Object[] namespaces = NamespaceHelper.inScopeNamespaces(lib, cursor); + cursor.dispose(); + return namespaces; + } + + /** + * + * @param child + * @param xml + */ + XML insertChildAfter(Object child, Object xml) + { + if (child == null) + { + // Spec says inserting after nothing is the same as prepending + prependChild(xml); + } + else if (child instanceof XML) + { + insertChild((XML) child, xml, APPEND_CHILD); + } + + return this; + } + + /** + * + * @param child + * @param xml + */ + XML insertChildBefore(Object child, Object xml) + { + if (child == null) + { + // Spec says inserting before nothing is the same as appending + appendChild(xml); + } + else if (child instanceof XML) + { + insertChild((XML) child, xml, PREPEND_CHILD); + } + + return this; + } + + /** + * + * @return + */ + boolean hasOwnProperty(XMLName xmlName) + { + boolean hasProperty = false; + + if (prototypeFlag) + { + String property = xmlName.localName(); + hasProperty = (0 != findPrototypeId(property)); + } + else + { + hasProperty = (getPropertyList(xmlName).length() > 0); + } + + return hasProperty; + } + + /** + * + * @return + */ + boolean hasComplexContent() + { + return !hasSimpleContent(); + } + + /** + * + * @return + */ + boolean hasSimpleContent() + { + boolean simpleContent = false; + + XmlCursor curs = newCursor(); + + if (curs.isAttr() || curs.isText()) { + return true; + } + + if (curs.isStartdoc()) + { + curs.toFirstContentToken(); + } + + simpleContent = !(curs.toFirstChild()); + + curs.dispose(); + + return simpleContent; + } + + /** + * Length of an XML object is always 1, it's a list of XML objects of size 1. + * + * @return + */ + int length() + { + return 1; + } + + /** + * + * @return + */ + String localName() + { + XmlCursor cursor = newCursor(); + if (cursor.isStartdoc()) + cursor.toFirstContentToken(); + + String name = null; + + if(cursor.isStart() || + cursor.isAttr() || + cursor.isProcinst()) + { + javax.xml.namespace.QName qname = cursor.getName(); + name = qname.getLocalPart(); + } + cursor.dispose(); + + return name; + } + + /** + * The name method returns the qualified name associated with this XML object. + * + * @return The qualified name associated with this XML object. + */ + QName name() + { + XmlCursor cursor = newCursor(); + if (cursor.isStartdoc()) + cursor.toFirstContentToken(); + + QName name = null; + + if(cursor.isStart() || + cursor.isAttr() || + cursor.isProcinst()) + { + javax.xml.namespace.QName qname = cursor.getName(); + if(cursor.isProcinst()) + { + name = new QName(lib, "", qname.getLocalPart(), ""); + } + else + { + String uri = qname.getNamespaceURI(); + String prefix = qname.getPrefix(); + name = new QName(lib, uri, qname.getLocalPart(), prefix); + } + } + + cursor.dispose(); + + return name; + } + + /** + * + * @param prefix + * @return + */ + Object namespace(String prefix) + { + XmlCursor cursor = newCursor(); + if (cursor.isStartdoc()) + { + cursor.toFirstContentToken(); + } + + Object result = null; + + if (prefix == null) + { + if(cursor.isStart() || + cursor.isAttr()) + { + Object[] inScopeNS = NamespaceHelper.inScopeNamespaces(lib, cursor); + // XXX Is it reaaly necessary to create the second cursor? + XmlCursor cursor2 = newCursor(); + if (cursor2.isStartdoc()) + cursor2.toFirstContentToken(); + + result = NamespaceHelper.getNamespace(lib, cursor2, inScopeNS); + + cursor2.dispose(); + } + } + else + { + Map prefixToURI = NamespaceHelper.getAllNamespaces(lib, cursor); + String uri = (String)prefixToURI.get(prefix); + result = (uri == null) ? Undefined.instance : new Namespace(lib, prefix, uri); + } + + cursor.dispose(); + + return result; + } + + /** + * + * @return + */ + Object[] namespaceDeclarations() + { + XmlCursor cursor = newCursor(); + Object[] namespaces = NamespaceHelper.namespaceDeclarations(lib, cursor); + cursor.dispose(); + return namespaces; + } + + /** + * + * @return + */ + Object nodeKind() + { + String result; + XmlCursor.TokenType tt = tokenType(); + + if (tt == XmlCursor.TokenType.ATTR) + { + result = "attribute"; + } + else if (tt == XmlCursor.TokenType.TEXT) + { + result = "text"; + } + else if (tt == XmlCursor.TokenType.COMMENT) + { + result = "comment"; + } + else if (tt == XmlCursor.TokenType.PROCINST) + { + result = "processing-instruction"; + } + else if (tt == XmlCursor.TokenType.START) + { + result = "element"; + } + else + { + // A non-existant node has the nodeKind() of text + result = "text"; + } + + return result; + } + + /** + * + */ + void normalize() + { + XmlCursor curs = newCursor(); + TokenType tt = curs.currentTokenType(); + + // Walk through the tokens removing empty text nodes and merging adjacent text nodes. + if (tt.isStartdoc()) + { + tt = curs.toFirstContentToken(); + } + + if (tt.isContainer()) + { + int nestLevel = 1; + String previousText = null; + + while (nestLevel > 0) + { + tt = curs.toNextToken(); + + if (tt == XmlCursor.TokenType.TEXT) + { + String currentText = curs.getChars().trim(); + + if (currentText.trim().length() == 0) + { + // Empty text node, remove. + removeToken(curs); + curs.toPrevToken(); + } + else if (previousText == null) + { + // No previous text node, reset to trimmed version + previousText = currentText; + } + else + { + // It appears that this case never happens with XBeans. + // Previous text node exists, concatenate + String newText = previousText + currentText; + + curs.toPrevToken(); + removeToken(curs); + removeToken(curs); + curs.insertChars(newText); + } + } + else + { + previousText = null; + } + + if (tt.isStart()) + { + nestLevel++; + } + else if (tt.isEnd()) + { + nestLevel--; + } + else if (tt.isEnddoc()) + { + // Shouldn't get here, but just in case. + break; + } + } + } + + + curs.dispose(); + } + + /** + * + * @return + */ + Object parent() + { + Object parent; + + XmlCursor curs = newCursor(); + + if (curs.isStartdoc()) + { + // At doc level - no parent + parent = Undefined.instance; + } + else + { + if (curs.toParent()) + { + if (curs.isStartdoc()) + { + // Was top-level - no parent + parent = Undefined.instance; + } + else + { + parent = getFromAnnotation(lib, findAnnotation(curs)); + } + } + else + { + // No parent + parent = Undefined.instance; + } + } + + curs.dispose(); + + return parent; + } + + /** + * + * @param xml + * @return + */ + XML prependChild (Object xml) + { + XmlCursor curs = newCursor(); + + if (curs.isStartdoc()) + { + curs.toFirstContentToken(); + } + + // Move the cursor to the first content token + curs.toFirstContentToken(); + + insertChild(curs, xml); + + curs.dispose(); + + return this; + } + + /** + * + * @return + */ + Object processingInstructions(XMLName xmlName) + { + return matchChildren(XmlCursor.TokenType.PROCINST, xmlName); + } + + /** + * + * @param name + * @return + */ + boolean propertyIsEnumerable(Object name) + { + boolean result; + if (name instanceof Integer) { + result = (((Integer)name).intValue() == 0); + } else if (name instanceof Number) { + double x = ((Number)name).doubleValue(); + // Check that number is posotive 0 + result = (x == 0.0 && 1.0 / x > 0); + } else { + result = ScriptRuntime.toString(name).equals("0"); + } + return result; + } + + /** + * + * @param namespace + */ + XML removeNamespace(Namespace ns) + { + XmlCursor cursor = newCursor(); + + try + { + if(cursor.isStartdoc()) + cursor.toFirstContentToken(); + if(!cursor.isStart()) return this; + + String nsPrefix = ns.prefix(); + String nsURI = ns.uri(); + Map prefixToURI = new HashMap(); + int depth = 1; + + while(!(cursor.isEnd() && depth == 0)) + { + if(cursor.isStart()) + { + // Get the namespaces declared in this element. + // The ones with undefined prefixes are not candidates + // for removal because they are used. + prefixToURI.clear(); + NamespaceHelper.getNamespaces(cursor, prefixToURI); + ObjArray inScopeNSBag = new ObjArray(); + Iterator i = prefixToURI.entrySet().iterator(); + while(i.hasNext()) + { + Map.Entry entry = (Map.Entry)i.next(); + ns = new Namespace(lib, (String)entry.getKey(), (String)entry.getValue()); + inScopeNSBag.add(ns); + } + + // Add the URI we are looking for to avoid matching + // non-existing Namespaces. + ns = new Namespace(lib, nsURI); + inScopeNSBag.add(ns); + + Object[] inScopeNS = inScopeNSBag.toArray(); + + // Check the element name + Namespace n = NamespaceHelper.getNamespace(lib, cursor, + inScopeNS); + if(nsURI.equals(n.uri()) && + (nsPrefix == null || + nsPrefix.equals(n.prefix()))) + { + // This namespace is used + return this; + } + + // Check the attributes + cursor.push(); + boolean hasNext = cursor.toFirstAttribute(); + while(hasNext) + { + n = NamespaceHelper.getNamespace(lib, cursor, inScopeNS); + if(nsURI.equals(n.uri()) && + (nsPrefix == null || + nsPrefix.equals(n.prefix()))) + { + // This namespace is used + return this; + } + + hasNext = cursor.toNextAttribute(); + } + cursor.pop(); + + if(nsPrefix == null) + { + // Remove all namespaces declarations that match nsURI + i = prefixToURI.entrySet().iterator(); + while(i.hasNext()) + { + Map.Entry entry = (Map.Entry)i.next(); + if(entry.getValue().equals(nsURI)) + NamespaceHelper.removeNamespace(cursor, (String)entry.getKey()); + } + } + else if(nsURI.equals(prefixToURI.get(nsPrefix))) + { + // Remove the namespace declaration that matches nsPrefix + NamespaceHelper.removeNamespace(cursor, String.valueOf(nsPrefix)); + } + } + + switch(cursor.toNextToken().intValue()) + { + case XmlCursor.TokenType.INT_START: + depth++; + break; + case XmlCursor.TokenType.INT_END: + depth--; + break; + } + } + } + finally + { + cursor.dispose(); + } + + return this; + } + + XML replace(long index, Object xml) + { + XMLList xlChildToReplace = child(index); + if (xlChildToReplace.length() > 0) + { + // One exists an that index + XML childToReplace = xlChildToReplace.item(0); + insertChildAfter(childToReplace, xml); + removeChild(index); + } + return this; + } + + /** + * + * @param propertyName + * @param xml + * @return + */ + XML replace(XMLName xmlName, Object xml) + { + putXMLProperty(xmlName, xml); + return this; + } + + /** + * + * @param xml + */ + XML setChildren(Object xml) + { + // remove all children + XMLName xmlName = XMLName.formStar(); + XMLList matches = getPropertyList(xmlName); + matches.remove(); + + // append new children + appendChild(xml); + + return this; + } + + /** + * + * @param name + */ + void setLocalName(String localName) + { + XmlCursor cursor = newCursor(); + + try + { + if(cursor.isStartdoc()) + cursor.toFirstContentToken(); + + if(cursor.isText() || cursor.isComment()) return; + + + javax.xml.namespace.QName qname = cursor.getName(); + cursor.setName(new javax.xml.namespace.QName( + qname.getNamespaceURI(), localName, qname.getPrefix())); + } + finally + { + cursor.dispose(); + } + } + + /** + * + * @param name + */ + void setName(QName qname) + { + XmlCursor cursor = newCursor(); + + try + { + if(cursor.isStartdoc()) + cursor.toFirstContentToken(); + + if(cursor.isText() || cursor.isComment()) return; + + if(cursor.isProcinst()) + { + String localName = qname.localName(); + cursor.setName(new javax.xml.namespace.QName(localName)); + } + else + { + String prefix = qname.prefix(); + if (prefix == null) { prefix = ""; } + cursor.setName(new javax.xml.namespace.QName( + qname.uri(), qname.localName(), prefix)); + } + } + finally + { + cursor.dispose(); + } + } + + /** + * + * @param ns + */ + void setNamespace(Namespace ns) + { + XmlCursor cursor = newCursor(); + + try + { + if(cursor.isStartdoc()) + cursor.toFirstContentToken(); + + if(cursor.isText() || + cursor.isComment() || + cursor.isProcinst()) return; + + String prefix = ns.prefix(); + if (prefix == null) { + prefix = ""; + } + cursor.setName(new javax.xml.namespace.QName( + ns.uri(), localName(), prefix)); + } + finally + { + cursor.dispose(); + } + } + + /** + * + * @return + */ + XMLList text() + { + return matchChildren(XmlCursor.TokenType.TEXT); + } + + /** + * + * @return + */ + public String toString() + { + String result; + XmlCursor curs = newCursor(); + + if (curs.isStartdoc()) + { + curs.toFirstContentToken(); + } + + if (curs.isText()) + { + result = curs.getChars(); + } + else if (curs.isStart() && hasSimpleContent()) + { + result = curs.getTextValue(); + } + else + { + result = toXMLString(0); + } + + return result; + } + + String toSource(int indent) + { + // XXX Does toXMLString always return valid XML literal? + return toXMLString(indent); + } + + /** + * + * @return + */ + String toXMLString(int indent) + { + // XXX indent is ignored + + String result; + + XmlCursor curs = newCursor(); + + if (curs.isStartdoc()) + { + curs.toFirstContentToken(); + } + + try + { + if (curs.isText()) + { + result = curs.getChars(); + } + else if (curs.isAttr()) + { + result = curs.getTextValue(); + } + else if (curs.isComment() || curs.isProcinst()) + { + result = XML.dumpNode(curs, getOptions()); + + // todo: XBeans-dependent hack here + // If it's a comment or PI, take off the xml-frament stuff + String start = "<xml-fragment>"; + String end = "</xml-fragment>"; + + if (result.startsWith(start)) + { + result = result.substring(start.length()); + } + + if (result.endsWith(end)) + { + result = result.substring(0, result.length() - end.length()); + } + } + else + { + result = XML.dumpNode(curs, getOptions()); + } + } + finally + { + curs.dispose(); + } + + return result; + } + + /** + * + * @return + */ + Object valueOf() + { + return this; + } + + // + // Other public Functions from XMLObject + // + + /** + * + * @param target + * @return + */ + boolean equivalentXml(Object target) + { + boolean result = false; + + if (target instanceof XML) + { + XML otherXml = (XML) target; + + // Compare with toString() if either side is text node or attribute + // otherwise compare as XML + XmlCursor.TokenType thisTT = tokenType(); + XmlCursor.TokenType otherTT = otherXml.tokenType(); + if (thisTT == XmlCursor.TokenType.ATTR || otherTT == XmlCursor.TokenType.ATTR || + thisTT == XmlCursor.TokenType.TEXT || otherTT == XmlCursor.TokenType.TEXT) + { + result = toString().equals(otherXml.toString()); + } + else + { + XmlCursor cursOne = newCursor(); + XmlCursor cursTwo = otherXml.newCursor(); + + result = LogicalEquality.nodesEqual(cursOne, cursTwo); + + cursOne.dispose(); + cursTwo.dispose(); + +// Old way of comparing by string. +// boolean orgPrettyPrinting = prototype.prettyPrinting; +// prototype.prettyPrinting = true; +// result = toXMLString(0).equals(otherXml.toXMLString(0)); +// prototype.prettyPrinting = orgPrettyPrinting; + } + } + else if (target instanceof XMLList) + { + XMLList otherList = (XMLList) target; + + if (otherList.length() == 1) + { + result = equivalentXml(otherList.getXmlFromAnnotation(0)); + } + } + else if (hasSimpleContent()) + { + String otherStr = ScriptRuntime.toString(target); + + result = toString().equals(otherStr); + } + + return result; + } + + /** + * + * @param name + * @param start + * @return + */ + XMLList getPropertyList(XMLName name) + { + XMLList result; + + // Get the named property + if (name.isDescendants()) + { + result = descendants(name); + } + else if (name.isAttributeName()) + { + result = attribute(name); + } + else + { + result = child(name); + } + + return result; + } + + protected Object jsConstructor(Context cx, boolean inNewExpr, + Object[] args) + { + if (args.length == 0) { + return createFromJS(lib, ""); + } else { + Object arg0 = args[0]; + if (!inNewExpr && arg0 instanceof XML) { + // XML(XML) returns the same object. + return arg0; + } + return createFromJS(lib, arg0); + } + } + + /** + * See ECMA 357, 11_2_2_1, Semantics, 3_f. + */ + public Scriptable getExtraMethodSource(Context cx) + { + if (hasSimpleContent()) { + String src = toString(); + return ScriptRuntime.toObjectOrNull(cx, src); + } + return null; + } + + XmlObject getXmlObject() + { + XmlObject xo; + XmlCursor cursor = newCursor(); + try { + xo = cursor.getObject(); + } finally { + cursor.dispose(); + } + return xo; + } +} diff --git a/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLCtor.java b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLCtor.java new file mode 100644 index 0000000..987c8ed --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLCtor.java @@ -0,0 +1,269 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Igor Bukanov + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.javascript.xml.impl.xmlbeans; + +import org.mozilla.javascript.*; + +class XMLCtor extends IdFunctionObject +{ + static final long serialVersionUID = -8708195078359817341L; + + private static final Object XMLCTOR_TAG = new Object(); + + private XMLLibImpl lib; + + XMLCtor(XML xml, Object tag, int id, int arity) + { + super(xml, tag, id, arity); + this.lib = xml.lib; + activatePrototypeMap(MAX_FUNCTION_ID); + } + + private void writeSetting(Scriptable target) + { + for (int i = 1; i <= MAX_INSTANCE_ID; ++i) { + int id = super.getMaxInstanceId() + i; + String name = getInstanceIdName(id); + Object value = getInstanceIdValue(id); + ScriptableObject.putProperty(target, name, value); + } + } + + private void readSettings(Scriptable source) + { + for (int i = 1; i <= MAX_INSTANCE_ID; ++i) { + int id = super.getMaxInstanceId() + i; + String name = getInstanceIdName(id); + Object value = ScriptableObject.getProperty(source, name); + if (value == Scriptable.NOT_FOUND) { + continue; + } + switch (i) { + case Id_ignoreComments: + case Id_ignoreProcessingInstructions: + case Id_ignoreWhitespace: + case Id_prettyPrinting: + if (!(value instanceof Boolean)) { + continue; + } + break; + case Id_prettyIndent: + if (!(value instanceof Number)) { + continue; + } + break; + default: + throw new IllegalStateException(); + } + setInstanceIdValue(id, value); + } + } + +// #string_id_map# + + private static final int + Id_ignoreComments = 1, + Id_ignoreProcessingInstructions = 2, + Id_ignoreWhitespace = 3, + Id_prettyIndent = 4, + Id_prettyPrinting = 5, + + MAX_INSTANCE_ID = 5; + + protected int getMaxInstanceId() + { + return super.getMaxInstanceId() + MAX_INSTANCE_ID; + } + + protected int findInstanceIdInfo(String s) { + int id; +// #generated# Last update: 2004-07-19 13:03:52 CEST + L0: { id = 0; String X = null; int c; + L: switch (s.length()) { + case 12: X="prettyIndent";id=Id_prettyIndent; break L; + case 14: c=s.charAt(0); + if (c=='i') { X="ignoreComments";id=Id_ignoreComments; } + else if (c=='p') { X="prettyPrinting";id=Id_prettyPrinting; } + break L; + case 16: X="ignoreWhitespace";id=Id_ignoreWhitespace; break L; + case 28: X="ignoreProcessingInstructions";id=Id_ignoreProcessingInstructions; break L; + } + if (X!=null && X!=s && !X.equals(s)) id = 0; + } +// #/generated# + + if (id == 0) return super.findInstanceIdInfo(s); + + int attr; + switch (id) { + case Id_ignoreComments: + case Id_ignoreProcessingInstructions: + case Id_ignoreWhitespace: + case Id_prettyIndent: + case Id_prettyPrinting: + attr = PERMANENT | DONTENUM; + break; + default: throw new IllegalStateException(); + } + return instanceIdInfo(attr, super.getMaxInstanceId() + id); + } + +// #/string_id_map# + + protected String getInstanceIdName(int id) + { + switch (id - super.getMaxInstanceId()) { + case Id_ignoreComments: return "ignoreComments"; + case Id_ignoreProcessingInstructions: return "ignoreProcessingInstructions"; + case Id_ignoreWhitespace: return "ignoreWhitespace"; + case Id_prettyIndent: return "prettyIndent"; + case Id_prettyPrinting: return "prettyPrinting"; + } + return super.getInstanceIdName(id); + } + + protected Object getInstanceIdValue(int id) + { + switch (id - super.getMaxInstanceId()) { + case Id_ignoreComments: + return ScriptRuntime.wrapBoolean(lib.ignoreComments); + case Id_ignoreProcessingInstructions: + return ScriptRuntime.wrapBoolean(lib.ignoreProcessingInstructions); + case Id_ignoreWhitespace: + return ScriptRuntime.wrapBoolean(lib.ignoreWhitespace); + case Id_prettyIndent: + return ScriptRuntime.wrapInt(lib.prettyIndent); + case Id_prettyPrinting: + return ScriptRuntime.wrapBoolean(lib.prettyPrinting); + } + return super.getInstanceIdValue(id); + } + + protected void setInstanceIdValue(int id, Object value) + { + switch (id - super.getMaxInstanceId()) { + case Id_ignoreComments: + lib.ignoreComments = ScriptRuntime.toBoolean(value); + return; + case Id_ignoreProcessingInstructions: + lib.ignoreProcessingInstructions = ScriptRuntime.toBoolean(value); + return; + case Id_ignoreWhitespace: + lib.ignoreWhitespace = ScriptRuntime.toBoolean(value); + return; + case Id_prettyIndent: + lib.prettyIndent = ScriptRuntime.toInt32(value); + return; + case Id_prettyPrinting: + lib.prettyPrinting = ScriptRuntime.toBoolean(value); + return; + } + super.setInstanceIdValue(id, value); + } + +// #string_id_map# + private static final int + Id_defaultSettings = 1, + Id_settings = 2, + Id_setSettings = 3, + MAX_FUNCTION_ID = 3; + + protected int findPrototypeId(String s) + { + int id; +// #generated# Last update: 2004-07-19 13:03:52 CEST + L0: { id = 0; String X = null; + int s_length = s.length(); + if (s_length==8) { X="settings";id=Id_settings; } + else if (s_length==11) { X="setSettings";id=Id_setSettings; } + else if (s_length==15) { X="defaultSettings";id=Id_defaultSettings; } + if (X!=null && X!=s && !X.equals(s)) id = 0; + } +// #/generated# + return id; + } +// #/string_id_map# + + protected void initPrototypeId(int id) + { + String s; + int arity; + switch (id) { + case Id_defaultSettings: arity=0; s="defaultSettings"; break; + case Id_settings: arity=0; s="settings"; break; + case Id_setSettings: arity=1; s="setSettings"; break; + default: throw new IllegalArgumentException(String.valueOf(id)); + } + initPrototypeMethod(XMLCTOR_TAG, id, s, arity); + } + + public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, + Scriptable thisObj, Object[] args) + { + if (!f.hasTag(XMLCTOR_TAG)) { + return super.execIdCall(f, cx, scope, thisObj, args); + } + int id = f.methodId(); + switch (id) { + case Id_defaultSettings: { + lib.defaultSettings(); + Scriptable obj = cx.newObject(scope); + writeSetting(obj); + return obj; + } + case Id_settings: { + Scriptable obj = cx.newObject(scope); + writeSetting(obj); + return obj; + } + case Id_setSettings: { + if (args.length == 0 + || args[0] == null + || args[0] == Undefined.instance) + { + lib.defaultSettings(); + } else if (args[0] instanceof Scriptable) { + readSettings((Scriptable)args[0]); + } + return Undefined.instance; + } + } + throw new IllegalArgumentException(String.valueOf(id)); + } +} diff --git a/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLLibImpl.java b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLLibImpl.java new file mode 100644 index 0000000..90da7d4 --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLLibImpl.java @@ -0,0 +1,754 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Igor Bukanov + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.javascript.xml.impl.xmlbeans; + +import java.io.Serializable; + +import org.mozilla.javascript.*; +import org.mozilla.javascript.xml.*; + +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlObject; + +public final class XMLLibImpl extends XMLLib implements Serializable +{ + private static final long serialVersionUID = 1L; + + private Scriptable globalScope; + + XML xmlPrototype; + XMLList xmlListPrototype; + Namespace namespacePrototype; + QName qnamePrototype; + + + // Environment settings... + boolean ignoreComments; + boolean ignoreProcessingInstructions; + boolean ignoreWhitespace; + boolean prettyPrinting; + int prettyIndent; + + Scriptable globalScope() + { + return globalScope; + } + + private XMLLibImpl(Scriptable globalScope) + { + this.globalScope = globalScope; + defaultSettings(); + } + + public static void init(Context cx, Scriptable scope, boolean sealed) + { + // To force LinkageError if XmlObject is not available + XmlObject.class.getName(); + + XMLLibImpl lib = new XMLLibImpl(scope); + XMLLib bound = lib.bindToScope(scope); + if (bound == lib) { + lib.exportToScope(sealed); + } + } + + private void exportToScope(boolean sealed) + { + xmlPrototype = XML.createEmptyXML(this); + xmlListPrototype = new XMLList(this); + namespacePrototype = new Namespace(this, "", ""); + qnamePrototype = new QName(this, "", "", ""); + + xmlPrototype.exportAsJSClass(sealed); + xmlListPrototype.exportAsJSClass(sealed); + namespacePrototype.exportAsJSClass(sealed); + qnamePrototype.exportAsJSClass(sealed); + } + + void defaultSettings() + { + ignoreComments = true; + ignoreProcessingInstructions = true; + ignoreWhitespace = true; + prettyPrinting = true; + prettyIndent = 2; + } + + XMLName toAttributeName(Context cx, Object nameValue) + { + String uri; + String localName; + + if (nameValue instanceof String) { + uri = ""; + localName = (String)nameValue; + } else if (nameValue instanceof XMLName) { + XMLName xmlName = (XMLName)nameValue; + if (!xmlName.isAttributeName()) { + xmlName.setAttributeName(); + } + return xmlName; + } else if (nameValue instanceof QName) { + QName qname = (QName)nameValue; + uri = qname.uri(); + localName = qname.localName(); + } else if (nameValue instanceof Boolean + || nameValue instanceof Number + || nameValue == Undefined.instance + || nameValue == null) + { + throw badXMLName(nameValue); + } else { + uri = ""; + localName = ScriptRuntime.toString(nameValue); + } + XMLName xmlName = XMLName.formProperty(uri, localName); + xmlName.setAttributeName(); + return xmlName; + } + + private static RuntimeException badXMLName(Object value) + { + String msg; + if (value instanceof Number) { + msg = "Can not construct XML name from number: "; + } else if (value instanceof Boolean) { + msg = "Can not construct XML name from boolean: "; + } else if (value == Undefined.instance || value == null) { + msg = "Can not construct XML name from "; + } else { + throw new IllegalArgumentException(value.toString()); + } + return ScriptRuntime.typeError(msg+ScriptRuntime.toString(value)); + } + + XMLName toXMLName(Context cx, Object nameValue) + { + XMLName result; + + if (nameValue instanceof XMLName) { + result = (XMLName)nameValue; + } else if (nameValue instanceof QName) { + QName qname = (QName)nameValue; + result = XMLName.formProperty(qname.uri(), qname.localName()); + } else if (nameValue instanceof String) { + result = toXMLNameFromString(cx, (String)nameValue); + } else if (nameValue instanceof Boolean + || nameValue instanceof Number + || nameValue == Undefined.instance + || nameValue == null) + { + throw badXMLName(nameValue); + } else { + String name = ScriptRuntime.toString(nameValue); + result = toXMLNameFromString(cx, name); + } + + return result; + } + + /** + * If value represents Uint32 index, make it available through + * ScriptRuntime.lastUint32Result(cx) and return null. + * Otherwise return the same value as toXMLName(cx, value). + */ + XMLName toXMLNameOrIndex(Context cx, Object value) + { + XMLName result; + + if (value instanceof XMLName) { + result = (XMLName)value; + } else if (value instanceof String) { + String str = (String)value; + long test = ScriptRuntime.testUint32String(str); + if (test >= 0) { + ScriptRuntime.storeUint32Result(cx, test); + result = null; + } else { + result = toXMLNameFromString(cx, str); + } + } else if (value instanceof Number) { + double d = ((Number)value).doubleValue(); + long l = (long)d; + if (l == d && 0 <= l && l <= 0xFFFFFFFFL) { + ScriptRuntime.storeUint32Result(cx, l); + result = null; + } else { + throw badXMLName(value); + } + } else if (value instanceof QName) { + QName qname = (QName)value; + String uri = qname.uri(); + boolean number = false; + result = null; + if (uri != null && uri.length() == 0) { + // Only in this case qname.toString() can resemble uint32 + long test = ScriptRuntime.testUint32String(uri); + if (test >= 0) { + ScriptRuntime.storeUint32Result(cx, test); + number = true; + } + } + if (!number) { + result = XMLName.formProperty(uri, qname.localName()); + } + } else if (value instanceof Boolean + || value == Undefined.instance + || value == null) + { + throw badXMLName(value); + } else { + String str = ScriptRuntime.toString(value); + long test = ScriptRuntime.testUint32String(str); + if (test >= 0) { + ScriptRuntime.storeUint32Result(cx, test); + result = null; + } else { + result = toXMLNameFromString(cx, str); + } + } + + return result; + } + + XMLName toXMLNameFromString(Context cx, String name) + { + if (name == null) + throw new IllegalArgumentException(); + + int l = name.length(); + if (l != 0) { + char firstChar = name.charAt(0); + if (firstChar == '*') { + if (l == 1) { + return XMLName.formStar(); + } + } else if (firstChar == '@') { + XMLName xmlName = XMLName.formProperty("", name.substring(1)); + xmlName.setAttributeName(); + return xmlName; + } + } + + String uri = getDefaultNamespaceURI(cx); + + return XMLName.formProperty(uri, name); + } + + Namespace constructNamespace(Context cx, Object uriValue) + { + String prefix; + String uri; + + if (uriValue instanceof Namespace) { + Namespace ns = (Namespace)uriValue; + prefix = ns.prefix(); + uri = ns.uri(); + } else if (uriValue instanceof QName) { + QName qname = (QName)uriValue; + uri = qname.uri(); + if (uri != null) { + prefix = qname.prefix(); + } else { + uri = qname.toString(); + prefix = null; + } + } else { + uri = ScriptRuntime.toString(uriValue); + prefix = (uri.length() == 0) ? "" : null; + } + + return new Namespace(this, prefix, uri); + } + + Namespace castToNamespace(Context cx, Object namescapeObj) + { + if (namescapeObj instanceof Namespace) { + return (Namespace)namescapeObj; + } + return constructNamespace(cx, namescapeObj); + } + + Namespace constructNamespace(Context cx) + { + return new Namespace(this, "", ""); + } + + public Namespace constructNamespace(Context cx, Object prefixValue, + Object uriValue) + { + String prefix; + String uri; + + if (uriValue instanceof QName) { + QName qname = (QName)uriValue; + uri = qname.uri(); + if (uri == null) { + uri = qname.toString(); + } + } else { + uri = ScriptRuntime.toString(uriValue); + } + + if (uri.length() == 0) { + if (prefixValue == Undefined.instance) { + prefix = ""; + } else { + prefix = ScriptRuntime.toString(prefixValue); + if (prefix.length() != 0) { + throw ScriptRuntime.typeError( + "Illegal prefix '"+prefix+"' for 'no namespace'."); + } + } + } else if (prefixValue == Undefined.instance) { + prefix = ""; + } else if (!isXMLName(cx, prefixValue)) { + prefix = ""; + } else { + prefix = ScriptRuntime.toString(prefixValue); + } + + return new Namespace(this, prefix, uri); + } + + String getDefaultNamespaceURI(Context cx) + { + String uri = ""; + if (cx == null) { + cx = Context.getCurrentContext(); + } + if (cx != null) { + Object ns = ScriptRuntime.searchDefaultNamespace(cx); + if (ns != null) { + if (ns instanceof Namespace) { + uri = ((Namespace)ns).uri(); + } else { + // Should not happen but for now it could + // due to bad searchDefaultNamespace implementation. + } + } + } + return uri; + } + + Namespace getDefaultNamespace(Context cx) + { + if (cx == null) { + cx = Context.getCurrentContext(); + if (cx == null) { + return namespacePrototype; + } + } + + Namespace result; + Object ns = ScriptRuntime.searchDefaultNamespace(cx); + if (ns == null) { + result = namespacePrototype; + } else { + if (ns instanceof Namespace) { + result = (Namespace)ns; + } else { + // Should not happen but for now it could + // due to bad searchDefaultNamespace implementation. + result = namespacePrototype; + } + } + return result; + } + + QName castToQName(Context cx, Object qnameValue) + { + if (qnameValue instanceof QName) { + return (QName)qnameValue; + } + return constructQName(cx, qnameValue); + } + + QName constructQName(Context cx, Object nameValue) + { + QName result; + + if (nameValue instanceof QName) { + QName qname = (QName)nameValue; + result = new QName(this, qname.uri(), qname.localName(), + qname.prefix()); + } else { + String localName = ScriptRuntime.toString(nameValue); + result = constructQNameFromString(cx, localName); + } + + return result; + } + + /** + * Optimized version of constructQName for String type + */ + QName constructQNameFromString(Context cx, String localName) + { + if (localName == null) + throw new IllegalArgumentException(); + + String uri; + String prefix; + + if ("*".equals(localName)) { + uri = null; + prefix = null; + } else { + Namespace ns = getDefaultNamespace(cx); + uri = ns.uri(); + prefix = ns.prefix(); + } + + return new QName(this, uri, localName, prefix); + } + + QName constructQName(Context cx, Object namespaceValue, Object nameValue) + { + String uri; + String localName; + String prefix; + + if (nameValue instanceof QName) { + QName qname = (QName)nameValue; + localName = qname.localName(); + } else { + localName = ScriptRuntime.toString(nameValue); + } + + Namespace ns; + if (namespaceValue == Undefined.instance) { + if ("*".equals(localName)) { + ns = null; + } else { + ns = getDefaultNamespace(cx); + } + } else if (namespaceValue == null) { + ns = null; + } else if (namespaceValue instanceof Namespace) { + ns = (Namespace)namespaceValue; + } else { + ns = constructNamespace(cx, namespaceValue); + } + + if (ns == null) { + uri = null; + prefix = null; + } else { + uri = ns.uri(); + prefix = ns.prefix(); + } + + return new QName(this, uri, localName, prefix); + } + + Object addXMLObjects(Context cx, XMLObject obj1, XMLObject obj2) + { + XMLList listToAdd = new XMLList(this); + + if (obj1 instanceof XMLList) { + XMLList list1 = (XMLList)obj1; + if (list1.length() == 1) { + listToAdd.addToList(list1.item(0)); + } else { + // Might be xmlFragment + xmlFragment + xmlFragment + ...; + // then the result will be an XMLList which we want to be an + // rValue and allow it to be assigned to an lvalue. + listToAdd = new XMLList(this, obj1); + } + } else { + listToAdd.addToList(obj1); + } + + if (obj2 instanceof XMLList) { + XMLList list2 = (XMLList)obj2; + for (int i = 0; i < list2.length(); i++) { + listToAdd.addToList(list2.item(i)); + } + } else if (obj2 instanceof XML) { + listToAdd.addToList(obj2); + } + + return listToAdd; + } + + // + // + // Overriding XMLLib methods + // + // + + /** + * See E4X 13.1.2.1. + */ + public boolean isXMLName(Context cx, Object nameObj) + { + String name; + try { + name = ScriptRuntime.toString(nameObj); + } catch (EcmaError ee) { + if ("TypeError".equals(ee.getName())) { + return false; + } + throw ee; + } + + // See http://w3.org/TR/xml-names11/#NT-NCName + int length = name.length(); + if (length != 0) { + if (isNCNameStartChar(name.charAt(0))) { + for (int i = 1; i != length; ++i) { + if (!isNCNameChar(name.charAt(i))) { + return false; + } + } + return true; + } + } + + return false; + } + + private static boolean isNCNameStartChar(int c) + { + if ((c & ~0x7F) == 0) { + // Optimize for ASCII and use A..Z < _ < a..z + if (c >= 'a') { + return c <= 'z'; + } else if (c >= 'A') { + if (c <= 'Z') { + return true; + } + return c == '_'; + } + } else if ((c & ~0x1FFF) == 0) { + return (0xC0 <= c && c <= 0xD6) + || (0xD8 <= c && c <= 0xF6) + || (0xF8 <= c && c <= 0x2FF) + || (0x370 <= c && c <= 0x37D) + || 0x37F <= c; + } + return (0x200C <= c && c <= 0x200D) + || (0x2070 <= c && c <= 0x218F) + || (0x2C00 <= c && c <= 0x2FEF) + || (0x3001 <= c && c <= 0xD7FF) + || (0xF900 <= c && c <= 0xFDCF) + || (0xFDF0 <= c && c <= 0xFFFD) + || (0x10000 <= c && c <= 0xEFFFF); + } + + private static boolean isNCNameChar(int c) + { + if ((c & ~0x7F) == 0) { + // Optimize for ASCII and use - < . < 0..9 < A..Z < _ < a..z + if (c >= 'a') { + return c <= 'z'; + } else if (c >= 'A') { + if (c <= 'Z') { + return true; + } + return c == '_'; + } else if (c >= '0') { + return c <= '9'; + } else { + return c == '-' || c == '.'; + } + } else if ((c & ~0x1FFF) == 0) { + return isNCNameStartChar(c) || c == 0xB7 + || (0x300 <= c && c <= 0x36F); + } + return isNCNameStartChar(c) || (0x203F <= c && c <= 0x2040); + } + + XMLName toQualifiedName(Context cx, Object namespaceValue, + Object nameValue) + { + // This is duplication of constructQName(cx, namespaceValue, nameValue) + // but for XMLName + + String uri; + String localName; + + if (nameValue instanceof QName) { + QName qname = (QName)nameValue; + localName = qname.localName(); + } else { + localName = ScriptRuntime.toString(nameValue); + } + + Namespace ns; + if (namespaceValue == Undefined.instance) { + if ("*".equals(localName)) { + ns = null; + } else { + ns = getDefaultNamespace(cx); + } + } else if (namespaceValue == null) { + ns = null; + } else if (namespaceValue instanceof Namespace) { + ns = (Namespace)namespaceValue; + } else { + ns = constructNamespace(cx, namespaceValue); + } + + if (ns == null) { + uri = null; + } else { + uri = ns.uri(); + } + + return XMLName.formProperty(uri, localName); + } + + public Ref nameRef(Context cx, Object name, + Scriptable scope, int memberTypeFlags) + { + if ((memberTypeFlags & Node.ATTRIBUTE_FLAG) == 0) { + // should only be called foir cases like @name or @[expr] + throw Kit.codeBug(); + } + XMLName xmlName = toAttributeName(cx, name); + return xmlPrimaryReference(cx, xmlName, scope); + } + + public Ref nameRef(Context cx, Object namespace, Object name, + Scriptable scope, int memberTypeFlags) + { + XMLName xmlName = toQualifiedName(cx, namespace, name); + if ((memberTypeFlags & Node.ATTRIBUTE_FLAG) != 0) { + if (!xmlName.isAttributeName()) { + xmlName.setAttributeName(); + } + } + return xmlPrimaryReference(cx, xmlName, scope); + } + + private Ref xmlPrimaryReference(Context cx, XMLName xmlName, + Scriptable scope) + { + XMLObjectImpl xmlObj; + XMLObjectImpl firstXmlObject = null; + for (;;) { + // XML object can only present on scope chain as a wrapper + // of XMLWithScope + if (scope instanceof XMLWithScope) { + xmlObj = (XMLObjectImpl)scope.getPrototype(); + if (xmlObj.hasXMLProperty(xmlName)) { + break; + } + if (firstXmlObject == null) { + firstXmlObject = xmlObj; + } + } + scope = scope.getParentScope(); + if (scope == null) { + xmlObj = firstXmlObject; + break; + } + } + + // xmlObj == null corresponds to undefined as the target of + // the reference + if (xmlObj != null) { + xmlName.initXMLObject(xmlObj); + } + return xmlName; + } + + /** + * Escapes the reserved characters in a value of an attribute + * + * @param value Unescaped text + * @return The escaped text + */ + public String escapeAttributeValue(Object value) + { + String text = ScriptRuntime.toString(value); + + if (text.length() == 0) return ""; + + XmlObject xo = XmlObject.Factory.newInstance(); + + XmlCursor cursor = xo.newCursor(); + cursor.toNextToken(); + cursor.beginElement("a"); + cursor.insertAttributeWithValue("a", text); + cursor.dispose(); + + String elementText = xo.toString(); + int begin = elementText.indexOf('"'); + int end = elementText.lastIndexOf('"'); + return elementText.substring(begin + 1, end); + } + + /** + * Escapes the reserved characters in a value of a text node + * + * @param value Unescaped text + * @return The escaped text + */ + public String escapeTextValue(Object value) + { + if (value instanceof XMLObjectImpl) { + return ((XMLObjectImpl)value).toXMLString(0); + } + + String text = ScriptRuntime.toString(value); + + if (text.length() == 0) return text; + + XmlObject xo = XmlObject.Factory.newInstance(); + + XmlCursor cursor = xo.newCursor(); + cursor.toNextToken(); + cursor.beginElement("a"); + cursor.insertChars(text); + cursor.dispose(); + + String elementText = xo.toString(); + int begin = elementText.indexOf('>') + 1; + int end = elementText.lastIndexOf('<'); + return (begin < end) ? elementText.substring(begin, end) : ""; + } + + public Object toDefaultXmlNamespace(Context cx, Object uriValue) + { + return constructNamespace(cx, uriValue); + } +} diff --git a/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLList.java b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLList.java new file mode 100644 index 0000000..b66ec96 --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLList.java @@ -0,0 +1,1617 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Ethan Hugg + * Terry Lucas + * Milen Nankov + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.javascript.xml.impl.xmlbeans; + +import java.util.Vector; + +import org.mozilla.javascript.*; +import org.mozilla.javascript.xml.*; + +import org.apache.xmlbeans.XmlCursor; + +class XMLList extends XMLObjectImpl implements Function +{ + static final long serialVersionUID = -4543618751670781135L; + + static class AnnotationList + { + private Vector v; + + + AnnotationList () + { + v = new Vector(); + } + + + void add (XML.XScriptAnnotation n) + { + v.add(n); + } + + + XML.XScriptAnnotation item(int index) + { + return (XML.XScriptAnnotation)(v.get(index)); + } + + + void remove (int index) + { + v.remove(index); + } + + + int length() + { + return v.size(); + } + }; + + + // Fields + private AnnotationList _annos; + + private XMLObjectImpl targetObject = null; + private javax.xml.namespace.QName targetProperty = null; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Constructors + // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * + */ + XMLList(XMLLibImpl lib) + { + super(lib, lib.xmlListPrototype); + _annos = new AnnotationList(); + } + + /** + * + * @param inputObject + */ + XMLList(XMLLibImpl lib, Object inputObject) + { + super(lib, lib.xmlListPrototype); + String frag; + + if (inputObject == null || inputObject instanceof Undefined) + { + frag = ""; + } + else if (inputObject instanceof XML) + { + XML xml = (XML) inputObject; + + _annos = new AnnotationList(); + _annos.add(xml.getAnnotation()); + } + else if (inputObject instanceof XMLList) + { + XMLList xmll = (XMLList) inputObject; + + _annos = new AnnotationList(); + + for (int i = 0; i < xmll._annos.length(); i++) + { + _annos.add(xmll._annos.item(i)); + } + } + else + { + frag = ScriptRuntime.toString(inputObject).trim(); + + if (!frag.startsWith("<>")) + { + frag = "<>" + frag + "</>"; + } + + frag = "<fragment>" + frag.substring(2); + if (!frag.endsWith("</>")) + { + throw ScriptRuntime.typeError("XML with anonymous tag missing end anonymous tag"); + } + + frag = frag.substring(0, frag.length() - 3) + "</fragment>"; + + XML orgXML = XML.createFromJS(lib, frag); + + // Now orphan the children and add them to our XMLList. + XMLList children = orgXML.children(); + + _annos = new AnnotationList(); + + for (int i = 0; i < children._annos.length(); i++) + { + // Copy here is so that they'll be orphaned (parent() will be undefined) + _annos.add(((XML) children.item(i).copy()).getAnnotation()); + } + } + } + + // + // + // TargetObject/Property accessors + // + // + + /** + * + * @param object + * @param property + */ + void setTargets(XMLObjectImpl object, javax.xml.namespace.QName property) + { + targetObject = object; + targetProperty = property; + } + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Private functions + // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * + * @param index + * @return + */ + XML getXmlFromAnnotation(int index) + { + XML retVal; + + if (index >= 0 && index < length()) + { + XML.XScriptAnnotation anno = _annos.item(index); + retVal = XML.getFromAnnotation(lib, anno); + } + else + { + retVal = null; + } + + return retVal; + } + + /** + * + * @param index + */ + private void internalRemoveFromList (int index) + { + _annos.remove(index); + } + + /** + * + * @param index + * @param xml + */ + void replace(int index, XML xml) + { + if (index < length()) + { + AnnotationList newAnnoList = new AnnotationList(); + + // Copy upto item to replace. + for (int i = 0; i < index; i++) + { + newAnnoList.add(_annos.item(i)); + } + + newAnnoList.add(xml.getAnnotation()); + + // Skip over old item we're going to replace we've already add new item on above line. + for (int i = index + 1; i < length(); i++) + { + newAnnoList.add(_annos.item(i)); + } + + _annos = newAnnoList; + } + } + + /** + * + * @param index + * @param xml + */ + private void insert(int index, XML xml) + { + if (index < length()) + { + AnnotationList newAnnoList = new AnnotationList(); + + // Copy upto item to insert. + for (int i = 0; i < index; i++) + { + newAnnoList.add(_annos.item(i)); + } + + newAnnoList.add(xml.getAnnotation()); + + for (int i = index; i < length(); i++) + { + newAnnoList.add(_annos.item(i)); + } + + _annos = newAnnoList; + } + } + + // + // + // methods overriding ScriptableObject + // + // + + public String getClassName () + { + return "XMLList"; + } + + // + // + // methods overriding IdScriptableObject + // + // + + /** + * + * @param index + * @param start + * @return + */ + public Object get(int index, Scriptable start) + { + //Log("get index: " + index); + + if (index >= 0 && index < length()) + { + return getXmlFromAnnotation(index); + } + else + { + return Scriptable.NOT_FOUND; + } + } + + /** + * + * @param name + * @param start + * @return + */ + boolean hasXMLProperty(XMLName xmlName) + { + boolean result = false; + + // Has now should return true if the property would have results > 0 or + // if it's a method name + String name = xmlName.localName(); + if ((getPropertyList(xmlName).length() > 0) || + (getMethod(name) != NOT_FOUND)) + { + result = true; + } + + return result; + } + + + /** + * + * @param index + * @param start + * @return + */ + public boolean has(int index, Scriptable start) + { + return 0 <= index && index < length(); + } + + /** + * + * @param name + * @param value + */ + void putXMLProperty(XMLName xmlName, Object value) + { + //Log("put property: " + name); + + // Special-case checks for undefined and null + if (value == null) + { + value = "null"; + } + else if (value instanceof Undefined) + { + value = "undefined"; + } + + if (length() > 1) + { + throw ScriptRuntime.typeError("Assignment to lists with more that one item is not supported"); + } + else if (length() == 0) + { + // Secret sauce for super-expandos. + // We set an element here, and then add ourselves to our target. + if (targetObject != null && + targetProperty != null && + !targetProperty.getLocalPart().equals("*")) + { + // Add an empty element with our targetProperty name and then set it. + XML xmlValue = XML.createTextElement(lib, targetProperty, ""); + addToList(xmlValue); + + if(xmlName.isAttributeName()) + { + setAttribute(xmlName, value); + } + else + { + XML xml = item(0); + xml.putXMLProperty(xmlName, value); + + // Update the list with the new item at location 0. + replace(0, item(0)); + } + + // Now add us to our parent + XMLName name2 = XMLName.formProperty(targetProperty.getNamespaceURI(), targetProperty.getLocalPart()); + targetObject.putXMLProperty(name2, this); + } + else + { + throw ScriptRuntime.typeError("Assignment to empty XMLList without targets not supported"); + } + } + else if(xmlName.isAttributeName()) + { + setAttribute(xmlName, value); + } + else + { + XML xml = item(0); + xml.putXMLProperty(xmlName, value); + + // Update the list with the new item at location 0. + replace(0, item(0)); + } + } + + /** + * + * @param name + * @return + */ + Object getXMLProperty(XMLName name) + { + return getPropertyList(name); + } + + /** + * + * @param index + * @param value + */ + public void put(int index, Scriptable start, Object value) + { + Object parent = Undefined.instance; + // Convert text into XML if needed. + XMLObject xmlValue; + + // Special-case checks for undefined and null + if (value == null) + { + value = "null"; + } + else if (value instanceof Undefined) + { + value = "undefined"; + } + + if (value instanceof XMLObject) + { + xmlValue = (XMLObject) value; + } + else + { + if (targetProperty == null) + { + xmlValue = XML.createFromJS(lib, value.toString()); + } + else + { + xmlValue = XML.createTextElement(lib, targetProperty, value.toString()); + } + } + + // Find the parent + if (index < length()) + { + parent = item(index).parent(); + } + else + { + // Appending + parent = parent(); + } + + if (parent instanceof XML) + { + // found parent, alter doc + XML xmlParent = (XML) parent; + + if (index < length()) + { + // We're replacing the the node. + XML xmlNode = getXmlFromAnnotation(index); + + if (xmlValue instanceof XML) + { + xmlNode.replaceAll((XML) xmlValue); + replace(index, xmlNode); + } + else if (xmlValue instanceof XMLList) + { + // Replace the first one, and add the rest on the list. + XMLList list = (XMLList) xmlValue; + + if (list.length() > 0) + { + int lastIndexAdded = xmlNode.childIndex(); + xmlNode.replaceAll(list.item(0)); + replace(index, list.item(0)); + + for (int i = 1; i < list.length(); i++) + { + xmlParent.insertChildAfter(xmlParent.getXmlChild(lastIndexAdded), list.item(i)); + lastIndexAdded++; + insert(index + i, list.item(i)); + } + } + } + } + else + { + // Appending + xmlParent.appendChild(xmlValue); + addToList(xmlParent.getXmlChild(index)); + } + } + else + { + // Don't all have same parent, no underlying doc to alter + if (index < length()) + { + XML xmlNode = XML.getFromAnnotation(lib, _annos.item(index)); + + if (xmlValue instanceof XML) + { + xmlNode.replaceAll((XML) xmlValue); + replace(index, xmlNode); + } + else if (xmlValue instanceof XMLList) + { + // Replace the first one, and add the rest on the list. + XMLList list = (XMLList) xmlValue; + + if (list.length() > 0) + { + xmlNode.replaceAll(list.item(0)); + replace(index, list.item(0)); + + for (int i = 1; i < list.length(); i++) + { + insert(index + i, list.item(i)); + } + } + } + } + else + { + addToList(xmlValue); + } + } + } + + + /** + * + * @param name + */ + void deleteXMLProperty(XMLName name) + { + for (int i = 0; i < length(); i++) + { + XML xml = getXmlFromAnnotation(i); + + if (xml.tokenType() == XmlCursor.TokenType.START) + { + xml.deleteXMLProperty(name); + } + } + } + + /** + * + * @param index + */ + public void delete(int index) + { + if (index >= 0 && index < length()) + { + XML xml = getXmlFromAnnotation(index); + + xml.remove(); + + internalRemoveFromList(index); + } + } + + + /** + * + * @return + */ + public Object[] getIds() + { + Object enumObjs[]; + + if (prototypeFlag) + { + enumObjs = new Object[0]; + } + else + { + enumObjs = new Object[length()]; + + for (int i = 0; i < enumObjs.length; i++) + { + enumObjs[i] = new Integer(i); + } + } + + return enumObjs; + } + + /** + * + * @return + */ + public Object[] getIdsForDebug() + { + return getIds(); + } + + + // XMLList will remove will delete all items in the list (a set delete) this differs from the XMLList delete operator. + void remove () + { + int nLen = length(); + for (int i = nLen - 1; i >= 0; i--) + { + XML xml = getXmlFromAnnotation(i); + if (xml != null) + { + xml.remove(); + internalRemoveFromList(i); + } + } + } + + /** + * + * @param index + * @return + */ + XML item (int index) + { + return _annos != null + ? getXmlFromAnnotation(index) : XML.createEmptyXML(lib); + } + + + /** + * + * @param name + * @param value + */ + private void setAttribute (XMLName xmlName, Object value) + { + for (int i = 0; i < length(); i++) + { + XML xml = getXmlFromAnnotation(i); + xml.setAttribute(xmlName, value); + } + } + + + /** + * + * @param toAdd + */ + void addToList(Object toAdd) + { + if (toAdd instanceof Undefined) + { + // Missing argument do nothing... + return; + } + + if (toAdd instanceof XMLList) + { + XMLList xmlSrc = (XMLList)toAdd; + for (int i = 0; i < xmlSrc.length(); i++) + { + _annos.add((xmlSrc.item(i)).getAnnotation()); + } + } + else if (toAdd instanceof XML) + { + _annos.add(((XML)(toAdd)).getAnnotation()); + } + else if (toAdd instanceof XML.XScriptAnnotation) + { + _annos.add((XML.XScriptAnnotation)toAdd); + } + } + + // + // + // Methods from section 12.4.4 in the spec + // + // + + /** + * + * @param toAdd + */ + XML addNamespace(Namespace ns) + { + if(length() == 1) + { + return getXmlFromAnnotation(0).addNamespace(ns); + } + else + { + throw ScriptRuntime.typeError("The addNamespace method works only on lists containing one item"); + } + } + + /** + * + * @param xml + * @return + */ + XML appendChild(Object xml) + { + if (length() == 1) + { + return getXmlFromAnnotation(0).appendChild(xml); + } + else + { + throw ScriptRuntime.typeError("The appendChild method works only on lists containing one item"); + } + } + + /** + * + * @param attr + * @return + */ + XMLList attribute(XMLName xmlName) + { + XMLList result = new XMLList(lib); + + for (int i = 0; i < length(); i++) + { + XML xml = getXmlFromAnnotation(i); + result.addToList(xml.attribute(xmlName)); + } + + return result; + } + + /** + * + * @return + */ + XMLList attributes() + { + XMLList result = new XMLList(lib); + + for (int i = 0; i < length(); i++) + { + XML xml = getXmlFromAnnotation(i); + result.addToList(xml.attributes()); + } + + return result; + } + + XMLList child(long index) + { + XMLList result = new XMLList(lib); + + for (int i = 0; i < length(); i++) + { + result.addToList(getXmlFromAnnotation(i).child(index)); + } + + return result; + } + + XMLList child(XMLName xmlName) + { + XMLList result = new XMLList(lib); + + for (int i = 0; i < length(); i++) + { + result.addToList(getXmlFromAnnotation(i).child(xmlName)); + } + + return result; + } + + /** + * + * @return + */ + int childIndex() + { + if (length() == 1) + { + return getXmlFromAnnotation(0).childIndex(); + } + else + { + throw ScriptRuntime.typeError("The childIndex method works only on lists containing one item"); + } + } + + /** + * + * @return + */ + XMLList children() + { + Vector v = new Vector(); + + for (int i = 0; i < length(); i++) + { + XML xml = getXmlFromAnnotation(i); + + if (xml != null) + { + Object o = xml.children(); + if (o instanceof XMLList) + { + XMLList childList = (XMLList)o; + + int cChildren = childList.length(); + for (int j = 0; j < cChildren; j++) + { + v.addElement(childList.item(j)); + } + } + } + } + + XMLList allChildren = new XMLList(lib); + int sz = v.size(); + + for (int i = 0; i < sz; i++) + { + allChildren.addToList(v.get(i)); + } + + return allChildren; + } + + /** + * + * @return + */ + XMLList comments() + { + XMLList result = new XMLList(lib); + + for (int i = 0; i < length(); i++) + { + XML xml = getXmlFromAnnotation(i); + + result.addToList(xml.comments()); + } + + return result; + } + + /** + * + * @param xml + * @return + */ + boolean contains(Object xml) + { + boolean result = false; + + for (int i = 0; i < length(); i++) + { + XML member = getXmlFromAnnotation(i); + + if (member.equivalentXml(xml)) + { + result = true; + break; + } + } + + return result; + } + + /** + * + * @return + */ + Object copy() + { + XMLList result = new XMLList(lib); + + for (int i = 0; i < length(); i++) + { + XML xml = getXmlFromAnnotation(i); + result.addToList(xml.copy()); + } + + return result; + } + + /** + * + * @return + */ + XMLList descendants(XMLName xmlName) + { + XMLList result = new XMLList(lib); + + for (int i = 0; i < length(); i++) + { + XML xml = getXmlFromAnnotation(i); + result.addToList(xml.descendants(xmlName)); + } + + return result; + } + + /** + * + * @return + */ + Object[] inScopeNamespaces() + { + if(length() == 1) + { + return getXmlFromAnnotation(0).inScopeNamespaces(); + } + else + { + throw ScriptRuntime.typeError("The inScopeNamespaces method works only on lists containing one item"); + } + } + + /** + * + * @param child + * @param xml + */ + XML insertChildAfter(Object child, Object xml) + { + if (length() == 1) + { + return getXmlFromAnnotation(0).insertChildAfter(child, xml); + } + else + { + throw ScriptRuntime.typeError("The insertChildAfter method works only on lists containing one item"); + } + } + + /** + * + * @param child + * @param xml + */ + XML insertChildBefore(Object child, Object xml) + { + if (length() == 1) + { + return getXmlFromAnnotation(0).insertChildAfter(child, xml); + } + else + { + throw ScriptRuntime.typeError("The insertChildBefore method works only on lists containing one item"); + } + } + + /** + * + * @return + */ + boolean hasOwnProperty(XMLName xmlName) + { + boolean hasProperty = false; + + if (prototypeFlag) + { + String property = xmlName.localName(); + hasProperty = (0 != findPrototypeId(property)); + } + else + { + hasProperty = (getPropertyList(xmlName).length() > 0); + } + + return hasProperty; + } + + /** + * + * @return + */ + boolean hasComplexContent() + { + boolean complexContent; + int length = length(); + + if (length == 0) + { + complexContent = false; + } + else if (length == 1) + { + complexContent = getXmlFromAnnotation(0).hasComplexContent(); + } + else + { + complexContent = false; + + for (int i = 0; i < length; i++) + { + XML nextElement = getXmlFromAnnotation(i); + if (nextElement.tokenType() == XmlCursor.TokenType.START) + { + complexContent = true; + break; + } + } + } + + return complexContent; + } + + /** + * + * @return + */ + boolean hasSimpleContent() + { + boolean simpleContent; + int length = length(); + + if (length == 0) + { + simpleContent = true; + } + else if (length == 1) + { + simpleContent = getXmlFromAnnotation(0).hasSimpleContent(); + } + else + { + simpleContent = true; + + for (int i = 0; i < length; i++) + { + XML nextElement = getXmlFromAnnotation(i); + if (nextElement.tokenType() == XmlCursor.TokenType.START) + { + simpleContent = false; + break; + } + } + } + + return simpleContent; + } + + /** + * + * @return + */ + int length() + { + int result = 0; + + if (_annos != null) + { + result = _annos.length(); + } + + return result; + } + + /** + * + * @return + */ + String localName() + { + if (length() == 1) + { + return name().localName(); + } + else + { + throw ScriptRuntime.typeError("The localName method works only on lists containing one item"); + } + } + + /** + * + * @return + */ + QName name() + { + if (length() == 1) + { + return getXmlFromAnnotation(0).name(); + } + else + { + throw ScriptRuntime.typeError("The name method works only on lists containing one item"); + } + } + + /** + * + * @param prefix + * @return + */ + Object namespace(String prefix) + { + if (length() == 1) + { + return getXmlFromAnnotation(0).namespace(prefix); + } + else + { + throw ScriptRuntime.typeError("The namespace method works only on lists containing one item"); + } + } + + /** + * + * @return + */ + Object[] namespaceDeclarations() + { + if (length() == 1) + { + return getXmlFromAnnotation(0).namespaceDeclarations(); + } + else + { + throw ScriptRuntime.typeError("The namespaceDeclarations method works only on lists containing one item"); + } + } + + /** + * + * @return + */ + Object nodeKind() + { + if (length() == 1) + { + return getXmlFromAnnotation(0).nodeKind(); + } + else + { + throw ScriptRuntime.typeError("The nodeKind method works only on lists containing one item"); + } + } + + /** + * + */ + void normalize() + { + for (int i = 0; i < length(); i++) + { + getXmlFromAnnotation(i).normalize(); + } + } + + /** + * If list is empty, return undefined, if elements have different parents return undefined, + * If they all have the same parent, return that parent. + * + * @return + */ + Object parent() + { + Object sameParent = Undefined.instance; + + if ((length() == 0) && (targetObject != null) && (targetObject instanceof XML)) + { + sameParent = targetObject; + } + else + { + for (int i = 0; i < length(); i++) + { + Object currParent = getXmlFromAnnotation(i).parent(); + + if (i == 0) + { + // Set the first for the rest to compare to. + sameParent = currParent; + } + else if (sameParent != currParent) + { + sameParent = Undefined.instance; + break; + } + } + } + + // If everything in the list is the sameParent then return that as the parent. + return sameParent; + } + + /** + * + * @param xml + * @return + */ + XML prependChild(Object xml) + { + if (length() == 1) + { + return getXmlFromAnnotation(0).prependChild(xml); + } + else + { + throw ScriptRuntime.typeError("The prependChild method works only on lists containing one item"); + } + } + + /** + * + * @return + */ + Object processingInstructions(XMLName xmlName) + { + XMLList result = new XMLList(lib); + + for (int i = 0; i < length(); i++) + { + XML xml = getXmlFromAnnotation(i); + + result.addToList(xml.processingInstructions(xmlName)); + } + + return result; + } + + /** + * + * @param name + * @return + */ + boolean propertyIsEnumerable(Object name) + { + long index; + if (name instanceof Integer) { + index = ((Integer)name).intValue(); + } else if (name instanceof Number) { + double x = ((Number)name).doubleValue(); + index = (long)x; + if (index != x) { + return false; + } + if (index == 0 && 1.0 / x < 0) { + // Negative 0 + return false; + } + } else { + String s = ScriptRuntime.toString(name); + index = ScriptRuntime.testUint32String(s); + } + return (0 <= index && index < length()); + } + + /** + * + * @param ns + */ + XML removeNamespace(Namespace ns) + { + if(length() == 1) + { + return getXmlFromAnnotation(0).removeNamespace(ns); + } + else + { + throw ScriptRuntime.typeError("The removeNamespace method works only on lists containing one item"); + } + } + + XML replace(long index, Object xml) + { + if (length() == 1) + { + return getXmlFromAnnotation(0).replace(index, xml); + } + else + { + throw ScriptRuntime.typeError("The replace method works only on lists containing one item"); + } + } + + /** + * + * @param propertyName + * @param xml + * @return + */ + XML replace(XMLName xmlName, Object xml) + { + if (length() == 1) + { + return getXmlFromAnnotation(0).replace(xmlName, xml); + } + else + { + throw ScriptRuntime.typeError("The replace method works only on lists containing one item"); + } + } + + /** + * + * @param xml + */ + XML setChildren(Object xml) + { + if (length() == 1) + { + return getXmlFromAnnotation(0).setChildren(xml); + } + else + { + throw ScriptRuntime.typeError("The setChildren method works only on lists containing one item"); + } + } + + /** + * + * @param name + */ + void setLocalName(String localName) + { + if (length() == 1) + { + getXmlFromAnnotation(0).setLocalName(localName); + } + else + { + throw ScriptRuntime.typeError("The setLocalName method works only on lists containing one item"); + } + } + + /** + * + * @param name + */ + void setName(QName qname) + { + if (length() == 1) + { + getXmlFromAnnotation(0).setName(qname); + } + else + { + throw ScriptRuntime.typeError("The setName method works only on lists containing one item"); + } + } + + /** + * + * @param ns + */ + void setNamespace(Namespace ns) + { + if (length() == 1) + { + getXmlFromAnnotation(0).setNamespace(ns); + } + else + { + throw ScriptRuntime.typeError("The setNamespace method works only on lists containing one item"); + } + } + + /** + * + * * @return + */ + XMLList text() + { + XMLList result = new XMLList(lib); + + for (int i = 0; i < length(); i++) + { + result.addToList(getXmlFromAnnotation(i).text()); + } + + return result; + } + + /** + * + * @return + */ + public String toString() + { + if (hasSimpleContent()) + { + StringBuffer sb = new StringBuffer(); + + for(int i = 0; i < length(); i++) + { + XML next = getXmlFromAnnotation(i); + sb.append(next.toString()); + } + + return sb.toString(); + } + else + { + return toXMLString(0); + } + } + + String toSource(int indent) + { + // XXX indent is ignored + return "<>"+toXMLString(0)+"</>"; + } + + /** + * + * @return + */ + String toXMLString(int indent) + { + StringBuffer sb = new StringBuffer(); + + for(int i = 0; i < length(); i++) + { + if (i > 0) + { + sb.append('\n'); + } + + sb.append(getXmlFromAnnotation(i).toXMLString(indent)); + } + + return sb.toString(); + } + + /** + * + * @return + */ + Object valueOf() + { + return this; + } + + // + // Other public Functions from XMLObject + // + + /** + * + * @param target + * @return + */ + boolean equivalentXml(Object target) + { + boolean result = false; + + // Zero length list should equate to undefined + if (target instanceof Undefined && length() == 0) + { + result = true; + } + else if (length() == 1) + { + result = getXmlFromAnnotation(0).equivalentXml(target); + } + else if (target instanceof XMLList) + { + XMLList otherList = (XMLList) target; + + if (otherList.length() == length()) + { + result = true; + + for (int i = 0; i < length(); i++) + { + if (!getXmlFromAnnotation(i).equivalentXml(otherList.getXmlFromAnnotation(i))) + { + result = false; + break; + } + } + } + } + + return result; + } + + /** + * + * @param name + * @param start + * @return + */ + private XMLList getPropertyList(XMLName name) + { + XMLList propertyList = new XMLList(lib); + javax.xml.namespace.QName qname = null; + + if (!name.isDescendants() && !name.isAttributeName()) + { + // Only set the targetProperty if this is a regular child get + // and not a descendant or attribute get + qname = new javax.xml.namespace.QName(name.uri(), name.localName()); + } + + propertyList.setTargets(this, qname); + + for (int i = 0; i < length(); i++) + { + propertyList.addToList( + getXmlFromAnnotation(i).getPropertyList(name)); + } + + return propertyList; + } + + private Object applyOrCall(boolean isApply, + Context cx, Scriptable scope, + Scriptable thisObj, Object[] args) + { + String methodName = isApply ? "apply" : "call"; + if(!(thisObj instanceof XMLList) || + ((XMLList)thisObj).targetProperty == null) + throw ScriptRuntime.typeError1("msg.isnt.function", + methodName); + + return ScriptRuntime.applyOrCall(isApply, cx, scope, thisObj, args); + } + + protected Object jsConstructor(Context cx, boolean inNewExpr, + Object[] args) + { + if (args.length == 0) { + return new XMLList(lib); + } else { + Object arg0 = args[0]; + if (!inNewExpr && arg0 instanceof XMLList) { + // XMLList(XMLList) returns the same object. + return arg0; + } + return new XMLList(lib, arg0); + } + } + + org.apache.xmlbeans.XmlObject getXmlObject() + { + if (length() == 1) { + return getXmlFromAnnotation(0).getXmlObject(); + } else { + throw ScriptRuntime.typeError("getXmlObject method works only on lists containing one item"); + } + } + + /** + * See ECMA 357, 11_2_2_1, Semantics, 3_e. + */ + public Scriptable getExtraMethodSource(Context cx) + { + if (length() == 1) { + return getXmlFromAnnotation(0); + } + return null; + } + + public Object call(Context cx, Scriptable scope, Scriptable thisObj, + Object[] args) + { + // This XMLList is being called as a Function. + // Let's find the real Function object. + if(targetProperty == null) + throw ScriptRuntime.notFunctionError(this); + + String methodName = targetProperty.getLocalPart(); + + boolean isApply = methodName.equals("apply"); + if(isApply || methodName.equals("call")) + return applyOrCall(isApply, cx, scope, thisObj, args); + + Callable method = ScriptRuntime.getElemFunctionAndThis( + this, methodName, cx); + // Call lastStoredScriptable to clear stored thisObj + // but ignore the result as the method should use the supplied + // thisObj, not one from redirected call + ScriptRuntime.lastStoredScriptable(cx); + return method.call(cx, scope, thisObj, args); + } + + public Scriptable construct(Context cx, Scriptable scope, Object[] args) + { + throw ScriptRuntime.typeError1("msg.not.ctor", "XMLList"); + } +} + + diff --git a/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLName.java b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLName.java new file mode 100644 index 0000000..8ff972e --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLName.java @@ -0,0 +1,171 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Igor Bukanov + * Milen Nankov + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.javascript.xml.impl.xmlbeans; + +import org.mozilla.javascript.Context; +import org.mozilla.javascript.Kit; +import org.mozilla.javascript.Ref; +import org.mozilla.javascript.ScriptRuntime; +import org.mozilla.javascript.Undefined; + +class XMLName extends Ref +{ + static final long serialVersionUID = 3832176310755686977L; + + private String uri; + private String localName; + private boolean isAttributeName; + private boolean isDescendants; + private XMLObjectImpl xmlObject; + + private XMLName(String uri, String localName) + { + this.uri = uri; + this.localName = localName; + } + + static XMLName formStar() + { + return new XMLName(null, "*"); + } + + static XMLName formProperty(String uri, String localName) + { + return new XMLName(uri, localName); + } + + void initXMLObject(XMLObjectImpl xmlObject) + { + if (xmlObject == null) throw new IllegalArgumentException(); + if (this.xmlObject != null) throw new IllegalStateException(); + this.xmlObject = xmlObject; + } + + String uri() + { + return uri; + } + + String localName() + { + return localName; + } + + boolean isAttributeName() + { + return isAttributeName; + } + + void setAttributeName() + { + if (isAttributeName) throw new IllegalStateException(); + isAttributeName = true; + } + + boolean isDescendants() + { + return isDescendants; + } + + void setIsDescendants() + { + if (isDescendants) throw new IllegalStateException(); + isDescendants = true; + } + + public boolean has(Context cx) + { + if (xmlObject == null) { + return false; + } + return xmlObject.hasXMLProperty(this); + } + + public Object get(Context cx) + { + if (xmlObject == null) { + throw ScriptRuntime.undefReadError(Undefined.instance, + toString()); + } + return xmlObject.getXMLProperty(this); + } + + public Object set(Context cx, Object value) + { + if (xmlObject == null) { + throw ScriptRuntime.undefWriteError(Undefined.instance, + toString(), + value); + } + // Assignment to descendants causes parse error on bad reference + // and this should not be called + if (isDescendants) throw Kit.codeBug(); + xmlObject.putXMLProperty(this, value); + return value; + } + + public boolean delete(Context cx) + { + if (xmlObject == null) { + return true; + } + xmlObject.deleteXMLProperty(this); + return !xmlObject.hasXMLProperty(this); + } + + public String toString() + { + //return qname.localName(); + StringBuffer buff = new StringBuffer(); + if (isDescendants) buff.append(".."); + if (isAttributeName) buff.append('@'); + if (uri == null) { + buff.append('*'); + if(localName().equals("*")) { + return buff.toString(); + } + } else { + buff.append('"').append(uri()).append('"'); + } + buff.append(':').append(localName()); + return buff.toString(); + } + +} diff --git a/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLObjectImpl.java b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLObjectImpl.java new file mode 100644 index 0000000..a6d47d5 --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLObjectImpl.java @@ -0,0 +1,724 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Igor Bukanov + * Ethan Hugg + * Terry Lucas + * Milen Nankov + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.javascript.xml.impl.xmlbeans; + +import org.mozilla.javascript.*; +import org.mozilla.javascript.xml.*; + +/** + * This abstract class describes what all XML objects (XML, XMLList) should have in common. + * + * @see XML + */ +abstract class XMLObjectImpl extends XMLObject +{ + private static final Object XMLOBJECT_TAG = new Object(); + + protected final XMLLibImpl lib; + protected boolean prototypeFlag; + + protected XMLObjectImpl(XMLLibImpl lib, XMLObject prototype) + { + super(lib.globalScope(), prototype); + this.lib = lib; + } + + /** + * ecmaHas(cx, id) calls this after resolving when id to XMLName + * and checking it is not Uint32 index. + */ + abstract boolean hasXMLProperty(XMLName name); + + /** + * ecmaGet(cx, id) calls this after resolving when id to XMLName + * and checking it is not Uint32 index. + */ + abstract Object getXMLProperty(XMLName name); + + /** + * ecmaPut(cx, id, value) calls this after resolving when id to XMLName + * and checking it is not Uint32 index. + */ + abstract void putXMLProperty(XMLName name, Object value); + + /** + * ecmaDelete(cx, id) calls this after resolving when id to XMLName + * and checking it is not Uint32 index. + */ + abstract void deleteXMLProperty(XMLName name); + + /** + * Test XML equality with target the target. + */ + abstract boolean equivalentXml(Object target); + + // Methods from section 12.4.4 in the spec + abstract XML addNamespace(Namespace ns); + abstract XML appendChild(Object xml); + abstract XMLList attribute(XMLName xmlName); + abstract XMLList attributes(); + abstract XMLList child(long index); + abstract XMLList child(XMLName xmlName); + abstract int childIndex(); + abstract XMLList children(); + abstract XMLList comments(); + abstract boolean contains(Object xml); + abstract Object copy(); + abstract XMLList descendants(XMLName xmlName); + abstract Object[] inScopeNamespaces(); + abstract XML insertChildAfter(Object child, Object xml); + abstract XML insertChildBefore(Object child, Object xml); + abstract boolean hasOwnProperty(XMLName xmlName); + abstract boolean hasComplexContent(); + abstract boolean hasSimpleContent(); + abstract int length(); + abstract String localName(); + abstract QName name(); + abstract Object namespace(String prefix); + abstract Object[] namespaceDeclarations(); + abstract Object nodeKind(); + abstract void normalize(); + abstract Object parent(); + abstract XML prependChild(Object xml); + abstract Object processingInstructions(XMLName xmlName); + abstract boolean propertyIsEnumerable(Object member); + abstract XML removeNamespace(Namespace ns); + abstract XML replace(long index, Object xml); + abstract XML replace(XMLName name, Object xml); + abstract XML setChildren(Object xml); + abstract void setLocalName(String name); + abstract void setName(QName xmlName); + abstract void setNamespace(Namespace ns); + abstract XMLList text(); + public abstract String toString(); + abstract String toSource(int indent); + abstract String toXMLString(int indent); + abstract Object valueOf(); + + /** + * Extension to access native implementation from scripts + */ + abstract org.apache.xmlbeans.XmlObject getXmlObject(); + + protected abstract Object jsConstructor(Context cx, boolean inNewExpr, + Object[] args); + + + final Object getMethod(String id) + { + return super.get(id, this); + } + + // + // + // Methods overriding ScriptableObject + // + // + + public final Object getDefaultValue(Class hint) + { + return toString(); + } + + public void delete(String name) + { + throw new IllegalArgumentException("String: [" + name + "]"); + } + + /** + * XMLObject always compare with any value and equivalentValues + * never returns {@link Scriptable#NOT_FOUND} for them but rather + * calls equivalentXml(value) and wrap the result as Boolean. + */ + protected final Object equivalentValues(Object value) + { + boolean result = equivalentXml(value); + return result ? Boolean.TRUE : Boolean.FALSE; + } + + // + // + // Methods overriding XMLObject + // + // + + public final XMLLib lib() + { + return lib; + } + + /** + * Implementation of ECMAScript [[Has]] + */ + public final boolean ecmaHas(Context cx, Object id) + { + if (cx == null) cx = Context.getCurrentContext(); + XMLName xmlName = lib.toXMLNameOrIndex(cx, id); + if (xmlName == null) { + long index = ScriptRuntime.lastUint32Result(cx); + // XXX Fix this cast + return has((int)index, this); + } + return hasXMLProperty(xmlName); + } + + /** + * Implementation of ECMAScript [[Get]] + */ + public final Object ecmaGet(Context cx, Object id) + { + if (cx == null) cx = Context.getCurrentContext(); + XMLName xmlName = lib.toXMLNameOrIndex(cx, id); + if (xmlName == null) { + long index = ScriptRuntime.lastUint32Result(cx); + // XXX Fix this cast + Object result = get((int)index, this); + if (result == Scriptable.NOT_FOUND) { + result = Undefined.instance; + } + return result; + } + return getXMLProperty(xmlName); + } + + /** + * Implementation of ECMAScript [[Put]] + */ + public final void ecmaPut(Context cx, Object id, Object value) + { + if (cx == null) cx = Context.getCurrentContext(); + XMLName xmlName = lib.toXMLNameOrIndex(cx, id); + if (xmlName == null) { + long index = ScriptRuntime.lastUint32Result(cx); + // XXX Fix this cast + put((int)index, this, value); + return; + } + putXMLProperty(xmlName, value); + } + + /** + * Implementation of ECMAScript [[Delete]]. + */ + public final boolean ecmaDelete(Context cx, Object id) + { + if (cx == null) cx = Context.getCurrentContext(); + XMLName xmlName = lib.toXMLNameOrIndex(cx, id); + if (xmlName == null) { + long index = ScriptRuntime.lastUint32Result(cx); + // XXX Fix this + delete((int)index); + return true; + } + deleteXMLProperty(xmlName); + return true; + } + + public Ref memberRef(Context cx, Object elem, int memberTypeFlags) + { + XMLName xmlName; + if ((memberTypeFlags & Node.ATTRIBUTE_FLAG) != 0) { + xmlName = lib.toAttributeName(cx, elem); + } else { + if ((memberTypeFlags & Node.DESCENDANTS_FLAG) == 0) { + // Code generation would use ecma(Get|Has|Delete|Set) for + // normal name idenrifiers so one ATTRIBUTE_FLAG + // or DESCENDANTS_FLAG has to be set + throw Kit.codeBug(); + } + xmlName = lib.toXMLName(cx, elem); + } + if ((memberTypeFlags & Node.DESCENDANTS_FLAG) != 0) { + xmlName.setIsDescendants(); + } + xmlName.initXMLObject(this); + return xmlName; + } + + /** + * Generic reference to implement x::ns, x.@ns::y, x..@ns::y etc. + */ + public Ref memberRef(Context cx, Object namespace, Object elem, + int memberTypeFlags) + { + XMLName xmlName = lib.toQualifiedName(cx, namespace, elem); + if ((memberTypeFlags & Node.ATTRIBUTE_FLAG) != 0) { + if (!xmlName.isAttributeName()) { + xmlName.setAttributeName(); + } + } + if ((memberTypeFlags & Node.DESCENDANTS_FLAG) != 0) { + xmlName.setIsDescendants(); + } + xmlName.initXMLObject(this); + return xmlName; + } + + public NativeWith enterWith(Scriptable scope) + { + return new XMLWithScope(lib, scope, this); + } + + public NativeWith enterDotQuery(Scriptable scope) + { + XMLWithScope xws = new XMLWithScope(lib, scope, this); + xws.initAsDotQuery(); + return xws; + } + + public final Object addValues(Context cx, boolean thisIsLeft, + Object value) + { + if (value instanceof XMLObject) { + XMLObject v1, v2; + if (thisIsLeft) { + v1 = this; + v2 = (XMLObject)value; + } else { + v1 = (XMLObject)value; + v2 = this; + } + return lib.addXMLObjects(cx, v1, v2); + } + if (value == Undefined.instance) { + // both "xml + undefined" and "undefined + xml" gives String(xml) + return ScriptRuntime.toString(this); + } + + return super.addValues(cx, thisIsLeft, value); + } + + // + // + // IdScriptableObject machinery + // + // + + final void exportAsJSClass(boolean sealed) + { + prototypeFlag = true; + exportAsJSClass(MAX_PROTOTYPE_ID, lib.globalScope(), sealed); + } + +// #string_id_map# + private final static int + Id_constructor = 1, + + Id_addNamespace = 2, + Id_appendChild = 3, + Id_attribute = 4, + Id_attributes = 5, + Id_child = 6, + Id_childIndex = 7, + Id_children = 8, + Id_comments = 9, + Id_contains = 10, + Id_copy = 11, + Id_descendants = 12, + Id_inScopeNamespaces = 13, + Id_insertChildAfter = 14, + Id_insertChildBefore = 15, + Id_hasOwnProperty = 16, + Id_hasComplexContent = 17, + Id_hasSimpleContent = 18, + Id_length = 19, + Id_localName = 20, + Id_name = 21, + Id_namespace = 22, + Id_namespaceDeclarations = 23, + Id_nodeKind = 24, + Id_normalize = 25, + Id_parent = 26, + Id_prependChild = 27, + Id_processingInstructions = 28, + Id_propertyIsEnumerable = 29, + Id_removeNamespace = 30, + Id_replace = 31, + Id_setChildren = 32, + Id_setLocalName = 33, + Id_setName = 34, + Id_setNamespace = 35, + Id_text = 36, + Id_toString = 37, + Id_toSource = 38, + Id_toXMLString = 39, + Id_valueOf = 40, + + Id_getXmlObject = 41, + + MAX_PROTOTYPE_ID = 41; + + protected int findPrototypeId(String s) + { + int id; +// #generated# Last update: 2004-11-10 15:38:11 CET + L0: { id = 0; String X = null; int c; + L: switch (s.length()) { + case 4: c=s.charAt(0); + if (c=='c') { X="copy";id=Id_copy; } + else if (c=='n') { X="name";id=Id_name; } + else if (c=='t') { X="text";id=Id_text; } + break L; + case 5: X="child";id=Id_child; break L; + case 6: c=s.charAt(0); + if (c=='l') { X="length";id=Id_length; } + else if (c=='p') { X="parent";id=Id_parent; } + break L; + case 7: c=s.charAt(0); + if (c=='r') { X="replace";id=Id_replace; } + else if (c=='s') { X="setName";id=Id_setName; } + else if (c=='v') { X="valueOf";id=Id_valueOf; } + break L; + case 8: switch (s.charAt(4)) { + case 'K': X="nodeKind";id=Id_nodeKind; break L; + case 'a': X="contains";id=Id_contains; break L; + case 'd': X="children";id=Id_children; break L; + case 'e': X="comments";id=Id_comments; break L; + case 'r': X="toString";id=Id_toString; break L; + case 'u': X="toSource";id=Id_toSource; break L; + } break L; + case 9: switch (s.charAt(2)) { + case 'c': X="localName";id=Id_localName; break L; + case 'm': X="namespace";id=Id_namespace; break L; + case 'r': X="normalize";id=Id_normalize; break L; + case 't': X="attribute";id=Id_attribute; break L; + } break L; + case 10: c=s.charAt(0); + if (c=='a') { X="attributes";id=Id_attributes; } + else if (c=='c') { X="childIndex";id=Id_childIndex; } + break L; + case 11: switch (s.charAt(0)) { + case 'a': X="appendChild";id=Id_appendChild; break L; + case 'c': X="constructor";id=Id_constructor; break L; + case 'd': X="descendants";id=Id_descendants; break L; + case 's': X="setChildren";id=Id_setChildren; break L; + case 't': X="toXMLString";id=Id_toXMLString; break L; + } break L; + case 12: switch (s.charAt(0)) { + case 'a': X="addNamespace";id=Id_addNamespace; break L; + case 'g': X="getXmlObject";id=Id_getXmlObject; break L; + case 'p': X="prependChild";id=Id_prependChild; break L; + case 's': c=s.charAt(3); + if (c=='L') { X="setLocalName";id=Id_setLocalName; } + else if (c=='N') { X="setNamespace";id=Id_setNamespace; } + break L; + } break L; + case 14: X="hasOwnProperty";id=Id_hasOwnProperty; break L; + case 15: X="removeNamespace";id=Id_removeNamespace; break L; + case 16: c=s.charAt(0); + if (c=='h') { X="hasSimpleContent";id=Id_hasSimpleContent; } + else if (c=='i') { X="insertChildAfter";id=Id_insertChildAfter; } + break L; + case 17: c=s.charAt(3); + if (c=='C') { X="hasComplexContent";id=Id_hasComplexContent; } + else if (c=='c') { X="inScopeNamespaces";id=Id_inScopeNamespaces; } + else if (c=='e') { X="insertChildBefore";id=Id_insertChildBefore; } + break L; + case 20: X="propertyIsEnumerable";id=Id_propertyIsEnumerable; break L; + case 21: X="namespaceDeclarations";id=Id_namespaceDeclarations; break L; + case 22: X="processingInstructions";id=Id_processingInstructions; break L; + } + if (X!=null && X!=s && !X.equals(s)) id = 0; + } +// #/generated# + return id; + } +// #/string_id_map# + + protected void initPrototypeId(int id) + { + String s; + int arity; + switch (id) { + case Id_constructor: { + IdFunctionObject ctor; + if (this instanceof XML) { + ctor = new XMLCtor((XML)this, XMLOBJECT_TAG, id, 1); + } else { + ctor = new IdFunctionObject(this, XMLOBJECT_TAG, id, 1); + } + initPrototypeConstructor(ctor); + return; + } + + case Id_addNamespace: arity=1; s="addNamespace"; break; + case Id_appendChild: arity=1; s="appendChild"; break; + case Id_attribute: arity=1; s="attribute"; break; + case Id_attributes: arity=0; s="attributes"; break; + case Id_child: arity=1; s="child"; break; + case Id_childIndex: arity=0; s="childIndex"; break; + case Id_children: arity=0; s="children"; break; + case Id_comments: arity=0; s="comments"; break; + case Id_contains: arity=1; s="contains"; break; + case Id_copy: arity=0; s="copy"; break; + case Id_descendants: arity=1; s="descendants"; break; + case Id_hasComplexContent: arity=0; s="hasComplexContent"; break; + case Id_hasOwnProperty: arity=1; s="hasOwnProperty"; break; + case Id_hasSimpleContent: arity=0; s="hasSimpleContent"; break; + case Id_inScopeNamespaces: arity=0; s="inScopeNamespaces"; break; + case Id_insertChildAfter: arity=2; s="insertChildAfter"; break; + case Id_insertChildBefore: arity=2; s="insertChildBefore"; break; + case Id_length: arity=0; s="length"; break; + case Id_localName: arity=0; s="localName"; break; + case Id_name: arity=0; s="name"; break; + case Id_namespace: arity=1; s="namespace"; break; + case Id_namespaceDeclarations: + arity=0; s="namespaceDeclarations"; break; + case Id_nodeKind: arity=0; s="nodeKind"; break; + case Id_normalize: arity=0; s="normalize"; break; + case Id_parent: arity=0; s="parent"; break; + case Id_prependChild: arity=1; s="prependChild"; break; + case Id_processingInstructions: + arity=1; s="processingInstructions"; break; + case Id_propertyIsEnumerable: + arity=1; s="propertyIsEnumerable"; break; + case Id_removeNamespace: arity=1; s="removeNamespace"; break; + case Id_replace: arity=2; s="replace"; break; + case Id_setChildren: arity=1; s="setChildren"; break; + case Id_setLocalName: arity=1; s="setLocalName"; break; + case Id_setName: arity=1; s="setName"; break; + case Id_setNamespace: arity=1; s="setNamespace"; break; + case Id_text: arity=0; s="text"; break; + case Id_toString: arity=0; s="toString"; break; + case Id_toSource: arity=1; s="toSource"; break; + case Id_toXMLString: arity=1; s="toXMLString"; break; + case Id_valueOf: arity=0; s="valueOf"; break; + + case Id_getXmlObject: arity=0; s="getXmlObject"; break; + default: throw new IllegalArgumentException(String.valueOf(id)); + } + initPrototypeMethod(XMLOBJECT_TAG, id, s, arity); + } + + /** + * + * @param f + * @param cx + * @param scope + * @param thisObj + * @param args + * @return + */ + public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, + Scriptable thisObj, Object[] args) + { + if (!f.hasTag(XMLOBJECT_TAG)) { + return super.execIdCall(f, cx, scope, thisObj, args); + } + int id = f.methodId(); + if (id == Id_constructor) { + return jsConstructor(cx, thisObj == null, args); + } + + // All (XML|XMLList).prototype methods require thisObj to be XML + if (!(thisObj instanceof XMLObjectImpl)) + throw incompatibleCallError(f); + XMLObjectImpl realThis = (XMLObjectImpl)thisObj; + + switch (id) { + case Id_addNamespace: { + Namespace ns = lib.castToNamespace(cx, arg(args, 0)); + return realThis.addNamespace(ns); + } + case Id_appendChild: + return realThis.appendChild(arg(args, 0)); + case Id_attribute: { + XMLName xmlName = lib.toAttributeName(cx, arg(args, 0)); + return realThis.attribute(xmlName); + } + case Id_attributes: + return realThis.attributes(); + case Id_child: { + XMLName xmlName = lib.toXMLNameOrIndex(cx, arg(args, 0)); + if (xmlName == null) { + long index = ScriptRuntime.lastUint32Result(cx); + return realThis.child(index); + } else { + return realThis.child(xmlName); + } + } + case Id_childIndex: + return ScriptRuntime.wrapInt(realThis.childIndex()); + case Id_children: + return realThis.children(); + case Id_comments: + return realThis.comments(); + case Id_contains: + return ScriptRuntime.wrapBoolean( + realThis.contains(arg(args, 0))); + case Id_copy: + return realThis.copy(); + case Id_descendants: { + XMLName xmlName = (args.length == 0) + ? XMLName.formStar() + : lib.toXMLName(cx, args[0]); + return realThis.descendants(xmlName); + } + case Id_inScopeNamespaces: { + Object[] array = realThis.inScopeNamespaces(); + return cx.newArray(scope, array); + } + case Id_insertChildAfter: + return realThis.insertChildAfter(arg(args, 0), arg(args, 1)); + case Id_insertChildBefore: + return realThis.insertChildBefore(arg(args, 0), arg(args, 1)); + case Id_hasOwnProperty: { + XMLName xmlName = lib.toXMLName(cx, arg(args, 0)); + return ScriptRuntime.wrapBoolean( + realThis.hasOwnProperty(xmlName)); + } + case Id_hasComplexContent: + return ScriptRuntime.wrapBoolean(realThis.hasComplexContent()); + case Id_hasSimpleContent: + return ScriptRuntime.wrapBoolean(realThis.hasSimpleContent()); + case Id_length: + return ScriptRuntime.wrapInt(realThis.length()); + case Id_localName: + return realThis.localName(); + case Id_name: + return realThis.name(); + case Id_namespace: { + String prefix = (args.length > 0) + ? ScriptRuntime.toString(args[0]) : null; + return realThis.namespace(prefix); + } + case Id_namespaceDeclarations: { + Object[] array = realThis.namespaceDeclarations(); + return cx.newArray(scope, array); + } + case Id_nodeKind: + return realThis.nodeKind(); + case Id_normalize: + realThis.normalize(); + return Undefined.instance; + case Id_parent: + return realThis.parent(); + case Id_prependChild: + return realThis.prependChild(arg(args, 0)); + case Id_processingInstructions: { + XMLName xmlName = (args.length > 0) + ? lib.toXMLName(cx, args[0]) + : XMLName.formStar(); + return realThis.processingInstructions(xmlName); + } + case Id_propertyIsEnumerable: { + return ScriptRuntime.wrapBoolean( + realThis.propertyIsEnumerable(arg(args, 0))); + } + case Id_removeNamespace: { + Namespace ns = lib.castToNamespace(cx, arg(args, 0)); + return realThis.removeNamespace(ns); + } + case Id_replace: { + XMLName xmlName = lib.toXMLNameOrIndex(cx, arg(args, 0)); + Object arg1 = arg(args, 1); + if (xmlName == null) { + long index = ScriptRuntime.lastUint32Result(cx); + return realThis.replace(index, arg1); + } else { + return realThis.replace(xmlName, arg1); + } + } + case Id_setChildren: + return realThis.setChildren(arg(args, 0)); + case Id_setLocalName: { + String localName; + Object arg = arg(args, 0); + if (arg instanceof QName) { + localName = ((QName)arg).localName(); + } else { + localName = ScriptRuntime.toString(arg); + } + realThis.setLocalName(localName); + return Undefined.instance; + } + case Id_setName: { + Object arg = (args.length != 0) ? args[0] : Undefined.instance; + QName qname; + if (arg instanceof QName) { + qname = (QName)arg; + if (qname.uri() == null) { + qname = lib.constructQNameFromString(cx, qname.localName()); + } else { + // E4X 13.4.4.35 requires to always construct QName + qname = lib.constructQName(cx, qname); + } + } else { + qname = lib.constructQName(cx, arg); + } + realThis.setName(qname); + return Undefined.instance; + } + case Id_setNamespace: { + Namespace ns = lib.castToNamespace(cx, arg(args, 0)); + realThis.setNamespace(ns); + return Undefined.instance; + } + case Id_text: + return realThis.text(); + case Id_toString: + return realThis.toString(); + case Id_toSource: { + int indent = ScriptRuntime.toInt32(args, 0); + return realThis.toSource(indent); + } + case Id_toXMLString: { + int indent = ScriptRuntime.toInt32(args, 0); + return realThis.toXMLString(indent); + } + case Id_valueOf: + return realThis.valueOf(); + + case Id_getXmlObject: { + org.apache.xmlbeans.XmlObject xmlObject = realThis.getXmlObject(); + return Context.javaToJS(xmlObject, scope); + } + } + throw new IllegalArgumentException(String.valueOf(id)); + } + + private static Object arg(Object[] args, int i) + { + return (i < args.length) ? args[i] : Undefined.instance; + } + +}
\ No newline at end of file diff --git a/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLWithScope.java b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLWithScope.java new file mode 100644 index 0000000..67a778d --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/deprecatedsrc/org/mozilla/javascript/xml/impl/xmlbeans/XMLWithScope.java @@ -0,0 +1,125 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Norris Boyd + * Ethan Hugg + * Terry Lucas + * Milen Nankov + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.javascript.xml.impl.xmlbeans; + +import org.mozilla.javascript.*; +import org.mozilla.javascript.xml.*; + +final class XMLWithScope extends NativeWith +{ + private static final long serialVersionUID = -696429282095170887L; + + private XMLLibImpl lib; + private int _currIndex; + private XMLList _xmlList; + private XMLObject _dqPrototype; + + XMLWithScope(XMLLibImpl lib, Scriptable parent, XMLObject prototype) + { + super(parent, prototype); + this.lib = lib; + } + + void initAsDotQuery() + { + XMLObject prototype = (XMLObject)getPrototype(); + // XMLWithScope also handles the .(xxx) DotQuery for XML + // basically DotQuery is a for/in/with statement and in + // the following 3 statements we setup to signal it's + // DotQuery, + // the index and the object being looped over. The + // xws.setPrototype is the scope of the object which is + // is a element of the lhs (XMLList). + _currIndex = 0; + _dqPrototype = prototype; + if (prototype instanceof XMLList) { + XMLList xl = (XMLList)prototype; + if (xl.length() > 0) { + setPrototype((Scriptable)(xl.get(0, null))); + } + } + // Always return the outer-most type of XML lValue of + // XML to left of dotQuery. + _xmlList = new XMLList(lib); + } + + protected Object updateDotQuery(boolean value) + { + // Return null to continue looping + + XMLObject seed = _dqPrototype; + XMLList xmlL = _xmlList; + + if (seed instanceof XMLList) { + // We're a list so keep testing each element of the list if the + // result on the top of stack is true then that element is added + // to our result list. If false, we try the next element. + XMLList orgXmlL = (XMLList)seed; + + int idx = _currIndex; + + if (value) { + xmlL.addToList(orgXmlL.get(idx, null)); + } + + // More elements to test? + if (++idx < orgXmlL.length()) { + // Yes, set our new index, get the next element and + // reset the expression to run with this object as + // the WITH selector. + _currIndex = idx; + setPrototype((Scriptable)(orgXmlL.get(idx, null))); + + // continue looping + return null; + } + } else { + // If we're not a XMLList then there's no looping + // just return DQPrototype if the result is true. + if (value) { + xmlL.addToList(seed); + } + } + + return xmlL; + } +} |