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>
  +&lt;jx:eval select="Expression"/&gt;
  +</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>
  
  
  

Reply via email to