1 /* 2 * $Source$ 3 * $Revision$ 4 * 5 * Copyright (C) 2006 Tim Pizey 6 * 7 * Part of Melati (http://melati.org), a framework for the rapid 8 * development of clean, maintainable web applications. 9 * 10 * Melati is free software; Permission is granted to copy, distribute 11 * and/or modify this software under the terms either: 12 * 13 * a) the GNU General Public License as published by the Free Software 14 * Foundation; either version 2 of the License, or (at your option) 15 * any later version, 16 * 17 * or 18 * 19 * b) any version of the Melati Software License, as published 20 * at http://melati.org 21 * 22 * You should have received a copy of the GNU General Public License and 23 * the Melati Software License along with this program; 24 * if not, write to the Free Software Foundation, Inc., 25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the 26 * GNU General Public License and visit http://melati.org to obtain the 27 * Melati Software License. 28 * 29 * Feel free to contact the Developers of Melati (http://melati.org), 30 * if you would like to work out a different arrangement than the options 31 * outlined here. It is our intention to allow Melati to be used by as 32 * wide an audience as possible. 33 * 34 * This program is distributed in the hope that it will be useful, 35 * but WITHOUT ANY WARRANTY; without even the implied warranty of 36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 37 * GNU General Public License for more details. 38 * 39 * Contact details for copyright holder: 40 * 41 * Tim Pizey <timp At paneris.org> 42 */ 43 package org.melati.template.velocity; 44 45 import java.io.ByteArrayInputStream; 46 import java.io.IOException; 47 import java.io.InputStream; 48 49 import org.apache.oro.text.perl.Perl5Util; 50 import org.melati.util.MelatiBugMelatiException; 51 52 /** 53 * Converter from WebMacro templates to Velocity templates. 54 * 55 * Note that this does not succeed for modern WebMacro syntax 56 * which uses optional #begin in #foreach. 57 * 58 * @author Tim Pizey based on work by Jason vanZyl and Tim Joyce. 59 * 60 * FIXME Refactor to use java regexp. 61 * 62 */ 63 public final class WebMacroConverter { 64 65 private WebMacroConverter() {} 66 /** 67 * The regexes to use for substitution. The regexes come 68 * in pairs. The first is the string to match, the 69 * second is the substitution to make. 70 */ 71 public static final String[] regExps = { 72 // Make #if directive match the Velocity directive style. 73 "#if\\s*[(]\\s*(.*\\S)\\s*[)]\\s*(#begin|{)[ \\t]?", 74 "#if( $1 )", 75 76 // Remove the WM #end #else #begin usage. 77 "([ \\t])?(#end|})\\s*#else\\s*(#begin|{)([ \\t])?(\\w)", 78 "#{else}$5", // avoid touching a followup word with embedded comment 79 80 "[ \\t]?(#end|})\\s*#else\\s*(#begin|{)[ \\t]?", 81 "#else", 82 83 // Convert nulls. 84 // This converts 85 // $var != null 86 // to 87 // $var 88 "\\s*(\\$[^\\s\\!]+)\\s*!=\\s*null\\s*", 89 " $1 ", 90 // This converts 91 // $var == null 92 // to 93 // !$var 94 "\\s*(\\$[^\\s\\!]+)\\s*==\\s*null\\s*", 95 " !$1 ", 96 97 // Convert WM style #foreach to Velocity directive style. 98 "#foreach\\s+(\\$\\w+)\\s+in\\s+(\\$[^\\s#]+)\\s*(#begin|{)[ \\t]?", 99 "#foreach( $1 in $2 )", 100 101 // Change the "}" to #end. Have to get more 102 // sophisticated here. Will assume either {} 103 // and no javascript, or #begin/#end with the 104 // possibility of javascript. 105 "\n}", // assumes that javascript is indented, WMs not!!! 106 "\n#end", 107 108 // Convert WM style #set to Velocity directive style. 109 //"#set\\s+(\\$[^\\s=]+)\\s*=\\s*(.*\\S)[ \\t]*", 110 "#set\\s+(\\$[^\\s=]+)\\s*=\\s*([\\S \\t]+)", 111 "#set( $1 = $2 )", 112 "(##[# \\t\\w]*)\\)", // fix comments included at end of line 113 ")$1", 114 115 // Convert WM style #parse to Velocity directive style. 116 "#parse\\s+([^\\s#]+)[ \\t]?", 117 "#parse( $1 )", 118 119 // parse is now deprecated for web macro 120 // include as template is recommended. 121 // Velocity supports only parse 122 // added for melati conversion 123 "#include\\s+as\\s+template\\s+([^\\s#]+)[ \\t]?", 124 "#parse( $1 )", 125 126 // Convert WM style #include to Velocity directive style. 127 "#include\\s+([^\\s#]+)[ \\t]?", 128 "#include( $1 )", 129 130 // Convert WM formal reference to VL syntax. 131 "\\$\\(([^\\)]+)\\)", 132 "\\${$1}", 133 "\\${([^}\\(]+)\\(([^}]+)}\\)", // fix encapsulated brackets: {(}) 134 "\\${$1($2)}", 135 136 // Velocity currently does not permit leading underscore. 137 "\\$_", 138 "\\$l_", 139 "\\${(_[^}]+)}", // within a formal reference 140 "\\${l$1}", 141 142 }; 143 144 /** 145 * Do the conversion. 146 * 147 * @param in 148 * @return the InputStream with substitutions applied 149 */ 150 public static InputStream convert(InputStream in) { 151 byte[] ca; 152 try { 153 ca = new byte[in.available()]; 154 in.read(ca); 155 String contents = convert(new String(ca)); 156 //System.err.println(contents); 157 return new ByteArrayInputStream(contents.getBytes()); 158 } catch (IOException e) { 159 throw new MelatiBugMelatiException( 160 "Problem loading WebMacro template as a VelocityTemplate", e); 161 } 162 } 163 164 public static String convert(String in) { 165 /* Regular expression tool */ 166 final Perl5Util perl = new Perl5Util(); 167 for (int i = 0; i < regExps.length; i += 2) { 168 while (perl.match("/" + regExps[i] + "/", in)) { 169 in = perl.substitute( 170 "s/" + regExps[i] + "/" + regExps[i+1] + "/", in); 171 } 172 } 173 return in; 174 } 175 }