From ec694154e4fe2c39c30bc6149ee1f99ce4e9cea8 Mon Sep 17 00:00:00 2001 From: crawshaw Date: Thu, 25 Nov 2004 15:43:31 +0000 Subject: [PATCH] eval expressions in normal html attributes darcs-hash:20041125154331-2eb37-976fcba80f60a56b479f872d116dc0c6ba438a6d.gz --- src/java/org/ibex/xt/JSLeaf.java | 68 +++++++++++++++++------------------- src/java/org/ibex/xt/Template.java | 23 ++++++------ 2 files changed, 45 insertions(+), 46 deletions(-) diff --git a/src/java/org/ibex/xt/JSLeaf.java b/src/java/org/ibex/xt/JSLeaf.java index 2def4c1..63bffbd 100644 --- a/src/java/org/ibex/xt/JSLeaf.java +++ b/src/java/org/ibex/xt/JSLeaf.java @@ -1,5 +1,6 @@ package org.ibex.xt; +import java.io.Reader; import java.io.Serializable; import java.io.StringReader; import java.io.Writer; @@ -34,42 +35,53 @@ public class JSLeaf implements Tree.Leaf, Serializable { 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); } public void out(Writer w) throws IOException { wrapped.out(w); } + public void out(OutputStream o) throws IOException { wrapped.out(o); } protected Object eval(String s) { if (s == null) return null; + StringBuffer ret = new StringBuffer(); - while (s.indexOf("${") != -1) { - ret.append(s.substring(0, s.indexOf("${"))); - String s2 = s.substring(s.indexOf("${")+2); - Object app = exec("return (" + s2.substring(0, s2.indexOf('}')) + ");\n"); - s = s.substring(s.indexOf('}') + 1); - - if (!(app == null || - app instanceof String || - app instanceof Number || - app instanceof Boolean)) + int exp, pos = 0; + while ((exp = s.indexOf("${", pos)) >= 0) { + ret.append(s.substring(pos, exp)); + pos = s.indexOf("}", exp); + Object app = exec("return (" + s.substring(exp + 2, pos) + ");"); + pos++; + + if (!(app == null || app instanceof String || + app instanceof Number || + app instanceof Boolean)) throw new Exn("javascripts within ${...} can only return " + "strings, numbers, and booleans; not a " + app.getClass().getName()); - ret.append(app == null ? "null" : app.toString()); } - ret.append(s); + + if (pos < s.length()) ret.append(s.substring(pos)); return ret.toString(); } protected Object exec(String s) { + StringBuffer ret = new StringBuffer(); + int exp, pos = 0; + while ((exp = s.indexOf("${", pos)) >= 0) { + ret.append(s.substring(pos, exp)); + pos = s.indexOf("}", exp); + ret.append("return ("); + ret.append(s.substring(exp + 2, pos)); + ret.append(");"); + pos++; + } + + Reader r = new StringReader(ret.toString()); try { return JS.eval(JS.cloneWithNewParentScope( - JS.fromReader("input", 0, new StringReader(s)), scope())); + JS.fromReader("input", 0, r), scope())); } catch (IOException e) { - e.printStackTrace(); throw new Exn("error parsing script", e); } catch (JSExn e) { throw new Exn(e); @@ -97,29 +109,15 @@ public class JSLeaf implements Tree.Leaf, Serializable { public Tree.Attributes getAttributes() { return ((Tree.Element)wrapped).getAttributes(); } public Tree.Prefixes getPrefixes() { return ((Tree.Element)wrapped).getPrefixes(); } + public void setAttributes(Tree.Attributes a) { ((Tree.Element)wrapped).setAttributes(a); } + public void setPrefixes(Tree.Prefixes p) { ((Tree.Element)wrapped).setPrefixes(p); } + 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 JSLeaf.Element with the element attributes merged with a second - * element. - * - * All functions of the Tree.Element interface are mapped onto the - * primary element, except getAttributes(). This function - * returns a MergedAttr instance with the secondary element - * acting as the primary attribute source. - */ - 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 Tree.Attributes getAttributes() { return a; } - } - /** Creates a single view onto two sets of Attributes, first * checking the primary array for an entry, or * otherwise returning any matching entry in the @@ -151,9 +149,9 @@ public class JSLeaf implements Tree.Leaf, Serializable { public String getUri(int i) { return i >= a.attrSize() ? b.getUri(i-a.attrSize()) : a.getUri(i); } public String getPrefix(int i) { - return i >= a.attrSize() ? b.getUri(i-a.attrSize()) : a.getUri(i); } + return i >= a.attrSize() ? b.getPrefix(i-a.attrSize()) : a.getPrefix(i); } public String getQName(int i) { - return i >= a.attrSize() ? b.getUri(i-a.attrSize()) : a.getUri(i); } + return i >= a.attrSize() ? b.getQName(i-a.attrSize()) : a.getQName(i); } public int attrSize() { return a.attrSize() + b.attrSize(); } } diff --git a/src/java/org/ibex/xt/Template.java b/src/java/org/ibex/xt/Template.java index c30ece6..01b8d7e 100644 --- a/src/java/org/ibex/xt/Template.java +++ b/src/java/org/ibex/xt/Template.java @@ -40,10 +40,7 @@ public class Template extends JSLeaf.Element { //#end } else if (uri.startsWith("http://xt.ibex.org/")) { - //#switch(uri.substring(19)) - case "io": System.out.println("ibex.xt.io not yet implemented"); // TODO - //#end - //throw new JSLeaf.Exn("Unknown XT library: "+uri); + throw new JSLeaf.Exn("Unknown XT library: "+uri); } else if (uri.startsWith("local:")) { // merge a new template into this tree @@ -62,15 +59,16 @@ public class Template extends JSLeaf.Element { e.getChildren().clear(); } - Tree.Element merged = new JSLeaf.Merge(t, e); + // merge the attributes of the template and its representative + t.setAttributes(new JSLeaf.MergeAttr(e.getAttributes(), t.getAttributes())); // remap the parent of the original element if (e.getParent() != null) { List ch = e.getParent().getChildren(); - ch.set(ch.indexOf(e), merged); + ch.set(ch.indexOf(e), t); } - return wrap(merged, s); + return wrap(t, s); } e = new Template.AttributeEval(e); @@ -107,11 +105,14 @@ public class Template extends JSLeaf.Element { /** Processes ${...} blocks in attributes, loads applicable * attributes into the JS scope and processes global attributes. */ public static class AttributeEval extends JSLeaf.Element implements Tree.Attributes { + // TODO: hide global attributes from out() function. waiting on util.XMLHelper protected Tree.Attributes a; - public AttributeEval(Tree.Element wrapped) { super(wrapped); a = wrapped.getAttributes(); } - - public Tree.Attributes getAttributes() { return this; } + public AttributeEval(Tree.Element wrapped) { + super(wrapped); + a = wrapped.getAttributes(); + wrapped.setAttributes(this); + } public int getIndex(String q) { return a.getIndex(q); } public int getIndex(String u, String k) { return a.getIndex(u, k); } @@ -134,7 +135,7 @@ public class Template extends JSLeaf.Element { case "declare": Object d = eval(a.getVal(i)); if (!(d instanceof String)) throw new JSLeaf.Exn( - "attribute "+getPrefix()+":declare can only contain a "+ + "attribute '"+getPrefix()+":declare' can only contain a "+ "space seperated list of variable names to declare."); StringTokenizer st = new StringTokenizer((String)d, " "); while (st.hasMoreTokens()) scope().declare(st.nextToken()); -- 1.7.10.4