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@codehaus.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.codehaus.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 (C) Intalio, Inc. All Rights Reserved.
42   *
43   * $Id$
44   */
45  package org.codehaus.modello.plugin.java.javasource;
46  
47  /*
48   * Copyright (c) 2004, Codehaus.org
49   *
50   * Permission is hereby granted, free of charge, to any person obtaining a copy of
51   * this software and associated documentation files (the "Software"), to deal in
52   * the Software without restriction, including without limitation the rights to
53   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
54   * of the Software, and to permit persons to whom the Software is furnished to do
55   * so, subject to the following conditions:
56   *
57   * The above copyright notice and this permission notice shall be included in all
58   * copies or substantial portions of the Software.
59   *
60   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
61   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
63   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
64   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
65   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
66   * SOFTWARE.
67   */
68  
69  /**
70   * A class that represents a Java comment.
71   * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
72   * @version $Revision$ $Date$
73   **/
74  public class JComment {
75  
76      /**
77       * The auto style, allows this JComment to automatically
78       * choose a style for this comment
79       **/
80      public static final short AUTO_STYLE = 0;
81  
82      /**
83       * The block comment style: \/* *\/
84       **/
85      public static final short BLOCK_STYLE = 1;
86  
87      /**
88       * The line comment style: \/\/
89       **/
90      public static final short LINE_STYLE = 2;
91  
92      /**
93       * The header style, similiar to block, but with an '*'
94       * at the start of each line.
95       **/
96      public static final short HEADER_STYLE = 3;
97  
98      /**
99       * Similiar to HEADER_STYLE, but starts with: \/**
100      **/
101     public static final short JAVADOC_STYLE = 4;
102 
103     private static final String START_BLOCK = "/*";
104     private static final String END_BLOCK = " */";
105 
106     private static final String START_JAVADOC = "/**";
107     private static final String END_JAVADOC = " */";
108 
109     private static final String ASTERIX_PREFIX = " * ";
110     private static final String LINE_COMMENT_PREFIX = "// ";
111     private static final String SPACE_PREFIX = " ";
112 
113     /**
114      * The style of this comment
115      **/
116     private short style = AUTO_STYLE;
117 
118     /**
119      * The main comment for this JDocComment
120      **/
121     private StringBuilder _comment = null;
122 
123     /**
124      * The maximum number of characters per line
125      **/
126     protected static final int MAX_LENGTH = 65;
127 
128     /**
129      * Creates a new Java Comment
130      **/
131     public JComment() {
132         super();
133         _comment = new StringBuilder();
134     } // -- JComment
135 
136     /**
137      * Creates a new Java comment with the given style
138      *
139      * @param style the comment style
140      **/
141     public JComment(short style) {
142         this();
143         this.style = style;
144     } // -- JComment
145 
146     /**
147      * Appends the comment String to this JDocComment
148      * @param comment the comment to append
149      **/
150     public void appendComment(String comment) {
151         _comment.append(comment);
152     } // -- appendComment
153 
154     /**
155      * prints this JComment using the given JSourceWriter
156      * @param jsw the JSourceWriter to print to
157      **/
158     public void print(JSourceWriter jsw) {
159 
160         if (jsw == null) return; // -- nothing to do
161 
162         LineFormatter formatter = null;
163 
164         // -- calculate comment length
165         short currentIndent = jsw.getIndentSize();
166         int maxLength = MAX_LENGTH - currentIndent;
167 
168         // -- a simple to check to make sure we have some room
169         // -- to print the comment
170         if (maxLength <= 17) maxLength = MAX_LENGTH / 2;
171 
172         short resolvedStyle = style;
173 
174         if (style == AUTO_STYLE) {
175             // -- estimation of number of lines
176             int nbrLines = _comment.length() / maxLength;
177 
178             if (nbrLines > 2) resolvedStyle = BLOCK_STYLE;
179             else resolvedStyle = LINE_STYLE;
180         }
181 
182         // -- start comment
183         String prefix = null;
184         String start = null;
185         String end = null;
186 
187         switch (resolvedStyle) {
188             case BLOCK_STYLE:
189                 start = START_BLOCK;
190                 end = END_BLOCK;
191                 prefix = SPACE_PREFIX;
192                 break;
193             case HEADER_STYLE:
194                 start = START_BLOCK;
195                 end = END_BLOCK;
196                 prefix = ASTERIX_PREFIX;
197                 break;
198             case JAVADOC_STYLE:
199                 start = START_JAVADOC;
200                 end = END_JAVADOC;
201                 prefix = ASTERIX_PREFIX;
202                 break;
203             default: // -- LINE
204                 prefix = LINE_COMMENT_PREFIX;
205                 break;
206         }
207         if (start != null) jsw.writeln(start);
208         // -- print main comment
209         formatter = new LineFormatter(_comment.toString(), maxLength, prefix);
210         while (formatter.hasMoreLines()) {
211             jsw.writeln(formatter.nextLine());
212         }
213         if (end != null) jsw.writeln(end);
214         jsw.flush();
215     } // -- print
216 
217     /**
218      * Sets the comment String of this JDocComment
219      * @param comment the comment String of this JDocComment
220      **/
221     public void setComment(String comment) {
222         _comment.setLength(0);
223         _comment.append(comment);
224     } // -- setComment
225 
226     /**
227      * Sets the style for this JComment
228      * @param style the style to use for this JComment
229      **/
230     public void setStyle(short style) {
231         this.style = style;
232     } // -- setStyle
233 
234     /**
235      * Returns the String representation of this Java Doc Comment
236      * @return the String representation of this Java Doc Comment
237      **/
238     public String toString() {
239         return "";
240     } // -- toString
241 } // -- JComment
242 
243 /**
244  * Formats a given String for use within a Java comment
245  * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
246  **/
247 class LineFormatter {
248 
249     String comment = null;
250 
251     int maxLength = 65;
252     int offset = 0;
253     int length = 0;
254 
255     String prefix = null;
256 
257     private StringBuilder sb = null;
258 
259     /**
260      * Creates a LineFormatter for the given comment
261      * @param comment the String to format
262      **/
263     LineFormatter(String comment) {
264         this.comment = comment;
265         if (comment != null) this.length = comment.length();
266         sb = new StringBuilder();
267     } // -- LineFormatter
268 
269     /**
270      * Creates a new LineFormatter for the given comment
271      * @param comment the String to format
272      * @param maxLength the maximum number of characters per line
273      **/
274     LineFormatter(String comment, int maxLength) {
275         this(comment, maxLength, null);
276     } // -- LineFormatter
277 
278     /**
279      * Creates a new LineFormatter for the given comment
280      * @param comment the String to format
281      * @param maxLength the maximum number of characters per line
282      * @param prefix a prefix to append to the beginning of each line
283      **/
284     LineFormatter(String comment, int maxLength, String prefix) {
285         this(comment);
286         this.maxLength = maxLength;
287         this.prefix = prefix;
288     } // -- LineFormatter
289 
290     boolean hasMoreLines() {
291         if (comment == null) return false;
292         return (offset < length);
293     } // -- isFinished
294 
295     String nextLine() {
296         if (comment == null) return null;
297         if (offset >= length) return null;
298 
299         sb.setLength(0);
300         if (prefix != null) sb.append(prefix);
301 
302         int max = offset + maxLength;
303         if (max > this.length) max = this.length;
304 
305         int index = offset;
306         int breakable = offset;
307         for (; index < max; index++) {
308             char ch = comment.charAt(index);
309             if (isNewLine(ch)) {
310                 sb.append(comment.substring(offset, index));
311                 offset = index + 1;
312                 return sb.toString();
313             }
314             if (isWhitespace(ch)) breakable = index;
315         }
316 
317         if (index < length - 1) {
318             // -- if we could not find a breakable character, we must look
319             // -- ahead
320             if (offset == breakable) {
321                 while (index < length) {
322                     if (isBreakable(comment.charAt(index))) break;
323                     ++index;
324                 }
325             } else index = breakable;
326         }
327         sb.append(comment.substring(offset, index));
328         offset = index + 1;
329         return sb.toString();
330     } // -- getNextLine
331 
332     /**
333      * Sets the prefix that should be appended to the beginning of
334      * each line
335      * @param prefix the prefix for this LineFormatter
336      **/
337     void setPrefix(String prefix) {
338         this.prefix = prefix;
339     } // -- setPrefix
340 
341     private boolean isBreakable(char ch) {
342         return (isWhitespace(ch) || isNewLine(ch));
343     }
344 
345     private boolean isWhitespace(char ch) {
346         return ((ch == ' ') || (ch == '\t'));
347     } // -- isWhitespace
348 
349     private boolean isNewLine(char ch) {
350         return ((ch == '\n') || (ch == '\r'));
351     } // -- isNewLineChar
352 } // -- LineFormatter