##### Coverage Report - org.webmacro.directive.WhileDirective

Classes in this File | Line Coverage | Branch Coverage | Complexity
WhileDirective |
0% | 0/44
0% | 0/26
| 4.5;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 |  |