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