1 /** 2 * Redistribution and use of this software and associated documentation 3 * ("Software"), with or without modification, are permitted provided 4 * that the following conditions are met: 5 * 6 * 1. Redistributions of source code must retain copyright 7 * statements and notices. Redistributions must also contain a 8 * copy of this document. 9 * 10 * 2. Redistributions in binary form must reproduce the 11 * above copyright notice, this list of conditions and the 12 * following disclaimer in the documentation and/or other 13 * materials provided with the distribution. 14 * 15 * 3. The name "Exolab" must not be used to endorse or promote 16 * products derived from this Software without prior written 17 * permission of Intalio, Inc. For written permission, 18 * please contact info@exolab.org. 19 * 20 * 4. Products derived from this Software may not be called "Exolab" 21 * nor may "Exolab" appear in their names without prior written 22 * permission of Intalio, Inc. Exolab is a registered 23 * trademark of Intalio, Inc. 24 * 25 * 5. Due credit should be given to the Exolab Project 26 * (http://www.exolab.org/). 27 * 28 * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT 30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 32 * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 39 * OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Copyright 1999-2001 (C) Intalio, Inc. All Rights Reserved. 42 */ 43 package org.exolab.javasource; 44 45 import java.text.MessageFormat; 46 import java.util.StringTokenizer; 47 import java.util.Vector; 48 49 /** 50 * A class for holding in-memory Java source code. 51 * 52 * @author <a href="mailto:keith AT kvisco DOT com">Keith Visco</a> 53 * @version $Revision$ $Date: 2005-03-05 06:42:06 -0700 (Sat, 05 Mar 2005) $ 54 */ 55 public final class JSourceCode { 56 //-------------------------------------------------------------------------- 57 58 /** Default indentation size. */ 59 public static final int DEFAULT_INDENT_SIZE = 4; 60 61 //-------------------------------------------------------------------------- 62 63 /** A list of JCodeStatements. */ 64 private Vector<JCodeStatement> _source = null; 65 66 /** The indent size. */ 67 private short _indentSize = DEFAULT_INDENT_SIZE; 68 69 /** The current indent size. */ 70 private short _currentIndent = _indentSize; 71 72 //-------------------------------------------------------------------------- 73 74 /** 75 * Creates an empty JSourceCode. 76 */ 77 public JSourceCode() { 78 super(); 79 80 _source = new Vector<JCodeStatement>(); 81 } 82 83 /** 84 * Creates a JSourceCode and adds the given String to its contents. 85 * 86 * @param sourceCode the source to add 87 */ 88 public JSourceCode(final String sourceCode) { 89 this(); 90 91 _source.addElement(new JCodeStatement(sourceCode, _currentIndent)); 92 } 93 94 //-------------------------------------------------------------------------- 95 96 /** 97 * Adds statement generated by replacing parameters of given pattern with given argument to 98 * this JSourceCode. The statement will be added on a new line. 99 * 100 * @param pattern Pattern for the statement. 101 * @param argument Argument to replace first parameter in pattern. 102 */ 103 public void add(final String pattern, final Object argument) { 104 add(pattern, new Object[] {argument}); 105 } 106 107 /** 108 * Adds statement generated by replacing parameters of given pattern with given arguments to 109 * this JSourceCode. The statement will be added on a new line. 110 * 111 * @param pattern Pattern for the statement. 112 * @param argument1 Argument to replace first parameter in pattern. 113 * @param argument2 Argument to replace second parameter in pattern. 114 */ 115 public void add(final String pattern, final Object argument1, final Object argument2) { 116 add(pattern, new Object[] {argument1, argument2}); 117 } 118 119 /** 120 * Adds statements generated by replacing parameters of given pattern with given arguments to 121 * this JSourceCode. Multiple statements can be separated by '\n' characters. Each statement 122 * will be added on a new line. If that statement starts with whitespace characters it will 123 * be indented. 124 * 125 * @param pattern Pattern for the statement. 126 * @param arguments Arguments to replace parameters in pattern. 127 */ 128 public void add(final String pattern, final Object[] arguments) { 129 StringTokenizer tokenizer = new StringTokenizer(pattern, "\n"); 130 while (tokenizer.hasMoreTokens()) { addWithIndent(tokenizer.nextToken(), arguments); } 131 } 132 133 /** 134 * Adds statement generated by replacing parameters of given pattern with given arguments to 135 * this JSourceCode. The statement will be added on a new line. If the statement starts with 136 * whitespace characters the statement will be indented. 137 * 138 * @param pattern Pattern for the statement. 139 * @param arguments Arguments to replace parameters in pattern. 140 */ 141 private void addWithIndent(final String pattern, final Object[] arguments) { 142 if (pattern.startsWith(" ")) { 143 indent(); 144 addWithIndent(pattern.substring(1), arguments); 145 unindent(); 146 } else if ((pattern.indexOf('{') + 2) == pattern.indexOf('}')) { 147 add(MessageFormat.format(pattern, arguments)); 148 } else { 149 add(pattern); 150 } 151 } 152 153 /** 154 * Adds the given statement to this JSourceCode. The statement will be added 155 * on a new line. 156 * 157 * @param statement The statement to add. 158 */ 159 public void add(final String statement) { 160 _source.addElement(new JCodeStatement(statement, _currentIndent)); 161 } 162 163 /** 164 * Adds the given statement to this JSourceCode. The statement will be added 165 * on a new line and added with increased indent. This is a convenience 166 * method for the sequence: 167 * <code> 168 * indent(); 169 * add(statement); 170 * unindent(); 171 * </code> 172 * @param statement The statement to add. 173 */ 174 public void addIndented(final String statement) { 175 indent(); 176 _source.addElement(new JCodeStatement(statement, _currentIndent)); 177 unindent(); 178 } 179 180 /** 181 * Appends the given String to the last line in this JSourceCode. 182 * 183 * @param segment The String to append. 184 */ 185 public void append(final String segment) { 186 if (_source.isEmpty()) { 187 add(segment); 188 } else { 189 JCodeStatement jcs = _source.lastElement(); 190 jcs.append(segment); 191 } 192 } 193 194 /** 195 * Clears all the code statements from this JSourceCode. 196 */ 197 public void clear() { 198 _source.removeAllElements(); 199 } 200 201 /** 202 * Copies the contents of this JSourceCode into the given JSourceCode. 203 * 204 * @param jsc The JSourceCode to copy this JSourceCode into. 205 */ 206 public void copyInto(final JSourceCode jsc) { 207 for (int i = 0; i < _source.size(); i++) { 208 jsc.addCodeStatement(_source.elementAt(i)); 209 } 210 } 211 212 /** 213 * Increases the current indent level by 1. 214 */ 215 public void indent() { 216 _currentIndent += _indentSize; 217 } 218 219 /** 220 * Returns true if this JSourceCode is empty (ie. no source). 221 * 222 * @return True if this JSourceCode is empty. 223 */ 224 public boolean isEmpty() { 225 return _source.isEmpty(); 226 } 227 228 /** 229 * Prints this JSourceCode to the given JSourceWriter. 230 * 231 * @param jsw The JSourceWriter to print to. 232 */ 233 public void print(final JSourceWriter jsw) { 234 for (int i = 0; i < _source.size(); i++) { 235 jsw.writeln(_source.elementAt(i).toString()); 236 } 237 } 238 239 /** 240 * Decreases the indent level by 1. 241 */ 242 public void unindent() { 243 _currentIndent -= _indentSize; 244 } 245 246 /** 247 * Returns the number of source code lines (aka JCodeStatements) set so far. 248 * 249 * @return The number of source code lines set so far. 250 */ 251 public int size() { 252 return _source.size(); 253 } 254 255 /** 256 * Adds the given JCodeStatement to this JSourceCode. 257 * 258 * @param jcs The JCodeStatement to add. 259 */ 260 private void addCodeStatement(final JCodeStatement jcs) { 261 short indent = (short) (jcs.getIndent() + _currentIndent - DEFAULT_INDENT_SIZE); 262 _source.addElement(new JCodeStatement(jcs.getStatement(), indent)); 263 } 264 265 /** 266 * Returns a vector of source lines. 267 * 268 * @return A vector of source lines. 269 */ 270 public Vector<JCodeStatement> getSource() { 271 return _source; 272 } 273 274 //-------------------------------------------------------------------------- 275 276 /** 277 * {@inheritDoc} 278 */ 279 public String toString() { 280 StringBuilder sb = new StringBuilder(100); 281 String lineSeparator = System.getProperty("line.separator"); 282 for (int i = 0; i < _source.size(); i++) { 283 sb.append(_source.elementAt(i).toString()); 284 sb.append(lineSeparator); 285 } 286 return sb.toString(); 287 } 288 289 //-------------------------------------------------------------------------- 290 }