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