coliver 2004/01/04 12:40:26
Modified: src/java/org/apache/cocoon/generation
JXTemplateGenerator.java
src/documentation/xdocs/userdocs/flow jxtemplate.xml
Log:
Added jx:eval tag which allows you to store a macro invocation in a variable
and evaluate it later.
Revision Changes Path
1.28 +41 -1
cocoon-2.1/src/java/org/apache/cocoon/generation/JXTemplateGenerator.java
Index: JXTemplateGenerator.java
===================================================================
RCS file:
/home/cvs/cocoon-2.1/src/java/org/apache/cocoon/generation/JXTemplateGenerator.java,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -r1.27 -r1.28
--- JXTemplateGenerator.java 4 Jan 2004 06:39:11 -0000 1.27
+++ JXTemplateGenerator.java 4 Jan 2004 20:40:26 -0000 1.28
@@ -918,6 +918,7 @@
final static String SET = "set";
final static String MACRO = "macro";
final static String EVALBODY = "evalBody";
+ final static String EVAL = "eval";
final static String PARAMETER = "parameter";
final static String FORMAT_NUMBER = "formatNumber";
final static String FORMAT_DATE = "formatDate";
@@ -1723,6 +1724,14 @@
}
}
+ static class StartEval extends StartInstruction {
+ StartEval(StartElement raw, Expression value) {
+ super(raw);
+ this.value = value;
+ }
+ final Expression value;
+ }
+
static class StartDefine extends StartInstruction {
StartDefine(StartElement raw, String namespace, String name) {
super(raw);
@@ -2600,6 +2609,14 @@
StartEvalBody startEval =
new StartEvalBody(startElement);
newEvent = startEval;
+ } else if (localName.equals(EVAL)) {
+ String value = attrs.getValue("select");
+ Expression valueExpr =
+ compileExpr(value, "eval: \"select\":",
+ locator);
+ StartEval startEval =
+ new StartEval(startElement, valueExpr);
+ newEvent = startEval;
} else if (localName.equals(SET)) {
String var = attrs.getValue("var");
String value = attrs.getValue("value");
@@ -3571,6 +3588,11 @@
MyVariables vars = new MyVariables(parent);
MyJexlContext localJexlContext =
new MyJexlContext(jexlContext);
+ HashMap macro = new HashMap();
+ macro.put("body", startElement);
+ macro.put("arguments", attributeMap);
+ localJexlContext.put("macro", macro);
+ vars.declareVariable("macro", macro);
Iterator iter = def.parameters.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry e = (Map.Entry)iter.next();
@@ -3761,6 +3783,24 @@
e);
}
} else if (ev instanceof StartTemplate) {
+ } else if (ev instanceof StartEval) {
+ StartEval startEval = (StartEval)ev;
+ Expression expr = startEval.value;
+ try {
+ Object val = getNode(expr, jexlContext, jxpathContext);
+ if (!(val instanceof StartElement)) {
+ throw new Exception("macro invocation required
instead of: " + val);
+ }
+ StartElement call = (StartElement)val;
+ execute(consumer, jexlContext,
+ jxpathContext, call,
+ call.next, call.endElement);
+ } catch (Exception exc) {
+ throw new SAXParseException(exc.getMessage(),
+ ev.location, exc);
+ }
+ ev = startEval.endInstruction.next;
+ continue;
} else if (ev instanceof StartEvalBody) {
StartEvalBody startEval = (StartEvalBody)ev;
try {
1.29 +71 -0
cocoon-2.1/src/documentation/xdocs/userdocs/flow/jxtemplate.xml
Index: jxtemplate.xml
===================================================================
RCS file:
/home/cvs/cocoon-2.1/src/documentation/xdocs/userdocs/flow/jxtemplate.xml,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -r1.28 -r1.29
--- jxtemplate.xml 4 Jan 2004 01:07:53 -0000 1.28
+++ jxtemplate.xml 4 Jan 2004 20:40:26 -0000 1.29
@@ -514,6 +514,77 @@
letter = g <br/>
]]> </source>
</s2>
+<s2 title="eval">
+<p>
+The <code>eval</code> tag permits dynamic evaluation of custom tags.
+</p>
+<source>
+<jx:eval select="Expression"/>
+</source>
+<p>
+Within the body of a macro, information about the current invocation is
available via a special variable <code>macro</code>. This variable contains the
following properties:
+</p>
+ <table>
+ <tr>
+ <td>
+ Property:
+ </td>
+ <td>
+ Description:
+ </td>
+ </tr>
+ <tr>
+ <td>
+ arguments
+ </td>
+ <td>
+ A map containing the all of the attributes from the tag invocation
+ </td>
+ </tr>
+ <tr>
+ <td>
+ body
+ </td>
+ <td>
+ A reference to the content of the tag invocation
+ </td>
+ </tr>
+ </table>
+<p>
+You can store the value of <code>body</code> in another variable and invoke
it later using <code>jx:eval</code>. The <code>select</code> attribute of
<code>jx:eval</code> specifies an expression that must evaluate to a macro
invocation. For example:
+</p>
+<source>
+<![CDATA[
+
+<jx:set var="tags" value="${java.util.HashMap()}"/>
+
+<jx:macro name="dynamic-tag">
+ <jx:parameter name="id"/>
+ <jx:set var="ignored" value="${tags.put(id, macro.body)}"/>
+</jx:macro>
+
+<dynamic-tag id="example">
+ <em>This tag was invoked dynamically</em>
+</dynamic-tag>
+
+<p>I'm about to invoke a dynamic tag:</p>
+<jx:eval select="${tags.example}"/>
+
+]]>
+
+</source>
+<p>
+The above template produces the following output:
+</p>
+<source>
+<![CDATA[
+<p>I'm about to invoke a dynamic tag:</p>
+
+
+<em>This tag was invoked dynamically</em>
+]]>
+</source>
+</s2>
</s1>
</body>
</document>