Skip to content

Method: simplifyJavaCode(String)

1: package de.fhdw.wtf.generator.transformer.clipper;
2:
3: import java.util.ArrayList;
4: import java.util.Collection;
5: import java.util.Iterator;
6: import java.util.regex.Matcher;
7: import java.util.regex.Pattern;
8:
9: import de.fhdw.wtf.generator.java.generatorModel.GenComment;
10: import de.fhdw.wtf.generator.java.generatorModel.GenFullParsedOperationState;
11: import de.fhdw.wtf.generator.java.generatorModel.GenOperationModifier;
12: import de.fhdw.wtf.generator.java.generatorModel.GenTypeReferenceByName;
13: import de.fhdw.wtf.generator.java.generatorModel.GenVisibility;
14: import de.fhdw.wtf.generator.transformer.exception.ClipperImportFormatException;
15: import de.fhdw.wtf.generator.transformer.exception.NoMatchingMethodException;
16: import de.fhdw.wtf.generator.transformer.util.Tuple;
17:
18: /**
19: * Helper functions used in the clipper. Used for analysis of java source code, comments, etc...
20: *
21: */
22: public final class ClipperUtils {
23:         
24:         /** Beginning of a Char-Literal '. */
25:         private static final String JAVA_STRING_LITERAL_SINGLE_SIGN = "\'";
26:         
27:         /** Beginning of a String-Literal ". */
28:         private static final String JAVA_STRING_LITERAL_DOUBLE_SIGN = "\"";
29:         
30:         /** Regular Expression for Java identifier names. */
31:         public static final String IDENTIFIER_REGEX = "[A-Za-z_$€][\\.A-Za-z_$€0-9]*";
32:         
33:         //
34:         /** Filename-constant for constructor-files. */
35:         public static final String CONSTRUCTOR_FILENAME = "#constructor";
36:         /** Filename-constant for area protected from clipping. */
37:         public static final String PROTECTED_AREA_FILENAME = "#protectedArea";
38:         /** Filename-constant for javadoc comments of classes. */
39:         public static final String CLASSCOMMENT_FILENAME = "#classcomment";
40:         /** Filename-constant for imports of classes. */
41:         public static final String IMPORTS_FILENAME = "#imports";
42:         /**
43:          * Filename-constant for clipper error files, where the correct filename cannot be determined.
44:          */
45:         public static final String ERRORFILE_FILENAME = "#errorFile";
46:         /** Seperator between operation parameters or attributes in operation-filenames. */
47:         public static final String SEPERATOR = "#";
48:         /** Filename constant for start of attribute filename. */
49:         public static final String ATTRIBUTE_START = "#attr#";
50:         /** Parameter separator. */
51:         public static final String PARAMETER_SEPARATOR = ",";
52:         /** Matches opening bracket of generic parameter list. */
53:         public static final String GENERIC_OPEN = "<";
54:         /** Replacement for opening bracket of generic parameter list, usable in filenames. */
55:         public static final String GENERIC_OPEN_REPLACEMENT = "%{";
56:         /** Matches closing bracket of generic parameter list. */
57:         public static final String GENERIC_CLOSE = ">";
58:         /** Replacement for closing bracket of generic parameter list, usable in filenames. */
59:         public static final String GENERIC_CLOSE_REPLACEMENT = "%}";
60:         /** Replacement character for any invalid character. */
61:         public static final String REPLACEMENT_FOR_ILLEGAL_CHAR = "_";
62:         /** Java source filename ending. */
63:         public static final String FILE_ENDING = ".java";
64:         /** Regular Expression for matching the non-generation part. */
65:         public static final String NON_GEN_PART_MATCH = ".*// --> NON-GENERATION-PART <--(.*)}\\s*";
66:         /** Start of javadoc comment. */
67:         public static final String COMMENT_OPEN = "/*";
68:         /** End of javadoc comment. */
69:         public static final String COMMENT_CLOSE = "*/";
70:         
71:         /** Error constants. */
72:         public static final String CLIPPER_ERROR_NO_METHOD = "Clipper Error: No method";
73:         
74:         /**
75:          * Unneccessary, because its a helper class with only static access.
76:          */
77:         private ClipperUtils() {
78:                 
79:         }
80:         
81:         /**
82:          * Deletes all java blockcomments in the file and replaces the comment region with equivalent amount of whitespace.
83:          *
84:          * @param file
85:          * file, possibly containing block comments
86:          * @return file of the same size with whitened (replaced with spaces) comments
87:          * @throws ClipperImportFormatException
88:          * when the parsing errors
89:          */
90:         public static String deleteBlockComments(final String file) throws ClipperImportFormatException {
91:                 String result = file;
92:                 final String nextStringLiteralDoubleSign = JAVA_STRING_LITERAL_DOUBLE_SIGN;
93:                 final String nextStringLiteralSingleSign = JAVA_STRING_LITERAL_SINGLE_SIGN;
94:                 final String commentSign = COMMENT_OPEN;
95:                 final String commentSignClose = COMMENT_CLOSE;
96:                 int pos = 0;
97:                 int doublePos = findNextQuotation(nextStringLiteralDoubleSign, result, pos);
98:                 int singlePos = findNextQuotation(nextStringLiteralSingleSign, result, pos);
99:                 int commentPos = result.indexOf(commentSign);
100:                 
101:                 while (true) {
102:                         if (commentPos < 0) {
103:                                 break;
104:                         }
105:                         if (doublePos < commentPos && (doublePos < singlePos || singlePos < 0) && doublePos > 0) {
106:                                 pos = findNextQuotation(nextStringLiteralDoubleSign, result, doublePos + 1);
107:                         } else if (singlePos < commentPos && (singlePos < doublePos || doublePos < 0) && singlePos > 0) {
108:                                 pos = findNextQuotation(nextStringLiteralSingleSign, result, singlePos + 1);
109:                                 singlePos = findNextQuotation(nextStringLiteralSingleSign, result, pos + 1);
110:                         } else if (commentPos >= pos) {
111:                                 final int oldPos = commentPos;
112:                                 pos = result.indexOf(commentSignClose, commentPos) + 2;
113:                                 result = replaceFromToWithWhitespace(result, oldPos, pos);
114:                                 commentPos = result.indexOf(commentSign, pos);
115:                         } else {
116:                                 break;
117:                         }
118:                         if (doublePos < pos && doublePos != -1) {
119:                                 doublePos = findNextQuotation(nextStringLiteralDoubleSign, result, pos + 1);
120:                         }
121:                         if (singlePos < pos && singlePos != -1) {
122:                                 singlePos = findNextQuotation(nextStringLiteralSingleSign, result, pos + 1);
123:                         }
124:                         if (commentPos < pos && commentPos != -1) {
125:                                 commentPos = result.indexOf(commentSign, pos + 1);
126:                         }
127:                         
128:                         if (pos < 0) {
129:                                 throw new ClipperImportFormatException("Error while parsing quotes");
130:                         }
131:                 }
132:                 return result;
133:         }
134:         
135:         /**
136:          * Replaces the given range of characters (from - to) with exact amount of whitespace.
137:          *
138:          * @param text
139:          * given text
140:          * @param from
141:          * begin position in text
142:          * @param to
143:          * end position in text
144:          * @return text with replaced characters
145:          */
146:         public static String replaceFromToWithWhitespace(final String text, final int from, final int to) {
147:                 String result = text;
148:                 final String pre = result.substring(0, from);
149:                 String oldComment;
150:                 if (to - from > 0) {
151:                         oldComment = generateSpaces(to - from);
152:                 } else {
153:                         oldComment = "";
154:                 }
155:                 final String after = result.substring(to);
156:                 result = pre + oldComment + after;
157:                 return result;
158:         }
159:         
160:         /**
161:          * Generates a String with the given number of spaces.
162:          *
163:          * @param n
164:          * The number of spaces in the return value
165:          * @return A given number (n) of spaces
166:          *
167:          */
168:         private static String generateSpaces(final int n) {
169:                 return String.format("%1$" + n + "s", "");
170:         }
171:         
172:         /**
173:          * Finds the next position of the given literal. Skips existing escaped literals.
174:          *
175:          * @param literal
176:          * java literal (", ') to be searched for.
177:          * @param file
178:          * text to be searched in
179:          * @param startPos
180:          * start position for searching non-escaped character
181:          * @return position in the file (after startPos) where the literal has been found
182:          */
183:         public static int findNextQuotation(final String literal, final String file, final int startPos) {
184:                 int pos = file.indexOf(literal, startPos);
185:                 while (pos > 0) {
186:                         if (isNotEscaped(file, pos)) {
187:                                 return pos;
188:                         }
189:                         
190:                         pos = file.indexOf(literal, pos + 1);
191:                 }
192:                 return pos;
193:         }
194:         
195:         private static boolean isNotEscaped(final String file, final int pos) {
196:                 final int startPos = pos;
197:                 int currentPos = pos;
198:                 while (file.charAt(currentPos - 1) == '\\') {
199:                         currentPos--;
200:                 }
201:                 return (currentPos - startPos) % 2 == 0;
202:         }
203:         
204:         /**
205:          * Searches for Java end line comments (//) and deletes them.
206:          *
207:          * @param file
208:          * text of the java source code
209:          * @return file with whithened comments (= replaced by equivalent amount of spaces).
210:          */
211:         public static String deleteEndOfLineComments(final String file) {
212:                 final String pattern = "(?<!\\*)//.*";
213:                 String withoutcomments = file;
214:                 final Pattern p = Pattern.compile(pattern);
215:                 final Matcher m = p.matcher(file);
216:                 while (m.find()) {
217:                         withoutcomments = replaceFromToWithWhitespace(withoutcomments, m.start(), m.end());
218:                 }
219:                 return withoutcomments;
220:         }
221:         
222:         /**
223:          * Search beginning from position backwards for possible comments.
224:          *
225:          * @param position
226:          * @param file
227:          * @param withoutcommentFile
228:          * @return Returns the start + end position of a possible comment. <operationStart> otherwise.
229:          */
230:         public static Tuple<Integer, Integer> getCommentBefore(final int position,
231:                         final String file,
232:                         final String withoutcommentFile) {
233:                 final int end = file.lastIndexOf(COMMENT_CLOSE, position);
234:                 final int begin = file.lastIndexOf(COMMENT_OPEN, position);
235:                 if (end > begin && end > 0 && begin >= 0 && !withoutcommentFile.substring(end, position).contains(";")
236:                                 && !withoutcommentFile.substring(end, position).contains("{")) {
237:                         return new Tuple<>(begin, end + 2);
238:                 }
239:                 return new Tuple<>(position, position);
240:         }
241:         
242:         /**
243:          * Searches for string literals and returns the file without string literals. They are replaced by spaces.
244:          *
245:          * @param file
246:          * file possibly containing string literals (String a = "This is a literal"; ==> String a = ;).
247:          * @return file containing no literals but spaces instead
248:          * @throws ClipperImportFormatException
249:          *
250:          * Attention: requires a file without comments!
251:          */
252:         public static String deleteStringLiterals(final String file) throws ClipperImportFormatException {
253:                 final String nextStringLiteralDoubleSign = JAVA_STRING_LITERAL_DOUBLE_SIGN;
254:                 final String nextStringLiteralSingleSign = JAVA_STRING_LITERAL_SINGLE_SIGN;
255:                 int start1, end1, start2, end2;
256:                 String withoutComments = file;
257:                 
258:                 int pos = 0;
259:                 
260:                 while (true) {
261:                         start2 = findNextQuotation(nextStringLiteralDoubleSign, file, pos);
262:                         end2 = findNextQuotation(nextStringLiteralDoubleSign, file, start2 + 1);
263:                         start1 = findNextQuotation(nextStringLiteralSingleSign, file, pos);
264:                         end1 = findNextQuotation(nextStringLiteralSingleSign, file, start1 + 1);
265:                         if ((end1 < start2 || start2 == -1) && end1 != -1 && start1 != -1) {
266:                                 pos = end1 + 1;
267:                                 withoutComments = replaceFromToWithWhitespace(withoutComments, start1, end1 + 1);
268:                         } else if ((end2 < start1 || start1 == -1) && end2 != -1 && start2 != -1) {
269:                                 pos = end2 + 1;
270:                                 withoutComments = replaceFromToWithWhitespace(withoutComments, start2, end2 + 1);
271:                         } else if (start2 != -1 && end2 == -1 || start1 != -1 && end1 == -1) {
272:                                 throw new ClipperImportFormatException("Error while parsing quotes");
273:                         } else {
274:                                 break;
275:                         }
276:                         
277:                 }
278:                 
279:                 return withoutComments;
280:         }
281:         
282:         /**
283:          * Simplifies Java code by removing comments, generics, implementations, visibilities and other modifiers.
284:          *
285:          * @param file
286:          * java source code
287:          * @return simplified java code
288:          * @throws ClipperImportFormatException
289:          * when the java code cannot be parsed
290:          */
291:         public static String simplifyJavaCode(final String file) throws ClipperImportFormatException {
292:                 String simpleFile = ClipperUtils.deleteEndOfLineComments(file);
293:                 simpleFile = ClipperUtils.deleteBlockComments(simpleFile);
294:                 simpleFile = ClipperUtils.deleteStringLiterals(simpleFile);
295:                 simpleFile = ClipperUtils.splitInnerClasses(simpleFile);
296:                 simpleFile = ClipperUtils.deleteAttributeImplementations(simpleFile);
297:                 // simpleFile = ClipperUtils.deleteAllGenerics(simpleFile);
298:                 simpleFile = ClipperUtils.deleteAllAnnotations(simpleFile);
299:                 final Collection<String> modifierList = new ArrayList<>();
300:                 modifierList.add("private");
301:                 modifierList.add("public");
302:                 modifierList.add("synchronized");
303:                 modifierList.add("protected");
304:                 modifierList.add("transient");
305:                 modifierList.add("static");
306:                 modifierList.add("final");
307:                 modifierList.add("abstract");
308:                 
309:                 final Iterator<String> i = modifierList.iterator();
310:•                while (i.hasNext()) {
311:                         final String current = i.next();
312:                         final String regex = "(?<![A-Za-z0-9_])" + current + "(?![A-Za-z0-9_])";
313:                         simpleFile = simpleFile.replaceAll(regex, generateSpaces(current.length()));
314:                 }
315:                 
316:                 return simpleFile;
317:         }
318:         
319:         /**
320:          * Replaces attribute implementations by ";", e.g. converts "int a = 5;" to "int a;".
321:          *
322:          * @param simpleFile
323:          * @return
324:          * @throws ClipperImportFormatException
325:          */
326:         @SuppressWarnings("javadoc")
327:         private static String deleteAttributeImplementations(final String simpleFile) throws ClipperImportFormatException {
328:                 String result = simpleFile;
329:                 while (true) {
330:                         final int start = result.indexOf('=');
331:                         if (start == -1) {
332:                                 break;
333:                         }
334:                         final int semicolon = result.indexOf(';', start);
335:                         if (semicolon == -1) {
336:                                 throw new ClipperImportFormatException("Semicolon missing!");
337:                         }
338:                         result = replaceFromToWithWhitespace(result, start, semicolon);
339:                 }
340:                 return result;
341:         }
342:         
343:         /**
344:          * Detects inner classes and does not remove them if the code will be simpliefied
345:          *
346:          * @param simpleFile
347:          * @return returns the simple code
348:          * @throws ClipperImportFormatException
349:          */
350:         public static String splitInnerClasses(final String simpleFile) throws ClipperImportFormatException {
351:                 
352:                 String result = "";
353:                 String suffix = simpleFile;
354:                 
355:                 final int classIndex = suffix.indexOf(" class ");
356:                 final int interfaceIndex = suffix.indexOf(" interface ");
357:                 int start =
358:                                 ((classIndex > -1 && interfaceIndex > -1) ? Math.min(classIndex, interfaceIndex) : Math.max(
359:                                                 classIndex,
360:                                                 interfaceIndex));
361:                 int open = suffix.indexOf('{');
362:                 
363:                 while (open > -1) {
364:                         final Integer close = ClipToFileTask.findCorrespondingClosingCurlyBracket(open, suffix);
365:                         
366:                         if (start == -1 || start > open) {
367:                                 // No class / interface found at the beginning
368:                                 final String sub = suffix.substring(0, close);
369:                                 result = result + replaceFromToWithWhitespace(sub, open, close) + ";";
370:                                 suffix = suffix.substring(close + 1);
371:                         } else {
372:                                 // Class / interface found at the beginning
373:                                 result = result + suffix.substring(0, open + 1);
374:                                 final String core = suffix.substring(open + 1, close);
375:                                 result = result + ClipperUtils.splitInnerClasses(core);
376:                                 suffix = suffix.substring(close);
377:                         }
378:                         start = Math.max(suffix.indexOf(" class "), suffix.indexOf(" interface "));
379:                         open = suffix.indexOf('{');
380:                 }
381:                 return result + (suffix.length() > 0 ? suffix : "");
382:         }
383:         
384:         private static String deleteAllAnnotations(final String withoutcommentFile) {
385:                 String result = withoutcommentFile;
386:                 while (true) {
387:                         final int indexStart = result.indexOf('@');
388:                         if (indexStart == -1) {
389:                                 break;
390:                         }
391:                         final String pattern = "@\\s*[A-Za-z0-9]+.*\\n";
392:                         final Pattern p = Pattern.compile(pattern);
393:                         final Matcher m = p.matcher(result);
394:                         if (m.find(indexStart)) {
395:                                 final int indexEnd = m.end() - 1;
396:                                 result = ClipperUtils.replaceFromToWithWhitespace(result, indexStart, indexEnd);
397:                         }
398:                 }
399:                 return result;
400:         }
401:         
402:         /**
403:          * TODO
404:          *
405:          * @param openBracketPos
406:          * @param file
407:          * @return
408:          * @throws ClipperImportFormatException
409:          */
410:         @SuppressWarnings("javadoc")
411:         public static Integer findCorrespondingClosingCurlyBracket(final int openBracketPos, final String file)
412:                         throws ClipperImportFormatException {
413:                 Integer result = openBracketPos;
414:                 Integer openBracketMinusClosed = 1;
415:                 while (openBracketMinusClosed != 0) {
416:                         final int indexOfClose = file.indexOf(String.valueOf('}'), result + 1);
417:                         final int indexOfOpen = file.indexOf(String.valueOf('{'), result + 1);
418:                         if (indexOfClose < indexOfOpen || indexOfOpen == -1) {
419:                                 openBracketMinusClosed--;
420:                                 result = indexOfClose;
421:                         } else {
422:                                 openBracketMinusClosed++;
423:                                 result = indexOfOpen;
424:                         }
425:                         if (indexOfClose == -1) {
426:                                 throw new ClipperImportFormatException("Unbalanced Brackets!");
427:                         }
428:                 }
429:                 return result;
430:         }
431:         
432:         /**
433:          * TODO
434:          *
435:          * @param openBracketPos
436:          * @param file
437:          * @return
438:          * @throws ClipperImportFormatException
439:          */
440:         @SuppressWarnings("javadoc")
441:         public static Integer findCorrespondingClosingRoundBracket(final int openBracketPos, final String file)
442:                         throws ClipperImportFormatException {
443:                 Integer result = openBracketPos;
444:                 Integer openBracketMinusClosed = 1;
445:                 while (openBracketMinusClosed != 0) {
446:                         final int indexOfClose = file.indexOf(String.valueOf(')'), result + 1);
447:                         final int indexOfOpen = file.indexOf(String.valueOf('('), result + 1);
448:                         if (indexOfClose < indexOfOpen || indexOfOpen == -1) {
449:                                 openBracketMinusClosed--;
450:                                 result = indexOfClose;
451:                         } else {
452:                                 openBracketMinusClosed++;
453:                                 result = indexOfOpen;
454:                         }
455:                         if (indexOfClose == -1) {
456:                                 throw new ClipperImportFormatException("Unbalanced Brackets!");
457:                         }
458:                 }
459:                 return result;
460:         }
461:         
462:         /**
463:          * Searches for generics and returns the file without generics. They are replaced by spaces.
464:          *
465:          * @param file
466:          * file possibly containing generics (Collection<Y extends Exception> list ==> Collection list).
467:          * @return file containing no generics but spaces instead
468:          *
469:          * Attention: requires a file without comments and literals
470:          * @throws ClipperImportFormatException
471:          * on parsing errors, e.g. when generics brackets are not closed
472:          */
473:         public static String deleteAllGenerics(final String file) throws ClipperImportFormatException {
474:                 String withoutComments = file;
475:                 int start, end;
476:                 final String genericsBeginSign = "<";
477:                 final String genericsEndSign = ">";
478:                 
479:                 int bracketCounter = 0;
480:                 int startBracketOpen = 0;
481:                 int pos = 0;
482:                 
483:                 while (true) {
484:                         start = findNextQuotation(genericsBeginSign, file, pos);
485:                         end = findNextQuotation(genericsEndSign, file, pos);
486:                         if (end == -1) {
487:                                 if (bracketCounter != 0) {
488:                                         throw new ClipperImportFormatException("Error while parsing generics");
489:                                 } else {
490:                                         break;
491:                                 }
492:                         } else if (start < end && start != -1) {
493:                                 pos = start + 1;
494:                                 if (bracketCounter == 0) {
495:                                         startBracketOpen = start;
496:                                 }
497:                                 bracketCounter++;
498:                                 
499:                         } else if (end < start || start == -1) {
500:                                 pos = end + 1;
501:                                 bracketCounter--;
502:                         }
503:                         if (bracketCounter == 0) {
504:                                 withoutComments = replaceFromToWithWhitespace(withoutComments, startBracketOpen, end + 1);
505:                         }
506:                         
507:                 }
508:                 
509:                 return withoutComments;
510:         }
511:         
512:         /**
513:          * Retrieves a full method from the string.
514:          *
515:          * @param operation
516:          * operation with method
517:          * @param opName
518:          * name of the given operation
519:          * @return parsed Operation
520:          * @throws NoMatchingMethodException
521:          * when the method cannot be parsed
522:          */
523:         public static GenFullParsedOperationState parseOperation(final String operation, final String opName)
524:                         throws NoMatchingMethodException {
525:                 GenVisibility vis = GenVisibility.DEFAULT;
526:                 final Collection<de.fhdw.wtf.generator.java.generatorModel.GenException> exc = new ArrayList<>();
527:                 String met = CLIPPER_ERROR_NO_METHOD;
528:                 String returntype = null;
529:                 final Collection<GenOperationModifier> modifier = new ArrayList<>();
530:                 String comment;
531:                 
532:                 try {
533:                         comment = "";
534:                         String withoutCommentsFile = ClipperUtils.deleteEndOfLineComments(operation);
535:                         withoutCommentsFile = ClipperUtils.deleteBlockComments(withoutCommentsFile);
536:                         final Matcher m = getMatcher(operation, withoutCommentsFile, opName);
537:                         if (m.matches()) {
538:                                 if (hasVisi(operation)) {
539:                                         vis = parseVisibility(m.group("visi"));
540:                                 }
541:                                 if (m.group("met") != null) {
542:                                         met = m.group("met").trim();
543:                                 }
544:                                 returntype = m.group("ret");
545:                                 if (hasComment(operation)) {
546:                                         comment = m.group("comment");
547:                                 }
548:                         } else {
549:                                 throw new NoMatchingMethodException(operation);
550:                         }
551:                         
552:                 } catch (final ClipperImportFormatException e) {
553:                         System.out.println(e.getMessage());
554:                         throw new NoMatchingMethodException(operation);
555:                 }
556:                 
557:                 return GenFullParsedOperationState.create(
558:                                 GenComment.create(comment),
559:                                 exc,
560:                                 GenTypeReferenceByName.create(returntype),
561:                                 modifier,
562:                                 vis,
563:                                 met);
564:         }
565:         
566:         private static Matcher getMatcher(final String file, final String withoutCommentsFile, final String opName) {
567:                 String commentReg = "";
568:                 if (hasComment(file)) {
569:                         commentReg = "(?<comment>/\\*.*\\*/)";
570:                 }
571:                 String visiReg = "(?<visi>(public|private|protected))";
572:                 if (!hasVisi(withoutCommentsFile)) {
573:                         visiReg += "?";
574:                 }
575:                 String abstractReg = "(?<abstract>\\sabstract\\s)";
576:                 if (!hasAbstract(withoutCommentsFile)) {
577:                         abstractReg = "";
578:                 }
579:                 final String returntypeReg = "(?<ret>([a-zA-Z_$\\.<>,]+))";
580:                 final String pattern =
581:                                 "\\s*" + commentReg + "\\s*(@[A-Za-z_<>\\(\\))]+)?\\s*" + visiReg + abstractReg + "\\s*"
582:                                                 + returntypeReg + "\\s+" + opName + "\\s*\\([^\\)]*\\)\\s*(\\{(?<met>.*)\\}|;)";
583:                 final Pattern p = Pattern.compile(pattern, Pattern.DOTALL);
584:                 final Matcher m = p.matcher(file);
585:                 return m;
586:         }
587:         
588:         private static boolean hasAbstract(final String withoutCommentsFile) {
589:                 final Pattern patt = Pattern.compile(".*\\sabstract\\s.*", Pattern.DOTALL);
590:                 final Matcher m = patt.matcher(withoutCommentsFile);
591:                 return m.matches();
592:         }
593:         
594:         /**
595:          * Checks whether the file contains an operation visibility.
596:          *
597:          * @param file
598:          * @return See comment
599:          */
600:         private static boolean hasVisi(final String file) {
601:                 final Pattern patt =
602:                                 Pattern.compile(
603:                                                 ".*(\\*/)?(\\s*)?(@[A-Za-z_<>\\(\\))]+)?\\s*(public|protected|private).*",
604:                                                 Pattern.DOTALL);
605:                 final Matcher m = patt.matcher(file);
606:                 return m.matches();
607:         }
608:         
609:         /**
610:          * Checks whether the file contains a leading operation comment.
611:          *
612:          * @param file
613:          * @return See comment
614:          */
615:         private static boolean hasComment(final String file) {
616:                 final Pattern patt = Pattern.compile("\\s*/\\*.*", Pattern.DOTALL);
617:                 final Matcher m = patt.matcher(file);
618:                 return m.matches();
619:         }
620:         
621:         private static GenVisibility parseVisibility(final String group) {
622:                 switch (group) {
623:                 case "public":
624:                         return GenVisibility.PUBLIC;
625:                 case "protected":
626:                         return GenVisibility.PROTECTED;
627:                 case "private":
628:                         return GenVisibility.PRIVATE;
629:                 default:
630:                         return GenVisibility.DEFAULT;
631:                 }
632:         }
633: }