coliver 2003/04/12 17:24:46
Modified: src/scratchpad/src/org/apache/cocoon/transformation JXPathTransformer.java JexlTransformer.java Log: added <set> and <remove> tags to JXPathTransformer and JexlTransformer: these can only be used to create local aliases of existing objects, but cannot be used to modify existing objects Revision Changes Path 1.9 +67 -10 cocoon-2.1/src/scratchpad/src/org/apache/cocoon/transformation/JXPathTransformer.java Index: JXPathTransformer.java =================================================================== RCS file: /home/cvs/cocoon-2.1/src/scratchpad/src/org/apache/cocoon/transformation/JXPathTransformer.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- JXPathTransformer.java 12 Apr 2003 23:35:29 -0000 1.8 +++ JXPathTransformer.java 13 Apr 2003 00:24:45 -0000 1.9 @@ -57,6 +57,7 @@ import java.io.Writer; import java.util.Iterator; import java.util.Map; +import java.util.HashMap; import java.util.Stack; import org.apache.avalon.framework.activity.Initializable; @@ -78,6 +79,7 @@ import org.apache.excalibur.source.SourceException; import org.w3c.dom.DocumentFragment; import org.xml.sax.Attributes; +import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.helpers.AttributesImpl; @@ -111,11 +113,16 @@ public static final String JXPATH_OTHERWISE = "otherwise"; public static final String JXPATH_VALUEOF = "value-of"; public static final String JXPATH_VALUEOF_SELECT = "select"; + public static final String JXPATH_VALUEOF_DEFAULT = "default"; public static final String JXPATH_CONTINUATION = "continuation"; public static final String JXPATH_CONTINUATION_SELECT = "select"; public static final String JXPATH_IF = "if"; public static final String JXPATH_IF_TEST = "test"; public static final String JXPATH_WHEN_TEST = "test"; + public static final String JXPATH_SET = "set"; + public static final String JXPATH_REMOVE = "remove"; + public static final String JXPATH_SET_REMOVE_VARNAME = "var"; + public static final String JXPATH_SET_VALUE = "value"; // web contination private WebContinuation kont; @@ -156,6 +163,11 @@ // Run as a generator for debugging: to get line numbers in error messages private Source inputSource; + private Locator locator = null; + + public void setDocumentLocator(Locator loc) { + this.locator = loc; + } public void generate() throws IOException, SAXException, ProcessingException { @@ -285,8 +297,11 @@ if (c == '}') { String str = expr.toString(); expr.setLength(0); - str = String.valueOf(getValue(str)); - out.write(str); + Object val = getValue(str); + if (val == null) { + val = ""; + } + out.write(String.valueOf(val)); inExpr = false; } else if (c == '\\') { ch = in.read(); @@ -338,7 +353,8 @@ try { substitute(reader, writer); } catch (Exception exc) { - throw new SAXException(exc.getMessage(), exc); + throw new SAXParseException(exc.getMessage(), + locator, exc); } impl.setValue(i, writer.toString()); } @@ -377,6 +393,14 @@ if (ignoreEventsCount == 0) { doContinuation(attr); } + } else if (JXPATH_SET.equals(name)) { + if (ignoreEventsCount == 0) { + doSet(attr); + } + } else if (JXPATH_REMOVE.equals(name)) { + if (ignoreEventsCount == 0) { + doRemove(attr); + } } else if (JXPATH_IF.equals(name)) { doIf(attr); } else if (JXPATH_FOR_EACH.equals(name)) { @@ -387,16 +411,17 @@ return; } else if (JXPATH_WHEN.equals(name)) { if (!inChoose) { - throw new ProcessingException("<when> must be contained in <choose>"); + throw new SAXParseException("<when> must be contained in <choose>", locator, null); } doWhen(attr); } else if (JXPATH_OTHERWISE.equals(name)) { if (!inChoose) { - throw new ProcessingException("<otherwise> must be contained in <choose>"); + throw new SAXParseException("<otherwise> must be contained in <choose>", locator, null); } doOtherwise(attr); } else { - throw new ProcessingException("unknown jxpath element: " + name); + throw new SAXParseException("unknown tag: " + name, + locator, null); } inChoose = false; } @@ -446,6 +471,8 @@ static class MyVariables implements Variables { + Map myVariables = new HashMap(); + static final String[] VARIABLES = new String[] { "continuation", "flowContext", @@ -478,7 +505,7 @@ return true; } } - return false; + return myVariables.containsKey(varName); } public Object getVariable(String varName) { @@ -497,13 +524,15 @@ } else if (varName.equals("parameters")) { return parameters; } - return null; + return myVariables.get(varName); } public void declareVariable(String varName, Object value) { + myVariables.put(varName, value); } public void undeclareVariable(String varName) { + myVariables.remove(varName); } } @@ -549,15 +578,20 @@ throws SAXException, ProcessingException { final String select = a.getValue(JXPATH_VALUEOF_SELECT); + final String def = a.getValue(JXPATH_VALUEOF_DEFAULT); if (null != select) { Object value = getValue(getExpr(select)); if (value == null) { - value = ""; + value = def; + if (value == null) { + value = ""; + } } sendTextEvent(value.toString()); } else { - throw new ProcessingException("jxpath: " + JXPATH_VALUEOF + " specified without a "+JXPATH_VALUEOF_SELECT+" attribute"); + throw new SAXParseException("value-of: \"select\" is required", + locator, null); } } @@ -577,6 +611,29 @@ : kont.getContinuation(0).getId(); sendTextEvent(id); + } + + + private void doSet(final Attributes a) + throws SAXException { + + final String varName = a.getValue(JXPATH_SET_REMOVE_VARNAME); + if (varName == null) { + throw new SAXParseException("set: \"var\" is required", + locator, null); + } + final String value = a.getValue(JXPATH_SET_VALUE); + variables.declareVariable(varName, getValue(getExpr(value))); + } + + private void doRemove(final Attributes a) + throws SAXException { + final String varName = a.getValue(JXPATH_SET_REMOVE_VARNAME); + if (varName == null) { + throw new SAXParseException("set: \"var\" is required", + locator, null); + } + variables.undeclareVariable(varName); } /** 1.6 +48 -6 cocoon-2.1/src/scratchpad/src/org/apache/cocoon/transformation/JexlTransformer.java Index: JexlTransformer.java =================================================================== RCS file: /home/cvs/cocoon-2.1/src/scratchpad/src/org/apache/cocoon/transformation/JexlTransformer.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- JexlTransformer.java 12 Apr 2003 23:35:29 -0000 1.5 +++ JexlTransformer.java 13 Apr 2003 00:24:45 -0000 1.6 @@ -431,6 +431,10 @@ public static final String JEXL_FOREACH_VAR = "var"; public static final String JEXL_FOREACH_VAR_STATUS = "varStatus"; public static final String JEXL_FOREACH_SELECT = "select"; + public static final String JEXL_SET = "set"; + public static final String JEXL_REMOVE = "remove"; + public static final String JEXL_SET_REMOVE_VAR = "var"; + public static final String JEXL_SET_VALUE = "value"; static { // Hack: there's no _nice_ way to add my introspector to Jexl right now @@ -575,6 +579,7 @@ private Object eval(String inStr, boolean iterate) throws SAXException { try { + if (inStr == null) return null; StringReader in = new StringReader(inStr.trim()); int ch; StringBuffer expr = new StringBuffer(); @@ -641,8 +646,11 @@ if (c == '}') { String str = expr.toString(); expr.setLength(0); - str = String.valueOf(getValue(str, xpath, false)); - out.write(str); + Object val = getValue(str, xpath, false); + if (val == null) { + val = ""; + } + out.write(String.valueOf(val)); inExpr = false; xpath = false; } else if (c == '\\') { @@ -738,6 +746,10 @@ } } else if (JEXL_IF.equals(name)) { doIf(attr); + } else if (JEXL_SET.equals(name)) { + doSet(attr); + } else if (JEXL_REMOVE.equals(name)) { + doRemove(attr); } else if (JEXL_FOREACH.equals(name)) { doForEach(attr); } else if (JEXL_CHOOSE.equals(name)) { @@ -806,6 +818,8 @@ static class MyVariables implements Variables { + Map myVariables = new HashMap(); + static final String[] VARIABLES = new String[] { "continuation", "flowContext", @@ -838,7 +852,7 @@ return true; } } - return false; + return myVariables.containsKey(varName); } public Object getVariable(String varName) { @@ -857,13 +871,15 @@ } else if (varName.equals("parameters")) { return parameters; } - return null; + return myVariables.get(varName); } public void declareVariable(String varName, Object value) { + myVariables.put(varName, value); } public void undeclareVariable(String varName) { + myVariables.remove(varName); } } @@ -1026,7 +1042,8 @@ // get the test variable String expr = a.getValue(JEXL_IF_TEST); if (expr == null) { - throw new SAXParseException("if: \"test\" is required", locator, null); + throw new SAXParseException("if: \"test\" is required", + locator, null); } final Object value = eval(expr); final boolean isTrueBoolean = @@ -1046,6 +1063,31 @@ } } + private void doSet(final Attributes a) + throws SAXException { + + final String varName = a.getValue(JEXL_SET_REMOVE_VAR); + if (varName == null) { + throw new SAXParseException("set: \"var\" is required", + locator, null); + } + final String value = a.getValue(JEXL_SET_VALUE); + Object result = eval(value); + variables.declareVariable(varName, result); + getJexlContext().getVars().put(varName, result); + } + + private void doRemove(final Attributes a) + throws SAXException { + + final String varName = a.getValue(JEXL_SET_REMOVE_VAR); + if (varName == null) { + throw new SAXParseException("remove: \"var\" is required", + locator, null); + } + variables.undeclareVariable(varName); + getJexlContext().getVars().remove(varName); + } /** * Helper method to process a <jexl-transformer:if test="..."> element.