4329ee0b24a3b7825d60b1a4428aa89bb5fb089a
[mir.git] / source / mir / generator / FreemarkerGenerator.java
1 package mir.generator;
2
3 import java.util.*;
4 import java.io.*;
5 import freemarker.template.*;
6 import mir.entity.*;
7 import mir.util.*;
8 import mir.misc.*;
9 import org.apache.struts.util.MessageResources;
10
11 public class FreemarkerGenerator implements Generator {
12   private Template template;
13
14   public FreemarkerGenerator(Template aTemplate) {
15     template = aTemplate;
16   }
17
18   public void generate(PrintWriter anOutputWriter, Map aValues, PrintWriter aLogger) throws GeneratorException {
19     aLogger.println("processing...<br/>");
20                 template.process((TemplateModelRoot) makeMapAdapter(aValues), anOutputWriter);
21     aLogger.println("processed...<br/>");
22         }
23
24   private static TemplateScalarModel makeStringAdapter(String aString) {
25     return new SimpleScalar(aString);
26   }
27
28   private static TemplateHashModel makeMapAdapter(Map aMap)  {
29     return new MapAdapter(aMap);
30   }
31
32   private static TemplateListModel makeIteratorAdapter(Iterator anIterator) {
33     return new IteratorAdapter(anIterator);
34   }
35
36         private static TemplateModel makeAdapter(Object anObject) throws TemplateModelException {
37           if (anObject == null)
38             return null;
39           if (anObject instanceof TemplateModel)
40             return (TemplateModel) anObject;
41 //        if (anObject instanceof Date)
42 //          return new DateAdapter((Date) anObject);
43           else if (anObject instanceof MessageResources)
44             return new MessageMethodModel((MessageResources) anObject);
45           else if (anObject instanceof String)
46             return makeStringAdapter((String) anObject);
47           else if (anObject instanceof Map)
48             return makeMapAdapter((Map) anObject);
49           else if (anObject instanceof Iterator)
50             return makeIteratorAdapter((Iterator) anObject);
51           else if (anObject instanceof List)
52             return makeIteratorAdapter(((List) anObject).iterator());
53           else
54             throw new TemplateModelException("Unadaptable class: " + anObject.getClass().getName());
55         }
56
57         private static class MapAdapter implements TemplateModelRoot {
58           Map map;
59           Map valuesCache;
60
61           private MapAdapter(Map aMap) {
62             map = aMap;
63             valuesCache = new HashMap();
64           }
65
66           public void put(String aKey, TemplateModel aModel) {
67             valuesCache.put(aKey, aModel);
68           }
69
70           public void remove(String aKey) {
71             // ML: kinda tricky...
72           }
73
74           public boolean isEmpty() {
75             return map.isEmpty();
76           }
77
78           public TemplateModel get(String aKey) throws TemplateModelException {
79             if (!valuesCache.containsKey(aKey)) {
80               Object value = map.get(aKey);
81
82 //    ML: this unfortunately doesn't work, because the entity doesn't seem to store
83 //        fields with null values
84 //    if (value == null && !map.containsKey(aKey))
85 //          throw new TemplateModelException("MapAdapter: no key "+aKey+" available");
86
87               valuesCache.put(aKey, makeAdapter(value));
88             }
89
90             return (TemplateModel) valuesCache.get(aKey);
91           }
92         }
93
94         private static class IteratorAdapter implements TemplateListModel {
95           Iterator iterator;
96           List valuesCache;
97           int position;
98
99           private IteratorAdapter(Iterator anIterator) {
100             iterator = anIterator;
101
102             valuesCache = new Vector();
103             position=0;
104
105
106             if (iterator instanceof RewindableIterator) {
107               ((RewindableIterator) iterator).rewind();
108             }
109           }
110
111           public boolean isEmpty() {
112             return valuesCache.isEmpty() && !iterator.hasNext();
113           }
114
115           private void getUntil(int anIndex) throws TemplateModelException {
116             while (valuesCache.size()<=anIndex && iterator.hasNext())
117             {
118               valuesCache.add(makeAdapter(iterator.next()));
119             }
120           };
121
122           public TemplateModel get(int anIndex) throws TemplateModelException {
123             TemplateModel result;
124
125             getUntil(anIndex);
126
127             if (anIndex<valuesCache.size())
128             {
129               result = (TemplateModel) valuesCache.get(anIndex);
130
131               return result;
132             }
133             else
134               throw new TemplateModelException( "Iterator out of bounds" );
135           }
136
137     public boolean hasNext() {
138       return position<valuesCache.size() || iterator.hasNext();
139     }
140
141     public boolean isRewound() {
142       return position==0;
143     }
144
145     public TemplateModel next() throws TemplateModelException {
146       TemplateModel result;
147
148       if (hasNext()) {
149         result = get(position);
150         position++;
151       }
152       else
153               throw new TemplateModelException( "Iterator out of bounds" );
154
155       return result;
156     }
157
158     public void rewind() {
159       position=0;
160     }
161         }
162
163         private static class ListAdapter implements TemplateListModel {
164           List list;
165           List valuesCache;
166           int position;
167
168           private ListAdapter(List aList) {
169             list = aList;
170             valuesCache = new Vector();
171             position=0;
172           }
173
174           public boolean isEmpty() {
175             return list.isEmpty();
176           }
177
178           public TemplateModel get(int i) throws TemplateModelException {
179
180             if (i>=valuesCache.size() && i<list.size()) {
181               for(int j=valuesCache.size(); j<=i; j++) {
182                 valuesCache.add(makeAdapter(list.get(j)));
183               }
184             }
185
186             if (i<valuesCache.size())
187               return (TemplateModel) valuesCache.get(i);
188             else
189               throw new TemplateModelException( "Iterator out of bounds" );
190           }
191
192     public boolean hasNext() {
193       return position<list.size();
194     }
195
196     public boolean isRewound() {
197       return position==0;
198     }
199
200     public TemplateModel next() throws TemplateModelException {
201       TemplateModel result;
202
203       if (hasNext()) {
204         result = get(position);
205         position++;
206       }
207             else
208               throw new TemplateModelException( "Iterator out of bounds" );
209
210       return result;
211     }
212
213     public void rewind() {
214       position=0;
215     }
216         }
217
218 /*      private static class DateAdapter implements TemplateHashModel {
219           Date date;
220
221           private DateAdapter(Date aDate) {
222             date = aDate;
223           }
224
225           public boolean isEmpty() {
226             return false;
227           }
228
229           public TemplateModel get(String aKey) throws TemplateModelException {
230             return makeAdapter(new SimpleDateFormat(aKey).format(date));
231           }
232         }
233 */
234 }