introduced AdapterEntityModel
[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     try {
20                   template.process((TemplateModelRoot) makeMapAdapter(aValues), anOutputWriter);
21     }
22     catch (Throwable t) {
23       aLogger.println("Exception occurred: "+t.getMessage());
24       t.printStackTrace(aLogger);
25     }
26         }
27
28   private static TemplateScalarModel makeStringAdapter(String aString) {
29     return new SimpleScalar(aString);
30   }
31
32   private static TemplateHashModel makeMapAdapter(Map aMap)  {
33     return new MapAdapter(aMap);
34   }
35
36   private static TemplateListModel makeIteratorAdapter(Iterator anIterator) {
37     return new IteratorAdapter(anIterator);
38   }
39
40         private static TemplateModel makeAdapter(Object anObject) throws TemplateModelException {
41           if (anObject == null)
42             return null;
43           if (anObject instanceof TemplateModel)
44             return (TemplateModel) anObject;
45 //        if (anObject instanceof Date)
46 //          return new DateAdapter((Date) anObject);
47           else if (anObject instanceof MessageResources)
48             return new MessageMethodModel((MessageResources) anObject);
49           else if (anObject instanceof String)
50             return makeStringAdapter((String) anObject);
51           else if (anObject instanceof Map)
52             return makeMapAdapter((Map) anObject);
53           else if (anObject instanceof Iterator)
54             return makeIteratorAdapter((Iterator) anObject);
55           else if (anObject instanceof List)
56             return makeIteratorAdapter(((List) anObject).iterator());
57           else
58             throw new TemplateModelException("Unadaptable class: " + anObject.getClass().getName());
59         }
60
61         private static class MapAdapter implements TemplateModelRoot {
62           Map map;
63           Map valuesCache;
64
65           private MapAdapter(Map aMap) {
66             map = aMap;
67             valuesCache = new HashMap();
68           }
69
70           public void put(String aKey, TemplateModel aModel) {
71             valuesCache.put(aKey, aModel);
72           }
73
74           public void remove(String aKey) {
75             // ML: kinda tricky...
76           }
77
78           public boolean isEmpty() {
79             return map.isEmpty();
80           }
81
82           public TemplateModel get(String aKey) throws TemplateModelException {
83             if (!valuesCache.containsKey(aKey)) {
84               Object value = map.get(aKey);
85
86       if (value == null && !map.containsKey(aKey))
87           throw new TemplateModelException("MapAdapter: no key "+aKey+" available");
88
89               valuesCache.put(aKey, makeAdapter(value));
90             }
91
92             return (TemplateModel) valuesCache.get(aKey);
93           }
94         }
95
96         private static class IteratorAdapter implements TemplateListModel {
97           Iterator iterator;
98           List valuesCache;
99           int position;
100
101           private IteratorAdapter(Iterator anIterator) {
102             iterator = anIterator;
103
104             valuesCache = new Vector();
105             position=0;
106
107
108             if (iterator instanceof RewindableIterator) {
109               ((RewindableIterator) iterator).rewind();
110             }
111           }
112
113           public boolean isEmpty() {
114             return valuesCache.isEmpty() && !iterator.hasNext();
115           }
116
117           private void getUntil(int anIndex) throws TemplateModelException {
118             while (valuesCache.size()<=anIndex && iterator.hasNext())
119             {
120               valuesCache.add(makeAdapter(iterator.next()));
121             }
122           };
123
124           public TemplateModel get(int anIndex) throws TemplateModelException {
125             TemplateModel result;
126
127             getUntil(anIndex);
128
129             if (anIndex<valuesCache.size())
130             {
131               result = (TemplateModel) valuesCache.get(anIndex);
132
133               return result;
134             }
135             else
136               throw new TemplateModelException( "Iterator out of bounds" );
137           }
138
139     public boolean hasNext() {
140       return position<valuesCache.size() || iterator.hasNext();
141     }
142
143     public boolean isRewound() {
144       return position==0;
145     }
146
147     public TemplateModel next() throws TemplateModelException {
148       TemplateModel result;
149
150       if (hasNext()) {
151         result = get(position);
152         position++;
153       }
154       else
155               throw new TemplateModelException( "Iterator out of bounds" );
156
157       return result;
158     }
159
160     public void rewind() {
161       position=0;
162     }
163         }
164
165         private static class ListAdapter implements TemplateListModel {
166           List list;
167           List valuesCache;
168           int position;
169
170           private ListAdapter(List aList) {
171             list = aList;
172             valuesCache = new Vector();
173             position=0;
174           }
175
176           public boolean isEmpty() {
177             return list.isEmpty();
178           }
179
180           public TemplateModel get(int i) throws TemplateModelException {
181
182             if (i>=valuesCache.size() && i<list.size()) {
183               for(int j=valuesCache.size(); j<=i; j++) {
184                 valuesCache.add(makeAdapter(list.get(j)));
185               }
186             }
187
188             if (i<valuesCache.size())
189               return (TemplateModel) valuesCache.get(i);
190             else
191               throw new TemplateModelException( "Iterator out of bounds" );
192           }
193
194     public boolean hasNext() {
195       return position<list.size();
196     }
197
198     public boolean isRewound() {
199       return position==0;
200     }
201
202     public TemplateModel next() throws TemplateModelException {
203       TemplateModel result;
204
205       if (hasNext()) {
206         result = get(position);
207         position++;
208       }
209             else
210               throw new TemplateModelException( "Iterator out of bounds" );
211
212       return result;
213     }
214
215     public void rewind() {
216       position=0;
217     }
218         }
219 }