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/");
772 }
773
774 if (pos == -1) {
775 pos = fileName.indexOf("service/");
776 }
777
778 if (pos == -1) {
779 throw new RuntimeException(fileName);
780 }
781
782 pos = fileName.indexOf("/", pos);
783
784 String srcFile = fileName.substring(pos + 1, fileName.length());
785
786 return StringUtil.replace(
787 srcFile.substring(0, srcFile.length() - 5), "/", ".");
788 }
789
790 private String _getFieldKey(Element fieldElement) {
791 return fieldElement.elementText("name");
792 }
793
794 private String _getFieldKey(JavaField javaField) {
795 return javaField.getName();
796 }
797
798 private String _getIndent(
799 String[] lines, AbstractBaseJavaEntity abstractBaseJavaEntity) {
800
801 String line = lines[abstractBaseJavaEntity.getLineNumber() - 1];
802
803 String indent = StringPool.BLANK;
804
805 for (char c : line.toCharArray()) {
806 if (Character.isWhitespace(c)) {
807 indent += c;
808 }
809 else {
810 break;
811 }
812 }
813
814 return indent;
815 }
816
817 private int _getIndentLength(String indent) {
818 int indentLength = 0;
819
820 for (char c : indent.toCharArray()) {
821 if (c == '\t') {
822 indentLength = indentLength + 4;
823 }
824 else {
825 indentLength++;
826 }
827 }
828
829 return indentLength;
830 }
831
832 private JavaClass _getJavaClass(String fileName, Reader reader)
833 throws Exception {
834
835 String className = _getClassName(fileName);
836
837 JavaDocBuilder javadocBuilder = new JavaDocBuilder();
838
839 if (reader == null) {
840 File file = new File(fileName);
841
842 if (!file.exists()) {
843 return null;
844 }
845
846 javadocBuilder.addSource(file);
847 }
848 else {
849 javadocBuilder.addSource(reader);
850 }
851
852 return javadocBuilder.getClassByName(className);
853 }
854
855 private String _getJavaClassComment(
856 Element rootElement, JavaClass javaClass) {
857
858 StringBundler sb = new StringBundler();
859
860 String indent = StringPool.BLANK;
861
862 sb.append("\n");
886
887 return sb.toString();
888 }
889
890 private int _getJavaClassLineNumber(JavaClass javaClass) {
891 int lineNumber = javaClass.getLineNumber();
892
893 Annotation[] annotations = javaClass.getAnnotations();
894
895 if (annotations.length == 0) {
896 return lineNumber;
897 }
898
899 for (Annotation annotation : annotations) {
900 int annotationLineNumber = annotation.getLineNumber();
901
902 Map<String, String> propertyMap = annotation.getPropertyMap();
903
904 if (propertyMap.isEmpty()) {
905 annotationLineNumber--;
906 }
907
908 if (annotationLineNumber < lineNumber) {
909 lineNumber = annotationLineNumber;
910 }
911 }
912
913 return lineNumber;
914 }
915
916 private Document _getJavadocDocument(JavaClass javaClass) throws Exception {
917 Element rootElement = _saxReaderUtil.createElement("javadoc");
918
919 Document document = _saxReaderUtil.createDocument(rootElement);
920
921 DocUtil.add(rootElement, "name", javaClass.getName());
922 DocUtil.add(rootElement, "type", javaClass.getFullyQualifiedName());
923
924 _addClassCommentElement(rootElement, javaClass);
925 _addDocletElements(rootElement, javaClass, "author");
926 _addDocletElements(rootElement, javaClass, "version");
927 _addDocletElements(rootElement, javaClass, "see");
928 _addDocletElements(rootElement, javaClass, "since");
929 _addDocletElements(rootElement, javaClass, "serial");
930 _addDocletElements(rootElement, javaClass, "deprecated");
931
932 JavaMethod[] javaMethods = javaClass.getMethods();
933
934 for (JavaMethod javaMethod : javaMethods) {
935 _addMethodElement(rootElement, javaMethod);
936 }
937
938 JavaField[] javaFields = javaClass.getFields();
939
940 for (JavaField javaField : javaFields) {
941 _addFieldElement(rootElement, javaField);
942 }
943
944 return document;
945 }
946
947 private Tuple _getJavadocsXmlTuple(String fileName) throws Exception {
948 File file = new File(_inputDir + fileName);
949
950 String absolutePath = file.getAbsolutePath();
951
952 absolutePath = StringUtil.replace(absolutePath, "\\", "/");
953 absolutePath = StringUtil.replace(absolutePath, "/./", "/");
954
955 int pos = absolutePath.indexOf("/portal-impl/src/");
956
957 String srcDirName = null;
958
959 if (pos != -1) {
960 srcDirName = absolutePath.substring(0, pos + 17);
961 }
962
963 if (srcDirName == null) {
964 pos = absolutePath.indexOf("/portal-kernel/src/");
965
966 if (pos == -1) {
967 pos = absolutePath.indexOf("/portal-service/src/");
968 }
969
970 if (pos == -1) {
971 pos = absolutePath.indexOf("/util-bridges/src/");
972 }
973
974 if (pos == -1) {
975 pos = absolutePath.indexOf("/util-java/src/");
976 }
977
978 if (pos == -1) {
979 pos = absolutePath.indexOf("/util-taglib/src/");
980 }
981
982 if (pos != -1) {
983 srcDirName =
984 absolutePath.substring(0, pos) + "/portal-impl/src/";
985 }
986 }
987
988 if (srcDirName == null) {
989 pos = absolutePath.indexOf("/WEB-INF/src/");
990
991 if (pos != -1) {
992 srcDirName = absolutePath.substring(0, pos + 13);
993 }
994 }
995
996 if (srcDirName == null) {
997 return null;
998 }
999
1000 Tuple tuple = _javadocxXmlTuples.get(srcDirName);
1001
1002 if (tuple != null) {
1003 return tuple;
1004 }
1005
1006 File javadocsXmlFile = new File(
1007 srcDirName, "META-INF/" + _outputFilePrefix + "-all.xml");
1008
1009 if (!javadocsXmlFile.exists()) {
1010 _fileUtil.write(
1011 javadocsXmlFile,
1012 "<?xml version=\"1.0\"?>\n\n<javadocs>\n</javadocs>");
1013 }
1014
1015 String javadocsXmlContent = _fileUtil.read(javadocsXmlFile);
1016
1017 Document javadocsXmlDocument = _saxReaderUtil.read(javadocsXmlContent);
1018
1019 tuple = new Tuple(
1020 srcDirName, javadocsXmlFile, javadocsXmlContent,
1021 javadocsXmlDocument);
1022
1023 _javadocxXmlTuples.put(srcDirName, tuple);
1024
1025 return tuple;
1026 }
1027
1028 private String _getJavaFieldComment(
1029 String[] lines, Map<String, Element> fieldElementsMap,
1030 JavaField javaField) {
1031
1032 String fieldKey = _getFieldKey(javaField);
1033
1034 Element fieldElement = fieldElementsMap.get(fieldKey);
1035
1036 if (fieldElement == null) {
1037 return null;
1038 }
1039
1040 String indent = _getIndent(lines, javaField);
1041
1042 StringBundler sb = new StringBundler();
1043
1044 sb.append(indent);
1045 sb.append("\n");
1069
1070 if (!_initializeMissingJavadocs && Validator.isNull(comment) &&
1071 Validator.isNull(docletTags)) {
1072
1073 return null;
1074 }
1075
1076 if (!_hasPublicModifier(javaField) && Validator.isNull(comment) &&
1077 Validator.isNull(docletTags)) {
1078
1079 return null;
1080 }
1081
1082 return sb.toString();
1083 }
1084
1085 private String _getJavaMethodComment(
1086 String[] lines, Map<String, Element> methodElementsMap,
1087 JavaMethod javaMethod) {
1088
1089 String methodKey = _getMethodKey(javaMethod);
1090
1091 Element methodElement = methodElementsMap.get(methodKey);
1092
1093 if (methodElement == null) {
1094 return null;
1095 }
1096
1097 String indent = _getIndent(lines, javaMethod);
1098
1099 StringBundler sb = new StringBundler();
1100
1101 sb.append(indent);
1102 sb.append("\n");
1129
1130 if (!_initializeMissingJavadocs && Validator.isNull(comment) &&
1131 Validator.isNull(docletTags)) {
1132
1133 return null;
1134 }
1135
1136 if (!_hasPublicModifier(javaMethod) && Validator.isNull(comment) &&
1137 Validator.isNull(docletTags)) {
1138
1139 return null;
1140 }
1141
1142 return sb.toString();
1143 }
1144
1145 private String _getMethodKey(Element methodElement) {
1146 StringBundler sb = new StringBundler();
1147
1148 sb.append(methodElement.elementText("name"));
1149 sb.append("(");
1150
1151 List<Element> paramElements = methodElement.elements("param");
1152
1153 for (Element paramElement : paramElements) {
1154 sb.append(paramElement.elementText("name"));
1155 sb.append("|");
1156 sb.append(paramElement.elementText("type"));
1157 sb.append(",");
1158 }
1159
1160 sb.append(")");
1161
1162 return sb.toString();
1163 }
1164
1165 private String _getMethodKey(JavaMethod javaMethod) {
1166 StringBundler sb = new StringBundler();
1167
1168 sb.append(javaMethod.getName());
1169 sb.append("(");
1170
1171 JavaParameter[] javaParameters = javaMethod.getParameters();
1172
1173 for (JavaParameter javaParameter : javaParameters) {
1174 sb.append(javaParameter.getName());
1175 sb.append("|");
1176 sb.append(_getTypeValue(javaParameter));
1177 sb.append(",");
1178 }
1179
1180 sb.append(")");
1181
1182 return sb.toString();
1183 }
1184
1185 private String _getSpacesIndent(int length) {
1186 String indent = StringPool.BLANK;
1187
1188 for (int i = 0; i < length; i++) {
1189 indent += StringPool.SPACE;
1190 }
1191
1192 return indent;
1193 }
1194
1195 private String _getTypeValue(JavaParameter javaParameter) {
1196 Type type = javaParameter.getType();
1197
1198 String typeValue = type.getValue();
1199
1200 if (type.isArray()) {
1201 typeValue += "[]";
1202 }
1203
1204 return typeValue;
1205 }
1206
1207 private boolean _hasAnnotation(
1208 AbstractBaseJavaEntity abstractBaseJavaEntity, String annotationName) {
1209
1210 Annotation[] annotations = abstractBaseJavaEntity.getAnnotations();
1211
1212 if (annotations == null) {
1213 return false;
1214 }
1215
1216 for (int i = 0; i < annotations.length; i++) {
1217 Type type = annotations[i].getType();
1218
1219 JavaClass javaClass = type.getJavaClass();
1220
1221 if (annotationName.equals(javaClass.getName())) {
1222 return true;
1223 }
1224 }
1225
1226 return false;
1227 }
1228
1229 private boolean _hasGeneratedTag(String content) {
1230 if (content.contains("* @generated") || content.contains("$ANTLR")) {
1231 return true;
1232 }
1233 else {
1234 return false;
1235 }
1236 }
1237
1238 private boolean _hasPublicModifier(AbstractJavaEntity abstractJavaEntity) {
1239 String[] modifiers = abstractJavaEntity.getModifiers();
1240
1241 if (modifiers == null) {
1242 return false;
1243 }
1244
1245 for (String modifier : modifiers) {
1246 if (modifier.equals("public")) {
1247 return true;
1248 }
1249 }
1250
1251 return false;
1252 }
1253
1254 private boolean _isOverrideMethod(
1255 JavaClass javaClass, JavaMethod javaMethod,
1256 Collection<JavaClass> ancestorJavaClasses) {
1257
1258 if (javaClass.isInterface() || javaMethod.isConstructor() ||
1259 javaMethod.isPrivate() || javaMethod.isStatic()) {
1260
1261 return false;
1262 }
1263
1264 String methodName = javaMethod.getName();
1265
1266 JavaParameter[] javaParameters = javaMethod.getParameters();
1267
1268 Type[] types = new Type[javaParameters.length];
1269
1270 for (int i = 0; i < javaParameters.length; i++) {
1271 types[i] = javaParameters[i].getType();
1272 }
1273
1274
1275
1276 for (JavaClass ancestorJavaClass : ancestorJavaClasses) {
1277 JavaMethod ancestorJavaMethod =
1278 ancestorJavaClass.getMethodBySignature(methodName, types);
1279
1280 if (ancestorJavaMethod == null) {
1281 continue;
1282 }
1283
1284 boolean samePackage = false;
1285
1286 JavaPackage ancestorJavaPackage = ancestorJavaClass.getPackage();
1287
1288 if (ancestorJavaPackage != null) {
1289 samePackage = ancestorJavaPackage.equals(
1290 javaClass.getPackage());
1291 }
1292
1293
1294
1295 if (samePackage) {
1296 return !ancestorJavaMethod.isPrivate();
1297 }
1298 else {
1299 if (ancestorJavaMethod.isProtected() ||
1300 ancestorJavaMethod.isPublic()) {
1301
1302 return true;
1303 }
1304 else {
1305 return false;
1306 }
1307 }
1308 }
1309
1310 return false;
1311 }
1312
1313 private String _removeJavadocFromJava(
1314 JavaClass javaClass, String content) {
1315
1316 Set<Integer> lineNumbers = new HashSet<Integer>();
1317
1318 lineNumbers.add(_getJavaClassLineNumber(javaClass));
1319
1320 JavaMethod[] javaMethods = javaClass.getMethods();
1321
1322 for (JavaMethod javaMethod : javaMethods) {
1323 lineNumbers.add(javaMethod.getLineNumber());
1324 }
1325
1326 JavaField[] javaFields = javaClass.getFields();
1327
1328 for (JavaField javaField : javaFields) {
1329 lineNumbers.add(javaField.getLineNumber());
1330 }
1331
1332 String[] lines = StringUtil.splitLines(content);
1333
1334 for (int lineNumber : lineNumbers) {
1335 if (lineNumber == 0) {
1336 continue;
1337 }
1338
1339 int pos = lineNumber - 2;
1340
1341 String line = lines[pos];
1342
1343 if (line == null) {
1344 continue;
1345 }
1346
1347 line = line.trim();
1348
1349 if (line.endsWith("*/")) {
1350 while (true) {
1351 lines[pos] = null;
1352
1353 if (line.startsWith("