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