001
014
015 package com.liferay.portal.tools;
016
017 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
018 import com.liferay.portal.kernel.util.GetterUtil;
019 import com.liferay.portal.kernel.util.StringBundler;
020 import com.liferay.portal.kernel.util.StringPool;
021 import com.liferay.portal.kernel.util.StringUtil;
022 import com.liferay.portal.kernel.util.Tuple;
023 import com.liferay.portal.kernel.util.Validator;
024 import com.liferay.portal.kernel.xml.Document;
025 import com.liferay.portal.kernel.xml.Element;
026 import com.liferay.portal.tools.servicebuilder.ServiceBuilder;
027 import com.liferay.portal.util.FileImpl;
028 import com.liferay.portal.xml.SAXReaderImpl;
029 import com.liferay.util.xml.DocUtil;
030
031 import com.thoughtworks.qdox.JavaDocBuilder;
032 import com.thoughtworks.qdox.model.AbstractBaseJavaEntity;
033 import com.thoughtworks.qdox.model.AbstractJavaEntity;
034 import com.thoughtworks.qdox.model.Annotation;
035 import com.thoughtworks.qdox.model.DocletTag;
036 import com.thoughtworks.qdox.model.JavaClass;
037 import com.thoughtworks.qdox.model.JavaField;
038 import com.thoughtworks.qdox.model.JavaMethod;
039 import com.thoughtworks.qdox.model.JavaPackage;
040 import com.thoughtworks.qdox.model.JavaParameter;
041 import com.thoughtworks.qdox.model.Type;
042
043 import java.io.File;
044 import java.io.FileInputStream;
045 import java.io.InputStream;
046 import java.io.Reader;
047
048 import java.util.ArrayList;
049 import java.util.Collection;
050 import java.util.HashMap;
051 import java.util.HashSet;
052 import java.util.List;
053 import java.util.Map;
054 import java.util.Set;
055 import java.util.TreeMap;
056 import java.util.regex.Matcher;
057 import java.util.regex.Pattern;
058
059 import org.apache.tools.ant.DirectoryScanner;
060
061
066 public class JavadocFormatter {
067
068 public static void main(String[] args) {
069 try {
070 new JavadocFormatter(args);
071 }
072 catch (Exception e) {
073 e.printStackTrace();
074 }
075 }
076
077 public JavadocFormatter(String[] args) throws Exception {
078 Map<String, String> arguments = ArgumentsUtil.parseArguments(args);
079
080 String init = arguments.get("javadoc.init");
081
082 if (Validator.isNotNull(init) && !init.startsWith("$")) {
083 _initializeMissingJavadocs = GetterUtil.getBoolean(init);
084 }
085
086 _inputDir = GetterUtil.getString(arguments.get("javadoc.input.dir"));
087
088 if (_inputDir.startsWith("$")) {
089 _inputDir = "./";
090 }
091
092 if (!_inputDir.endsWith("/")) {
093 _inputDir += "/";
094 }
095
096 System.out.println("Input directory is " + _inputDir);
097
098 String limit = arguments.get("javadoc.limit");
099
100 _outputFilePrefix = GetterUtil.getString(
101 arguments.get("javadoc.output.file.prefix"));
102
103 if (_outputFilePrefix.startsWith("$")) {
104 _outputFilePrefix = "javadocs";
105 }
106
107 String update = arguments.get("javadoc.update");
108
109 if (Validator.isNotNull(update) && !update.startsWith("$")) {
110 _updateJavadocs = GetterUtil.getBoolean(update);
111 }
112
113 DirectoryScanner directoryScanner = new DirectoryScanner();
114
115 directoryScanner.setBasedir(_inputDir);
116 directoryScanner.setExcludes(
117 new String[] {"**\\classes\\**", "**\\portal-client\\**"});
118
119 List<String> includes = new ArrayList<String>();
120
121 if (Validator.isNotNull(limit) && !limit.startsWith("$")) {
122 System.out.println("Limit on " + limit);
123
124 String[] limitArray = StringUtil.split(limit, '/');
125
126 for (String curLimit : limitArray) {
127 includes.add(
128 "**\\" + StringUtil.replace(curLimit, ".", "\\") +
129 "\\**\\*.java");
130 includes.add("**\\" + curLimit + ".java");
131 }
132 }
133 else {
134 includes.add("**\\*.java");
135 }
136
137 directoryScanner.setIncludes(
138 includes.toArray(new String[includes.size()]));
139
140 directoryScanner.scan();
141
142 String[] fileNames = directoryScanner.getIncludedFiles();
143
144 if ((fileNames.length == 0) && Validator.isNotNull(limit) &&
145 !limit.startsWith("$")) {
146
147 StringBundler sb = new StringBundler("Limit file not found: ");
148
149 sb.append(limit);
150
151 if (limit.contains(".")) {
152 sb.append(" Specify limit filename without package path or ");
153 sb.append("file type suffix.");
154 }
155
156 System.out.println(sb.toString());
157 }
158
159 for (String fileName : fileNames) {
160 fileName = StringUtil.replace(fileName, "\\", "/");
161
162 _format(fileName);
163 }
164
165 for (Map.Entry<String, Tuple> entry : _javadocxXmlTuples.entrySet()) {
166 Tuple tuple = entry.getValue();
167
168 File javadocsXmlFile = (File)tuple.getObject(1);
169 String oldJavadocsXmlContent = (String)tuple.getObject(2);
170 Document javadocsXmlDocument = (Document)tuple.getObject(3);
171
172 Element javadocsXmlRootElement =
173 javadocsXmlDocument.getRootElement();
174
175 javadocsXmlRootElement.sortElementsByChildElement(
176 "javadoc", "type");
177
178 String newJavadocsXmlContent =
179 javadocsXmlDocument.formattedString();
180
181 if (!oldJavadocsXmlContent.equals(newJavadocsXmlContent)) {
182 _fileUtil.write(javadocsXmlFile, newJavadocsXmlContent);
183 }
184
185 _detachUnnecessaryTypes(javadocsXmlRootElement);
186
187 File javadocsRuntimeXmlFile = new File(
188 StringUtil.replaceLast(
189 javadocsXmlFile.toString(), "-all.xml", "-rt.xml"));
190
191 String oldJavadocsRuntimeXmlContent = StringPool.BLANK;
192
193 if (javadocsRuntimeXmlFile.exists()) {
194 oldJavadocsRuntimeXmlContent = _fileUtil.read(
195 javadocsRuntimeXmlFile);
196 }
197
198 String newJavadocsRuntimeXmlContent =
199 javadocsXmlDocument.compactString();
200
201 if (!oldJavadocsRuntimeXmlContent.equals(
202 newJavadocsRuntimeXmlContent)) {
203
204 _fileUtil.write(
205 javadocsRuntimeXmlFile, newJavadocsRuntimeXmlContent);
206 }
207 }
208 }
209
210 private void _addClassCommentElement(
211 Element rootElement, JavaClass javaClass) {
212
213 String comment = _getCDATA(javaClass);
214
215 if (comment.startsWith("Copyright (c)")) {
216 comment = StringPool.BLANK;
217 }
218
219 if (Validator.isNull(comment)) {
220 return;
221 }
222
223 Element commentElement = rootElement.addElement("comment");
224
225 commentElement.addCDATA(comment);
226 }
227
228 private void _addDocletElements(
229 Element parentElement, AbstractJavaEntity abstractJavaEntity,
230 String name)
231 throws Exception {
232
233 DocletTag[] docletTags = abstractJavaEntity.getTagsByName(name);
234
235 for (DocletTag docletTag : docletTags) {
236 String value = docletTag.getValue();
237
238 value = _trimMultilineText(value);
239
240 value = StringUtil.replace(value, " </", "</");
241
242 Element element = parentElement.addElement(name);
243
244 element.addCDATA(value);
245 }
246
247 if ((docletTags.length == 0) && name.equals("author")) {
248 Element element = parentElement.addElement(name);
249
250 element.addCDATA(ServiceBuilder.AUTHOR);
251 }
252 }
253
254 private String _addDocletTags(
255 Element parentElement, String[] tagNames, String indent,
256 boolean publicAccess) {
257
258 List<String> allTagNames = new ArrayList<String>();
259 List<String> commonTagNamesWithComments = new ArrayList<String>();
260 List<String> customTagNames = new ArrayList<String>();
261
262 for (String tagName : tagNames) {
263 List<Element> elements = parentElement.elements(tagName);
264
265 for (Element element : elements) {
266 Element commentElement = element.element("comment");
267
268 String comment = null;
269
270
271
272 if (commentElement != null) {
273 comment = commentElement.getText();
274 }
275 else {
276 comment = element.getText();
277 }
278
279 if (tagName.equals("param") || tagName.equals("return") ||
280 tagName.equals("throws")) {
281
282 if (Validator.isNotNull(comment)) {
283 commonTagNamesWithComments.add(tagName);
284 }
285 }
286 else {
287 customTagNames.add(tagName);
288 }
289
290 allTagNames.add(tagName);
291 }
292 }
293
294 int maxTagNameLength = 0;
295
296 List<String> maxTagNameLengthTags = new ArrayList<String>();
297
298 if (_initializeMissingJavadocs) {
299 maxTagNameLengthTags.addAll(allTagNames);
300 }
301 else if (_updateJavadocs) {
302 if (!commonTagNamesWithComments.isEmpty()) {
303 maxTagNameLengthTags.addAll(allTagNames);
304 }
305 else {
306 maxTagNameLengthTags.addAll(commonTagNamesWithComments);
307 maxTagNameLengthTags.addAll(customTagNames);
308 }
309 }
310 else {
311 maxTagNameLengthTags.addAll(commonTagNamesWithComments);
312 maxTagNameLengthTags.addAll(customTagNames);
313 }
314
315 for (String name : maxTagNameLengthTags) {
316 if (name.length() > maxTagNameLength) {
317 maxTagNameLength = name.length();
318 }
319 }
320
321
322
323 maxTagNameLength += 2;
324
325 String tagNameIndent = _getSpacesIndent(maxTagNameLength);
326
327 StringBundler sb = new StringBundler();
328
329 for (String tagName : tagNames) {
330 List<Element> elements = parentElement.elements(tagName);
331
332 for (Element element : elements) {
333 Element commentElement = element.element("comment");
334
335 String comment = null;
336
337 if (commentElement != null) {
338 comment = commentElement.getText();
339 }
340 else {
341 comment = element.getText();
342 }
343
344 String elementName = null;
345
346 if (commentElement != null) {
347 elementName = element.elementText("name");
348 }
349
350 if (Validator.isNotNull(comment)) {
351 comment = _assembleTagComment(
352 tagName, elementName, comment, indent, tagNameIndent);
353
354 sb.append(comment);
355 }
356 else {
357 if (_initializeMissingJavadocs && publicAccess) {
358
359
360
361 comment = _assembleTagComment(
362 tagName, elementName, comment, indent,
363 tagNameIndent);
364
365 sb.append(comment);
366 }
367 else if (_updateJavadocs && publicAccess) {
368 if (!tagName.equals("param") &&
369 !tagName.equals("return") &&
370 !tagName.equals("throws")) {
371
372
373
374 comment = _assembleTagComment(
375 tagName, elementName, comment, indent,
376 tagNameIndent);
377
378 sb.append(comment);
379 }
380 else if (!commonTagNamesWithComments.isEmpty()) {
381
382
383
384 comment = _assembleTagComment(
385 tagName, elementName, comment, indent,
386 tagNameIndent);
387
388 sb.append(comment);
389 }
390 else {
391
392
393
394 }
395 }
396 else {
397 if (!tagName.equals("param") &&
398 !tagName.equals("return") &&
399 !tagName.equals("throws")) {
400
401
402
403 comment = _assembleTagComment(
404 tagName, elementName, comment, indent,
405 tagNameIndent);
406
407 sb.append(comment);
408 }
409 else {
410
411
412
413 }
414 }
415 }
416 }
417 }
418
419 return sb.toString();
420 }
421
422 private void _addFieldElement(Element rootElement, JavaField javaField)
423 throws Exception {
424
425 Element fieldElement = rootElement.addElement("field");
426
427 DocUtil.add(fieldElement, "name", javaField.getName());
428
429 String comment = _getCDATA(javaField);
430
431 if (Validator.isNotNull(comment)) {
432 Element commentElement = fieldElement.addElement("comment");
433
434 commentElement.addCDATA(comment);
435 }
436
437 _addDocletElements(fieldElement, javaField, "version");
438 _addDocletElements(fieldElement, javaField, "see");
439 _addDocletElements(fieldElement, javaField, "since");
440 _addDocletElements(fieldElement, javaField, "deprecated");
441 }
442
443 private void _addMethodElement(Element rootElement, JavaMethod javaMethod)
444 throws Exception {
445
446 Element methodElement = rootElement.addElement("method");
447
448 DocUtil.add(methodElement, "name", javaMethod.getName());
449
450 String comment = _getCDATA(javaMethod);
451
452 if (Validator.isNotNull(comment)) {
453 Element commentElement = methodElement.addElement("comment");
454
455 commentElement.addCDATA(_getCDATA(javaMethod));
456 }
457
458 _addDocletElements(methodElement, javaMethod, "version");
459 _addParamElements(methodElement, javaMethod);
460 _addReturnElement(methodElement, javaMethod);
461 _addThrowsElements(methodElement, javaMethod);
462 _addDocletElements(methodElement, javaMethod, "see");
463 _addDocletElements(methodElement, javaMethod, "since");
464 _addDocletElements(methodElement, javaMethod, "deprecated");
465 }
466
467 private void _addParamElement(
468 Element methodElement, JavaParameter javaParameter,
469 DocletTag[] paramDocletTags) {
470
471 String name = javaParameter.getName();
472
473 String value = null;
474
475 for (DocletTag paramDocletTag : paramDocletTags) {
476 String curValue = paramDocletTag.getValue();
477
478 if (!curValue.startsWith(name)) {
479 continue;
480 }
481 else {
482 value = curValue;
483
484 break;
485 }
486 }
487
488 Element paramElement = methodElement.addElement("param");
489
490 DocUtil.add(paramElement, "name", name);
491 DocUtil.add(paramElement, "type", _getTypeValue(javaParameter));
492
493 if (value != null) {
494 value = value.substring(name.length());
495 }
496
497 value = _trimMultilineText(value);
498
499 if (Validator.isNotNull(value)) {
500 Element commentElement = paramElement.addElement("comment");
501
502 commentElement.addCDATA(value);
503 }
504 }
505
506 private void _addParamElements(
507 Element methodElement, JavaMethod javaMethod) {
508
509 JavaParameter[] javaParameters = javaMethod.getParameters();
510
511 DocletTag[] paramDocletTags = javaMethod.getTagsByName("param");
512
513 for (JavaParameter javaParameter : javaParameters) {
514 _addParamElement(methodElement, javaParameter, paramDocletTags);
515 }
516 }
517
518 private void _addReturnElement(
519 Element methodElement, JavaMethod javaMethod)
520 throws Exception {
521
522 Type returns = javaMethod.getReturns();
523
524 if (returns == null) {
525 return;
526 }
527
528 String returnsValue = returns.getValue();
529
530 if (returnsValue.equals("void")) {
531 return;
532 }
533
534 DocletTag[] returnDocletTags = javaMethod.getTagsByName("return");
535
536 String comment = StringPool.BLANK;
537
538 if (returnDocletTags.length > 0) {
539 DocletTag returnDocletTag = returnDocletTags[0];
540
541 comment = GetterUtil.getString(returnDocletTag.getValue());
542 }
543
544 comment = _trimMultilineText(comment);
545
546 if (Validator.isNotNull(comment)) {
547 Element returnElement = methodElement.addElement("return");
548
549 Element commentElement = returnElement.addElement("comment");
550
551 commentElement.addCDATA(comment);
552 }
553 }
554
555 private void _addThrowsElement(
556 Element methodElement, Type exceptionType,
557 DocletTag[] throwsDocletTags) {
558
559 JavaClass javaClass = exceptionType.getJavaClass();
560
561 String name = javaClass.getName();
562
563 String value = null;
564
565 for (DocletTag throwsDocletTag : throwsDocletTags) {
566 String curValue = throwsDocletTag.getValue();
567
568 if (!curValue.startsWith(name)) {
569 continue;
570 }
571 else {
572 value = curValue;
573
574 break;
575 }
576 }
577
578 Element throwsElement = methodElement.addElement("throws");
579
580 DocUtil.add(throwsElement, "name", name);
581 DocUtil.add(throwsElement, "type", exceptionType.getValue());
582
583 if (value != null) {
584 value = value.substring(name.length());
585 }
586
587 value = _trimMultilineText(value);
588
589 if (Validator.isNotNull(value)) {
590 Element commentElement = throwsElement.addElement("comment");
591
592 commentElement.addCDATA(_getCDATA(value));
593 }
594 }
595
596 private void _addThrowsElements(
597 Element methodElement, JavaMethod javaMethod) {
598
599 Type[] exceptionTypes = javaMethod.getExceptions();
600
601 DocletTag[] throwsDocletTags = javaMethod.getTagsByName("throws");
602
603 for (Type exceptionType : exceptionTypes) {
604 _addThrowsElement(methodElement, exceptionType, throwsDocletTags);
605 }
606 }
607
608 private String _assembleTagComment(
609 String tagName, String elementName, String comment, String indent,
610 String tagNameIndent) {
611
612 String indentAndTagName = indent + StringPool.AT + tagName;
613
614 if (Validator.isNotNull(elementName)) {
615 if (Validator.isNotNull(comment)) {
616 comment = elementName + StringPool.SPACE + comment;
617 }
618 else {
619 comment = elementName;
620 }
621
622
623
624 comment = _wrapText(comment, indent + tagNameIndent);
625
626
627
628 comment =
629 indentAndTagName + comment.substring(indentAndTagName.length());
630 }
631 else {
632 if (Validator.isNotNull(comment)) {
633
634
635
636 comment = _wrapText(comment, indent + tagNameIndent);
637
638
639
640 comment =
641 indentAndTagName +
642 comment.substring(indentAndTagName.length());
643 }
644 else {
645
646
647
648 comment = indentAndTagName + "\n";
649 }
650 }
651
652 return comment;
653 }
654
655 private void _detachUnnecessaryTypes(Element rootElement) {
656 List<Element> elements = rootElement.elements();
657
658 for (Element element : elements) {
659 String type = element.elementText("type");
660
661 if (!type.contains(".service.") || !type.endsWith("ServiceImpl")) {
662 element.detach();
663 }
664 }
665 }
666
667 private void _format(String fileName) throws Exception {
668 InputStream inputStream = new FileInputStream(_inputDir + fileName);
669
670 byte[] bytes = new byte[inputStream.available()];
671
672 inputStream.read(bytes);
673
674 inputStream.close();
675
676 String originalContent = new String(bytes, StringPool.UTF8);
677
678 if (fileName.endsWith("JavadocFormatter.java") ||
679 fileName.endsWith("SourceFormatter.java") ||
680 _hasGeneratedTag(originalContent)) {
681
682 return;
683 }
684
685 JavaClass javaClass = _getJavaClass(
686 fileName, new UnsyncStringReader(originalContent));
687
688 String javadocLessContent = _removeJavadocFromJava(
689 javaClass, originalContent);
690
691 Document document = _getJavadocDocument(javaClass);
692
693 _updateJavadocsXmlFile(fileName, javaClass, document);
694
695 _updateJavaFromDocument(
696 fileName, originalContent, javadocLessContent, document);
697 }
698
699 private String _formatInlines(String text) {
700
701
702
703 text = text.replaceAll("(?i)\\bid(s)?\\b", "ID$1");
704
705
706
707 text = text.replaceAll(
708 "(?i)(?<!<code>|\\w)(null|false|true)(?!\\w)", "<code>$1</code>");
709
710 return text;
711 }
712
713 private List<JavaClass> _getAncestorJavaClasses(JavaClass javaClass) {
714 List<JavaClass> ancestorJavaClasses = new ArrayList<JavaClass>();
715
716 while ((javaClass = javaClass.getSuperJavaClass()) != null) {
717 ancestorJavaClasses.add(javaClass);
718 }
719
720 return ancestorJavaClasses;
721 }
722
723 private String _getCDATA(AbstractJavaEntity abstractJavaEntity) {
724 return _getCDATA(abstractJavaEntity.getComment());
725 }
726
727 private String _getCDATA(String cdata) {
728 if (cdata == null) {
729 return StringPool.BLANK;
730 }
731
732 cdata = cdata.replaceAll(
733 "(?s)\\s*<(p|pre|[ou]l)>\\s*(.*?)\\s*</\\1>\\s*",
734 "\n\n<$1>\n$2\n</$1>\n\n");
735 cdata = cdata.replaceAll(
736 "(?s)\\s*<li>\\s*(.*?)\\s*</li>\\s*", "\n<li>\n$1\n</li>\n");
737 cdata = StringUtil.replace(cdata, "</li>\n\n<li>", "</li>\n<li>");
738 cdata = cdata.replaceAll("\n\\s+\n", "\n\n");
739 cdata = cdata.replaceAll(" +", " ");
740
741
742
743 Pattern pattern = Pattern.compile(
744 "(^.*?(?=\n\n|$)+|(?<=<p>\n).*?(?=\n</p>))", Pattern.DOTALL);
745
746 Matcher matcher = pattern.matcher(cdata);
747
748 StringBuffer sb = new StringBuffer();
749
750 while (matcher.find()) {
751 String trimmed = _trimMultilineText(matcher.group());
752
753
754
755 trimmed = trimmed.replaceAll("\\$", "\\\\\\$");
756
757 matcher.appendReplacement(sb, trimmed);
758 }
759
760 matcher.appendTail(sb);
761
762 cdata = sb.toString();
763
764 return cdata.trim();
765 }
766
767 private String _getClassName(String fileName) {
768 int pos = fileName.indexOf("src/");
769
770 if (pos == -1) {
771 pos = fileName.indexOf("test/integration/");
772
773 if (pos != -1) {
774 pos = fileName.indexOf("integration/", pos);
775 }
776 }
777
778 if (pos == -1) {
779 pos = fileName.indexOf("test/unit/");
780
781 if (pos != -1) {
782 pos = fileName.indexOf("unit/", pos);
783 }
784 }
785
786 if (pos == -1) {
787 pos = fileName.indexOf("test/");
788 }
789
790 if (pos == -1) {
791 pos = fileName.indexOf("service/");
792 }
793
794 if (pos == -1) {
795 throw new RuntimeException(fileName);
796 }
797
798 pos = fileName.indexOf("/", pos);
799
800 String srcFile = fileName.substring(pos + 1, fileName.length());
801
802 return StringUtil.replace(
803 srcFile.substring(0, srcFile.length() - 5), "/", ".");
804 }
805
806 private String _getFieldKey(Element fieldElement) {
807 return fieldElement.elementText("name");
808 }
809
810 private String _getFieldKey(JavaField javaField) {
811 return javaField.getName();
812 }
813
814 private String _getIndent(
815 String[] lines, AbstractBaseJavaEntity abstractBaseJavaEntity) {
816
817 String line = lines[abstractBaseJavaEntity.getLineNumber() - 1];
818
819 String indent = StringPool.BLANK;
820
821 for (char c : line.toCharArray()) {
822 if (Character.isWhitespace(c)) {
823 indent += c;
824 }
825 else {
826 break;
827 }
828 }
829
830 return indent;
831 }
832
833 private int _getIndentLength(String indent) {
834 int indentLength = 0;
835
836 for (char c : indent.toCharArray()) {
837 if (c == '\t') {
838 indentLength = indentLength + 4;
839 }
840 else {
841 indentLength++;
842 }
843 }
844
845 return indentLength;
846 }
847
848 private JavaClass _getJavaClass(String fileName, Reader reader)
849 throws Exception {
850
851 String className = _getClassName(fileName);
852
853 JavaDocBuilder javadocBuilder = new JavaDocBuilder();
854
855 if (reader == null) {
856 File file = new File(fileName);
857
858 if (!file.exists()) {
859 return null;
860 }
861
862 javadocBuilder.addSource(file);
863 }
864 else {
865 javadocBuilder.addSource(reader);
866 }
867
868 return javadocBuilder.getClassByName(className);
869 }
870
871 private String _getJavaClassComment(
872 Element rootElement, JavaClass javaClass) {
873
874 StringBundler sb = new StringBundler();
875
876 String indent = StringPool.BLANK;
877
878 sb.append("\n");
902
903 return sb.toString();
904 }
905
906 private int _getJavaClassLineNumber(JavaClass javaClass) {
907 int lineNumber = javaClass.getLineNumber();
908
909 Annotation[] annotations = javaClass.getAnnotations();
910
911 if (annotations.length == 0) {
912 return lineNumber;
913 }
914
915 for (Annotation annotation : annotations) {
916 int annotationLineNumber = annotation.getLineNumber();
917
918 Map<String, String> propertyMap = annotation.getPropertyMap();
919
920 if (propertyMap.isEmpty()) {
921 annotationLineNumber--;
922 }
923
924 if (annotationLineNumber < lineNumber) {
925 lineNumber = annotationLineNumber;
926 }
927 }
928
929 return lineNumber;
930 }
931
932 private Document _getJavadocDocument(JavaClass javaClass) throws Exception {
933 Element rootElement = _saxReaderUtil.createElement("javadoc");
934
935 Document document = _saxReaderUtil.createDocument(rootElement);
936
937 DocUtil.add(rootElement, "name", javaClass.getName());
938 DocUtil.add(rootElement, "type", javaClass.getFullyQualifiedName());
939
940 _addClassCommentElement(rootElement, javaClass);
941 _addDocletElements(rootElement, javaClass, "author");
942 _addDocletElements(rootElement, javaClass, "version");
943 _addDocletElements(rootElement, javaClass, "see");
944 _addDocletElements(rootElement, javaClass, "since");
945 _addDocletElements(rootElement, javaClass, "serial");
946 _addDocletElements(rootElement, javaClass, "deprecated");
947
948 JavaMethod[] javaMethods = javaClass.getMethods();
949
950 for (JavaMethod javaMethod : javaMethods) {
951 _addMethodElement(rootElement, javaMethod);
952 }
953
954 JavaField[] javaFields = javaClass.getFields();
955
956 for (JavaField javaField : javaFields) {
957 _addFieldElement(rootElement, javaField);
958 }
959
960 return document;
961 }
962
963 private Tuple _getJavadocsXmlTuple(String fileName) throws Exception {
964 File file = new File(_inputDir + fileName);
965
966 String absolutePath = file.getAbsolutePath();
967
968 absolutePath = StringUtil.replace(absolutePath, "\\", "/");
969 absolutePath = StringUtil.replace(absolutePath, "/./", "/");
970
971 int pos = absolutePath.indexOf("/portal-impl/src/");
972
973 String srcDirName = null;
974
975 if (pos != -1) {
976 srcDirName = absolutePath.substring(0, pos + 17);
977 }
978
979 if (srcDirName == null) {
980 pos = absolutePath.indexOf("/portal-kernel/src/");
981
982 if (pos == -1) {
983 pos = absolutePath.indexOf("/portal-service/src/");
984 }
985
986 if (pos == -1) {
987 pos = absolutePath.indexOf("/util-bridges/src/");
988 }
989
990 if (pos == -1) {
991 pos = absolutePath.indexOf("/util-java/src/");
992 }
993
994 if (pos == -1) {
995 pos = absolutePath.indexOf("/util-taglib/src/");
996 }
997
998 if (pos != -1) {
999 srcDirName =
1000 absolutePath.substring(0, pos) + "/portal-impl/src/";
1001 }
1002 }
1003
1004 if (srcDirName == null) {
1005 pos = absolutePath.indexOf("/WEB-INF/src/");
1006
1007 if (pos != -1) {
1008 srcDirName = absolutePath.substring(0, pos + 13);
1009 }
1010 }
1011
1012 if (srcDirName == null) {
1013 return null;
1014 }
1015
1016 Tuple tuple = _javadocxXmlTuples.get(srcDirName);
1017
1018 if (tuple != null) {
1019 return tuple;
1020 }
1021
1022 File javadocsXmlFile = new File(
1023 srcDirName, "META-INF/" + _outputFilePrefix + "-all.xml");
1024
1025 if (!javadocsXmlFile.exists()) {
1026 _fileUtil.write(
1027 javadocsXmlFile,
1028 "<?xml version=\"1.0\"?>\n\n<javadocs>\n</javadocs>");
1029 }
1030
1031 String javadocsXmlContent = _fileUtil.read(javadocsXmlFile);
1032
1033 Document javadocsXmlDocument = _saxReaderUtil.read(javadocsXmlContent);
1034
1035 tuple = new Tuple(
1036 srcDirName, javadocsXmlFile, javadocsXmlContent,
1037 javadocsXmlDocument);
1038
1039 _javadocxXmlTuples.put(srcDirName, tuple);
1040
1041 return tuple;
1042 }
1043
1044 private String _getJavaFieldComment(
1045 String[] lines, Map<String, Element> fieldElementsMap,
1046 JavaField javaField) {
1047
1048 String fieldKey = _getFieldKey(javaField);
1049
1050 Element fieldElement = fieldElementsMap.get(fieldKey);
1051
1052 if (fieldElement == null) {
1053 return null;
1054 }
1055
1056 String indent = _getIndent(lines, javaField);
1057
1058 StringBundler sb = new StringBundler();
1059
1060 sb.append(indent);
1061 sb.append("\n");
1085
1086 if (!_initializeMissingJavadocs && Validator.isNull(comment) &&
1087 Validator.isNull(docletTags)) {
1088
1089 return null;
1090 }
1091
1092 if (!_hasPublicModifier(javaField) && Validator.isNull(comment) &&
1093 Validator.isNull(docletTags)) {
1094
1095 return null;
1096 }
1097
1098 return sb.toString();
1099 }
1100
1101 private String _getJavaMethodComment(
1102 String[] lines, Map<String, Element> methodElementsMap,
1103 JavaMethod javaMethod) {
1104
1105 String methodKey = _getMethodKey(javaMethod);
1106
1107 Element methodElement = methodElementsMap.get(methodKey);
1108
1109 if (methodElement == null) {
1110 return null;
1111 }
1112
1113 String indent = _getIndent(lines, javaMethod);
1114
1115 StringBundler sb = new StringBundler();
1116
1117 sb.append(indent);
1118 sb.append("\n");
1145
1146 if (!_initializeMissingJavadocs && Validator.isNull(comment) &&
1147 Validator.isNull(docletTags)) {
1148
1149 return null;
1150 }
1151
1152 if (!_hasPublicModifier(javaMethod) && Validator.isNull(comment) &&
1153 Validator.isNull(docletTags)) {
1154
1155 return null;
1156 }
1157
1158 return sb.toString();
1159 }
1160
1161 private String _getMethodKey(Element methodElement) {
1162 StringBundler sb = new StringBundler();
1163
1164 sb.append(methodElement.elementText("name"));
1165 sb.append(StringPool.OPEN_PARENTHESIS);
1166
1167 List<Element> paramElements = methodElement.elements("param");
1168
1169 for (Element paramElement : paramElements) {
1170 sb.append(paramElement.elementText("name"));
1171 sb.append("|");
1172 sb.append(paramElement.elementText("type"));
1173 sb.append(",");
1174 }
1175
1176 sb.append(StringPool.CLOSE_PARENTHESIS);
1177
1178 return sb.toString();
1179 }
1180
1181 private String _getMethodKey(JavaMethod javaMethod) {
1182 StringBundler sb = new StringBundler();
1183
1184 sb.append(javaMethod.getName());
1185 sb.append(StringPool.OPEN_PARENTHESIS);
1186
1187 JavaParameter[] javaParameters = javaMethod.getParameters();
1188
1189 for (JavaParameter javaParameter : javaParameters) {
1190 sb.append(javaParameter.getName());
1191 sb.append("|");
1192 sb.append(_getTypeValue(javaParameter));
1193 sb.append(",");
1194 }
1195
1196 sb.append(StringPool.CLOSE_PARENTHESIS);
1197
1198 return sb.toString();
1199 }
1200
1201 private String _getSpacesIndent(int length) {
1202 String indent = StringPool.BLANK;
1203
1204 for (int i = 0; i < length; i++) {
1205 indent += StringPool.SPACE;
1206 }
1207
1208 return indent;
1209 }
1210
1211 private String _getTypeValue(JavaParameter javaParameter) {
1212 Type type = javaParameter.getType();
1213
1214 String typeValue = type.getValue();
1215
1216 if (type.isArray()) {
1217 typeValue += "[]";
1218 }
1219
1220 return typeValue;
1221 }
1222
1223 private boolean _hasAnnotation(
1224 AbstractBaseJavaEntity abstractBaseJavaEntity, String annotationName) {
1225
1226 Annotation[] annotations = abstractBaseJavaEntity.getAnnotations();
1227
1228 if (annotations == null) {
1229 return false;
1230 }
1231
1232 for (int i = 0; i < annotations.length; i++) {
1233 Type type = annotations[i].getType();
1234
1235 JavaClass javaClass = type.getJavaClass();
1236
1237 if (annotationName.equals(javaClass.getName())) {
1238 return true;
1239 }
1240 }
1241
1242 return false;
1243 }
1244
1245 private boolean _hasGeneratedTag(String content) {
1246 if (content.contains("* @generated") || content.contains("$ANTLR")) {
1247 return true;
1248 }
1249 else {
1250 return false;
1251 }
1252 }
1253
1254 private boolean _hasPublicModifier(AbstractJavaEntity abstractJavaEntity) {
1255 String[] modifiers = abstractJavaEntity.getModifiers();
1256
1257 if (modifiers == null) {
1258 return false;
1259 }
1260
1261 for (String modifier : modifiers) {
1262 if (modifier.equals("public")) {
1263 return true;
1264 }
1265 }
1266
1267 return false;
1268 }
1269
1270 private boolean _isOverrideMethod(
1271 JavaClass javaClass, JavaMethod javaMethod,
1272 Collection<JavaClass> ancestorJavaClasses) {
1273
1274 if (javaClass.isInterface() || javaMethod.isConstructor() ||
1275 javaMethod.isPrivate() || javaMethod.isStatic()) {
1276
1277 return false;
1278 }
1279
1280 String methodName = javaMethod.getName();
1281
1282 JavaParameter[] javaParameters = javaMethod.getParameters();
1283
1284 Type[] types = new Type[javaParameters.length];
1285
1286 for (int i = 0; i < javaParameters.length; i++) {
1287 types[i] = javaParameters[i].getType();
1288 }
1289
1290
1291
1292 for (JavaClass ancestorJavaClass : ancestorJavaClasses) {
1293 JavaMethod ancestorJavaMethod =
1294 ancestorJavaClass.getMethodBySignature(methodName, types);
1295
1296 if (ancestorJavaMethod == null) {
1297 continue;
1298 }
1299
1300 boolean samePackage = false;
1301
1302 JavaPackage ancestorJavaPackage = ancestorJavaClass.getPackage();
1303
1304 if (ancestorJavaPackage != null) {
1305 samePackage = ancestorJavaPackage.equals(
1306 javaClass.getPackage());
1307 }
1308
1309
1310
1311 if (samePackage) {
1312 return !ancestorJavaMethod.isPrivate();
1313 }
1314 else {
1315 if (ancestorJavaMethod.isProtected() ||
1316 ancestorJavaMethod.isPublic()) {
1317
1318 return true;
1319 }
1320 else {
1321 return false;
1322 }
1323 }
1324 }
1325
1326 return false;
1327 }
1328
1329 private String _removeJavadocFromJava(
1330 JavaClass javaClass, String content) {
1331
1332 Set<Integer> lineNumbers = new HashSet<Integer>();
1333
1334 lineNumbers.add(_getJavaClassLineNumber(javaClass));
1335
1336 JavaMethod[] javaMethods = javaClass.getMethods();
1337
1338 for (JavaMethod javaMethod : javaMethods) {
1339 lineNumbers.add(javaMethod.getLineNumber());
1340 }
1341
1342 JavaField[] javaFields = javaClass.getFields();
1343
1344 for (JavaField javaField : javaFields) {
1345 lineNumbers.add(javaField.getLineNumber());
1346 }
1347
1348 String[] lines = StringUtil.splitLines(content);
1349
1350 for (int lineNumber : lineNumbers) {
1351 if (lineNumber == 0) {
1352 continue;
1353 }
1354
1355 int pos = lineNumber - 2;
1356
1357 String line = lines[pos];
1358
1359 if (line == null) {
1360 continue;
1361 }
1362
1363 line = line.trim();
1364
1365 if (line.endsWith("*/")) {
1366 while (true) {
1367 lines[pos] = null;
1368
1369 if (line.startsWith("