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