X-Git-Url: http://git.megacz.com/?p=org.ibex.core.git;a=blobdiff_plain;f=src%2Forg%2Fxwt%2FTemplate.java;h=2cc62420e61021993a5953448a3eb93b2588140c;hp=0af2e0a4d87eee54f217aa6097ef21fbf678ac72;hb=16c24a73c1c1b2955db0bbbaf5a940215329bca1;hpb=6242c991f365dbd67eba62ecfa5df769a83fcbc6 diff --git a/src/org/xwt/Template.java b/src/org/xwt/Template.java index 0af2e0a..2cc6242 100644 --- a/src/org/xwt/Template.java +++ b/src/org/xwt/Template.java @@ -1,21 +1,17 @@ -// Copyright 2002 Adam Megacz, see the COPYING file for licensing [GPL] +// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] package org.xwt; import java.io.*; import java.util.zip.*; import java.util.*; import java.lang.*; -import org.mozilla.javascript.*; +import org.xwt.js.*; +import org.xwt.translators.*; import org.xwt.util.*; /** * Encapsulates a template node (the <template/> element of a - * .xwt file, or any child element thereof). Each instance of - * Template has a nodeName -- this is the resource name of - * the file that the template node occurs in, concatenated with the - * path from the root element to this node, each step of which is in - * the form .n for some integer n. Static nodes use the string "._" - * as a path. + * .xwt file, or any child element thereof). * * Note that the Template instance corresponding to the * <template/> node carries all the header information -- hence @@ -30,492 +26,225 @@ public class Template { // Instance Members /////////////////////////////////////////////////////// - /** this instance's nodeName */ - String nodeName; + String id = null; ///< the id of this box + String redirect = null; ///< the id of the redirect target; only meaningful on a root node + private String[] keys; ///< keys to be "put" to instances of this template; elements correspond to those of vals + private Object[] vals; ///< values to be "put" to instances of this template; elements correspond to those of keys + private String[] urikeys; + private String[] urivals; + private Vec children = new Vec(); ///< during XML parsing, this holds the list of currently-parsed children; null otherwise + private JS script = null; ///< the script on this node + Template prev; + JSScope staticScope = null; ///< the scope in which the static block is executed - /** the id of the redirect target; only meaningful on a root node */ - String redirect = null; - /** templates that should be preapplied (in the order of application); only meaningful on a root node */ - private String[] preapply; + // Only used during parsing ///////////////////////////////////////////////////////////////// - /** 'linked' form of preapply -- the String references have been resolved into instance references */ - private Template[] _preapply = null; - - /** templates that should be postapplied (in the order of application); only meaningful on a root node */ - private String[] postapply; - - /** 'linked' form of postapply -- the String references have been resolved into instance references */ - private Template[] _postapply = null; - - /** keys to be "put" to instances of this template; elements correspond to those of vals */ - private String[] keys; - - /** values to be "put" to instances of this template; elements correspond to those of keys */ - private Object[] vals; - - /** array of strings representing the importlist for this template */ - private String[] importlist; - - /** child template objects */ - private Template[] children; - - /** an array of the names of properties to be preserved when retheming; only meaningful on a root node */ - private String[] preserve = null; - - /** the id attribute on this node */ - private String id = ""; - - /** see numUnits(); -1 means that this value has not yet been computed */ - private int numunits = -1; - - /** true iff the resolution of this template's preapply/postapply sets changed as a result of the most recent call to retheme() */ - private boolean changed = false; - - /** the script on the static node of this template, null if it has already been executed */ - private Script staticscript = null; - - /** the script on this node */ - private Script script = null; - - /** during XML parsing, this holds the list of currently-parsed children; null otherwise */ - private Vec childvect = new Vec(); - - /** during XML parsing, this holds partially-read character data; null otherwise */ - private StringBuffer content = null; - - /** line number of the first line of content */ - private int content_start = 0; - - /** number of lines in content */ - private int content_lines = 0; + private StringBuffer content = null; ///< during XML parsing, this holds partially-read character data; null otherwise + private int content_start = 0; ///< line number of the first line of content + private int startLine = -1; ///< the line number that this element starts on + private XWT xwt; // Static data/methods /////////////////////////////////////////////////////////////////// - /** a template cache so that only one Template object is created for each xwt */ - private static Hashtable cache = new Hashtable(1000); - - /** The default importlist; in future revisions this will contain "xwt.*" */ - public static final String[] defaultImportList = new String[] { }; - - /** returns the appropriate template, resolving and theming as needed */ - public static Template getTemplate(String name, String[] importlist) { - String resolved = Resources.resolve(name + ".xwt", importlist); - Template t = resolved == null ? null : (Template)cache.get(resolved.substring(0, resolved.length() - 4)); - if (t != null) return t; - if (resolved == null) return null; - - // note that Templates in xwar's are instantiated as read in via loadStream() -- - // the following code only runs when XWT is reading templates from a filesystem. - ByteArrayInputStream bais = new ByteArrayInputStream(Resources.getResource(resolved)); - return buildTemplate(bais, resolved.substring(0, resolved.length() - 4)); - } - - public static Template buildTemplate(InputStream is, String nodeName) { - try { - return new Template(is, nodeName); - } catch (XML.SAXParseException e) { - if (Log.on) Log.log(Template.class, "error parsing template at " + nodeName + ":" + e.getLineNumber() + "," + e.getColumnNumber()); - if (Log.on) Log.log(Template.class, e); - return null; - } catch (XML.SAXException e) { - if (Log.on) Log.log(Template.class, "error parsing template " + nodeName); - if (Log.on) Log.log(Template.class, e); - return null; - } catch (TemplateException te) { - if (Log.on) Log.log(Template.class, "error parsing template " + nodeName); - if (Log.on) Log.log(Template.class, te); - return null; - } catch (IOException e) { - if (Log.on) Log.log(Template.class, "IOException while parsing template " + nodeName + " -- this should never happen"); - if (Log.on) Log.log(Template.class, e); - return null; - } - } - + // for non-root nodes + private Template(Template t, int startLine) { prev = t; this.xwt = t.xwt; this.startLine = startLine; } + private Template(XWT xwt) { this.xwt = xwt; } + // Methods to apply templates //////////////////////////////////////////////////////// - private Template() { } - private Template(InputStream is, String nodeName) throws XML.SAXException, IOException { - this.nodeName = nodeName; - cache.put(nodeName, this); - new TemplateHelper().parseit(is, this); - } - - /** calculates, caches, and returns an integer approximation of how long it will take to apply this template, including pre/post and children */ - int numUnits() { - link(); - if (numunits != -1) return numunits; - numunits = 1; - for(int i=0; _preapply != null && i<_preapply.length; i++) if (_preapply[i] != null) numunits += _preapply[i].numUnits(); - for(int i=0; _postapply != null && i<_postapply.length; i++) if (_postapply[i] != null) numunits += _postapply[i].numUnits(); - if (script != null) numunits += 10; - numunits += keys == null ? 0 : keys.length; - for(int i=0; children != null && i elements of any - // of the templates which would be applied in step 7." - Vec keys = new Vec(); - b.template.gatherPreserves(keys); - Object[] vals = new Object[keys.size()]; - for(int i=0; i= 0; i--) { - kids[i] = b.redirect.getChild(i); - kids[i].remove(); + if (script != null) JS.cloneWithNewParentScope(script, pis).call(null, null, null, null, 0); + + Object key, val; + for(int i=0; keys != null && i < keys.length; i++) { + if (keys[i] == null) continue; + key = keys[i]; + val = vals[i]; + + if ("null".equals(val)) val = null; + + if (val != null && val instanceof String && ((String)val).length() > 0) { + switch (((String)val).charAt(0)) { + case '$': + val = pis.get(val); + if (val == null) throw new JSExn("unknown box id '"+vals[i]+"' referenced in XML attribute"); + break; + case '.': + val = xwt.resolveString(((String)val).substring(1), false); + // FIXME: url case + // FIXME: should we be resolving all of these in the XML-parsing code? } } - - // Ref 7.5.4: "Set the box's redirect target to self" - b.redirect = b; - - // Ref 7.5.5: "Remove all of the box's immediate children" - for(Box cur = b.getChild(b.numChildren() - 1); cur != null;) { - Box oldcur = cur; - cur = cur.prevSibling(); - oldcur.remove(); - } - - // Ref 7.5.6: "Remove all traps set by scripts run during the application of any template to this box" - Trap.removeAllTrapsByBox(b); - - // Ref 7.5.7: "Apply the template to the box according to the usual application procedure" - b.template.apply(b, null, null); - - // Ref 7.5.8: "Re-add the saved children which were removed in step 3" - for(int i=0; kids != null && ichange as needed */ - void link() { link(false); } - /** same as link(), except that with a true value, it will force a re-link */ - private void link(boolean force) { - if (staticscript != null) try { - Scriptable s = Static.getStatic(nodeName); - if (staticscript != null) { - Script temp = staticscript; - staticscript = null; - temp.exec(Context.enter(), s); - } - } catch (EcmaError e) { - if (Log.on) Log.log(this, "WARNING: uncaught interpreter exception: " + e.getMessage()); - if (Log.on) Log.log(this, " thrown while executing block for " + nodeName + - " at " + e.getSourceName() + ":" + e.getLineNumber()); - } catch (JavaScriptException e) { - if (Log.on) Log.log(this, "WARNING: uncaught ecmascript exception: " + e.getMessage()); - if (Log.on) Log.log(this, " thrown while executing block for " + nodeName + " at " + e.sourceFile + ":" + e.line); - } + // XML Parsing ///////////////////////////////////////////////////////////////// - if (!(force || (preapply != null && _preapply == null) || (postapply != null && _postapply == null))) return; - - if (preapply != null) { - if (_preapply == null) _preapply = new Template[preapply.length]; - for(int i=0; i<_preapply.length; i++) { - Template t = getTemplate(preapply[i], importlist); - if (t != _preapply[i]) changed = true; - _preapply[i] = t; - } - } - if (postapply != null) { - if (_postapply == null) _postapply = new Template[postapply.length]; - for(int i=0; i<_postapply.length; i++) { - Template t = getTemplate(postapply[i], importlist); - if (t != _postapply[i]) changed = true; - _postapply[i] = t; - } + public static Template buildTemplate(InputStream is, XWT xwt) { + try { + return new TemplateHelper(is, xwt).t; + } catch (Exception e) { + Log.error(Template.class, e); + return null; } - - for(int i=0; children != null && iroot */ - void parseit(InputStream is, Template root) throws XML.SAXException, IOException { - t = root; - parse(new TabAndMaxColumnEnforcingReader(new InputStreamReader(is), root.nodeName)); - } + static final class TemplateHelper extends XML { - /** parsing state: true iff we have already encountered the open-tag */ - boolean rootNodeHasBeenEncountered = false; + private int state = STATE_INITIAL; + private static final int STATE_INITIAL = 0; + private static final int STATE_IN_XWT_NODE = 1; + private static final int STATE_IN_TEMPLATE_NODE = 2; + private static final int STATE_IN_META_NODE = 3; - /** parsing state: true iff we have already encountered the