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 if (value == null && !map.containsKey(aKey))
87 throw new TemplateModelException("MapAdapter: no key "+aKey+" available");
89 valuesCache.put(aKey, makeAdapter(value));
92 return (TemplateModel) valuesCache.get(aKey);
96 private static class IteratorAdapter implements TemplateListModel {
101 private IteratorAdapter(Iterator anIterator) {
102 iterator = anIterator;
104 valuesCache = new Vector();
108 if (iterator instanceof RewindableIterator) {
109 ((RewindableIterator) iterator).rewind();
113 public boolean isEmpty() {
114 return valuesCache.isEmpty() && !iterator.hasNext();
117 private void getUntil(int anIndex) throws TemplateModelException {
118 while (valuesCache.size()<=anIndex && iterator.hasNext())
120 valuesCache.add(makeAdapter(iterator.next()));
124 public TemplateModel get(int anIndex) throws TemplateModelException {
125 TemplateModel result;
129 if (anIndex<valuesCache.size())
131 result = (TemplateModel) valuesCache.get(anIndex);
136 throw new TemplateModelException( "Iterator out of bounds" );
139 public boolean hasNext() {
140 return position<valuesCache.size() || iterator.hasNext();
143 public boolean isRewound() {
147 public TemplateModel next() throws TemplateModelException {
148 TemplateModel result;
151 result = get(position);
155 throw new TemplateModelException( "Iterator out of bounds" );
160 public void rewind() {
165 private static class ListAdapter implements TemplateListModel {
170 private ListAdapter(List aList) {
172 valuesCache = new Vector();
176 public boolean isEmpty() {
177 return list.isEmpty();
180 public TemplateModel get(int i) throws TemplateModelException {
182 if (i>=valuesCache.size() && i<list.size()) {
183 for(int j=valuesCache.size(); j<=i; j++) {
184 valuesCache.add(makeAdapter(list.get(j)));
188 if (i<valuesCache.size())
189 return (TemplateModel) valuesCache.get(i);
191 throw new TemplateModelException( "Iterator out of bounds" );
194 public boolean hasNext() {
195 return position<list.size();
198 public boolean isRewound() {
202 public TemplateModel next() throws TemplateModelException {
203 TemplateModel result;
206 result = get(position);
210 throw new TemplateModelException( "Iterator out of bounds" );
215 public void rewind() {