Coverage Report - net.sourceforge.cobertura.reporting.html.JavaToHtml
 
Classes in this File Line Coverage Branch Coverage Complexity
JavaToHtml
84%
117/140
74%
87/118
12.5
JavaToHtml$State
0%
0/1
N/A
12.5
 
 1  
 /*
 2  
  * Cobertura - http://cobertura.sourceforge.net/
 3  
  *
 4  
  * Copyright (C) 2005 Mark Doliner
 5  
  *
 6  
  * Cobertura is free software; you can redistribute it and/or modify
 7  
  * it under the terms of the GNU General Public License as published
 8  
  * by the Free Software Foundation; either version 2 of the License,
 9  
  * or (at your option) any later version.
 10  
  *
 11  
  * Cobertura is distributed in the hope that it will be useful, but
 12  
  * WITHOUT ANY WARRANTY; without even the implied warranty of
 13  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 14  
  * General Public License for more details.
 15  
  *
 16  
  * You should have received a copy of the GNU General Public License
 17  
  * along with Cobertura; if not, write to the Free Software
 18  
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 19  
  * USA
 20  
  */
 21  
 
 22  
 package net.sourceforge.cobertura.reporting.html;
 23  
 
 24  
 import java.util.Arrays;
 25  
 import java.util.Collection;
 26  
 import java.util.HashSet;
 27  
 
 28  12
 public class JavaToHtml
 29  
 {
 30  
 
 31  
         // Could use a J2SE 5.0 enum instead of this.
 32  0
         public abstract static class State
 33  
         {
 34  
                 public final static int COMMENT_JAVADOC = 0;
 35  
                 public final static int COMMENT_MULTI = 1;
 36  
                 public final static int COMMENT_SINGLE = 2;
 37  
                 public final static int DEFAULT = 3;
 38  
                 public final static int KEYWORD = 4;
 39  
                 public final static int IMPORT_NAME = 5;
 40  
                 public final static int PACKAGE_NAME = 6;
 41  
                 public final static int QUOTE_DOUBLE = 8;
 42  
                 public final static int QUOTE_SINGLE = 9;
 43  
         }
 44  
 
 45  
         // TODO: Set a style for JavaDoc tags
 46  
         //private static final Collection javaJavaDocTags;
 47  
         private static final Collection javaKeywords;
 48  
         private static final Collection javaPrimitiveLiterals;
 49  
         private static final Collection javaPrimitiveTypes;
 50  
 
 51  
         static
 52  
         {
 53  
                 // TODO: Probably need to add anything new in J2SE 5.0
 54  
                 //final String javaJavaDocTagsArray[] = { "see", "author", "version", "param", "return", "exception",
 55  
                 //                "deprecated", "throws", "link", "since", "serial", "serialField", "serialData", "beaninfo" };
 56  5
                 final String[] javaKeywordsArray = { "abstract", "assert", "break",
 57  
                                 "case", "catch", "class", "const", "continue", "default",
 58  
                                 "do", "else", "extends", "final", "finally", "for", "goto",
 59  
                                 "if", "interface", "implements", "import", "instanceof",
 60  
                                 "native", "new", "package", "private", "protected", "public",
 61  
                                 "return", "static", "strictfp", "super", "switch",
 62  
                                 "synchronized", "this", "throw", "throws", "transient",
 63  
                                 "try", "volatile", "while" };
 64  5
                 final String javaPrimitiveTypesArray[] = { "boolean", "byte", "char",
 65  
                                 "double", "float", "int", "long", "short", "void" };
 66  5
                 final String javaPrimitiveLiteralsArray[] = { "false", "null", "true" };
 67  
 
 68  
                 //javaJavaDocTags = new HashSet(Arrays.asList(javaJavaDocTagsArray));
 69  5
                 javaKeywords = new HashSet(Arrays.asList(javaKeywordsArray));
 70  5
                 javaPrimitiveTypes = new HashSet(Arrays
 71  
                                 .asList(javaPrimitiveTypesArray));
 72  5
                 javaPrimitiveLiterals = new HashSet(Arrays
 73  
                                 .asList(javaPrimitiveLiteralsArray));
 74  5
         }
 75  
 
 76  12
         private int state = State.DEFAULT;
 77  
 
 78  
         private static String escapeEntity(final char character)
 79  
         {
 80  7967
                 if (character == '&')
 81  4
                         return "&";
 82  7963
                 else if (character == '<')
 83  2
                         return "&lt;";
 84  7961
                 else if (character == '>')
 85  3
                         return "&gt;";
 86  7958
                 else if (character == '\t')
 87  331
                         return "        ";
 88  
                 else
 89  7627
                         return new Character(character).toString();
 90  
         }
 91  
 
 92  
         /**
 93  
          * Add HTML colorization to a block of Java code.
 94  
          *
 95  
          * @param text The block of Java code.
 96  
          * @return The same block of Java code with added span tags.
 97  
          *         Newlines are preserved.
 98  
          */
 99  
         public String process(final String text)
 100  
         {
 101  500
                 if (text == null)
 102  0
                         throw new IllegalArgumentException("\"text\" can not be null.");
 103  
 
 104  500
                 StringBuffer ret = new StringBuffer();
 105  
 
 106  
                 // This look is really complicated because it preserves all
 107  
                 // combinations of \r, \n, \r\n, and \n\r
 108  
                 int begin, end, nextCR;
 109  500
                 begin = 0;
 110  500
                 end = text.indexOf('\n', begin);
 111  500
                 nextCR = text.indexOf('\r', begin);
 112  500
                 if ((nextCR != -1) && ((end == -1) || (nextCR < end)))
 113  0
                         end = nextCR;
 114  500
                 while (end != -1)
 115  
                 {
 116  0
                         ret.append(processLine(text.substring(begin, end)) + "<br/>");
 117  
 
 118  0
                         if ((end + 1 < text.length())
 119  
                                         && ((text.charAt(end + 1) == '\n') || (text
 120  
                                                         .charAt(end + 1) == '\r')))
 121  
                         {
 122  0
                                 ret.append(text.substring(end, end + 1));
 123  0
                                 begin = end + 2;
 124  0
                         }
 125  
                         else
 126  
                         {
 127  0
                                 ret.append(text.charAt(end));
 128  0
                                 begin = end + 1;
 129  
                         }
 130  
 
 131  0
                         end = text.indexOf('\n', begin);
 132  0
                         nextCR = text.indexOf('\r', begin);
 133  0
                         if ((nextCR != -1) && ((end == -1) || (nextCR < end)))
 134  0
                                 end = nextCR;
 135  
                 }
 136  500
                 ret.append(processLine(text.substring(begin)));
 137  
 
 138  500
                 return ret.toString();
 139  
         }
 140  
 
 141  
         /**
 142  
          * Add HTML colorization to a single line of Java code.
 143  
          *
 144  
          * @param line One line of Java code.
 145  
          * @return The same line of Java code with added span tags.
 146  
          */
 147  
         private String processLine(final String line)
 148  
         {
 149  500
                 if (line == null)
 150  0
                         throw new IllegalArgumentException("\"line\" can not be null.");
 151  500
                 if ((line.indexOf('\n') != -1) || (line.indexOf('\r') != -1))
 152  0
                         throw new IllegalArgumentException(
 153  
                                         "\"line\" can not contain newline or carriage return characters.");
 154  
 
 155  500
                 StringBuffer ret = new StringBuffer();
 156  500
                 int currentIndex = 0;
 157  
 
 158  2937
                 while (currentIndex != line.length())
 159  
                 {
 160  2437
                         if (state == State.DEFAULT)
 161  
                         {
 162  1719
                                 if ((currentIndex + 2 < line.length())
 163  
                                                 && line.substring(currentIndex, currentIndex + 3)
 164  
                                                                 .equals("/**"))
 165  
                                 {
 166  9
                                         state = State.COMMENT_JAVADOC;
 167  
 
 168  9
                                 }
 169  1710
                                 else if ((currentIndex + 1 < line.length())
 170  
                                                 && line.substring(currentIndex, currentIndex + 2)
 171  
                                                                 .equals("/*"))
 172  
                                 {
 173  7
                                         state = State.COMMENT_MULTI;
 174  
 
 175  7
                                 }
 176  1703
                                 else if ((currentIndex + 1 < line.length())
 177  
                                                 && (line.substring(currentIndex, currentIndex + 2)
 178  
                                                                 .equals("//")))
 179  
                                 {
 180  8
                                         state = State.COMMENT_SINGLE;
 181  
 
 182  8
                                 }
 183  1695
                                 else if (Character.isJavaIdentifierStart(line
 184  
                                                 .charAt(currentIndex)))
 185  
                                 {
 186  478
                                         state = State.KEYWORD;
 187  
 
 188  478
                                 }
 189  1217
                                 else if (line.charAt(currentIndex) == '\'')
 190  
                                 {
 191  3
                                         state = State.QUOTE_SINGLE;
 192  
 
 193  3
                                 }
 194  1214
                                 else if (line.charAt(currentIndex) == '"')
 195  
                                 {
 196  20
                                         state = State.QUOTE_DOUBLE;
 197  
 
 198  20
                                 }
 199  
                                 else
 200  
                                 {
 201  
                                         // Default: No highlighting.
 202  1194
                                         ret.append(escapeEntity(line.charAt(currentIndex++)));
 203  
                                 }
 204  1194
                         } // End of State.DEFAULT
 205  
 
 206  718
                         else if ((state == State.COMMENT_MULTI)
 207  
                                         || (state == State.COMMENT_JAVADOC))
 208  
                         {
 209  
                                 // Print everything from the current character until the
 210  
                                 // closing */  No exceptions.
 211  188
                                 ret.append("<span class=\"comment\">");
 212  
                                 while ((currentIndex != line.length())
 213  6474
                                                 && !((currentIndex + 1 < line.length()) && (line
 214  
                                                                 .substring(currentIndex, currentIndex + 2)
 215  
                                                                 .equals("*/"))))
 216  
                                 {
 217  6286
                                         ret.append(escapeEntity(line.charAt(currentIndex++)));
 218  6286
                                 }
 219  188
                                 if (currentIndex == line.length())
 220  
                                 {
 221  172
                                         ret.append("</span>");
 222  172
                                 }
 223  
                                 else
 224  
                                 {
 225  16
                                         ret.append("*/</span>");
 226  16
                                         state = State.DEFAULT;
 227  16
                                         currentIndex += 2;
 228  
                                 }
 229  16
                         } // End of State.COMMENT_MULTI
 230  
 
 231  530
                         else if (state == State.COMMENT_SINGLE)
 232  
                         {
 233  
                                 // Print everything from the current character until the 
 234  
                                 // end of the line
 235  8
                                 ret.append("<span class=\"comment\">");
 236  395
                                 while (currentIndex != line.length())
 237  
                                 {
 238  387
                                         ret.append(escapeEntity(line.charAt(currentIndex++)));
 239  387
                                 }
 240  8
                                 ret.append("</span>");
 241  8
                                 state = State.DEFAULT;
 242  
 
 243  8
                         } // End of State.COMMENT_SINGLE
 244  
 
 245  522
                         else if (state == State.KEYWORD)
 246  
                         {
 247  478
                                 StringBuffer tmp = new StringBuffer();
 248  
                                 do
 249  
                                 {
 250  2875
                                         tmp.append(line.charAt(currentIndex++));
 251  
                                 } while ((currentIndex != line.length())
 252  2875
                                                 && (Character.isJavaIdentifierPart(line
 253  
                                                                 .charAt(currentIndex))));
 254  478
                                 if (javaKeywords.contains(tmp.toString()))
 255  166
                                         ret.append("<span class=\"keyword\">" + tmp + "</span>");
 256  312
                                 else if (javaPrimitiveLiterals.contains(tmp.toString()))
 257  13
                                         ret.append("<span class=\"keyword\">" + tmp + "</span>");
 258  299
                                 else if (javaPrimitiveTypes.contains(tmp.toString()))
 259  45
                                         ret.append("<span class=\"keyword\">" + tmp + "</span>");
 260  
                                 else
 261  254
                                         ret.append(tmp);
 262  478
                                 if (tmp.toString().equals("import"))
 263  9
                                         state = State.IMPORT_NAME;
 264  469
                                 else if (tmp.toString().equals("package"))
 265  12
                                         state = State.PACKAGE_NAME;
 266  
                                 else
 267  457
                                         state = State.DEFAULT;
 268  478
                         } // End of State.KEYWORD
 269  
 
 270  44
                         else if (state == State.IMPORT_NAME)
 271  
                         {
 272  9
                                 ret.append(escapeEntity(line.charAt(currentIndex++)));
 273  9
                                 state = State.DEFAULT;
 274  9
                         } // End of State.IMPORT_NAME
 275  
 
 276  35
                         else if (state == State.PACKAGE_NAME)
 277  
                         {
 278  12
                                 ret.append(escapeEntity(line.charAt(currentIndex++)));
 279  12
                                 state = State.DEFAULT;
 280  12
                         } // End of State.PACKAGE_NAME
 281  
 
 282  23
                         else if (state == State.QUOTE_DOUBLE)
 283  
                         {
 284  
                                 // Print everything from the current character until the
 285  
                                 // closing ", checking for \"
 286  20
                                 ret.append("<span class=\"string\">");
 287  
                                 do
 288  
                                 {
 289  71
                                         ret.append(escapeEntity(line.charAt(currentIndex++)));
 290  
                                 } while ((currentIndex != line.length())
 291  71
                                                 && (!(line.charAt(currentIndex) == '"') || ((line
 292  
                                                                 .charAt(currentIndex - 1) == '\\') && (line
 293  
                                                                 .charAt(currentIndex - 2) != '\\'))));
 294  20
                                 if (currentIndex == line.length())
 295  
                                 {
 296  0
                                         ret.append("</span>");
 297  0
                                 }
 298  
                                 else
 299  
                                 {
 300  20
                                         ret.append("\"</span>");
 301  20
                                         state = State.DEFAULT;
 302  20
                                         currentIndex++;
 303  
                                 }
 304  20
                         } // End of State.QUOTE_DOUBLE
 305  
 
 306  3
                         else if (state == State.QUOTE_SINGLE)
 307  
                         {
 308  
                                 // Print everything from the current character until the
 309  
                                 // closing ', checking for \'
 310  3
                                 ret.append("<span class=\"string\">");
 311  
                                 do
 312  
                                 {
 313  8
                                         ret.append(escapeEntity(line.charAt(currentIndex++)));
 314  
                                 } while ((currentIndex != line.length())
 315  8
                                                 && (!(line.charAt(currentIndex) == '\'') || ((line
 316  
                                                                 .charAt(currentIndex - 1) == '\\') && (line
 317  
                                                                 .charAt(currentIndex - 2) != '\\'))));
 318  3
                                 if (currentIndex == line.length())
 319  
                                 {
 320  0
                                         ret.append("</span>");
 321  0
                                 }
 322  
                                 else
 323  
                                 {
 324  3
                                         ret.append("\'</span>");
 325  3
                                         state = State.DEFAULT;
 326  3
                                         currentIndex++;
 327  
                                 }
 328  3
                         } // End of State.QUOTE_SINGLE
 329  
 
 330  
                         else
 331  
                         {
 332  
                                 // Default: No highlighting.
 333  0
                                 ret.append(escapeEntity(line.charAt(currentIndex++)));
 334  
                         } // End of unknown state
 335  0
                 }
 336  
 
 337  500
                 return ret.toString();
 338  
         }
 339  
 
 340  
         /**
 341  
          * Reset the state of this Java parser.  Call this if you have
 342  
          * been parsing one Java file and you want to begin parsing
 343  
          * another Java file.
 344  
          *
 345  
          */
 346  
         public void reset()
 347  
         {
 348  0
                 state = State.DEFAULT;
 349  0
         }
 350  
 
 351  
 }