5 import freemarker.template.*;
9 import org.apache.struts.util.MessageResources;
11 public class FreemarkerGenerator implements Generator {
12 private Template template;
14 public FreemarkerGenerator(Template aTemplate) {
18 public void generate(PrintWriter anOutputWriter, Map aValues, PrintWriter aLogger) throws GeneratorException {
20 template.process((TemplateModelRoot) makeMapAdapter(aValues), anOutputWriter);
23 aLogger.println("Exception occurred: "+t.getMessage());
24 t.printStackTrace(aLogger);
28 private static TemplateScalarModel makeStringAdapter(String aString) {
29 return new SimpleScalar(aString);
32 private static TemplateHashModel makeMapAdapter(Map aMap) {
33 return new MapAdapter(aMap);
36 private static TemplateListModel makeIteratorAdapter(Iterator anIterator) {
37 return new IteratorAdapter(anIterator);
40 private static TemplateModel makeAdapter(Object anObject) throws TemplateModelException {
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());
58 throw new TemplateModelException("Unadaptable class: " + anObject.getClass().getName());
61 private static class MapAdapter implements TemplateModelRoot {
65 private MapAdapter(Map aMap) {
67 valuesCache = new HashMap();
70 public void put(String aKey, TemplateModel aModel) {
71 valuesCache.put(aKey, aModel);
74 public void remove(String aKey) {
75 // ML: kinda tricky...
78 public boolean isEmpty() {
82 public TemplateModel get(String aKey) throws TemplateModelException {
83 if (!valuesCache.containsKey(aKey)) {
84 Object value = map.get(aKey);
86 // ML: this unfortunately doesn't work, because the entity doesn't seem to store
87 // fields with null values
88 // if (value == null && !map.containsKey(aKey))
89 // throw new TemplateModelException("MapAdapter: no key "+aKey+" available");
91 valuesCache.put(aKey, makeAdapter(value));
94 return (TemplateModel) valuesCache.get(aKey);
98 private static class IteratorAdapter implements TemplateListModel {
103 private IteratorAdapter(Iterator anIterator) {
104 iterator = anIterator;
106 valuesCache = new Vector();
110 if (iterator instanceof RewindableIterator) {
111 ((RewindableIterator) iterator).rewind();
115 public boolean isEmpty() {
116 return valuesCache.isEmpty() && !iterator.hasNext();
119 private void getUntil(int anIndex) throws TemplateModelException {
120 while (valuesCache.size()<=anIndex && iterator.hasNext())
122 valuesCache.add(makeAdapter(iterator.next()));
126 public TemplateModel get(int anIndex) throws TemplateModelException {
127 TemplateModel result;
131 if (anIndex<valuesCache.size())
133 result = (TemplateModel) valuesCache.get(anIndex);
138 throw new TemplateModelException( "Iterator out of bounds" );
141 public boolean hasNext() {
142 return position<valuesCache.size() || iterator.hasNext();
145 public boolean isRewound() {
149 public TemplateModel next() throws TemplateModelException {
150 TemplateModel result;
153 result = get(position);
157 throw new TemplateModelException( "Iterator out of bounds" );
162 public void rewind() {
167 private static class ListAdapter implements TemplateListModel {
172 private ListAdapter(List aList) {
174 valuesCache = new Vector();
178 public boolean isEmpty() {
179 return list.isEmpty();
182 public TemplateModel get(int i) throws TemplateModelException {
184 if (i>=valuesCache.size() && i<list.size()) {
185 for(int j=valuesCache.size(); j<=i; j++) {
186 valuesCache.add(makeAdapter(list.get(j)));
190 if (i<valuesCache.size())
191 return (TemplateModel) valuesCache.get(i);
193 throw new TemplateModelException( "Iterator out of bounds" );
196 public boolean hasNext() {
197 return position<list.size();
200 public boolean isRewound() {
204 public TemplateModel next() throws TemplateModelException {
205 TemplateModel result;
208 result = get(position);
212 throw new TemplateModelException( "Iterator out of bounds" );
217 public void rewind() {
222 /* private static class DateAdapter implements TemplateHashModel {
225 private DateAdapter(Date aDate) {
229 public boolean isEmpty() {
233 public TemplateModel get(String aKey) throws TemplateModelException {
234 return makeAdapter(new SimpleDateFormat(aKey).format(date));