package org.ibex.xt;
+import java.io.Serializable;
import java.io.StringReader;
import java.io.Writer;
import java.io.OutputStream;
import org.ibex.js.JSScope;
import org.ibex.js.JSExn;
-public class JSElement extends JSScope implements XML.Element {
- protected XML.Element wrapped;
+public class JSLeaf implements Tree.Leaf, Serializable {
+ private transient JSScope scope = null;
+ protected Tree.Leaf wrapped;
- /** Creates an Element around <tt>wrapped</tt>, replacing
- * references to it in its parent and children with this object. */
- public JSElement(XML.Element wrapped) {
- super(findScope(wrapped));
+ /** Creates a Leaf around <tt>wrapped</tt>, replacing
+ * references to it in its parent with this object. */
+ public JSLeaf(Tree.Leaf wrapped) {
this.wrapped = wrapped;
// remap parent and children
List c = wrapped.getParent().getChildren();
c.set(c.indexOf(wrapped), this);
}
- List c = wrapped.getChildren();
- for (int i=0; i < c.size(); i++) ((Tree.Leaf)c.get(i)).setParent(this);
+ }
+
+ public JSScope scope() {
+ if (scope == null) {
+ Tree.Leaf e = wrapped;
+ while (e != null && !(e instanceof JSLeaf)) e = e.getParent();
+ scope = new JSScope(e == null ? null : ((JSLeaf)e).scope());
+ }
+
+ return scope;
}
public void out(OutputStream o) throws IOException { wrapped.out(o); }
return ret.toString();
}
- public Object exec(String s) {
+ protected Object exec(String s) {
try {
return JS.eval(JS.cloneWithNewParentScope(
- JS.fromReader("input", 0, new StringReader(s)), this));
+ JS.fromReader("input", 0, new StringReader(s)), scope()));
} catch (IOException e) {
e.printStackTrace();
throw new Exn("error parsing script", e);
// Pass Through ///////////////////////////////////////////////////////////
- public void setParent(Tree.Node p) { wrapped.setParent(p); }
- public Tree.Node getParent() { return wrapped.getParent(); }
- public XML.Attributes getAttributes() { return wrapped.getAttributes(); }
- public XML.Prefixes getPrefixes() { return wrapped.getPrefixes(); }
- public List getChildren() { return wrapped.getChildren(); }
- public String getQName() { return wrapped.getQName(); }
- public String getLocalName() { return wrapped.getLocalName(); }
- public String getPrefix() { return wrapped.getPrefix(); }
- public String getUri() { return wrapped.getUri(); }
-
- /** Works up the Element object model until an instance of a JSScope is found. */
- private static JSScope findScope(Tree.Node e) {
- while (e != null && !(e instanceof JSScope)) e = e.getParent();
- return (JSScope)e;
+ public void setParent(Tree.Node p) { wrapped.setParent(p); }
+ public Tree.Node getParent() { return wrapped.getParent(); }
+
+ public static class Node extends JSLeaf implements Tree.Node {
+ public Node(Tree.Node wrapped) {
+ super(wrapped);
+ List c = wrapped.getChildren();
+ for (int i=0; i < c.size(); i++) ((Tree.Leaf)c.get(i)).setParent(this);
+ }
+
+ public List getChildren() { return ((Tree.Node)wrapped).getChildren(); }
+ }
+
+ public static class Element extends Node implements Tree.Element {
+ public Element(Tree.Element wrapped) { super(wrapped); }
+
+ public Tree.Attributes getAttributes() { return ((Tree.Element)wrapped).getAttributes(); }
+ public Tree.Prefixes getPrefixes() { return ((Tree.Element)wrapped).getPrefixes(); }
+
+ public String getQName() { return ((Tree.Element)wrapped).getQName(); }
+ public String getLocalName() { return ((Tree.Element)wrapped).getLocalName(); }
+ public String getPrefix() { return ((Tree.Element)wrapped).getPrefix(); }
+ public String getUri() { return ((Tree.Element)wrapped).getUri(); }
}
- /** A JSElement with the element attributes merged with a second
+ /** A JSLeaf.Element with the element attributes merged with a second
* element.
*
- * All functions of the XML.Element interface are mapped onto the
+ * All functions of the Tree.Element interface are mapped onto the
* primary element, except <tt>getAttributes()</tt>. This function
* returns a MergedAttr instance with the <b>secondary</b> element
* acting as the primary attribute source.
*/
- public static class Merge extends JSElement {
- private final XML.Attributes a;
- public Merge(XML.Element wrapped, XML.Element merge) {
+ public static class Merge extends Element {
+ private final Tree.Attributes a;
+ public Merge(Tree.Element wrapped, Tree.Element merge) {
super(wrapped);
a = new MergeAttr(merge.getAttributes(), wrapped.getAttributes());
}
- public XML.Attributes getAttributes() { return a; }
+ public Tree.Attributes getAttributes() { return a; }
}
/** Creates a single view onto two sets of Attributes, first
* otherwise returning any matching entry in the
* <tt>secondary</tt> Attributes object.
*
- * FIXME: toXML() produces invalid XML if qname in both a and b.
+ * FIXME: out(Writer) produces invalid XML if qname in both a and b.
+ * create org.ibex.util.XMLHelper and have a proper version of
+ * this as a subclass.
*/
- public static final class MergeAttr implements XML.Attributes {
- private final XML.Attributes a, b;
- public MergeAttr(XML.Attributes primary, XML.Attributes secondary) {
+ public static final class MergeAttr implements Tree.Attributes {
+ private final Tree.Attributes a, b;
+ public MergeAttr(Tree.Attributes primary, Tree.Attributes secondary) {
a = primary; b = secondary;
}
public int getIndex(String qname) {