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