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