Coverage Report - org.webmacro.directive.EvalDirective
 
Classes in this File Line Coverage Branch Coverage Complexity
EvalDirective
73%
44/60
73%
19/26
5.2
 
 1  
 /*
 2  
  * EvalDirective.java
 3  
  *
 4  
  * Created on May 12, 2003, 2:25 PM
 5  
  *
 6  
  * Copyright (C) 1998-2003 Semiotek Inc.  All Rights Reserved.
 7  
  *
 8  
  * Redistribution and use in source and binary forms, with or without
 9  
  * modification, are permitted under the terms of either of the following
 10  
  * Open Source licenses:
 11  
  *
 12  
  * The GNU General Public License, version 2, or any later version, as
 13  
  * published by the Free Software Foundation
 14  
  * (http://www.fsf.org/copyleft/gpl.html);
 15  
  *
 16  
  *  or
 17  
  *
 18  
  * The Semiotek Public License (http://webmacro.org/LICENSE.)
 19  
  *
 20  
  * This software is provided "as is", with NO WARRANTY, not even the
 21  
  * implied warranties of fitness to purpose, or merchantability. You
 22  
  * assume all risks and liabilities associated with its use.
 23  
  *
 24  
  * See www.webmacro.org for more information on the WebMacro project.
 25  
  */
 26  
 
 27  
 package org.webmacro.directive;
 28  
 
 29  
 import org.webmacro.Context;
 30  
 import org.webmacro.Macro;
 31  
 import org.webmacro.PropertyException;
 32  
 import org.webmacro.TemplateVisitor;
 33  
 import org.webmacro.engine.BuildContext;
 34  
 import org.webmacro.engine.BuildException;
 35  
 import org.webmacro.engine.StringMacro;
 36  
 import org.webmacro.engine.Variable;
 37  
 
 38  
 /**
 39  
  * Evaluate an instance of a webmacro target.
 40  
  * <pre>
 41  
  *   #eval $macroVar
 42  
  * or
 43  
  *   #eval $macroVar using $mapVar
 44  
  * </pre>
 45  
  *
 46  
  * @author  kkirsch
 47  
  */
 48  
 
 49  
 public class EvalDirective extends org.webmacro.directive.Directive
 50  
 {
 51  
 
 52  
    private static final int EVAL_EXPR = 1;
 53  
    private static final int EVAL_USING = 2;
 54  
    private static final int EVAL_MAP = 3;
 55  
    private static final int MAX_RECURSION_DEPTH = 100;
 56  
 
 57  
    //private Macro _evalMacro;
 58  
    private Object _evalTarget;
 59  34
    private Object _mapExpr = null;
 60  
 
 61  40
    private static final ArgDescriptor[] myArgs =
 62  
       new ArgDescriptor[] {
 63  
          new RValueArg(EVAL_EXPR),
 64  
          new OptionalGroup(2),
 65  
          new KeywordArg(EVAL_USING, "using"),
 66  
          new RValueArg(EVAL_MAP)};
 67  
 
 68  40
    private static final DirectiveDescriptor myDescr =
 69  
       new DirectiveDescriptor("eval", null, myArgs, null);
 70  
 
 71  
    public static DirectiveDescriptor getDescriptor()
 72  
    {
 73  63
       return myDescr;
 74  
    }
 75  
 
 76  
    /** Creates a new instance of EvalDirective. */
 77  
    public EvalDirective()
 78  34
    {
 79  34
    }
 80  
 
 81  
    public Object build(DirectiveBuilder builder, BuildContext bc)
 82  
       throws BuildException
 83  
    {
 84  34
       _evalTarget = builder.getArg(EVAL_EXPR, bc);
 85  34
       if (builder.getArg(EVAL_USING) != null)
 86  
       {
 87  
          // "using" keyword specified, get map expression
 88  33
          _mapExpr = builder.getArg(EVAL_MAP, bc);
 89  
       }
 90  
       //_result = (org.webmacro.engine.Block)builder.getArg(TEMPLET_RESULT, bc);
 91  34
       return this;
 92  
    }
 93  
 
 94  
    public void write(org.webmacro.FastWriter out, org.webmacro.Context context)
 95  
       throws org.webmacro.PropertyException, java.io.IOException
 96  
    {
 97  
       try
 98  
       {
 99  33
          Macro macro = null;
 100  
 
 101  
          // The target may be:
 102  
          // 1) a variable referencing a Macro
 103  
          // 2) a String to be evaluated as a template
 104  
          // 3) an expression that evaluates into one of the above?
 105  33
          Object targ = _evalTarget;
 106  33
          if (targ instanceof Variable)
 107  
          {
 108  
             // if variable, get it's value
 109  32
             targ = ((Variable) _evalTarget).getValue(context);
 110  
          }
 111  33
          if (targ instanceof String)
 112  
          {
 113  
             // convert string to template
 114  2
             targ = new StringMacro((String) targ);
 115  
          }
 116  33
          if (targ instanceof Macro)
 117  
          {
 118  33
             macro = (Macro) targ;
 119  
          }
 120  
          else
 121  
          {
 122  
             // throw and exception ... we don't know what to do with this!
 123  0
             throw new PropertyException("Invalid argument to #eval directive.  First arg must be a Macro or a String.");
 124  
          }
 125  33
          if (_mapExpr == null)
 126  
          {
 127  
             // no map specified, use current context
 128  1
             macro.write(out, context);
 129  
          }
 130  
          else
 131  
          {
 132  32
             Object argmap = _mapExpr;
 133  32
             if (argmap instanceof Macro)
 134  
             {
 135  29
                argmap = ((Macro) argmap).evaluate(context);
 136  
             }
 137  32
             if (!(argmap instanceof java.util.Map))
 138  
             {
 139  0
                throw new PropertyException("The supplied expression did not evaluate to a java.util.Map instance.");
 140  
             }
 141  
             // check for max recursion
 142  32
             int recursionDepth = 0;
 143  32
             if (context.containsKey("EvalDepth"))
 144  
             { // check the value
 145  
                try
 146  
                {
 147  7
                   recursionDepth =
 148  
                      ((Integer) context.get("EvalDepth")).intValue();
 149  7
                   recursionDepth++;
 150  
                }
 151  0
                catch (Exception e)
 152  
                {
 153  
                   // something bad happend, leave depth at default
 154  7
                }
 155  7
                                         if (recursionDepth > MAX_RECURSION_DEPTH)
 156  
                                         {
 157  0
                                                 throw new PropertyException(
 158  
                                                         "ERROR: A recursive call to #eval exceeded the maximum depth of "
 159  
                                                                 + MAX_RECURSION_DEPTH);
 160  
                                         }
 161  
             }
 162  32
             java.util.Map outerVars = null;
 163  32
             if (context.containsKey("OuterVars"))
 164  
             { // check the value
 165  
                try
 166  
                {
 167  7
                   outerVars = (java.util.Map) context.get("OuterVars");
 168  
                }
 169  0
                catch (Exception e)
 170  
                {
 171  
                   // something bad happened, use vars from calling context
 172  7
                }
 173  
             }
 174  32
             if (outerVars == null)
 175  25
                outerVars = context.getMap();
 176  32
             Context c = new Context(context.getBroker());
 177  
             // replace _variables map with supplied map
 178  32
             c.setMap((java.util.Map) argmap);
 179  
             // put current depth into the new context
 180  32
             c.put("EvalDepth", recursionDepth);
 181  
             // add a reference to parent context variables
 182  32
             c.put("OuterVars", outerVars);
 183  
             // add a reference to this macro
 184  32
             c.put("Self", macro);
 185  32
             macro.write(out, c);
 186  
          }
 187  
       }
 188  0
       catch (Exception e)
 189  
       {
 190  0
          if (e instanceof PropertyException)
 191  0
             throw (PropertyException) e;
 192  0
          throw new PropertyException("#eval: Unable to evaluate macro.", e);
 193  33
       }
 194  33
    }
 195  
 
 196  
    public void accept(TemplateVisitor v)
 197  
    {
 198  0
       v.beginDirective(myDescr.name);
 199  0
       v.visitDirectiveArg("EvalTarget", _evalTarget);
 200  0
       if (_mapExpr != null)
 201  
       {
 202  0
          v.visitDirectiveArg("EvalKeyword", "using");
 203  0
          v.visitDirectiveArg("EvalMap", _mapExpr);
 204  
       }
 205  0
       v.endDirective();
 206  0
    }
 207  
 
 208  
 }