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 }