some small changes delting unneeded imports. two new exceptions in mir.storage. usage...
[mir.git] / source / mir / misc / HTMLTemplateProcessor.java
1 /*\r
2  * Copyright (C) 2001, 2002  The Mir-coders group\r
3  *\r
4  * This file is part of Mir.\r
5  *\r
6  * Mir is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 2 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * Mir is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with Mir; if not, write to the Free Software\r
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19  *\r
20  * In addition, as a special exception, The Mir-coders gives permission to link\r
21  * the code of this program with the com.oreilly.servlet library, any library\r
22  * licensed under the Apache Software License, The Sun (tm) Java Advanced\r
23  * Imaging library (JAI), The Sun JIMI library (or with modified versions of\r
24  * the above that use the same license as the above), and distribute linked\r
25  * combinations including the two.  You must obey the GNU General Public\r
26  * License in all respects for all of the code used other than the above\r
27  * mentioned libraries.  If you modify this file, you may extend this exception\r
28  * to your version of the file, but you are not obligated to do so.  If you do\r
29  * not wish to do so, delete this exception statement from your version.\r
30  */\r
31 \r
32 package mir.misc;\r
33 \r
34 import freemarker.template.*;\r
35 import mir.util.*;\r
36 import mir.generator.*;\r
37 import mir.config.MirPropertiesConfiguration;\r
38 import mir.config.MirPropertiesConfiguration.PropertiesConfigExc;\r
39 import mir.entity.Entity;\r
40 import mir.entity.EntityList;\r
41 import mir.storage.StorageObjectFailure;\r
42 import org.apache.struts.util.MessageResources;\r
43 \r
44 import javax.servlet.http.HttpServletResponse;\r
45 import java.io.PrintWriter;\r
46 import java.net.URLEncoder;\r
47 import java.util.*;\r
48 \r
49 \r
50 /**\r
51  * Hilfsklasse zum Mergen von Template und Daten\r
52  */\r
53 public final class HTMLTemplateProcessor {\r
54 \r
55   public static String templateDir;\r
56   private static MirPropertiesConfiguration configuration;\r
57   private static FileTemplateCache templateCache;\r
58   private static Logfile theLog;\r
59   private static String docRoot;\r
60   private static String actionRoot;\r
61 \r
62   static {\r
63     try {\r
64       configuration = MirPropertiesConfiguration.instance();\r
65     } catch (PropertiesConfigExc e) {\r
66       e.printStackTrace();\r
67     }\r
68     theLog = Logfile.getInstance(\r
69       configuration.getStringWithHome("HTMLTemplateProcessor.Logfile"));\r
70     templateDir = \r
71         configuration.getStringWithHome("HTMLTemplateProcessor.Dir");\r
72     theLog.printDebugInfo("templateDir: " + templateDir);\r
73     templateCache = new FileTemplateCache(templateDir);\r
74     templateCache.setLoadingPolicy(FileTemplateCache.LOAD_ON_DEMAND);\r
75     // gone in freemarker 1.7.1: templateCache.startAutoUpdate();\r
76 \r
77 \r
78     docRoot = configuration.getString("RootUri");\r
79     try {\r
80       actionRoot = docRoot +configuration.getString("Producer.ActionServlet");\r
81     }\r
82     catch (ConfigException ce) {\r
83       // if  Producer.ActionServlet is not set in the conf file\r
84       actionRoot = docRoot + "/Mir";\r
85     }\r
86   }\r
87 \r
88   /**\r
89    * empty private constructor, to avoid instantiation\r
90    */\r
91   private HTMLTemplateProcessor() {\r
92   }\r
93 \r
94   // process-methods to merge different datastructures\r
95   // with freemarker templates\r
96 \r
97   /**\r
98        * Wandelt <code>anEntity</code> in freemarker-Struktur um, mischt die Daten mit\r
99    * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter\r
100    * <code>out</code>\r
101    *\r
102    * @param templateFilename\r
103    * @param anEntity\r
104    * @param out\r
105    * @exception HTMLParseException\r
106    */\r
107 \r
108   public static void process(String templateFilename, Entity anEntity,\r
109                              PrintWriter out) throws HTMLParseException {\r
110     if (anEntity == null)\r
111       throw new HTMLParseException("entity is empty!");\r
112     else\r
113       process(templateFilename, anEntity, out);\r
114   }\r
115 \r
116   /**\r
117    * Wandelt Liste mit Entities <code>entList</code> in freemarker-Struktur um, mischt die Daten mit\r
118    * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter\r
119    * <code>out</code>\r
120    *\r
121    * @param templateFilename\r
122    * @param entList\r
123    * @param out\r
124    * @exception HTMLParseException\r
125    */\r
126   public static void process(HttpServletResponse res, String templateFilename,\r
127    EntityList entList, PrintWriter out, Locale locale) throws HTMLParseException {\r
128     process(res, templateFilename, entList, (String)null, (TemplateModelRoot)null,\r
129             out, locale);\r
130   }\r
131 \r
132   /**\r
133    * Wandelt Entitylist in freemarker-Struktur um, f?gt <code>additionalModel</code>\r
134        * unter dem Namen <code>additionalModelName</code> ein und mischt die Daten mit\r
135    * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter\r
136    * <code>out</code>\r
137    *\r
138    * @param templateFilename\r
139    * @param entList\r
140    * @param additionalModelName\r
141    * @param additionalModel\r
142    * @param out\r
143    * @exception HTMLParseException\r
144    */\r
145 \r
146   public static void process(HttpServletResponse res, String templateFilename,\r
147                              EntityList entList, String additionalModelName,\r
148                              TemplateModelRoot additionalModel, PrintWriter out,\r
149                              Locale locale) throws HTMLParseException {\r
150 \r
151     SimpleHash modelRoot = new SimpleHash();\r
152 \r
153     if (entList == null) {\r
154       process(null, templateFilename, modelRoot, out, locale);\r
155     }\r
156     else {\r
157       try {\r
158         modelRoot = makeSimpleHashWithEntitylistInfos(entList);\r
159 \r
160         // Quickhack um mal ein Popup mit reinzunhemen ..\r
161         if (additionalModelName != null && additionalModel != null)\r
162           modelRoot.put(additionalModelName, additionalModel);\r
163 \r
164         process(res, templateFilename, modelRoot, out, locale);\r
165       }\r
166       catch (StorageObjectFailure e) {\r
167         throw new HTMLParseException(e.toString());\r
168       }\r
169     }\r
170   }\r
171 \r
172 \r
173   /**\r
174    * Gibt Template <code>templateFilename</code> an den PrintWriter\r
175    * <code>out</code>\r
176    *\r
177    * @param templateFilename\r
178    * @param mergeData\r
179    * @param out\r
180    * @exception HTMLParseException\r
181    */\r
182   public static void process(String templateFilename, PrintWriter out,\r
183                              Locale locale) throws HTMLParseException {\r
184     process(null, templateFilename, (TemplateModelRoot)null, out, locale);\r
185   }\r
186 \r
187   /**\r
188    * Mischt die freemarker-Struktur <code>tmr</code> mit\r
189    * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter\r
190    * <code>out</code>\r
191    *\r
192    * @param templateFilename\r
193    * @param mergeData\r
194    * @param out\r
195    * @exception HTMLParseException\r
196    */\r
197   public static void process(HttpServletResponse res, String templateFilename,\r
198                              TemplateModelRoot tmr, PrintWriter out,\r
199                              Locale locale) throws HTMLParseException {\r
200     process(res, templateFilename, tmr, null, out, locale);\r
201   }\r
202 \r
203   public static void process(HttpServletResponse res, String templateFilename,\r
204                              TemplateModelRoot tmr, TemplateModelRoot extra,\r
205                              PrintWriter out, Locale locale) throws HTMLParseException {\r
206     process(res, templateFilename, tmr, extra, out, locale, "bundles.adminlocal", "bundles.admin");\r
207   }\r
208 \r
209   public static void process(HttpServletResponse res, String templateFilename,\r
210        TemplateModelRoot tmr, TemplateModelRoot extra, PrintWriter out,\r
211        Locale locale, String bundles) throws HTMLParseException {\r
212     process(res, templateFilename, tmr, extra, out, locale, bundles, null);\r
213   }\r
214 \r
215   /**\r
216    * Mischt die freemarker-Struktur <code>tmr</code> mit\r
217    * Template <code>templateFilename</code> und gibt das Ergebnis an den PrintWriter\r
218    * <code>out</code>\r
219    *\r
220    * @param templateFilename\r
221    * @param mergeData\r
222    * @param out\r
223    * @exception HTMLParseException\r
224    */\r
225   public static void process(HttpServletResponse res, String templateFilename,\r
226                              TemplateModelRoot tmr, TemplateModelRoot extra,\r
227                              PrintWriter out, Locale locale, String bundles,\r
228                              String bundles2) throws\r
229       HTMLParseException {\r
230     if (out == null)\r
231       throw new HTMLParseException("no outputstream");\r
232     Template tmpl = getTemplateFor(templateFilename);\r
233     if (tmpl == null)\r
234       throw new HTMLParseException("no template: " + templateFilename);\r
235     if (tmr == null)\r
236       tmr = new SimpleHash();\r
237 \r
238       /** @todo  what is this for? (rk) */\r
239     String session = "";\r
240     if (res != null) {\r
241       session = res.encodeURL("");\r
242     }\r
243 \r
244     SimpleHash configHash = new SimpleHash();\r
245 \r
246     // pass the whole config hash to the templates\r
247     Iterator it = configuration.getKeys();\r
248     String key;\r
249     while (it.hasNext()) {\r
250       key = (String) it.next();\r
251       configHash.put(key, new SimpleScalar(\r
252         configuration.getString(key))\r
253       );\r
254     }\r
255 \r
256     // this does not come directly from the config file\r
257     configHash.put("docRoot", new SimpleScalar(docRoot));\r
258     configHash.put("actionRoot", new SimpleScalar(actionRoot + session));\r
259     configHash.put("now",\r
260                    new SimpleScalar(StringUtil.date2readableDateTime(new GregorianCalendar())));\r
261 \r
262     // this conform to updated freemarker syntax\r
263     configHash.put("compressWhitespace",\r
264                    new freemarker.template.utility.CompressWhitespace());\r
265 \r
266     SimpleHash utilityHash = new SimpleHash();\r
267     try {\r
268       utilityHash.put("compressWhitespace",\r
269                       new freemarker.template.utility.CompressWhitespace());\r
270       utilityHash.put("encodeURI",\r
271                       FreemarkerGenerator.makeAdapter(new GeneratorHTMLFunctions.\r
272           encodeURIGeneratorFunction()));\r
273       utilityHash.put("encodeHTML",\r
274                       FreemarkerGenerator.makeAdapter(new GeneratorHTMLFunctions.\r
275           encodeHTMLGeneratorFunction()));\r
276       utilityHash.put("isOdd",\r
277                       FreemarkerGenerator.makeAdapter(new GeneratorIntegerFunctions.\r
278           isOddFunction()));\r
279       utilityHash.put("increment",\r
280                       FreemarkerGenerator.makeAdapter(new GeneratorIntegerFunctions.\r
281           incrementFunction()));\r
282     }\r
283     catch (Throwable t) {\r
284       throw new HTMLParseException(t.getMessage());\r
285     }\r
286 \r
287     SimpleHash outPutHash = new SimpleHash();\r
288 \r
289     if (extra != null) {\r
290       outPutHash.put("extra", extra);\r
291       try {\r
292         while ( ( (SimpleList) extra).hasNext()) {\r
293           theLog.printDebugInfo( ( (SimpleList) extra).next().toString());\r
294         }\r
295       }\r
296       catch (Exception e) {\r
297       }\r
298     }\r
299     outPutHash.put("data", tmr);\r
300     outPutHash.put("config", configHash);\r
301     outPutHash.put("utility", utilityHash);\r
302 \r
303     MessageResources messages = MessageResources.getMessageResources(bundles);\r
304     if (bundles2!=null) {\r
305       outPutHash.put("lang", new MessageMethodModel(locale, MessageResources.getMessageResources(bundles), MessageResources.getMessageResources(bundles2)));\r
306     }\r
307     else {\r
308       outPutHash.put("lang", new MessageMethodModel(locale, MessageResources.getMessageResources(bundles)));\r
309     }\r
310 \r
311     tmpl.process(outPutHash, out);\r
312   }\r
313 \r
314   /**\r
315    *   Converts Entity-List to SimpleList of SimpleHashes.\r
316    *   @param aList ist eine Liste von Entity\r
317    *   @return eine freemarker.template.SimpleList von SimpleHashes.\r
318    *\r
319    *    @deprecated EntityLists comply with TemplateListModel now.\r
320    */\r
321   public static SimpleList makeSimpleList(EntityList aList) throws\r
322       StorageObjectFailure {\r
323     theLog.printWarning(\r
324         "## using deprecated makeSimpleList(entityList) - a waste of resources");\r
325     SimpleList simpleList = new SimpleList();\r
326     if (aList != null) {\r
327       for (int i = 0; i < aList.size(); i++) {\r
328         simpleList.add(aList.elementAt(i));\r
329       }\r
330     }\r
331     return simpleList;\r
332   }\r
333 \r
334   /**\r
335    *  Konvertiert ein EntityList in ein freemarker.template.SimpleHash-Modell. Im Hash\r
336    *  sind die einzelnen Entities ueber ihre id zu erreichen.\r
337    *  @param aList ist die EntityList\r
338    *  @return SimpleHash mit den entsprechenden freemarker Daten\r
339    *\r
340    */\r
341   public static SimpleHash makeSimpleHash(EntityList aList) throws\r
342       StorageObjectFailure {\r
343     SimpleHash simpleHash = new SimpleHash();\r
344     Entity currentEntity;\r
345 \r
346     if (aList != null) {\r
347       for (int i = 0; i < aList.size(); i++) {\r
348         currentEntity = (Entity) aList.elementAt(i);\r
349         simpleHash.put(currentEntity.getId(), currentEntity);\r
350       }\r
351     }\r
352     return simpleHash;\r
353   }\r
354 \r
355   /**\r
356    *  Konvertiert ein Hashtable mit den keys und values als String\r
357    *  in ein freemarker.template.SimpleHash-Modell\r
358    *  @param mergeData der HashMap mit den String / String Daten\r
359    *  @return SimpleHash mit den entsprechenden freemarker Daten\r
360    *\r
361    */\r
362   public static SimpleHash makeSimpleHash(HashMap mergeData) {\r
363     SimpleHash modelRoot = new SimpleHash();\r
364     String aField;\r
365     if (mergeData != null) {\r
366       Set set = mergeData.keySet();\r
367       Iterator it = set.iterator();\r
368       for (int i = 0; i < set.size(); i++) {\r
369         aField = (String) it.next();\r
370         modelRoot.put(aField, (String) mergeData.get(aField));\r
371       }\r
372     }\r
373     return modelRoot;\r
374   }\r
375 \r
376   /**\r
377    * Converts EntityList in SimpleHash and adds additional information\r
378    * to the returned SimpleHash\r
379    *\r
380    * @param entList\r
381    * @return SimpleHash returns SimpleHash with the converted EntityList plus\r
382    *        additional Data about the list.\r
383    * @exception StorageObjectException\r
384    */\r
385 \r
386   public static SimpleHash makeSimpleHashWithEntitylistInfos(EntityList entList) throws\r
387       StorageObjectFailure {\r
388     SimpleHash modelRoot = new SimpleHash();\r
389     if (entList != null) {\r
390       modelRoot.put("contentlist", entList);\r
391       modelRoot.put("count",\r
392                     new SimpleScalar( (new Integer(entList.getCount())).toString()));\r
393       if (entList.getWhere() != null) {\r
394         modelRoot.put("where", new SimpleScalar(entList.getWhere()));\r
395         modelRoot.put("where_encoded",\r
396                       new SimpleScalar(URLEncoder.encode(entList.getWhere())));\r
397       }\r
398       if (entList.getOrder() != null) {\r
399         modelRoot.put("order", new SimpleScalar(entList.getOrder()));\r
400         modelRoot.put("order_encoded",\r
401                       new SimpleScalar(URLEncoder.encode(entList.getOrder())));\r
402       }\r
403       modelRoot.put("from",\r
404                     new SimpleScalar( (new Integer(entList.getFrom())).toString()));\r
405       modelRoot.put("to",\r
406                     new SimpleScalar( (new Integer(entList.getTo())).toString()));\r
407 \r
408       if (entList.hasNextBatch())\r
409         modelRoot.put("next",\r
410                       new SimpleScalar( (new Integer(entList.getNextBatch())).\r
411                                        toString()));\r
412       if (entList.hasPrevBatch())\r
413         modelRoot.put("prev",\r
414                       new SimpleScalar( (new Integer(entList.getPrevBatch())).\r
415                                        toString()));\r
416     }\r
417     return modelRoot;\r
418   }\r
419 \r
420   /**\r
421    * Private methods to get template from a templateFilename\r
422    * @param templateFilename\r
423    * @return Template\r
424    * @exception HTMLParseException\r
425    */\r
426   private static Template getTemplateFor(String templateFilename) throws\r
427       HTMLParseException {\r
428     Template returnTemplate = null;\r
429     if (templateFilename != null)\r
430       returnTemplate = (Template) templateCache.getItem(templateFilename,\r
431           "template");\r
432 \r
433     if (returnTemplate == null) {\r
434       theLog.printError("CACHE (ERR): Unknown template: " + templateFilename);\r
435       throw new HTMLParseException("Templatefile: " + templateFilename +\r
436                                    " not found.");\r
437     }\r
438 \r
439     return returnTemplate;\r
440   }\r
441 \r
442   public static void stopAutoUpdate() {\r
443     templateCache.stopAutoUpdate();\r
444     templateCache = null;\r
445   }\r
446 \r
447 }