1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.tools;
24  
25  import com.liferay.portal.kernel.util.StringPool;
26  import com.liferay.portal.kernel.util.StringUtil;
27  import com.liferay.portal.kernel.util.Validator;
28  import com.liferay.portal.kernel.xml.Document;
29  import com.liferay.portal.kernel.xml.Element;
30  import com.liferay.portal.util.FileImpl;
31  import com.liferay.portal.xml.SAXReaderImpl;
32  import com.liferay.util.xml.DocUtil;
33  
34  import com.thoughtworks.qdox.JavaDocBuilder;
35  import com.thoughtworks.qdox.model.AbstractJavaEntity;
36  import com.thoughtworks.qdox.model.DocletTag;
37  import com.thoughtworks.qdox.model.JavaClass;
38  import com.thoughtworks.qdox.model.JavaField;
39  import com.thoughtworks.qdox.model.JavaMethod;
40  import com.thoughtworks.qdox.model.JavaParameter;
41  import com.thoughtworks.qdox.model.Type;
42  
43  import jargs.gnu.CmdLineParser;
44  
45  import java.io.File;
46  import java.io.Reader;
47  import java.io.StringReader;
48  
49  import java.util.ArrayList;
50  import java.util.HashMap;
51  import java.util.HashSet;
52  import java.util.List;
53  import java.util.Map;
54  import java.util.Set;
55  import java.util.TreeMap;
56  
57  import org.apache.tools.ant.DirectoryScanner;
58  
59  /**
60   * <a href="JavadocBuilder.java.html"><b><i>View Source</i></b></a>
61   *
62   * @author Brian Wing Shun Chan
63   */
64  public class JavadocBuilder {
65  
66      public static void main(String[] args) {
67          try {
68              new JavadocBuilder(args);
69          }
70          catch (Exception e) {
71              e.printStackTrace();
72          }
73      }
74  
75      public JavadocBuilder(String[] args) throws Exception {
76          CmdLineParser cmdLineParser = new CmdLineParser();
77  
78          CmdLineParser.Option commandOption = cmdLineParser.addStringOption(
79              "command");
80          CmdLineParser.Option limitOption = cmdLineParser.addStringOption(
81              "limit");
82          CmdLineParser.Option ignoreAutogeneratedOption =
83              cmdLineParser.addBooleanOption("ignoreAutogenerated");
84  
85          cmdLineParser.parse(args);
86  
87          String command = (String)cmdLineParser.getOptionValue(commandOption);
88          String limit = (String)cmdLineParser.getOptionValue(limitOption);
89          Boolean ignoreAutogenerated = (Boolean)cmdLineParser.getOptionValue(
90              ignoreAutogeneratedOption);
91  
92          _process(command, limit, ignoreAutogenerated);
93      }
94  
95      private void _addClassCommentElement(
96          Element rootElement, JavaClass javaClass) {
97  
98          Element commentElement = rootElement.addElement("comment");
99  
100         String comment = _getCDATA(javaClass);
101 
102         if (comment.startsWith("Copyright (c) 2000-2009 Liferay, Inc.")) {
103             comment = StringPool.BLANK;
104         }
105 
106         if (comment.startsWith(
107                 "<a href=\"" + javaClass.getName() + ".java.html\">")) {
108 
109             int pos = comment.indexOf("</a>");
110 
111             comment = comment.substring(pos + 4).trim();
112         }
113 
114         commentElement.addCDATA(comment);
115     }
116 
117     private void _addDocletElements(
118         Element parentElement, AbstractJavaEntity abstractJavaEntity,
119         String name) {
120 
121         DocletTag[] docletTags = abstractJavaEntity.getTagsByName(name);
122 
123         for (DocletTag docletTag : docletTags) {
124             String value = docletTag.getValue();
125 
126             if (name.equals("author") || name.equals("see") ||
127                 name.equals("since") || name.equals("version")) {
128 
129                 if (value.startsWith("Raymond Aug")) {
130                     value = "Raymond Aug\u00c3\u00a9";
131                 }
132 
133                 DocUtil.add(parentElement, name, value);
134             }
135             else {
136                 Element element = parentElement.addElement(name);
137 
138                 element.addCDATA(value);
139             }
140         }
141     }
142 
143     private void _addDocletTags(
144         Element parentElement, String name, String indent, StringBuilder sb) {
145 
146         List<Element> elements = parentElement.elements(name);
147 
148         for (Element element : elements) {
149             sb.append(indent);
150             sb.append(" * @");
151             sb.append(name);
152             sb.append(" ");
153 
154             Element commentElement = element.element("comment");
155 
156             if (commentElement != null) {
157                 sb.append(element.elementText("name"));
158                 sb.append(" ");
159                 sb.append(_getCDATA(element.elementText("comment")));
160             }
161             else {
162                 sb.append(_getCDATA(element.getText()));
163             }
164 
165             sb.append("\n");
166         }
167     }
168 
169     private void _addFieldElement(Element rootElement, JavaField javaField) {
170         Element fieldElement = rootElement.addElement("field");
171 
172         DocUtil.add(fieldElement, "name", javaField.getName());
173 
174         Element commentElement = fieldElement.addElement("comment");
175 
176         commentElement.addCDATA(_getCDATA(javaField));
177 
178         _addDocletElements(fieldElement, javaField, "deprecated");
179         _addDocletElements(fieldElement, javaField, "see");
180         _addDocletElements(fieldElement, javaField, "since");
181         _addDocletElements(fieldElement, javaField, "version");
182     }
183 
184     private void _addMethodElement(Element rootElement, JavaMethod javaMethod) {
185         Element methodElement = rootElement.addElement("method");
186 
187         DocUtil.add(methodElement, "name", javaMethod.getName());
188 
189         Element commentElement = methodElement.addElement("comment");
190 
191         commentElement.addCDATA(_getCDATA(javaMethod));
192 
193         _addDocletElements(methodElement, javaMethod, "deprecated");
194         _addParamElements(methodElement, javaMethod);
195         _addReturnElement(methodElement, javaMethod);
196         _addDocletElements(methodElement, javaMethod, "see");
197         _addDocletElements(methodElement, javaMethod, "since");
198         _addThrowsElements(methodElement, javaMethod);
199         _addDocletElements(methodElement, javaMethod, "version");
200     }
201 
202     private void _addParamElement(
203         Element methodElement, JavaParameter javaParameter,
204         DocletTag[] paramDocletTags) {
205 
206         String name = javaParameter.getName();
207         String type = javaParameter.getType().getValue();
208         String value = null;
209 
210         for (DocletTag paramDocletTag : paramDocletTags) {
211             String curValue = paramDocletTag.getValue();
212 
213             if (!curValue.startsWith(name)) {
214                 continue;
215             }
216             else {
217                 curValue = value;
218 
219                 break;
220             }
221         }
222 
223         Element paramElement = methodElement.addElement("param");
224 
225         DocUtil.add(paramElement, "name", name);
226         DocUtil.add(paramElement, "type", type);
227 
228         if (value != null) {
229             value = value.substring(name.length());
230         }
231 
232         Element commentElement = paramElement.addElement("comment");
233 
234         commentElement.addCDATA(_getCDATA(value));
235     }
236 
237     private void _addParamElements(
238         Element methodElement, JavaMethod javaMethod) {
239 
240         JavaParameter[] javaParameters = javaMethod.getParameters();
241 
242         DocletTag[] paramDocletTags = javaMethod.getTagsByName("param");
243 
244         for (JavaParameter javaParameter : javaParameters) {
245             _addParamElement(methodElement, javaParameter, paramDocletTags);
246         }
247     }
248 
249     private void _addReturnElement(
250         Element methodElement, JavaMethod javaMethod) {
251 
252         Type returns = javaMethod.getReturns();
253 
254         if ((returns == null) || returns.getValue().equals("void")) {
255             return;
256         }
257 
258         _addDocletElements(methodElement, javaMethod, "return");
259     }
260 
261     private void _addThrowsElement(
262         Element methodElement, Type exception, DocletTag[] throwsDocletTags) {
263 
264         String name = exception.getJavaClass().getName();
265         String value = null;
266 
267         for (DocletTag throwsDocletTag : throwsDocletTags) {
268             String curValue = throwsDocletTag.getValue();
269 
270             if (!curValue.startsWith(name)) {
271                 continue;
272             }
273             else {
274                 curValue = value;
275 
276                 break;
277             }
278         }
279 
280         Element throwsElement = methodElement.addElement("throws");
281 
282         DocUtil.add(throwsElement, "name", name);
283         DocUtil.add(throwsElement, "type", exception.getValue());
284 
285         if (value != null) {
286             value = value.substring(name.length());
287         }
288 
289         Element commentElement = throwsElement.addElement("comment");
290 
291         commentElement.addCDATA(_getCDATA(value));
292 
293     }
294 
295     private void _addThrowsElements(
296         Element methodElement, JavaMethod javaMethod) {
297 
298         Type[] exceptions = javaMethod.getExceptions();
299 
300         DocletTag[] throwsDocletTags = javaMethod.getTagsByName("throws");
301 
302         for (Type exception : exceptions) {
303             _addThrowsElement(methodElement, exception, throwsDocletTags);
304         }
305     }
306 
307     private String _getCDATA(AbstractJavaEntity abstractJavaEntity) {
308         return _getCDATA(abstractJavaEntity.getComment());
309     }
310 
311     private String _getCDATA(String cdata) {
312         if (cdata == null) {
313             return StringPool.BLANK;
314         }
315 
316         cdata = StringUtil.replace(
317             cdata,
318             new String[] {"\n", "<p>", "</p>"},
319             new String[] {" ", " <p> ", " </p> "});
320 
321         while (cdata.contains("  ")) {
322             cdata = StringUtil.replace(cdata, "  ", " ");
323         }
324 
325         return cdata.trim();
326     }
327 
328     private String _getFieldKey(Element fieldElement) {
329         return fieldElement.elementText("name");
330     }
331 
332     private String _getFieldKey(JavaField javaField) {
333         return javaField.getName();
334     }
335 
336     private JavaClass _getJavaClass(String fileName) throws Exception {
337         return _getJavaClass(fileName, null);
338     }
339 
340     private JavaClass _getJavaClass(String fileName, Reader reader)
341         throws Exception {
342 
343         int pos = fileName.indexOf("src/");
344 
345         if (pos == -1) {
346             pos = fileName.indexOf("test/");
347         }
348 
349         if (pos == -1) {
350             throw new RuntimeException(fileName);
351         }
352 
353         pos = fileName.indexOf("/", pos);
354 
355         String srcFile = fileName.substring(pos + 1, fileName.length());
356         String className = StringUtil.replace(
357             srcFile.substring(0, srcFile.length() - 5), "/", ".");
358 
359         JavaDocBuilder builder = new JavaDocBuilder();
360 
361         if (reader == null) {
362             File file = new File(fileName);
363 
364             if (!file.exists()) {
365                 return null;
366             }
367 
368             builder.addSource(file);
369         }
370         else {
371             builder.addSource(reader);
372         }
373 
374         return builder.getClassByName(className);
375     }
376 
377     private String _getJavaClassComment(
378         Element rootElement, JavaClass javaClass) {
379 
380         StringBuilder sb = new StringBuilder();
381 
382         sb.append("/**\n");
383         sb.append(" * <a href=\"");
384         sb.append(javaClass.getName());
385         sb.append(".java.html\"><b><i>View Source</i></b></a>\n");
386         sb.append(" *\n");
387         sb.append(" * ");
388         sb.append(_getCDATA(rootElement.elementText("comment")));
389         sb.append("\n");
390         sb.append(" *\n");
391 
392         String indent = StringPool.BLANK;
393 
394         _addDocletTags(rootElement, "author", indent, sb);
395         _addDocletTags(rootElement, "deprecated", indent, sb);
396         _addDocletTags(rootElement, "see", indent, sb);
397         _addDocletTags(rootElement, "serial", indent, sb);
398         _addDocletTags(rootElement, "since", indent, sb);
399         _addDocletTags(rootElement, "version", indent, sb);
400 
401         sb.append(" */\n");
402 
403         return sb.toString();
404     }
405 
406     private String _getJavadocXml(JavaClass javaClass) throws Exception {
407         Element rootElement = _saxReaderUtil.createElement("javadoc");
408 
409         Document document = _saxReaderUtil.createDocument(rootElement);
410 
411         DocUtil.add(rootElement, "name", javaClass.getName());
412         DocUtil.add(rootElement, "type", javaClass.getFullyQualifiedName());
413 
414         _addClassCommentElement(rootElement, javaClass);
415         _addDocletElements(rootElement, javaClass, "author");
416         _addDocletElements(rootElement, javaClass, "deprecated");
417         _addDocletElements(rootElement, javaClass, "see");
418         _addDocletElements(rootElement, javaClass, "serial");
419         _addDocletElements(rootElement, javaClass, "since");
420         _addDocletElements(rootElement, javaClass, "version");
421 
422         JavaMethod[] javaMethods = javaClass.getMethods();
423 
424         for (JavaMethod javaMethod : javaMethods) {
425             _addMethodElement(rootElement, javaMethod);
426         }
427 
428         JavaField[] javaFields = javaClass.getFields();
429 
430         for (JavaField javaField : javaFields) {
431             _addFieldElement(rootElement, javaField);
432         }
433 
434         return document.formattedString();
435     }
436 
437     private String _getJavaFieldComment(
438         String[] lines, Map<String, Element> fieldElementsMap,
439         JavaField javaField) {
440 
441         String fieldKey = _getFieldKey(javaField);
442 
443         Element fieldElement = fieldElementsMap.get(fieldKey);
444 
445         if (fieldElement == null) {
446             return null;
447         }
448 
449         String line = lines[javaField.getLineNumber() - 1];
450 
451         String indent = StringPool.BLANK;
452 
453         for (char c : line.toCharArray()) {
454             if (Character.isWhitespace(c)) {
455                 indent += c;
456             }
457             else {
458                 break;
459             }
460         }
461 
462         StringBuilder sb = new StringBuilder();
463 
464         sb.append(indent);
465         sb.append("/**\n");
466         sb.append(indent);
467         sb.append(" * ");
468         sb.append(fieldElement.elementText("comment"));
469         sb.append("\n");
470         sb.append(indent);
471         sb.append(" *\n");
472 
473         _addDocletTags(fieldElement, "deprecated", indent, sb);
474         _addDocletTags(fieldElement, "see", indent, sb);
475         _addDocletTags(fieldElement, "since", indent, sb);
476         _addDocletTags(fieldElement, "version", indent, sb);
477 
478         sb.append(indent);
479         sb.append(" */\n");
480 
481         return sb.toString();
482     }
483 
484     private String _getJavaMethodComment(
485         String[] lines, Map<String, Element> methodElementsMap,
486         JavaMethod javaMethod) {
487 
488         String methodKey = _getMethodKey(javaMethod);
489 
490         Element methodElement = methodElementsMap.get(methodKey);
491 
492         if (methodElement == null) {
493             return null;
494         }
495 
496         String line = lines[javaMethod.getLineNumber() - 1];
497 
498         String indent = StringPool.BLANK;
499 
500         for (char c : line.toCharArray()) {
501             if (Character.isWhitespace(c)) {
502                 indent += c;
503             }
504             else {
505                 break;
506             }
507         }
508 
509         StringBuilder sb = new StringBuilder();
510 
511         sb.append(indent);
512         sb.append("/**\n");
513         sb.append(indent);
514         sb.append(" * ");
515         sb.append(methodElement.elementText("comment"));
516         sb.append("\n");
517         sb.append(indent);
518         sb.append(" *\n");
519 
520         _addDocletTags(methodElement, "deprecated", indent, sb);
521         _addDocletTags(methodElement, "param", indent, sb);
522         _addDocletTags(methodElement, "return", indent, sb);
523         _addDocletTags(methodElement, "see", indent, sb);
524         _addDocletTags(methodElement, "since", indent, sb);
525         _addDocletTags(methodElement, "throws", indent, sb);
526         _addDocletTags(methodElement, "version", indent, sb);
527 
528         sb.append(indent);
529         sb.append(" */\n");
530 
531         return sb.toString();
532     }
533 
534     private String _getMethodKey(Element methodElement) {
535         StringBuilder sb = new StringBuilder();
536 
537         sb.append(methodElement.elementText("name"));
538         sb.append("(");
539 
540         List<Element> paramElements = methodElement.elements("param");
541 
542         for (Element paramElement : paramElements) {
543             sb.append(paramElement.elementText("name"));
544             sb.append("|");
545             sb.append(paramElement.elementText("type"));
546             sb.append(",");
547         }
548 
549         sb.append(")");
550 
551         return sb.toString();
552     }
553 
554     private String _getMethodKey(JavaMethod javaMethod) {
555         StringBuilder sb = new StringBuilder();
556 
557         sb.append(javaMethod.getName());
558         sb.append("(");
559 
560         JavaParameter[] javaParameters = javaMethod.getParameters();
561 
562         for (JavaParameter javaParameter : javaParameters) {
563             sb.append(javaParameter.getName());
564             sb.append("|");
565             sb.append(javaParameter.getType().getValue());
566             sb.append(",");
567         }
568 
569         sb.append(")");
570 
571         return sb.toString();
572     }
573 
574     private boolean _isGenerated(String content) {
575         if (content.contains("<javadoc autogenerated=\"true\">")) {
576             return true;
577         }
578         else {
579             return false;
580         }
581     }
582 
583     private void _process(
584             String command, String limit, Boolean ignoreAutogenerated)
585         throws Exception {
586 
587         DirectoryScanner ds = new DirectoryScanner();
588 
589         ds.setBasedir(_basedir);
590         ds.setExcludes(
591             new String[] {
592                 "**\\classes\\**", "**\\portal-client\\**", "**\\portal-web\\**"
593             });
594 
595         List<String> includes = new ArrayList<String>();
596 
597         if (Validator.isNotNull(limit) && !limit.startsWith("$")) {
598             String[] limitArray = StringUtil.split(limit, "/");
599 
600             for (String curLimit : limitArray) {
601                 includes.add(
602                     "**\\" + StringUtil.replace(curLimit, ".", "\\") +
603                         "\\**\\*.java");
604                 includes.add("**\\" + curLimit + ".java");
605             }
606         }
607         else {
608             includes.add("**\\*.java");
609         }
610 
611         ds.setIncludes(includes.toArray(new String[includes.size()]));
612 
613         ds.scan();
614 
615         String[] fileNames = ds.getIncludedFiles();
616 
617         for (String fileName : fileNames) {
618             fileName = StringUtil.replace(fileName, "\\", "/");
619 
620             /*if (!fileName.endsWith("Isolation.java")) {
621                 continue;
622             }*/
623 
624             if ((ignoreAutogenerated != null) &&
625                 (ignoreAutogenerated.booleanValue())) {
626 
627                 File file = new File(_basedir + fileName);
628 
629                 if (file.exists()) {
630                     String oldContent = _fileUtil.read(
631                         _basedir + fileName + "doc");
632 
633                     if (_isGenerated(oldContent)) {
634                         continue;
635                     }
636                 }
637             }
638 
639             if (command.equals("cleanup")) {
640                 _processGet(fileName);
641                 _processSave(fileName);
642                 _processDelete(fileName);
643             }
644             else if (command.equals("commit")) {
645                 _processSave(fileName);
646                 _processDelete(fileName);
647             }
648             else if (command.equals("delete")) {
649                 _processDelete(fileName);
650             }
651             else if (command.equals("get")) {
652                 _processGet(fileName);
653             }
654             else if (command.equals("save")) {
655                 _processSave(fileName);
656             }
657         }
658     }
659 
660     private void _processDelete(String fileName) throws Exception {
661         _removeJavadocFromJava(fileName, true);
662     }
663 
664     private void _processGet(String fileName) throws Exception {
665         File javadocFile = new File(_basedir + fileName + "doc");
666 
667         if (!javadocFile.exists()) {
668             _updateJavadocFromJava(fileName);
669         }
670 
671         String javaWithoutJavadoc = _removeJavadocFromJava(fileName, false);
672 
673         _updateJavaFromJavadoc(fileName, javaWithoutJavadoc);
674     }
675 
676     private void _processSave(String fileName) throws Exception {
677         _updateJavadocFromJava(fileName);
678     }
679 
680     private String _removeJavadocFromJava(String fileName, boolean log)
681         throws Exception {
682 
683         File file = new File(_basedir + fileName);
684 
685         String oldContent = _fileUtil.read(file);
686 
687         String[] lines = StringUtil.split(oldContent, "\n");
688 
689         JavaClass javaClass = _getJavaClass(
690             fileName, new StringReader(oldContent));
691 
692         Set<Integer> lineNumbers = new HashSet<Integer>();
693 
694         lineNumbers.add(javaClass.getLineNumber());
695 
696         JavaMethod[] javaMethods = javaClass.getMethods();
697 
698         for (JavaMethod javaMethod : javaMethods) {
699             lineNumbers.add(javaMethod.getLineNumber());
700         }
701 
702         JavaField[] javaFields = javaClass.getFields();
703 
704         for (JavaField javaField : javaFields) {
705             lineNumbers.add(javaField.getLineNumber());
706         }
707 
708         for (int lineNumber : lineNumbers) {
709             int pos = lineNumber - 2;
710 
711             String line = lines[pos].trim();
712 
713             if (line.endsWith("*/")) {
714                 while (true) {
715                     lines[pos] = null;
716 
717                     if (line.startsWith("/**")) {
718                         break;
719                     }
720 
721                     line = lines[--pos].trim();
722                 }
723             }
724         }
725 
726         StringBuilder sb = new StringBuilder(oldContent.length());
727 
728         for (String line : lines) {
729             if (line != null) {
730                 sb.append(line);
731                 sb.append("\n");
732             }
733         }
734 
735         String newContent = sb.toString().trim();
736 
737         if ((oldContent == null) || !oldContent.equals(newContent)) {
738             _fileUtil.write(file, newContent);
739 
740             if (log) {
741                 System.out.println("Writing " + file);
742             }
743         }
744 
745         return newContent;
746     }
747 
748     private void _updateJavadocFromJava(String fileName) throws Exception {
749         File file = new File(_basedir + fileName + "doc");
750 
751         String oldContent = null;
752 
753         if (file.exists()) {
754             oldContent = _fileUtil.read(file);
755 
756             if (_isGenerated(oldContent)) {
757                 return;
758             }
759         }
760 
761         JavaClass javaClass = _getJavaClass(fileName);
762 
763         String newContent = _getJavadocXml(javaClass);
764 
765         if ((oldContent == null) || !oldContent.equals(newContent)) {
766             _fileUtil.write(file, newContent.getBytes());
767 
768             System.out.println("Writing " + file);
769         }
770     }
771 
772     private void _updateJavaFromJavadoc(String fileName, String oldContent)
773         throws Exception {
774 
775         File javadocFile = new File(_basedir + fileName + "doc");
776 
777         if (!javadocFile.exists()) {
778             return;
779         }
780 
781         File file = new File(_basedir + fileName);
782 
783         if (oldContent == null) {
784             oldContent = _fileUtil.read(file);
785         }
786 
787         String[] lines = StringUtil.split(oldContent, "\n");
788 
789         JavaClass javaClass = _getJavaClass(
790             fileName, new StringReader(oldContent));
791 
792         Document document = _saxReaderUtil.read(javadocFile);
793 
794         Element rootElement = document.getRootElement();
795 
796         Map<Integer, String> commentsMap = new TreeMap<Integer, String>();
797 
798         commentsMap.put(
799             javaClass.getLineNumber(),
800             _getJavaClassComment(rootElement, javaClass));
801 
802         Map<String, Element> methodElementsMap = new HashMap<String, Element>();
803 
804         List<Element> methodElements = rootElement.elements("method");
805 
806         for (Element methodElement : methodElements) {
807             String methodKey = _getMethodKey(methodElement);
808 
809             methodElementsMap.put(methodKey, methodElement);
810         }
811 
812         JavaMethod[] javaMethods = javaClass.getMethods();
813 
814         for (JavaMethod javaMethod : javaMethods) {
815             if (commentsMap.containsKey(javaMethod.getLineNumber())) {
816                 continue;
817             }
818 
819             commentsMap.put(
820                 javaMethod.getLineNumber(),
821                 _getJavaMethodComment(lines, methodElementsMap, javaMethod));
822         }
823 
824         Map<String, Element> fieldElementsMap = new HashMap<String, Element>();
825 
826         List<Element> fieldElements = rootElement.elements("field");
827 
828         for (Element fieldElement : fieldElements) {
829             String fieldKey = _getFieldKey(fieldElement);
830 
831             fieldElementsMap.put(fieldKey, fieldElement);
832         }
833 
834         JavaField[] javaFields = javaClass.getFields();
835 
836         for (JavaField javaField : javaFields) {
837             if (commentsMap.containsKey(javaField.getLineNumber())) {
838                 continue;
839             }
840 
841             commentsMap.put(
842                 javaField.getLineNumber(),
843                 _getJavaFieldComment(lines, fieldElementsMap, javaField));
844         }
845 
846         StringBuilder sb = new StringBuilder(oldContent.length());
847 
848         for (int lineNumber = 1; lineNumber <= lines.length; lineNumber++) {
849             String line = lines[lineNumber - 1];
850 
851             String comments = commentsMap.get(lineNumber);
852 
853             if (comments != null) {
854                 sb.append(comments);
855             }
856 
857             sb.append(line);
858             sb.append("\n");
859         }
860 
861         String newContent = sb.toString().trim();
862 
863         if ((oldContent == null) || !oldContent.equals(newContent)) {
864             _fileUtil.write(file, newContent);
865 
866             System.out.println("Writing " + file);
867         }
868     }
869 
870     private static FileImpl _fileUtil = FileImpl.getInstance();
871     private static SAXReaderImpl _saxReaderUtil = SAXReaderImpl.getInstance();
872 
873     private String _basedir = "./";
874 
875 }