DefaultCommentGenerator.java
/*
* Copyright 2006-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mybatis.generator.internal;
import static org.mybatis.generator.internal.util.StringUtility.isTrue;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import org.mybatis.generator.api.CommentGenerator;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.api.dom.OutputUtilities;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.InnerClass;
import org.mybatis.generator.api.dom.java.InnerEnum;
import org.mybatis.generator.api.dom.java.InnerRecord;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.api.dom.kotlin.KotlinFile;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.config.MergeConstants;
import org.mybatis.generator.config.PropertyRegistry;
public class DefaultCommentGenerator implements CommentGenerator {
private final Properties properties = new Properties();
private boolean suppressDate;
private boolean suppressAllComments;
private boolean minimizeComments;
/** If suppressAllComments or minimizeComments is true, this option is ignored. */
private boolean addRemarkComments;
private final FullyQualifiedJavaType generatedImport =
new FullyQualifiedJavaType("jakarta.annotation.Generated"); //$NON-NLS-1$
public DefaultCommentGenerator() {
super();
suppressDate = false;
suppressAllComments = false;
addRemarkComments = false;
minimizeComments = false;
}
@Override
public void addConfigurationProperties(Properties props) {
this.properties.putAll(props);
suppressDate = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_DATE));
suppressAllComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS));
addRemarkComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_ADD_REMARK_COMMENTS));
minimizeComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_MINIMIZE_COMMENTS));
}
/**
* Adds a suitable comment to warn users that the element was generated and
* when it was generated.
*
* @param xmlElement the XML element
*/
@Override
public void addComment(XmlElement xmlElement) {
if (suppressAllComments) {
return;
}
xmlElement.addElement(new TextElement("<!--")); //$NON-NLS-1$
String sb = OutputUtilities.xmlIndent(1)
+ "Generated Code - " //$NON-NLS-1$
+ MergeConstants.NEW_ELEMENT_TAG;
xmlElement.addElement(new TextElement(sb));
if (!minimizeComments) {
xmlElement.addElement(
new TextElement(OutputUtilities.xmlIndent(1)
+ "This element is automatically generated by MyBatis Generator," //$NON-NLS-1$
+ " do not modify.")); //$NON-NLS-1$
}
getDateString().ifPresent(s -> {
String text = OutputUtilities.xmlIndent(1)
+ "This element was generated on " //$NON-NLS-1$
+ s
+ '.';
xmlElement.addElement(new TextElement(text));
});
xmlElement.addElement(new TextElement("-->")); //$NON-NLS-1$
}
/**
* Returns a formatted date string to include in the Javadoc tag and XML
* comments. You may return null if you do not want the date in these
* documentation elements.
*
* @return a string representing the current timestamp, or null
*/
protected Optional<String> getDateString() {
if (suppressDate || minimizeComments) {
return Optional.empty();
} else {
return Optional.of(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.now()));
}
}
@Override
public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
if (suppressAllComments || minimizeComments) {
return;
}
if (addRemarkComments) {
introspectedTable.getRemarks().ifPresent(remarks -> {
topLevelClass.addJavaDocLine("/**"); //$NON-NLS-1$
topLevelClass.addJavaDocLine(" * Database Table Remarks:"); //$NON-NLS-1$
String[] remarkLines = remarks.split(System.lineSeparator());
for (String remarkLine : remarkLines) {
topLevelClass.addJavaDocLine(" * " + remarkLine); //$NON-NLS-1$
}
topLevelClass.addJavaDocLine(" */"); //$NON-NLS-1$
});
}
}
@Override
public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable,
Set<FullyQualifiedJavaType> imports) {
if (suppressAllComments) {
return;
}
imports.add(generatedImport);
String comment = "Source Table: " + introspectedTable.getFullyQualifiedTable(); //$NON-NLS-1$
method.addAnnotation(getGeneratedAnnotation(comment, false));
}
@Override
public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn, Set<FullyQualifiedJavaType> imports) {
if (suppressAllComments) {
return;
}
imports.add(generatedImport);
String comment = "Source field: " //$NON-NLS-1$
+ introspectedTable.getFullyQualifiedTable() + "." //$NON-NLS-1$
+ introspectedColumn.getActualColumnName();
method.addAnnotation(getGeneratedAnnotation(comment, false));
}
@Override
public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable,
Set<FullyQualifiedJavaType> imports) {
if (suppressAllComments) {
return;
}
imports.add(generatedImport);
String comment = "Source Table: " + introspectedTable.getFullyQualifiedTable(); //$NON-NLS-1$
field.addAnnotation(getGeneratedAnnotation(comment, false));
}
@Override
public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn, Set<FullyQualifiedJavaType> imports) {
if (suppressAllComments) {
return;
}
imports.add(generatedImport);
String comment = "Source field: " //$NON-NLS-1$
+ introspectedTable.getFullyQualifiedTable() + "." //$NON-NLS-1$
+ introspectedColumn.getActualColumnName();
field.addAnnotation(getGeneratedAnnotation(comment, false));
if (!minimizeComments && addRemarkComments) {
introspectedColumn.getRemarks().ifPresent(r -> {
field.addJavaDocLine("/**"); //$NON-NLS-1$
field.addJavaDocLine(" * Database Column Remarks:"); //$NON-NLS-1$
String[] remarkLines = r.split(System.lineSeparator());
for (String remarkLine : remarkLines) {
field.addJavaDocLine(" * " + remarkLine); //$NON-NLS-1$
}
field.addJavaDocLine(" */"); //$NON-NLS-1$
});
}
}
@Override
public void addClassAnnotation(InnerClass innerClass, IntrospectedTable introspectedTable,
Set<FullyQualifiedJavaType> imports) {
if (suppressAllComments) {
return;
}
imports.add(generatedImport);
String comment = "Source Table: " + introspectedTable.getFullyQualifiedTable(); //$NON-NLS-1$
innerClass.addAnnotation(getGeneratedAnnotation(comment, false));
}
@Override
public void addClassAnnotationAndMarkAsDoNotDelete(InnerClass innerClass, IntrospectedTable introspectedTable,
Set<FullyQualifiedJavaType> imports) {
if (suppressAllComments) {
return;
}
imports.add(generatedImport);
innerClass.addAnnotation(getGeneratedAnnotation(MergeConstants.DO_NOT_DELETE_DURING_MERGE, true));
}
@Override
public void addRecordAnnotation(InnerRecord innerRecord, IntrospectedTable introspectedTable,
Set<FullyQualifiedJavaType> imports) {
if (suppressAllComments) {
return;
}
imports.add(generatedImport);
String comment = "Source Table: " + introspectedTable.getFullyQualifiedTable(); //$NON-NLS-1$
innerRecord.addAnnotation(getGeneratedAnnotation(comment, false));
}
@Override
public void addEnumAnnotation(InnerEnum innerEnum, IntrospectedTable introspectedTable,
Set<FullyQualifiedJavaType> imports) {
if (suppressAllComments) {
return;
}
imports.add(generatedImport);
String comment = "Source Table: " + introspectedTable.getFullyQualifiedTable(); //$NON-NLS-1$
innerEnum.addAnnotation(getGeneratedAnnotation(comment, false));
}
private String getGeneratedAnnotation(String comment, boolean forceComment) {
StringBuilder buffer = new StringBuilder();
buffer.append("@Generated("); //$NON-NLS-1$
if (forceComment || !minimizeComments) {
buffer.append("value=\""); //$NON-NLS-1$
} else {
buffer.append('\"');
}
buffer.append(MyBatisGenerator.class.getName());
buffer.append('\"');
getDateString().ifPresent(s -> buffer.append(String.format(", date=\"%s\"", s))); //$NON-NLS-1$
if (forceComment || !minimizeComments) {
buffer.append(String.format(", comments=\"%s\"", comment)); //$NON-NLS-1$
}
buffer.append(')');
return buffer.toString();
}
@Override
public void addFileComment(KotlinFile kotlinFile) {
if (suppressAllComments) {
return;
}
kotlinFile.addFileCommentLine("/*"); //$NON-NLS-1$
kotlinFile.addFileCommentLine(" * Auto-generated file. Created by MyBatis Generator"); //$NON-NLS-1$
getDateString().ifPresent(s -> kotlinFile.addFileCommentLine(" * Generation date: " + s));
kotlinFile.addFileCommentLine(" */"); //$NON-NLS-1$
}
}