1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.generator.runtime.kotlin;
17
18 import static org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities.getEscapedColumnName;
19 import static org.mybatis.generator.internal.util.StringUtility.escapeStringForKotlin;
20
21 import java.util.List;
22 import java.util.Objects;
23
24 import org.mybatis.generator.api.IntrospectedColumn;
25 import org.mybatis.generator.api.IntrospectedTable;
26 import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
27 import org.mybatis.generator.api.dom.kotlin.FullyQualifiedKotlinType;
28 import org.mybatis.generator.api.dom.kotlin.JavaToKotlinTypeConverter;
29 import org.mybatis.generator.api.dom.kotlin.KotlinFile;
30 import org.mybatis.generator.api.dom.kotlin.KotlinProperty;
31 import org.mybatis.generator.api.dom.kotlin.KotlinType;
32 import org.mybatis.generator.config.Context;
33 import org.mybatis.generator.config.PropertyRegistry;
34 import org.mybatis.generator.internal.util.JavaBeansUtil;
35 import org.mybatis.generator.internal.util.StringUtility;
36 import org.mybatis.generator.internal.util.messages.Messages;
37
38 public class KotlinDynamicSqlSupportClassGenerator {
39 private final IntrospectedTable introspectedTable;
40 private final Context context;
41 private final List<String> warnings;
42 private KotlinFile kotlinFile;
43 private KotlinType innerClass;
44 private KotlinType outerObject;
45 private KotlinProperty tableProperty;
46
47 public KotlinDynamicSqlSupportClassGenerator(Context context, IntrospectedTable introspectedTable,
48 List<String> warnings) {
49 this.introspectedTable = Objects.requireNonNull(introspectedTable);
50 this.context = Objects.requireNonNull(context);
51 this.warnings = Objects.requireNonNull(warnings);
52 generate();
53 }
54
55 private void generate() {
56 FullyQualifiedJavaType type =
57 new FullyQualifiedJavaType(introspectedTable.getMyBatisDynamicSqlSupportType());
58
59 kotlinFile = buildBasicFile(type);
60
61 outerObject = buildOuterObject(kotlinFile, type);
62
63 tableProperty = calculateTableProperty();
64 outerObject.addNamedItem(tableProperty);
65
66 innerClass = buildInnerClass();
67
68 List<IntrospectedColumn> columns = introspectedTable.getAllColumns();
69 for (IntrospectedColumn column : columns) {
70 handleColumn(kotlinFile, outerObject, innerClass, getTablePropertyName(), column);
71 }
72
73 outerObject.addNamedItem(innerClass);
74 }
75
76 public KotlinFile getKotlinFile() {
77 return kotlinFile;
78 }
79
80 public String getTablePropertyName() {
81 return tableProperty.getName();
82 }
83
84 public KotlinType getInnerClass() {
85 return innerClass;
86 }
87
88 public KotlinType getOuterObject() {
89 return outerObject;
90 }
91
92 public String getTablePropertyImport() {
93 return getSupportObjectImport()
94 + "."
95 + tableProperty.getName();
96 }
97
98 public String getSupportObjectImport() {
99 return kotlinFile.getPackage().map(s -> s + ".").orElse("")
100 + outerObject.getName();
101 }
102
103 private KotlinFile buildBasicFile(FullyQualifiedJavaType type) {
104 KotlinFile kf = new KotlinFile(type.getShortNameWithoutTypeArguments());
105 kf.setPackage(type.getPackageName());
106 context.getCommentGenerator().addFileComment(kf);
107
108 return kf;
109 }
110
111 private KotlinType buildOuterObject(KotlinFile kotlinFile, FullyQualifiedJavaType type) {
112 KotlinType outerObject = KotlinType.newObject(type.getShortNameWithoutTypeArguments())
113 .build();
114
115 kotlinFile.addImport("org.mybatis.dynamic.sql.AliasableSqlTable");
116 kotlinFile.addImport("org.mybatis.dynamic.sql.util.kotlin.elements.column");
117 kotlinFile.addImport("java.sql.JDBCType");
118 kotlinFile.addNamedItem(outerObject);
119 return outerObject;
120 }
121
122
123 private KotlinType buildInnerClass() {
124 String domainObjectName = introspectedTable.getMyBatisDynamicSQLTableObjectName();
125
126 return KotlinType.newClass(domainObjectName)
127 .withSuperType("AliasableSqlTable<" + domainObjectName + ">(\""
128 + escapeStringForKotlin(introspectedTable.getFullyQualifiedTableNameAtRuntime())
129 + "\", ::" + domainObjectName
130 + ")")
131 .build();
132 }
133
134 private KotlinProperty calculateTableProperty() {
135 String tableType = introspectedTable.getMyBatisDynamicSQLTableObjectName();
136 String fieldName =
137 JavaBeansUtil.getValidPropertyName(introspectedTable.getMyBatisDynamicSQLTableObjectName());
138
139 return KotlinProperty.newVal(fieldName)
140 .withInitializationString(tableType + "()")
141 .build();
142 }
143
144 private void handleColumn(KotlinFile kotlinFile, KotlinType outerObject, KotlinType innerClass,
145 String tableFieldName, IntrospectedColumn column) {
146
147 FullyQualifiedKotlinType kt = JavaToKotlinTypeConverter.convert(column.getFullyQualifiedJavaType());
148
149 kotlinFile.addImports(kt.getImportList());
150
151 String fieldName = column.getJavaProperty();
152
153
154 if (fieldName.equals(tableFieldName)) {
155
156 warnings.add(
157 Messages.getString("Warning.29",
158 fieldName, getSupportObjectImport()));
159 } else {
160 KotlinProperty prop = KotlinProperty.newVal(fieldName)
161 .withInitializationString(tableFieldName + "." + fieldName)
162 .build();
163 outerObject.addNamedItem(prop);
164 }
165
166
167
168 KotlinProperty property = KotlinProperty.newVal(fieldName)
169 .withInitializationString(calculateInnerInitializationString(column, kt))
170 .build();
171
172 innerClass.addNamedItem(property);
173 }
174
175 private String calculateInnerInitializationString(IntrospectedColumn column, FullyQualifiedKotlinType kt) {
176 StringBuilder initializationString = new StringBuilder();
177
178 initializationString.append(String.format("column<%s>(name = \"%s\", jdbcType = JDBCType.%s",
179 kt.getShortNameWithTypeArguments(),
180 escapeStringForKotlin(getEscapedColumnName(column)),
181 column.getJdbcTypeName()));
182
183 if (StringUtility.stringHasValue(column.getTypeHandler())) {
184 initializationString.append(
185 String.format(", typeHandler = \"%s\"", column.getTypeHandler()));
186 }
187
188 if (StringUtility.isTrue(
189 column.getProperties().getProperty(PropertyRegistry.COLUMN_OVERRIDE_FORCE_JAVA_TYPE))) {
190 initializationString.append(
191 String.format(", javaType = %s::class", kt.getShortNameWithoutTypeArguments()));
192 }
193
194 initializationString.append(')');
195
196 return initializationString.toString();
197 }
198 }