001: /*
002: * Copyright 2007 Frank W. Zammetti
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package com.omnytex;
018:
019: import freemarker.cache.ClassTemplateLoader;
020: import freemarker.template.Configuration;
021: import freemarker.template.DefaultObjectWrapper;
022: import freemarker.template.Template;
023: import java.io.StringWriter;
024: import java.io.Writer;
025: import java.util.HashMap;
026: import java.util.Iterator;
027: import java.util.Map;
028: import org.apache.commons.logging.Log;
029: import org.apache.commons.logging.LogFactory;
030:
031: /**
032: * The Freemarker class is a class you remote with DWR which accepts input
033: * data, and the name of a Freemarker template, and it generates output using
034: * that template and data. To use it, add this to your dwr.xml file:
035: * <br><br>
036: * <allow><br>
037: * ...<br>
038: * <convert converter="bean" match="com.omnytex.FreemarkerData"
039: * /><br>
040: * <create creator="new" javascript="Freemarker"><br>
041: * <param name="class" value="com.omnytex.Freemarker"
042: * /><br>
043: * </create><br>
044: * ...<br>
045: * </allow><br>
046: * <signatures><br>
047: * <![CDATA[<br>
048: * import java.util.Map;<br>
049: * import com.omnytex.FreemarkerData;<br>
050: * FreemarkerData.setMapData(final Map<String, Map>
051: * inMapData);<br>
052: * ]]><br>
053: * </signatures><br>
054: * <br><br>
055: * Then, call it using this form:
056: * <br><br>
057: * var d =
058: * { template : "aaaaa",
059: * rootData : { bbbbb : ccccc, ... },
060: * mapData : {
061: * xxxxx : { yyyyy : "zzzzz", ... }, ...
062: * }
063: * };
064: * Freemarker.run(d, callback );
065: * <br><br>
066: * Where:
067: * <br>
068: * <ul>
069: * <li><b>aaaaa</b> is the fully-qualified name of the Freemarker template to
070: * execute. This template must be in the classpath, and you must use slashes
071: * to specify it rather than dot notation. For example: com/omnytex/test/ftl
072: * </li>
073: * <li><b>bbbbb</b> is zero or more data elements to be placed at the root of
074: * the Freemarker data model (<b>ccccc</b> is the value of the element)
075: * </li>
076: * <li>xxxxx</b> is the key for zero or more Map elements to be inserted into
077: * the Freemarker data model (<b>yyyyy</b> is the key of an alement in the Map,
078: * and <b>zzzzz</b> is the value fo that element)
079: * </li>
080: * </ul>
081: * If you are unfamiliar with the Freemarker data model, please read the
082: * Freemarker documentation. But, in short, it is a tree structure with leaves
083: * directly off the root, and/or a collection of Maps off the root.
084: *
085: * @author <a href="mailto:fzammetti@omnytex.com">Frank W. Zammetti</a>
086: */
087: public class Freemarker {
088:
089: /**
090: * Log instance.
091: */
092: private static Log log = LogFactory.getLog(Freemarker.class);
093:
094: /**
095: * The run() is called to execute a Freemarker template.
096: *
097: * @param inData The FreemarkerData object populated from the incoming
098: * data from the client.
099: * @return The results of executing the template.
100: * @throws Exception If anything goes wrong.
101: */
102: public String run(FreemarkerData inData) throws Exception {
103:
104: log.trace("Freemarker.run() entry");
105:
106: if (log.isDebugEnabled()) {
107: log.debug(("inData = " + inData));
108: }
109:
110: // Create our data model.
111: Map root = new HashMap();
112:
113: // First, iterate over the data that will go directly into the root and
114: // insert it now.
115: Map rootData = inData.getRootData();
116: for (Iterator it = rootData.keySet().iterator(); it.hasNext();) {
117: String nextKey = (String) it.next();
118: root.put(nextKey, rootData.get(nextKey));
119: }
120: if (log.isDebugEnabled()) {
121: log.debug(("root = " + root));
122: }
123:
124: // Next, iterate over the data that consists of Maps and insert it all
125: // into the root.
126: Map mapData = inData.getMapData();
127: for (Iterator it = mapData.keySet().iterator(); it.hasNext();) {
128: String nextKey = (String) it.next();
129: root.put(nextKey, mapData.get(nextKey));
130: }
131: if (log.isDebugEnabled()) {
132: log.debug(("root = " + root));
133: }
134:
135: // Set up Freemarker.
136: Configuration fmConfig = new Configuration();
137: fmConfig.setObjectWrapper(new DefaultObjectWrapper());
138: fmConfig.setTemplateLoader(new ClassTemplateLoader(
139: new Freemarker().getClass(), "/"));
140:
141: // Read in the Freemarker template specified.
142: Template template = null;
143: try {
144: template = fmConfig.getTemplate(inData.getTemplate());
145: } catch (Exception e) {
146: log
147: .error("Could not load Freemarker template "
148: + inData.getTemplate()
149: + "... is it in the classpath in the "
150: + "expected location? Is the template value passed in "
151: + "fully-qualified? (Error: " + e);
152: return "error";
153: }
154:
155: // Generate the output.
156: Writer out = new StringWriter();
157: template.process(root, out);
158: out.flush();
159: if (log.isDebugEnabled()) {
160: log.debug("Generated output = " + out);
161: }
162:
163: // Return output.
164: log.trace("Freemarker.run() exit");
165: return out.toString();
166:
167: } // End run().
168:
169: } // End class.
|