View Javadoc
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 }