001 /* sillyview : a free model-view-controller system for Java
002 * Copyright (C) 2004 T.J. Willis
003 *
004 * This program is free software; you can redistribute it and/or
005 * modify it under the terms of the GNU General Public License
006 * as published by the Free Software Foundation; either version 2
007 * of the License, or (at your option) any later version.
008 *
009 * This program is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012 * GNU General Public License for more details.
013 *
014 * You should have received a copy of the GNU General Public License
015 * along with this program; if not, write to the Free Software
016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
017 *
018 * $Header: /cvsroot/sillyview/sillyview/src/net/sourceforge/sillyview/VelocityModel.java,v 1.2 2004/05/15 01:58:51 tj_willis Exp $
019 */
020 package net.sourceforge.sillyview;
021
022 import java.io.*;
023 import java.net.*;
024 import java.util.Hashtable;
025 import java.util.regex.*;
026 import javax.swing.*;
027 import javax.swing.border.*;
028
029 import org.apache.velocity.Template;
030 import org.apache.velocity.VelocityContext;
031 import org.apache.velocity.app.Velocity;
032 import org.apache.velocity.exception.ParseErrorException;
033 import org.apache.velocity.exception.ResourceNotFoundException;
034 import org.apache.velocity.exception.ParseErrorException;
035 import org.apache.velocity.exception.MethodInvocationException;
036
037 import org.apache.log4j.*;
038
039 /**
040 * Creates a WidgetModel backed by a Velocity Template.
041 *
042 * @author <a href="mailto:tj_willis@users.sourceforge.net">T.J. Willis</a>
043 * @version 1.0
044 */
045 public class VelocityModel implements WidgetModel {
046 private static Category cat
047 = Category.getInstance(VelocityModel.class.getName());
048
049 /**
050 * The VelocityContext to which tokens are delegated.
051 *
052 */
053 protected VelocityContext context;
054 /**
055 * The raw velocity template.
056 *
057 */
058 protected String template;
059
060 /**
061 * Initializes velocity and creates a new context.
062 */
063 private void init ()
064 throws java.lang.Exception
065 {
066 Velocity.init ();
067 context = new VelocityContext ();
068 template = null;
069 }
070
071 /**
072 * Initializes Velocity, creates a new context, and sets this model's
073 * template to the file at the given URL.
074 *
075 * @param templateURL an <code>URL</code> value
076 * @exception IOException if an error occurs
077 * @exception Exception if an error occurs
078 */
079 public VelocityModel (URL templateURL) throws IOException, Exception {
080 init ();
081 template = getTemplate(templateURL);
082 }
083
084 private String getTemplate(URL templateURL) throws IOException, Exception {
085 StringBuffer cont = new StringBuffer ();
086
087 InputStream is = templateURL.openStream ();
088 InputStreamReader isr = new InputStreamReader (is);
089 BufferedReader in = new BufferedReader (isr);
090 String foo = in.readLine ();
091 while (foo != null) {
092 cont.append (foo).append ("\n"); // += foo +"\n";
093 foo = in.readLine ();
094 }
095 //is.flush();
096 is.close();
097 return cont.toString ();
098 }
099
100
101 /**
102 * Allows several models to share a context. Assumes that
103 * Velocity.init() has already been called.
104 * @param context a <code>VelocityContext</code> value
105 * @param templateURL an <code>URL</code> value
106 * @exception IOException if an error occurs
107 * @exception Exception if an error occurs
108 */
109 public VelocityModel(VelocityContext context, URL templateURL)
110 throws IOException, Exception
111 {
112 this.context = context;
113 template = getTemplate(templateURL);
114 }
115
116 /**
117 * Creates a new <code>VelocityModel</code> instance with the
118 * given String as its template.
119 *
120 * @param templateString a <code>String</code> value
121 * @exception Exception if an error occurs
122 */
123 public VelocityModel (final String templateString)
124 throws Exception
125 {
126 init ();
127 template = templateString;
128 }
129
130 /**
131 * Returns the current model as a String.
132 *
133 * @return an <code>Object</code> value
134 */
135 public Object getCurrentModel () {
136 return this.toString ();
137 }
138
139 /**
140 * Returns the template without applying existing token values.
141 *
142 * @return an <code>Object</code> value
143 */
144 public Object getRawModel () {
145 return template;
146 }
147
148 /**
149 * Updates the template without modifying the current tokens.
150 * @param newTemplate an <code>Object</code> value
151 */
152 public void setRawModel (final Object newTemplate) {
153 template = newTemplate.toString ();
154 }
155
156 /**
157 * Uses Velocity.evaluate() to merge the current token values
158 * with the template string.
159 *
160 * @return a <code>String</code> value
161 */
162 public String toString () {
163 StringWriter w = new StringWriter();
164 try
165 {
166 Velocity.evaluate( context, w, "mystring", template );
167 w.flush();
168 w.close();
169 }
170 catch( ParseErrorException pee )
171 {
172 /*
173 * thrown if something is wrong with the
174 * syntax of our template string
175 */
176 cat.error("ParseErrorException : ",pee);
177 }
178 catch( MethodInvocationException mee )
179 {
180 /*
181 * thrown if a method of a reference
182 * called by the template
183 * throws an exception. That won't happen here
184 * as we aren't calling any methods in this
185 * example, but we have to catch them anyway
186 */
187 cat.error("MethodInvocationException : ",mee );
188 }
189 catch( Exception e )
190 {
191 cat.error("Exception : ",e );
192 }
193 //String s = TemplateParser.parseTemplate (template, props)
194 ;
195 // if(checkIfDefs)
196 // return IfDefProcessor.processTokens(s,props);
197 return w.toString();
198 }
199
200 /**
201 * Sets the named token, delegating it to the VelocityContext.
202 *
203 * @param key an <code>Object</code> value
204 * @param value an <code>Object</code> value
205 */
206 public void setToken (final Object key, final Object value) {
207 context.put(key.toString(),value);
208 }
209
210 /**
211 * Returns the value of the named token, taking it from the
212 * VelocityContext.
213 *
214 * @param key an <code>Object</code> value
215 * @return an <code>Object</code> value
216 */
217 public Object getValue (final Object key) {
218 return context.get (key.toString());
219
220 }
221
222 /**
223 * Static factory method for creating a VelocityModel with the
224 * raw velocity template at the given URL. Calls Velocity.init()
225 * and creates a new VelocityContext.
226 *
227 * @param url a <code>String</code> value
228 * @return a <code>VelocityModel</code> value
229 */
230 public static VelocityModel getModel (final String url) {
231 VelocityModel model = null;
232 try {
233 URL u = new java.net.URL (url);
234 model = new VelocityModel (u);
235 } catch (Exception e) {
236 cat.error("getting model: " + url,e);
237 }
238 return model;
239 }
240
241 }