Coverage Report - org.webmacro.directive.WhileDirective
 
Classes in this File Line Coverage Branch Coverage Complexity
WhileDirective
0%
0/44
0%
0/26
4.5
 
 1  
 /*
 2  
  * Copyright (C) 2005. 
 3  
  * All Rights Reserved. Redistribution and use in source and binary forms, 
 4  
  * with or without modification, are permitted under the terms of either of 
 5  
  * the following Open Source licenses: 
 6  
  *   The GNU General Public License, version 2, or 
 7  
  * any later version, as published by the Free Software Foundation
 8  
  * (http://www.fsf.org/copyleft/gpl.html); 
 9  
  *
 10  
  * This software is provided "as is", with NO WARRANTY, not even the implied
 11  
  * warranties of fitness to purpose, or merchantability. You assume all risks 
 12  
  * and liabilities associated with its use.
 13  
  * See www.webmacro.org for more information on the WebMacro project.
 14  
  *  
 15  
  * @author Mike Weerdenburg 
 16  
  * @author Marcel Huijkman
 17  
  *
 18  
  *
 19  
  */
 20  
 
 21  
 package org.webmacro.directive;
 22  
 
 23  
 import java.io.IOException;
 24  
 
 25  
 import org.webmacro.Context;
 26  
 import org.webmacro.FastWriter;
 27  
 import org.webmacro.Macro;
 28  
 import org.webmacro.PropertyException;
 29  
 import org.webmacro.TemplateVisitor;
 30  
 import org.webmacro.engine.Block;
 31  
 import org.webmacro.engine.BuildContext;
 32  
 import org.webmacro.engine.BuildException;
 33  
 import org.webmacro.engine.Expression;
 34  
 import org.webmacro.engine.UndefinedMacro;
 35  
 
 36  
 /**
 37  
  * Syntax: #while (condition) [limit (int)] { block } WhileDirective implements
 38  
  * a WebMacro directive for an while control structure. If you use it without
 39  
  * the limit option than it stops after 1000000 loops! Use a limit value < 0 to
 40  
  * create a loop without a limit, this could hang your template! Introduced at
 41  
  * release 2.0 as an experimental directive.
 42  
  * 
 43  
  * TODO Introduce unit test and mainline or drop the directive.
 44  
  * 
 45  
  * @author Mike Weerdenburg
 46  
  * @author Marcel Huijkman
 47  
  * 
 48  
  * @since   14-01-2005
 49  
  * @version 02-03-2005
 50  
  */
 51  0
 class WhileDirective extends Directive
 52  
 {
 53  
     private static final int WHILE_COND = 1;
 54  
 
 55  
     private static final int WHILE_LIMIT_K = 2;
 56  
 
 57  
     private static final int WHILE_LIMIT = 3;
 58  
 
 59  
     private static final int WHILE_BLOCK = 4;
 60  
 
 61  
     /* The condition as Object. */
 62  
     private Object _obCondition;
 63  
 
 64  
     /* The condition as a Macro. */
 65  0
     private Macro _macroCondition = null;
 66  
 
 67  
     /* The condition as a boolean. */
 68  0
     private boolean boolExpression = false;
 69  
 
 70  
     private Block _whileBlock;
 71  
 
 72  
     private Object _limitExpr;
 73  
 
 74  0
     private static final UndefinedMacro UNDEF = UndefinedMacro.getInstance();
 75  
 
 76  0
     private static final ArgDescriptor[] ifArgs = new ArgDescriptor[] {
 77  
             new ConditionArg(WHILE_COND), new OptionalGroup(2),
 78  
             new KeywordArg(WHILE_LIMIT_K, "limit"), new RValueArg(WHILE_LIMIT),
 79  
 
 80  
             new BlockArg(WHILE_BLOCK), };
 81  
 
 82  0
     private static final DirectiveDescriptor _desc = new DirectiveDescriptor(
 83  
             "while", null, ifArgs, null);
 84  
 
 85  
     public static DirectiveDescriptor getDescriptor ()
 86  
     {
 87  0
         return _desc;
 88  
     }
 89  
 
 90  
     //
 91  
     // these values are customized for this directive during build()
 92  
     //
 93  
 
 94  
     /**
 95  
      * The name given to the directive by webmacro configuration.
 96  
      */
 97  
     protected String _directiveName;
 98  
 
 99  
     public Object build (DirectiveBuilder builder, BuildContext bc)
 100  
             throws BuildException
 101  
     {
 102  
         // name of this directive.
 103  0
         _directiveName = builder.getName();
 104  
 
 105  
         // While condition.
 106  0
         _obCondition = builder.getArg(WHILE_COND, bc);
 107  
 
 108  0
         if (_obCondition instanceof Macro) {
 109  0
             _macroCondition = (Macro) _obCondition;
 110  0
         } else if (_obCondition instanceof Boolean) {
 111  0
             boolExpression = Expression.isTrue(_obCondition);
 112  
         } else {
 113  
             // No valid condition!
 114  0
             throw new BuildException("#" + _directiveName
 115  
                     + ": does not provide a valid condition!");
 116  
         }
 117  
 
 118  
         // While limit (number).
 119  0
         _limitExpr = builder.getArg(WHILE_LIMIT, bc);
 120  
 
 121  
         // While block.
 122  0
         _whileBlock = (Block) builder.getArg(WHILE_BLOCK, bc);
 123  
 
 124  0
         return this;
 125  
     }
 126  
 
 127  
     public void write (FastWriter out, Context context)
 128  
             throws PropertyException, IOException
 129  
     {
 130  
         Object limit;
 131  0
         int loopLimit = 1000000, loopIndex = 0;
 132  
 
 133  0
         if (_limitExpr != null) {
 134  0
             limit = _limitExpr;
 135  0
             while (limit instanceof Macro && limit != UNDEF) {
 136  0
                 limit = ((Macro) limit).evaluate(context);
 137  
             }
 138  0
             if (Expression.isNumber(limit)) {
 139  0
                 loopLimit = (int) Expression.numberValue(limit);
 140  
             } else {
 141  0
                 String warning = "#" + _directiveName
 142  
                         + ": Cannot evaluate limit";
 143  0
                 writeWarning(warning, context, out);
 144  
             }
 145  
         }
 146  
 
 147  
         // evaluate the condition against the current context
 148  0
         if (_macroCondition != null)
 149  0
             boolExpression = Expression.isTrue(_macroCondition
 150  
                     .evaluate(context));
 151  
 
 152  
         // while the expression is true and loopLimit <0 or loopIndex <
 153  
         // loopLimit not exeeded.
 154  0
         while ((boolExpression) && ((loopLimit < 0) || (loopIndex < loopLimit))) {
 155  0
             _whileBlock.write(out, context);
 156  
 
 157  
             // evaluate the condition against the current context.
 158  0
             if (_macroCondition != null)
 159  0
                 boolExpression = Expression.isTrue(_macroCondition
 160  
                         .evaluate(context));
 161  0
             ++loopIndex;
 162  
         }
 163  
 
 164  0
         if (loopIndex >= loopLimit) {
 165  
             // exeeded the limit!
 166  0
             String warning = "#" + _directiveName + ": exeeded the limit of "
 167  
                     + loopLimit;
 168  0
             writeWarning(warning, context, out);
 169  
         }
 170  0
     }
 171  
 
 172  
     public void accept (TemplateVisitor v)
 173  
     {
 174  0
         v.beginDirective(_desc.name);
 175  0
         v.visitDirectiveArg("WhileCondition", _macroCondition);
 176  0
         v.visitDirectiveArg("WhileBlock", _whileBlock);
 177  0
         if (_limitExpr != null)
 178  0
             v.visitDirectiveArg("WhileLimit", _limitExpr);
 179  0
         v.endDirective();
 180  0
     }
 181  
 }
 182