View Javadoc
1   /*
2    *    Copyright 2006-2026 the original author or authors.
3    *
4    *    Licensed under the Apache License, Version 2.0 (the "License");
5    *    you may not use this file except in compliance with the License.
6    *    You may obtain a copy of the License at
7    *
8    *       https://www.apache.org/licenses/LICENSE-2.0
9    *
10   *    Unless required by applicable law or agreed to in writing, software
11   *    distributed under the License is distributed on an "AS IS" BASIS,
12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *    See the License for the specific language governing permissions and
14   *    limitations under the License.
15   */
16  package org.mybatis.generator.internal;
17  
18  import static org.mybatis.generator.internal.util.StringUtility.isTrue;
19  
20  import java.time.ZonedDateTime;
21  import java.time.format.DateTimeFormatter;
22  import java.util.Optional;
23  import java.util.Properties;
24  import java.util.Set;
25  
26  import org.mybatis.generator.api.CommentGenerator;
27  import org.mybatis.generator.api.IntrospectedColumn;
28  import org.mybatis.generator.api.IntrospectedTable;
29  import org.mybatis.generator.api.MyBatisGenerator;
30  import org.mybatis.generator.api.dom.OutputUtilities;
31  import org.mybatis.generator.api.dom.java.Field;
32  import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
33  import org.mybatis.generator.api.dom.java.InnerClass;
34  import org.mybatis.generator.api.dom.java.InnerEnum;
35  import org.mybatis.generator.api.dom.java.InnerRecord;
36  import org.mybatis.generator.api.dom.java.Method;
37  import org.mybatis.generator.api.dom.java.TopLevelClass;
38  import org.mybatis.generator.api.dom.kotlin.KotlinFile;
39  import org.mybatis.generator.api.dom.xml.TextElement;
40  import org.mybatis.generator.api.dom.xml.XmlElement;
41  import org.mybatis.generator.config.MergeConstants;
42  import org.mybatis.generator.config.PropertyRegistry;
43  
44  public class DefaultCommentGenerator implements CommentGenerator {
45  
46      private final Properties properties = new Properties();
47  
48      private boolean suppressDate;
49  
50      private boolean suppressAllComments;
51  
52      private boolean minimizeComments;
53  
54      /** If suppressAllComments or minimizeComments is true, this option is ignored. */
55      private boolean addRemarkComments;
56  
57      private final FullyQualifiedJavaType generatedImport =
58              new FullyQualifiedJavaType("jakarta.annotation.Generated"); //$NON-NLS-1$
59  
60      public DefaultCommentGenerator() {
61          super();
62          suppressDate = false;
63          suppressAllComments = false;
64          addRemarkComments = false;
65          minimizeComments = false;
66      }
67  
68      @Override
69      public void addConfigurationProperties(Properties props) {
70          this.properties.putAll(props);
71  
72          suppressDate = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_DATE));
73          suppressAllComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS));
74          addRemarkComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_ADD_REMARK_COMMENTS));
75          minimizeComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_MINIMIZE_COMMENTS));
76      }
77  
78      /**
79       * Adds a suitable comment to warn users that the element was generated and
80       * when it was generated.
81       *
82       * @param xmlElement the XML element
83       */
84      @Override
85      public void addComment(XmlElement xmlElement) {
86          if (suppressAllComments) {
87              return;
88          }
89  
90          xmlElement.addElement(new TextElement("<!--")); //$NON-NLS-1$
91  
92          String sb = OutputUtilities.xmlIndent(1)
93                  + "Generated Code - " //$NON-NLS-1$
94                  + MergeConstants.NEW_ELEMENT_TAG;
95          xmlElement.addElement(new TextElement(sb));
96  
97          if (!minimizeComments) {
98              xmlElement.addElement(
99                      new TextElement(OutputUtilities.xmlIndent(1)
100                             + "This element is automatically generated by MyBatis Generator," //$NON-NLS-1$
101                             + " do not modify.")); //$NON-NLS-1$
102         }
103 
104         getDateString().ifPresent(s -> {
105             String text = OutputUtilities.xmlIndent(1)
106                     + "This element was generated on " //$NON-NLS-1$
107                     + s
108                     + '.';
109             xmlElement.addElement(new TextElement(text));
110 
111         });
112 
113         xmlElement.addElement(new TextElement("-->")); //$NON-NLS-1$
114     }
115 
116     /**
117      * Returns a formatted date string to include in the Javadoc tag and XML
118      * comments. You may return null if you do not want the date in these
119      * documentation elements.
120      *
121      * @return a string representing the current timestamp, or null
122      */
123     protected Optional<String> getDateString() {
124         if (suppressDate || minimizeComments) {
125             return Optional.empty();
126         } else {
127             return Optional.of(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.now()));
128         }
129     }
130 
131     @Override
132     public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
133         if (suppressAllComments || minimizeComments) {
134             return;
135         }
136 
137         if (addRemarkComments) {
138             introspectedTable.getRemarks().ifPresent(remarks -> {
139                 topLevelClass.addJavaDocLine("/**"); //$NON-NLS-1$
140                 topLevelClass.addJavaDocLine(" * Database Table Remarks:"); //$NON-NLS-1$
141                 String[] remarkLines = remarks.split(System.lineSeparator());
142                 for (String remarkLine : remarkLines) {
143                     topLevelClass.addJavaDocLine(" *   " + remarkLine); //$NON-NLS-1$
144                 }
145                 topLevelClass.addJavaDocLine(" */"); //$NON-NLS-1$
146             });
147         }
148     }
149 
150     @Override
151     public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable,
152             Set<FullyQualifiedJavaType> imports) {
153         if (suppressAllComments) {
154             return;
155         }
156 
157         imports.add(generatedImport);
158         String comment = "Source Table: " + introspectedTable.getFullyQualifiedTable(); //$NON-NLS-1$
159         method.addAnnotation(getGeneratedAnnotation(comment, false));
160     }
161 
162     @Override
163     public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable,
164             IntrospectedColumn introspectedColumn, Set<FullyQualifiedJavaType> imports) {
165         if (suppressAllComments) {
166             return;
167         }
168 
169         imports.add(generatedImport);
170         String comment = "Source field: " //$NON-NLS-1$
171                 + introspectedTable.getFullyQualifiedTable() + "." //$NON-NLS-1$
172                 + introspectedColumn.getActualColumnName();
173         method.addAnnotation(getGeneratedAnnotation(comment, false));
174     }
175 
176     @Override
177     public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable,
178             Set<FullyQualifiedJavaType> imports) {
179         if (suppressAllComments) {
180             return;
181         }
182 
183         imports.add(generatedImport);
184         String comment = "Source Table: " + introspectedTable.getFullyQualifiedTable(); //$NON-NLS-1$
185         field.addAnnotation(getGeneratedAnnotation(comment, false));
186     }
187 
188     @Override
189     public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable,
190             IntrospectedColumn introspectedColumn, Set<FullyQualifiedJavaType> imports) {
191         if (suppressAllComments) {
192             return;
193         }
194 
195         imports.add(generatedImport);
196         String comment = "Source field: " //$NON-NLS-1$
197                 + introspectedTable.getFullyQualifiedTable() + "." //$NON-NLS-1$
198                 + introspectedColumn.getActualColumnName();
199         field.addAnnotation(getGeneratedAnnotation(comment, false));
200 
201         if (!minimizeComments && addRemarkComments) {
202             introspectedColumn.getRemarks().ifPresent(r -> {
203                 field.addJavaDocLine("/**"); //$NON-NLS-1$
204                 field.addJavaDocLine(" * Database Column Remarks:"); //$NON-NLS-1$
205                 String[] remarkLines = r.split(System.lineSeparator());
206                 for (String remarkLine : remarkLines) {
207                     field.addJavaDocLine(" *   " + remarkLine); //$NON-NLS-1$
208                 }
209                 field.addJavaDocLine(" */"); //$NON-NLS-1$
210             });
211         }
212     }
213 
214     @Override
215     public void addClassAnnotation(InnerClass innerClass, IntrospectedTable introspectedTable,
216             Set<FullyQualifiedJavaType> imports) {
217         if (suppressAllComments) {
218             return;
219         }
220 
221         imports.add(generatedImport);
222         String comment = "Source Table: " + introspectedTable.getFullyQualifiedTable(); //$NON-NLS-1$
223         innerClass.addAnnotation(getGeneratedAnnotation(comment, false));
224     }
225 
226     @Override
227     public void addClassAnnotationAndMarkAsDoNotDelete(InnerClass innerClass, IntrospectedTable introspectedTable,
228                                                        Set<FullyQualifiedJavaType> imports) {
229         if (suppressAllComments) {
230             return;
231         }
232 
233         imports.add(generatedImport);
234         innerClass.addAnnotation(getGeneratedAnnotation(MergeConstants.DO_NOT_DELETE_DURING_MERGE, true));
235     }
236 
237     @Override
238     public void addRecordAnnotation(InnerRecord innerRecord, IntrospectedTable introspectedTable,
239                                     Set<FullyQualifiedJavaType> imports) {
240         if (suppressAllComments) {
241             return;
242         }
243 
244         imports.add(generatedImport);
245         String comment = "Source Table: " + introspectedTable.getFullyQualifiedTable(); //$NON-NLS-1$
246         innerRecord.addAnnotation(getGeneratedAnnotation(comment, false));
247     }
248 
249     @Override
250     public void addEnumAnnotation(InnerEnum innerEnum, IntrospectedTable introspectedTable,
251                                   Set<FullyQualifiedJavaType> imports) {
252         if (suppressAllComments) {
253             return;
254         }
255 
256         imports.add(generatedImport);
257         String comment = "Source Table: " + introspectedTable.getFullyQualifiedTable(); //$NON-NLS-1$
258         innerEnum.addAnnotation(getGeneratedAnnotation(comment, false));
259     }
260 
261     private String getGeneratedAnnotation(String comment, boolean forceComment) {
262         StringBuilder buffer = new StringBuilder();
263         buffer.append("@Generated("); //$NON-NLS-1$
264 
265         if (forceComment || !minimizeComments) {
266             buffer.append("value=\""); //$NON-NLS-1$
267         } else {
268             buffer.append('\"');
269         }
270 
271 
272         buffer.append(MyBatisGenerator.class.getName());
273         buffer.append('\"');
274 
275         getDateString().ifPresent(s -> buffer.append(String.format(", date=\"%s\"", s))); //$NON-NLS-1$
276 
277         if (forceComment || !minimizeComments) {
278             buffer.append(String.format(", comments=\"%s\"", comment)); //$NON-NLS-1$
279         }
280 
281         buffer.append(')');
282         return buffer.toString();
283     }
284 
285     @Override
286     public void addFileComment(KotlinFile kotlinFile) {
287         if (suppressAllComments) {
288             return;
289         }
290 
291         kotlinFile.addFileCommentLine("/*"); //$NON-NLS-1$
292         kotlinFile.addFileCommentLine(" * Auto-generated file. Created by MyBatis Generator"); //$NON-NLS-1$
293         getDateString().ifPresent(s -> kotlinFile.addFileCommentLine(" * Generation date: " + s));
294         kotlinFile.addFileCommentLine(" */"); //$NON-NLS-1$
295     }
296 }