001: /**
002: * Redistribution and use of this software and associated documentation
003: * ("Software"), with or without modification, are permitted provided
004: * that the following conditions are met:
005: *
006: * 1. Redistributions of source code must retain copyright
007: * statements and notices. Redistributions must also contain a
008: * copy of this document.
009: *
010: * 2. Redistributions in binary form must reproduce the
011: * above copyright notice, this list of conditions and the
012: * following disclaimer in the documentation and/or other
013: * materials provided with the distribution.
014: *
015: * 3. The name "Exolab" must not be used to endorse or promote
016: * products derived from this Software without prior written
017: * permission of Intalio, Inc. For written permission,
018: * please contact info@exolab.org.
019: *
020: * 4. Products derived from this Software may not be called "Exolab"
021: * nor may "Exolab" appear in their names without prior written
022: * permission of Intalio, Inc. Exolab is a registered
023: * trademark of Intalio, Inc.
024: *
025: * 5. Due credit should be given to the Exolab Project
026: * (http://www.exolab.org/).
027: *
028: * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
029: * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
030: * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
031: * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
032: * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
033: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
034: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
035: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
036: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
037: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
038: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
039: * OF THE POSSIBILITY OF SUCH DAMAGE.
040: *
041: * Copyright 1999-2001 (C) Intalio, Inc. All Rights Reserved.
042: */package org.exolab.javasource;
043:
044: import java.text.MessageFormat;
045: import java.util.StringTokenizer;
046: import java.util.Vector;
047:
048: /**
049: * A class for holding in-memory Java source code.
050: *
051: * @author <a href="mailto:keith AT kvisco DOT com">Keith Visco</a>
052: * @version $Revision: 6729 $ $Date: 2005-03-05 06:42:06 -0700 (Sat, 05 Mar 2005) $
053: */
054: public final class JSourceCode {
055: //--------------------------------------------------------------------------
056:
057: /** Default indentation size. */
058: public static final int DEFAULT_INDENT_SIZE = 4;
059:
060: //--------------------------------------------------------------------------
061:
062: /** A list of JCodeStatements. */
063: private Vector _source = null;
064:
065: /** The indent size. */
066: private short _indentSize = DEFAULT_INDENT_SIZE;
067:
068: /** The current indent size. */
069: private short _currentIndent = _indentSize;
070:
071: //--------------------------------------------------------------------------
072:
073: /**
074: * Creates an empty JSourceCode.
075: */
076: public JSourceCode() {
077: super ();
078:
079: _source = new Vector();
080: }
081:
082: /**
083: * Creates a JSourceCode and adds the given String to its contents.
084: *
085: * @param sourceCode the source to add
086: */
087: public JSourceCode(final String sourceCode) {
088: this ();
089:
090: _source.addElement(new JCodeStatement(sourceCode,
091: _currentIndent));
092: }
093:
094: //--------------------------------------------------------------------------
095:
096: /**
097: * Adds statement generated by replacing parameters of given pattern with given argument to
098: * this JSourceCode. The statement will be added on a new line.
099: *
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,
116: final Object argument2) {
117: add(pattern, new Object[] { argument1, argument2 });
118: }
119:
120: /**
121: * Adds statements generated by replacing parameters of given pattern with given arguments to
122: * this JSourceCode. Multiple statements can be separated by '\n' characters. Each statement
123: * will be added on a new line. If that statement starts with whitespace characters it will
124: * be indented.
125: *
126: * @param pattern Pattern for the statement.
127: * @param arguments Arguments to replace parameters in pattern.
128: */
129: public void add(final String pattern, final Object[] arguments) {
130: StringTokenizer tokenizer = new StringTokenizer(pattern, "\n");
131: while (tokenizer.hasMoreTokens()) {
132: addWithIndent(tokenizer.nextToken(), arguments);
133: }
134: }
135:
136: /**
137: * Adds statement generated by replacing parameters of given pattern with given arguments to
138: * this JSourceCode. The statement will be added on a new line. If the statement starts with
139: * whitespace characters the statement will be indented.
140: *
141: * @param pattern Pattern for the statement.
142: * @param arguments Arguments to replace parameters in pattern.
143: */
144: private void addWithIndent(final String pattern,
145: final Object[] arguments) {
146: if (pattern.startsWith(" ")) {
147: indent();
148: addWithIndent(pattern.substring(1), arguments);
149: unindent();
150: } else if ((pattern.indexOf('{') + 2) == pattern.indexOf('}')) {
151: add(MessageFormat.format(pattern, arguments));
152: } else {
153: add(pattern);
154: }
155: }
156:
157: /**
158: * Adds the given statement to this JSourceCode. The statement will be added
159: * on a new line.
160: *
161: * @param statement The statement to add.
162: */
163: public void add(final String statement) {
164: _source
165: .addElement(new JCodeStatement(statement,
166: _currentIndent));
167: }
168:
169: /**
170: * Adds the given statement to this JSourceCode. The statement will be added
171: * on a new line and added with increased indent. This is a convenience
172: * method for the sequence:
173: * <code>
174: * indent();
175: * add(statement);
176: * unindent();
177: * </code>
178: * @param statement The statement to add.
179: */
180: public void addIndented(final String statement) {
181: indent();
182: _source
183: .addElement(new JCodeStatement(statement,
184: _currentIndent));
185: unindent();
186: }
187:
188: /**
189: * Appends the given String to the last line in this JSourceCode.
190: *
191: * @param segment The String to append.
192: */
193: public void append(final String segment) {
194: if (_source.isEmpty()) {
195: add(segment);
196: } else {
197: JCodeStatement jcs = (JCodeStatement) _source.lastElement();
198: jcs.append(segment);
199: }
200: }
201:
202: /**
203: * Clears all the code statements from this JSourceCode.
204: */
205: public void clear() {
206: _source.removeAllElements();
207: }
208:
209: /**
210: * Copies the contents of this JSourceCode into the given JSourceCode.
211: *
212: * @param jsc The JSourceCode to copy this JSourceCode into.
213: */
214: public void copyInto(final JSourceCode jsc) {
215: for (int i = 0; i < _source.size(); i++) {
216: jsc.addCodeStatement((JCodeStatement) _source.elementAt(i));
217: }
218: }
219:
220: /**
221: * Increases the current indent level by 1.
222: */
223: public void indent() {
224: _currentIndent += _indentSize;
225: }
226:
227: /**
228: * Returns true if this JSourceCode is empty (ie. no source).
229: *
230: * @return True if this JSourceCode is empty.
231: */
232: public boolean isEmpty() {
233: return _source.isEmpty();
234: }
235:
236: /**
237: * Prints this JSourceCode to the given JSourceWriter.
238: *
239: * @param jsw The JSourceWriter to print to.
240: */
241: public void print(final JSourceWriter jsw) {
242: for (int i = 0; i < _source.size(); i++) {
243: jsw.writeln(_source.elementAt(i).toString());
244: }
245: }
246:
247: /**
248: * Decreases the indent level by 1.
249: */
250: public void unindent() {
251: _currentIndent -= _indentSize;
252: }
253:
254: /**
255: * Returns the number of source code lines (aka JCodeStatements) set so far.
256: *
257: * @return The number of source code lines set so far.
258: */
259: public int size() {
260: return _source.size();
261: }
262:
263: /**
264: * Adds the given JCodeStatement to this JSourceCode.
265: *
266: * @param jcs The JCodeStatement to add.
267: */
268: private void addCodeStatement(final JCodeStatement jcs) {
269: short indent = (short) (jcs.getIndent() + _currentIndent - DEFAULT_INDENT_SIZE);
270: _source.addElement(new JCodeStatement(jcs.getStatement(),
271: indent));
272: }
273:
274: //--------------------------------------------------------------------------
275:
276: /**
277: * {@inheritDoc}
278: */
279: public String toString() {
280: StringBuffer sb = new StringBuffer();
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: }
|