View Javadoc

1   /*
2    * TemplateTool.java
3    *
4    * Created on August 28, 2001, 10:45 PM
5    */
6   
7   package org.webmacro.servlet;
8   
9   import org.webmacro.Context;
10  import org.webmacro.PropertyException;
11  import org.webmacro.Template;
12  import org.webmacro.ContextTool;
13  import org.webmacro.engine.StringTemplate;
14  
15  import java.util.ArrayList;
16  
17  //import java.util.Map;
18  
19  /*** This is an experimental context tool that allows templates
20   * to be used as macros.  The tool places a
21   * MacroTemplateFactory instance into the context that can
22   * be referenced as $Template in WMScript.  The factory has
23   * two methods, each of which returns a MacroTemplate object,
24   * created either from a string or a file.
25   *
26   * @author Keats Kirsch
27   * @version 0.2
28   */
29  public class TemplateTool extends ContextTool
30  {
31  
32      private Context _context = null;
33      /***
34       * flag set when destroy is first called, to prevent subsequent calls from
35       * invoking the destroy() method on the factory object.
36       */
37      private boolean _destroyed = false;
38  
39      /*** Creates new TemplateTool */
40      public TemplateTool ()
41      {
42      }
43  
44      /*** Create a factory object that can be accessed from WMScript as
45       * $Template for creating MacroTemplate objects.
46       * @param c The context of the current request.
47       * @throws PropertyException From the ContextTool interface
48       * @return a new MacroTemplateFactory for each request.
49       */
50      public Object init (Context c) throws PropertyException
51      {
52          _context = c;
53          return new MacroTemplateFactory(c);
54      }
55  
56      /*** A factory class for creating MacroTemplate objects.
57       */
58      public class MacroTemplateFactory
59      {
60  
61          private Context _context;
62          private ArrayList _macros = new ArrayList(10);
63  
64          /*** Constructor
65           * @param ctx the context for the current request
66           */
67          public MacroTemplateFactory (Context ctx)
68          {
69              _context = ctx;
70          }
71  
72          /*** Creates a MacroTemplate from a string with a new context.
73           * @param s the template string
74           * @return the new MacroTemplate
75           */
76          public MacroTemplate fromString (String s)
77          {
78              MacroTemplate mt = new MacroTemplate(_context, s);
79              _macros.add(mt);
80              return mt;
81          }
82  
83          /*** Creates a MacroTemplate from a file reference with a
84           * new context.
85           * @param fileRef a reference to the template file
86           * @throws org.webmacro.ResourceException if the file cannot be found or parsed
87           * @return a new MacroTemplate
88           */
89          public MacroTemplate fromFile (String fileRef)
90                  throws org.webmacro.ResourceException
91          {
92              Template t = (Template) _context.getBroker()
93                      .getProvider("template").get(fileRef);
94              MacroTemplate mt = new MacroTemplate(_context, t);
95              _macros.add(mt);
96              return mt;
97          }
98  
99      }
100 
101     /*** Encapsulates a template and a context, allowing a template
102      * to be used like a function or "macro".
103      */
104     public class MacroTemplate
105     {
106 
107         private Template _template;
108         private Context _context, _origContext;
109 
110         /*** Constructor
111          * @param c the current request context
112          * @param t the template to be used as a macro
113          */
114         public MacroTemplate (Context c, Template t)
115         {
116             _template = t;
117             _origContext = c;
118             // @@@ Just get a new one?
119             _context = c.cloneContext();
120         }
121 
122         /*** Construct a MacroTemplate with a StringTemplate
123          * @param c The context of the current request
124          * @param src the string for the StringTemplate
125          */
126         public MacroTemplate (Context c, String src)
127         {
128             this(c, new StringTemplate(c.getBroker(), src));
129         }
130 
131         /*** Exposes the context of the current MacroTemplate.  This allows
132          * "arguments" to be set from a template.  E.g.,
133          * <CODE>#set $myMacro.Args.Name = $User.Name</CODE>
134          * @return the context of the macro
135          */
136         public Context getArgs ()
137         {
138             return _context;
139         }
140 
141         /*** Evaluates the macro's template against its context and returns the
142          * resulting string.
143          * @throws PropertyException runtime errors in evaluating the macro's template
144          * @return the resultant string after the template is evaluated.
145          */
146         public Object eval () throws PropertyException
147         {
148             synchronized (_context)
149             {
150                 return _template.evaluateAsString(_context);
151             }
152         }
153 
154         public Object eval (Object[] args) throws PropertyException
155         {
156             if (args != null)
157             {
158                 for (int i = 0; i < args.length; i++)
159                 {
160                     _context.put("arg" + (i + 1), args[i]);
161                 }
162                 _context.put("args", args);
163             }
164             return eval();
165         }
166 
167         public Object eval (Object[] args, Object[] names) throws PropertyException
168         {
169             if (args == null || names == null || args.length != names.length)
170                 throw new PropertyException(
171                         "Usage error: both args must be arrays of equal length!");
172             for (int i = 0; i < args.length; i++)
173             {
174                 _context.put(names[i], args[i]);
175             }
176             _context.put("args", args);
177             return eval();
178         }
179 
180         public Object eval (java.util.Map map) throws PropertyException
181         {
182             _context.putAll(map);
183             return eval();
184         }
185 
186         /*** Copies all variables from the current request context into the context
187          * of the macro.
188          */
189         public void copyCurrentContext ()
190         {
191             synchronized (_context)
192             {
193                 _context.putAll(_origContext);
194             }
195         }
196 
197     }
198 }
199