View Javadoc
1   /*
2    *    Copyright 2006-2023 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.codegen.mybatis3.model;
17  
18  import static org.mybatis.generator.internal.util.JavaBeansUtil.getGetterMethodName;
19  import static org.mybatis.generator.internal.util.StringUtility.stringHasValue;
20  import static org.mybatis.generator.internal.util.messages.Messages.getString;
21  
22  import java.util.ArrayList;
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import org.mybatis.generator.api.CommentGenerator;
27  import org.mybatis.generator.api.FullyQualifiedTable;
28  import org.mybatis.generator.api.IntrospectedColumn;
29  import org.mybatis.generator.api.dom.OutputUtilities;
30  import org.mybatis.generator.api.dom.java.CompilationUnit;
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.JavaVisibility;
35  import org.mybatis.generator.api.dom.java.Method;
36  import org.mybatis.generator.api.dom.java.Parameter;
37  import org.mybatis.generator.api.dom.java.TopLevelClass;
38  import org.mybatis.generator.codegen.AbstractJavaGenerator;
39  import org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities;
40  
41  public class ExampleGenerator extends AbstractJavaGenerator {
42  
43      public ExampleGenerator(String project) {
44          super(project);
45      }
46  
47      @Override
48      public List<CompilationUnit> getCompilationUnits() {
49          FullyQualifiedTable table = introspectedTable.getFullyQualifiedTable();
50          progressCallback.startTask(getString("Progress.6", table.toString())); //$NON-NLS-1$
51          CommentGenerator commentGenerator = context.getCommentGenerator();
52  
53          FullyQualifiedJavaType type = new FullyQualifiedJavaType(introspectedTable.getExampleType());
54          TopLevelClass topLevelClass = new TopLevelClass(type);
55          topLevelClass.setVisibility(JavaVisibility.PUBLIC);
56          commentGenerator.addJavaFileComment(topLevelClass);
57  
58          // add default constructor
59          Method method = new Method(type.getShortName());
60          method.setVisibility(JavaVisibility.PUBLIC);
61          method.setConstructor(true);
62          method.addBodyLine("oredCriteria = new ArrayList<>();"); //$NON-NLS-1$
63  
64          commentGenerator.addGeneralMethodComment(method, introspectedTable);
65          topLevelClass.addMethod(method);
66  
67          // add field, getter, setter for orderby clause
68          Field field = new Field("orderByClause", FullyQualifiedJavaType.getStringInstance()); //$NON-NLS-1$
69          field.setVisibility(JavaVisibility.PROTECTED);
70          commentGenerator.addFieldComment(field, introspectedTable);
71          topLevelClass.addField(field);
72  
73          method = new Method("setOrderByClause"); //$NON-NLS-1$
74          method.setVisibility(JavaVisibility.PUBLIC);
75          method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "orderByClause")); //$NON-NLS-1$
76          method.addBodyLine("this.orderByClause = orderByClause;"); //$NON-NLS-1$
77          commentGenerator.addGeneralMethodComment(method, introspectedTable);
78          topLevelClass.addMethod(method);
79  
80          method = new Method("getOrderByClause"); //$NON-NLS-1$
81          method.setVisibility(JavaVisibility.PUBLIC);
82          method.setReturnType(FullyQualifiedJavaType.getStringInstance());
83          method.addBodyLine("return orderByClause;"); //$NON-NLS-1$
84          commentGenerator.addGeneralMethodComment(method, introspectedTable);
85          topLevelClass.addMethod(method);
86  
87          // add field, getter, setter for distinct
88          field = new Field("distinct", FullyQualifiedJavaType.getBooleanPrimitiveInstance()); //$NON-NLS-1$
89          field.setVisibility(JavaVisibility.PROTECTED);
90          commentGenerator.addFieldComment(field, introspectedTable);
91          topLevelClass.addField(field);
92  
93          method = new Method("setDistinct"); //$NON-NLS-1$
94          method.setVisibility(JavaVisibility.PUBLIC);
95          method.addParameter(
96                  new Parameter(FullyQualifiedJavaType.getBooleanPrimitiveInstance(), "distinct")); //$NON-NLS-1$
97          method.addBodyLine("this.distinct = distinct;"); //$NON-NLS-1$
98          commentGenerator.addGeneralMethodComment(method, introspectedTable);
99          topLevelClass.addMethod(method);
100 
101         method = new Method("isDistinct"); //$NON-NLS-1$
102         method.setVisibility(JavaVisibility.PUBLIC);
103         method.setReturnType(FullyQualifiedJavaType.getBooleanPrimitiveInstance());
104         method.addBodyLine("return distinct;"); //$NON-NLS-1$
105         commentGenerator.addGeneralMethodComment(method, introspectedTable);
106         topLevelClass.addMethod(method);
107 
108         // add field and methods for the list of ored criteria
109         FullyQualifiedJavaType fqjt = new FullyQualifiedJavaType("java.util.List<Criteria>"); //$NON-NLS-1$
110         field = new Field("oredCriteria", fqjt); //$NON-NLS-1$
111         field.setVisibility(JavaVisibility.PROTECTED);
112 
113         commentGenerator.addFieldComment(field, introspectedTable);
114         topLevelClass.addField(field);
115 
116         method = new Method("getOredCriteria"); //$NON-NLS-1$
117         method.setVisibility(JavaVisibility.PUBLIC);
118         method.setReturnType(fqjt);
119         method.addBodyLine("return oredCriteria;"); //$NON-NLS-1$
120         commentGenerator.addGeneralMethodComment(method, introspectedTable);
121         topLevelClass.addMethod(method);
122 
123         method = new Method("or"); //$NON-NLS-1$
124         method.setVisibility(JavaVisibility.PUBLIC);
125         method.addParameter(new Parameter(FullyQualifiedJavaType.getCriteriaInstance(), "criteria")); //$NON-NLS-1$
126         method.addBodyLine("oredCriteria.add(criteria);"); //$NON-NLS-1$
127         commentGenerator.addGeneralMethodComment(method, introspectedTable);
128         topLevelClass.addMethod(method);
129 
130         method = new Method("or"); //$NON-NLS-1$
131         method.setVisibility(JavaVisibility.PUBLIC);
132         method.setReturnType(FullyQualifiedJavaType.getCriteriaInstance());
133         method.addBodyLine("Criteria criteria = createCriteriaInternal();"); //$NON-NLS-1$
134         method.addBodyLine("oredCriteria.add(criteria);"); //$NON-NLS-1$
135         method.addBodyLine("return criteria;"); //$NON-NLS-1$
136         commentGenerator.addGeneralMethodComment(method, introspectedTable);
137         topLevelClass.addMethod(method);
138 
139         method = new Method("createCriteria"); //$NON-NLS-1$
140         method.setVisibility(JavaVisibility.PUBLIC);
141         method.setReturnType(FullyQualifiedJavaType.getCriteriaInstance());
142         method.addBodyLine("Criteria criteria = createCriteriaInternal();"); //$NON-NLS-1$
143         method.addBodyLine("if (oredCriteria.size() == 0) {"); //$NON-NLS-1$
144         method.addBodyLine("oredCriteria.add(criteria);"); //$NON-NLS-1$
145         method.addBodyLine("}"); //$NON-NLS-1$
146         method.addBodyLine("return criteria;"); //$NON-NLS-1$
147         commentGenerator.addGeneralMethodComment(method, introspectedTable);
148         topLevelClass.addMethod(method);
149 
150         method = new Method("createCriteriaInternal"); //$NON-NLS-1$
151         method.setVisibility(JavaVisibility.PROTECTED);
152         method.setReturnType(FullyQualifiedJavaType.getCriteriaInstance());
153         method.addBodyLine("Criteria criteria = new Criteria();"); //$NON-NLS-1$
154         method.addBodyLine("return criteria;"); //$NON-NLS-1$
155         commentGenerator.addGeneralMethodComment(method, introspectedTable);
156         topLevelClass.addMethod(method);
157 
158         method = new Method("clear"); //$NON-NLS-1$
159         method.setVisibility(JavaVisibility.PUBLIC);
160         method.addBodyLine("oredCriteria.clear();"); //$NON-NLS-1$
161         method.addBodyLine("orderByClause = null;"); //$NON-NLS-1$
162         method.addBodyLine("distinct = false;"); //$NON-NLS-1$
163         commentGenerator.addGeneralMethodComment(method, introspectedTable);
164         topLevelClass.addMethod(method);
165 
166         // now generate the inner class that holds the AND conditions
167         topLevelClass.addInnerClass(getGeneratedCriteriaInnerClass(topLevelClass));
168 
169         topLevelClass.addInnerClass(getCriteriaInnerClass());
170 
171         topLevelClass.addInnerClass(getCriterionInnerClass());
172 
173         List<CompilationUnit> answer = new ArrayList<>();
174         if (context.getPlugins().modelExampleClassGenerated(topLevelClass, introspectedTable)) {
175             answer.add(topLevelClass);
176         }
177         return answer;
178     }
179 
180     private InnerClass getCriterionInnerClass() {
181         InnerClass answer = new InnerClass(new FullyQualifiedJavaType("Criterion")); //$NON-NLS-1$
182         answer.setVisibility(JavaVisibility.PUBLIC);
183         answer.setStatic(true);
184         context.getCommentGenerator().addClassComment(answer, introspectedTable);
185 
186         Field field = new Field("condition", FullyQualifiedJavaType.getStringInstance()); //$NON-NLS-1$
187         field.setVisibility(JavaVisibility.PRIVATE);
188         answer.addField(field);
189         answer.addMethod(getGetter(field));
190 
191         field = new Field("value", FullyQualifiedJavaType.getObjectInstance()); //$NON-NLS-1$
192         field.setVisibility(JavaVisibility.PRIVATE);
193         answer.addField(field);
194         answer.addMethod(getGetter(field));
195 
196         field = new Field("secondValue", FullyQualifiedJavaType.getObjectInstance()); //$NON-NLS-1$
197         field.setVisibility(JavaVisibility.PRIVATE);
198         answer.addField(field);
199         answer.addMethod(getGetter(field));
200 
201         field = new Field("noValue", FullyQualifiedJavaType.getBooleanPrimitiveInstance()); //$NON-NLS-1$
202         field.setVisibility(JavaVisibility.PRIVATE);
203         answer.addField(field);
204         answer.addMethod(getGetter(field));
205 
206         field = new Field("singleValue", FullyQualifiedJavaType.getBooleanPrimitiveInstance()); //$NON-NLS-1$
207         field.setVisibility(JavaVisibility.PRIVATE);
208         answer.addField(field);
209         answer.addMethod(getGetter(field));
210 
211         field = new Field("betweenValue", FullyQualifiedJavaType.getBooleanPrimitiveInstance()); //$NON-NLS-1$
212         field.setVisibility(JavaVisibility.PRIVATE);
213         answer.addField(field);
214         answer.addMethod(getGetter(field));
215 
216         field = new Field("listValue", FullyQualifiedJavaType.getBooleanPrimitiveInstance()); //$NON-NLS-1$
217         field.setVisibility(JavaVisibility.PRIVATE);
218         answer.addField(field);
219         answer.addMethod(getGetter(field));
220 
221         field = new Field("typeHandler", FullyQualifiedJavaType.getStringInstance()); //$NON-NLS-1$
222         field.setVisibility(JavaVisibility.PRIVATE);
223         answer.addField(field);
224         answer.addMethod(getGetter(field));
225 
226         Method method = new Method("Criterion"); //$NON-NLS-1$
227         method.setVisibility(JavaVisibility.PROTECTED);
228         method.setConstructor(true);
229         method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); //$NON-NLS-1$
230         method.addBodyLine("super();"); //$NON-NLS-1$
231         method.addBodyLine("this.condition = condition;"); //$NON-NLS-1$
232         method.addBodyLine("this.typeHandler = null;"); //$NON-NLS-1$
233         method.addBodyLine("this.noValue = true;"); //$NON-NLS-1$
234         answer.addMethod(method);
235 
236         method = new Method("Criterion"); //$NON-NLS-1$
237         method.setVisibility(JavaVisibility.PROTECTED);
238         method.setConstructor(true);
239         method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); //$NON-NLS-1$
240         method.addParameter(new Parameter(FullyQualifiedJavaType.getObjectInstance(), "value")); //$NON-NLS-1$
241         method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "typeHandler")); //$NON-NLS-1$
242         method.addBodyLine("super();"); //$NON-NLS-1$
243         method.addBodyLine("this.condition = condition;"); //$NON-NLS-1$
244         method.addBodyLine("this.value = value;"); //$NON-NLS-1$
245         method.addBodyLine("this.typeHandler = typeHandler;"); //$NON-NLS-1$
246         method.addBodyLine("if (value instanceof List<?>) {"); //$NON-NLS-1$
247         method.addBodyLine("this.listValue = true;"); //$NON-NLS-1$
248         method.addBodyLine("} else {"); //$NON-NLS-1$
249         method.addBodyLine("this.singleValue = true;"); //$NON-NLS-1$
250         method.addBodyLine("}"); //$NON-NLS-1$
251         answer.addMethod(method);
252 
253         method = createCriterionConstructor();
254         method.addBodyLine("this(condition, value, null);"); //$NON-NLS-1$
255         answer.addMethod(method);
256 
257         method = createCriterionConstructor();
258         method.addParameter(new Parameter(FullyQualifiedJavaType.getObjectInstance(), "secondValue")); //$NON-NLS-1$
259         method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "typeHandler")); //$NON-NLS-1$
260         method.addBodyLine("super();"); //$NON-NLS-1$
261         method.addBodyLine("this.condition = condition;"); //$NON-NLS-1$
262         method.addBodyLine("this.value = value;"); //$NON-NLS-1$
263         method.addBodyLine("this.secondValue = secondValue;"); //$NON-NLS-1$
264         method.addBodyLine("this.typeHandler = typeHandler;"); //$NON-NLS-1$
265         method.addBodyLine("this.betweenValue = true;"); //$NON-NLS-1$
266         answer.addMethod(method);
267 
268         method = createCriterionConstructor();
269         method.addParameter(new Parameter(FullyQualifiedJavaType.getObjectInstance(), "secondValue")); //$NON-NLS-1$
270         method.addBodyLine("this(condition, value, secondValue, null);"); //$NON-NLS-1$
271         answer.addMethod(method);
272 
273         return answer;
274     }
275 
276     private Method createCriterionConstructor() {
277         Method method = new Method("Criterion"); //$NON-NLS-1$
278         method.setVisibility(JavaVisibility.PROTECTED);
279         method.setConstructor(true);
280         method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); //$NON-NLS-1$
281         method.addParameter(new Parameter(FullyQualifiedJavaType.getObjectInstance(), "value")); //$NON-NLS-1$
282         return method;
283     }
284 
285     private InnerClass getCriteriaInnerClass() {
286         InnerClass answer = new InnerClass(FullyQualifiedJavaType.getCriteriaInstance());
287 
288         answer.setVisibility(JavaVisibility.PUBLIC);
289         answer.setStatic(true);
290         answer.setSuperClass(FullyQualifiedJavaType.getGeneratedCriteriaInstance());
291 
292         context.getCommentGenerator().addClassComment(answer, introspectedTable, true);
293 
294         Method method = new Method("Criteria"); //$NON-NLS-1$
295         method.setVisibility(JavaVisibility.PROTECTED);
296         method.setConstructor(true);
297         method.addBodyLine("super();"); //$NON-NLS-1$
298         answer.addMethod(method);
299 
300         return answer;
301     }
302 
303     private InnerClass getGeneratedCriteriaInnerClass(TopLevelClass topLevelClass) {
304         Field field;
305 
306         InnerClass answer = new InnerClass(FullyQualifiedJavaType.getGeneratedCriteriaInstance());
307 
308         answer.setVisibility(JavaVisibility.PROTECTED);
309         answer.setStatic(true);
310         answer.setAbstract(true);
311         context.getCommentGenerator().addClassComment(answer, introspectedTable);
312 
313         Method method = new Method("GeneratedCriteria"); //$NON-NLS-1$
314         method.setVisibility(JavaVisibility.PROTECTED);
315         method.setConstructor(true);
316         method.addBodyLine("super();"); //$NON-NLS-1$
317         method.addBodyLine("criteria = new ArrayList<>();"); //$NON-NLS-1$
318         answer.addMethod(method);
319 
320         List<String> criteriaLists = new ArrayList<>();
321         criteriaLists.add("criteria"); //$NON-NLS-1$
322 
323         for (IntrospectedColumn introspectedColumn : introspectedTable.getNonBLOBColumns()) {
324             if (stringHasValue(introspectedColumn.getTypeHandler())) {
325                 String name = addTypeHandledObjectsAndMethods(introspectedColumn, method, answer);
326                 criteriaLists.add(name);
327             }
328         }
329 
330         // now generate the isValid method
331         method = new Method("isValid"); //$NON-NLS-1$
332         method.setVisibility(JavaVisibility.PUBLIC);
333         method.setReturnType(FullyQualifiedJavaType.getBooleanPrimitiveInstance());
334         StringBuilder sb = new StringBuilder();
335         Iterator<String> strIter = criteriaLists.iterator();
336         sb.append("return "); //$NON-NLS-1$
337         sb.append(strIter.next());
338         sb.append(".size() > 0"); //$NON-NLS-1$
339         if (!strIter.hasNext()) {
340             sb.append(';');
341         }
342         method.addBodyLine(sb.toString());
343         while (strIter.hasNext()) {
344             sb.setLength(0);
345             OutputUtilities.javaIndent(sb, 1);
346             sb.append("|| "); //$NON-NLS-1$
347             sb.append(strIter.next());
348             sb.append(".size() > 0"); //$NON-NLS-1$
349             if (!strIter.hasNext()) {
350                 sb.append(';');
351             }
352             method.addBodyLine(sb.toString());
353         }
354         answer.addMethod(method);
355 
356         // now generate the getAllCriteria method
357         if (criteriaLists.size() > 1) {
358             field = new Field("allCriteria", //$NON-NLS-1$
359                     new FullyQualifiedJavaType("List<Criterion>")); //$NON-NLS-1$
360             field.setVisibility(JavaVisibility.PROTECTED);
361             answer.addField(field);
362         }
363 
364         method = new Method("getAllCriteria"); //$NON-NLS-1$
365         method.setVisibility(JavaVisibility.PUBLIC);
366         method.setReturnType(new FullyQualifiedJavaType("List<Criterion>")); //$NON-NLS-1$
367         if (criteriaLists.size() < 2) {
368             method.addBodyLine("return criteria;"); //$NON-NLS-1$
369         } else {
370             method.addBodyLine("if (allCriteria == null) {"); //$NON-NLS-1$
371             method.addBodyLine("allCriteria = new ArrayList<>();"); //$NON-NLS-1$
372 
373             strIter = criteriaLists.iterator();
374             while (strIter.hasNext()) {
375                 method.addBodyLine(String.format("allCriteria.addAll(%s);", strIter.next())); //$NON-NLS-1$
376             }
377 
378             method.addBodyLine("}"); //$NON-NLS-1$
379             method.addBodyLine("return allCriteria;"); //$NON-NLS-1$
380         }
381         answer.addMethod(method);
382 
383         // now we need to generate the methods that will be used in the SqlMap
384         // to generate the dynamic where clause
385         topLevelClass.addImportedType(FullyQualifiedJavaType.getNewListInstance());
386         topLevelClass.addImportedType(FullyQualifiedJavaType.getNewArrayListInstance());
387 
388         FullyQualifiedJavaType listOfCriterion =
389                 new FullyQualifiedJavaType("java.util.List<Criterion>"); //$NON-NLS-1$
390         field = new Field("criteria", listOfCriterion); //$NON-NLS-1$
391         field.setVisibility(JavaVisibility.PROTECTED);
392         answer.addField(field);
393 
394         method = new Method(getGetterMethodName(field.getName(), field.getType()));
395         method.setVisibility(JavaVisibility.PUBLIC);
396         method.setReturnType(field.getType());
397         method.addBodyLine("return criteria;"); //$NON-NLS-1$
398         answer.addMethod(method);
399 
400         // now add the methods for simplifying the individual field set methods
401         method = new Method("addCriterion"); //$NON-NLS-1$
402         method.setVisibility(JavaVisibility.PROTECTED);
403         method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); //$NON-NLS-1$
404         method.addBodyLine("if (condition == null) {"); //$NON-NLS-1$
405         method.addBodyLine("throw new RuntimeException(\"Value for condition cannot be null\");"); //$NON-NLS-1$
406         method.addBodyLine("}"); //$NON-NLS-1$
407         method.addBodyLine("criteria.add(new Criterion(condition));"); //$NON-NLS-1$
408         if (criteriaLists.size() > 1) {
409             method.addBodyLine("allCriteria = null;"); //$NON-NLS-1$
410         }
411         answer.addMethod(method);
412 
413         method = new Method("addCriterion"); //$NON-NLS-1$
414         method.setVisibility(JavaVisibility.PROTECTED);
415         method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); //$NON-NLS-1$
416         method.addParameter(new Parameter(FullyQualifiedJavaType.getObjectInstance(), "value")); //$NON-NLS-1$
417         method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); //$NON-NLS-1$
418         method.addBodyLine("if (value == null) {"); //$NON-NLS-1$
419         method.addBodyLine(
420                 "throw new RuntimeException(\"Value for \" + property + \" cannot be null\");"); //$NON-NLS-1$
421         method.addBodyLine("}"); //$NON-NLS-1$
422         method.addBodyLine("criteria.add(new Criterion(condition, value));"); //$NON-NLS-1$
423         if (criteriaLists.size() > 1) {
424             method.addBodyLine("allCriteria = null;"); //$NON-NLS-1$
425         }
426         answer.addMethod(method);
427 
428         method = new Method("addCriterion"); //$NON-NLS-1$
429         method.setVisibility(JavaVisibility.PROTECTED);
430         method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); //$NON-NLS-1$
431         method.addParameter(new Parameter(FullyQualifiedJavaType.getObjectInstance(), "value1")); //$NON-NLS-1$
432         method.addParameter(new Parameter(FullyQualifiedJavaType.getObjectInstance(), "value2")); //$NON-NLS-1$
433         method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); //$NON-NLS-1$
434         method.addBodyLine("if (value1 == null || value2 == null) {"); //$NON-NLS-1$
435         method.addBodyLine(
436                 "throw new RuntimeException(\"Between values for \" + property + \" cannot be null\");"); //$NON-NLS-1$
437         method.addBodyLine("}"); //$NON-NLS-1$
438         method.addBodyLine("criteria.add(new Criterion(condition, value1, value2));"); //$NON-NLS-1$
439         if (criteriaLists.size() > 1) {
440             method.addBodyLine("allCriteria = null;"); //$NON-NLS-1$
441         }
442         answer.addMethod(method);
443 
444         FullyQualifiedJavaType listOfDates =
445                 new FullyQualifiedJavaType("java.util.List<java.util.Date>"); //$NON-NLS-1$
446 
447         if (introspectedTable.hasJDBCDateColumns()) {
448             topLevelClass.addImportedType(FullyQualifiedJavaType.getDateInstance());
449             topLevelClass.addImportedType(FullyQualifiedJavaType.getNewIteratorInstance());
450             method = new Method("addCriterionForJDBCDate"); //$NON-NLS-1$
451             method.setVisibility(JavaVisibility.PROTECTED);
452             method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); //$NON-NLS-1$
453             method.addParameter(new Parameter(FullyQualifiedJavaType.getDateInstance(), "value")); //$NON-NLS-1$
454             method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); //$NON-NLS-1$
455             method.addBodyLine("if (value == null) {"); //$NON-NLS-1$
456             method.addBodyLine(
457                     "throw new RuntimeException(\"Value for \" + property + \" cannot be null\");"); //$NON-NLS-1$
458             method.addBodyLine("}"); //$NON-NLS-1$
459             method.addBodyLine(
460                     "addCriterion(condition, new java.sql.Date(value.getTime()), property);"); //$NON-NLS-1$
461             answer.addMethod(method);
462 
463             method = new Method("addCriterionForJDBCDate"); //$NON-NLS-1$
464             method.setVisibility(JavaVisibility.PROTECTED);
465             method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); //$NON-NLS-1$
466             method.addParameter(new Parameter(listOfDates, "values")); //$NON-NLS-1$
467             method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); //$NON-NLS-1$
468             method.addBodyLine("if (values == null || values.size() == 0) {"); //$NON-NLS-1$
469             method.addBodyLine(
470                     "throw new RuntimeException(\"Value list for \" + property + \"" //$NON-NLS-1$
471                     + " cannot be null or empty\");"); //$NON-NLS-1$
472             method.addBodyLine("}"); //$NON-NLS-1$
473             method.addBodyLine("List<java.sql.Date> dateList = new ArrayList<>();"); //$NON-NLS-1$
474             method.addBodyLine("Iterator<Date> iter = values.iterator();"); //$NON-NLS-1$
475             method.addBodyLine("while (iter.hasNext()) {"); //$NON-NLS-1$
476             method.addBodyLine("dateList.add(new java.sql.Date(iter.next().getTime()));"); //$NON-NLS-1$
477             method.addBodyLine("}"); //$NON-NLS-1$
478             method.addBodyLine("addCriterion(condition, dateList, property);"); //$NON-NLS-1$
479             answer.addMethod(method);
480 
481             method = new Method("addCriterionForJDBCDate"); //$NON-NLS-1$
482             method.setVisibility(JavaVisibility.PROTECTED);
483             method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); //$NON-NLS-1$
484             method.addParameter(new Parameter(FullyQualifiedJavaType.getDateInstance(), "value1")); //$NON-NLS-1$
485             method.addParameter(new Parameter(FullyQualifiedJavaType.getDateInstance(), "value2")); //$NON-NLS-1$
486             method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); //$NON-NLS-1$
487             method.addBodyLine("if (value1 == null || value2 == null) {"); //$NON-NLS-1$
488             method.addBodyLine(
489                     "throw new RuntimeException(\"Between values for \" + property + \"" //$NON-NLS-1$
490                     + " cannot be null\");"); //$NON-NLS-1$
491             method.addBodyLine("}"); //$NON-NLS-1$
492             method.addBodyLine(
493                     "addCriterion(condition, new java.sql.Date(value1.getTime())," //$NON-NLS-1$
494                     + " new java.sql.Date(value2.getTime()), property);"); //$NON-NLS-1$
495             answer.addMethod(method);
496         }
497 
498         if (introspectedTable.hasJDBCTimeColumns()) {
499             topLevelClass.addImportedType(FullyQualifiedJavaType.getDateInstance());
500             topLevelClass.addImportedType(FullyQualifiedJavaType.getNewIteratorInstance());
501             method = new Method("addCriterionForJDBCTime"); //$NON-NLS-1$
502             method.setVisibility(JavaVisibility.PROTECTED);
503             method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); //$NON-NLS-1$
504             method.addParameter(new Parameter(FullyQualifiedJavaType.getDateInstance(), "value")); //$NON-NLS-1$
505             method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); //$NON-NLS-1$
506             method.addBodyLine("if (value == null) {"); //$NON-NLS-1$
507             method.addBodyLine(
508                     "throw new RuntimeException(\"Value for \" + property + \" cannot be null\");"); //$NON-NLS-1$
509             method.addBodyLine("}"); //$NON-NLS-1$
510             method.addBodyLine(
511                     "addCriterion(condition, new java.sql.Time(value.getTime()), property);"); //$NON-NLS-1$
512             answer.addMethod(method);
513 
514             method = new Method("addCriterionForJDBCTime"); //$NON-NLS-1$
515             method.setVisibility(JavaVisibility.PROTECTED);
516             method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); //$NON-NLS-1$
517             method.addParameter(new Parameter(listOfDates, "values")); //$NON-NLS-1$
518             method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); //$NON-NLS-1$
519             method.addBodyLine("if (values == null || values.size() == 0) {"); //$NON-NLS-1$
520             method.addBodyLine(
521                     "throw new RuntimeException(\"Value list for \" + property + \"" //$NON-NLS-1$
522                     + " cannot be null or empty\");"); //$NON-NLS-1$
523             method.addBodyLine("}"); //$NON-NLS-1$
524             method.addBodyLine("List<java.sql.Time> timeList = new ArrayList<>();"); //$NON-NLS-1$
525             method.addBodyLine("Iterator<Date> iter = values.iterator();"); //$NON-NLS-1$
526             method.addBodyLine("while (iter.hasNext()) {"); //$NON-NLS-1$
527             method.addBodyLine("timeList.add(new java.sql.Time(iter.next().getTime()));"); //$NON-NLS-1$
528             method.addBodyLine("}"); //$NON-NLS-1$
529             method.addBodyLine("addCriterion(condition, timeList, property);"); //$NON-NLS-1$
530             answer.addMethod(method);
531 
532             method = new Method("addCriterionForJDBCTime"); //$NON-NLS-1$
533             method.setVisibility(JavaVisibility.PROTECTED);
534             method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); //$NON-NLS-1$
535             method.addParameter(new Parameter(FullyQualifiedJavaType.getDateInstance(), "value1")); //$NON-NLS-1$
536             method.addParameter(new Parameter(FullyQualifiedJavaType.getDateInstance(), "value2")); //$NON-NLS-1$
537             method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); //$NON-NLS-1$
538             method.addBodyLine("if (value1 == null || value2 == null) {"); //$NON-NLS-1$
539             method.addBodyLine(
540                     "throw new RuntimeException(\"Between values for \" + property + \"" //$NON-NLS-1$
541                     + " cannot be null\");"); //$NON-NLS-1$
542             method.addBodyLine("}"); //$NON-NLS-1$
543             method.addBodyLine(
544                     "addCriterion(condition, new java.sql.Time(value1.getTime())," //$NON-NLS-1$
545                     + " new java.sql.Time(value2.getTime()), property);"); //$NON-NLS-1$
546             answer.addMethod(method);
547         }
548 
549         for (IntrospectedColumn introspectedColumn : introspectedTable.getNonBLOBColumns()) {
550             topLevelClass.addImportedType(introspectedColumn.getFullyQualifiedJavaType());
551 
552             // here we need to add the individual methods for setting the
553             // conditions for a field
554             answer.addMethod(getSetNullMethod(introspectedColumn));
555             answer.addMethod(getSetNotNullMethod(introspectedColumn));
556             answer.addMethod(getSetEqualMethod(introspectedColumn));
557             answer.addMethod(getSetNotEqualMethod(introspectedColumn));
558             answer.addMethod(getSetGreaterThanMethod(introspectedColumn));
559             answer.addMethod(getSetGreaterThenOrEqualMethod(introspectedColumn));
560             answer.addMethod(getSetLessThanMethod(introspectedColumn));
561             answer.addMethod(getSetLessThanOrEqualMethod(introspectedColumn));
562 
563             if (introspectedColumn.isJdbcCharacterColumn()) {
564                 answer.addMethod(getSetLikeMethod(introspectedColumn));
565                 answer.addMethod(getSetNotLikeMethod(introspectedColumn));
566             }
567 
568             answer.addMethod(getSetInOrNotInMethod(introspectedColumn, true));
569             answer.addMethod(getSetInOrNotInMethod(introspectedColumn, false));
570             answer.addMethod(getSetBetweenOrNotBetweenMethod(introspectedColumn, true));
571             answer.addMethod(getSetBetweenOrNotBetweenMethod(introspectedColumn, false));
572         }
573 
574         return answer;
575     }
576 
577     private Method getSetNullMethod(IntrospectedColumn introspectedColumn) {
578         return getNoValueMethod(introspectedColumn, "IsNull", "is null"); //$NON-NLS-1$ //$NON-NLS-2$
579     }
580 
581     private Method getSetNotNullMethod(IntrospectedColumn introspectedColumn) {
582         return getNoValueMethod(introspectedColumn, "IsNotNull", "is not null"); //$NON-NLS-1$ //$NON-NLS-2$
583     }
584 
585     private Method getSetEqualMethod(IntrospectedColumn introspectedColumn) {
586         return getSingleValueMethod(introspectedColumn, "EqualTo", "="); //$NON-NLS-1$ //$NON-NLS-2$
587     }
588 
589     private Method getSetNotEqualMethod(IntrospectedColumn introspectedColumn) {
590         return getSingleValueMethod(introspectedColumn, "NotEqualTo", "<>"); //$NON-NLS-1$ //$NON-NLS-2$
591     }
592 
593     private Method getSetGreaterThanMethod(IntrospectedColumn introspectedColumn) {
594         return getSingleValueMethod(introspectedColumn, "GreaterThan", ">"); //$NON-NLS-1$ //$NON-NLS-2$
595     }
596 
597     private Method getSetGreaterThenOrEqualMethod(IntrospectedColumn introspectedColumn) {
598         return getSingleValueMethod(introspectedColumn,"GreaterThanOrEqualTo", ">="); //$NON-NLS-1$ //$NON-NLS-2$
599     }
600 
601     private Method getSetLessThanMethod(IntrospectedColumn introspectedColumn) {
602         return getSingleValueMethod(introspectedColumn, "LessThan", "<"); //$NON-NLS-1$ //$NON-NLS-2$
603     }
604 
605     private Method getSetLessThanOrEqualMethod(IntrospectedColumn introspectedColumn) {
606         return getSingleValueMethod(introspectedColumn,"LessThanOrEqualTo", "<="); //$NON-NLS-1$ //$NON-NLS-2$
607     }
608 
609     private Method getSetLikeMethod(IntrospectedColumn introspectedColumn) {
610         return getSingleValueMethod(introspectedColumn, "Like", "like"); //$NON-NLS-1$ //$NON-NLS-2$
611     }
612 
613     private Method getSetNotLikeMethod(IntrospectedColumn introspectedColumn) {
614         return getSingleValueMethod(introspectedColumn, "NotLike", "not like"); //$NON-NLS-1$ //$NON-NLS-2$
615     }
616 
617     private Method getSingleValueMethod(IntrospectedColumn introspectedColumn, String nameFragment, String operator) {
618 
619         StringBuilder sb = new StringBuilder();
620         sb.append(initializeAndMethodName(introspectedColumn));
621         sb.append(nameFragment);
622 
623         Method method = new Method(sb.toString());
624         method.setVisibility(JavaVisibility.PUBLIC);
625         method.addParameter(new Parameter(introspectedColumn.getFullyQualifiedJavaType(), "value")); //$NON-NLS-1$
626         method.setReturnType(FullyQualifiedJavaType.getCriteriaInstance());
627 
628         sb.setLength(0);
629         sb.append(initializeAddLine(introspectedColumn));
630         sb.append(' ');
631         sb.append(operator);
632         sb.append("\", "); //$NON-NLS-1$
633         sb.append("value"); //$NON-NLS-1$
634         sb.append(", \""); //$NON-NLS-1$
635         sb.append(introspectedColumn.getJavaProperty());
636         sb.append("\");"); //$NON-NLS-1$
637         method.addBodyLine(sb.toString());
638         method.addBodyLine("return (Criteria) this;"); //$NON-NLS-1$
639 
640         return method;
641     }
642 
643     private String initializeAndMethodName(IntrospectedColumn introspectedColumn) {
644         StringBuilder sb = new StringBuilder();
645         sb.append(introspectedColumn.getJavaProperty());
646         sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
647         sb.insert(0, "and"); //$NON-NLS-1$
648         return sb.toString();
649     }
650 
651     private String initializeAddLine(IntrospectedColumn introspectedColumn) {
652         StringBuilder sb = new StringBuilder();
653         if (introspectedColumn.isJDBCDateColumn()) {
654             sb.append("addCriterionForJDBCDate(\""); //$NON-NLS-1$
655         } else if (introspectedColumn.isJDBCTimeColumn()) {
656             sb.append("addCriterionForJDBCTime(\""); //$NON-NLS-1$
657         } else if (stringHasValue(introspectedColumn.getTypeHandler())) {
658             sb.append("add"); //$NON-NLS-1$
659             sb.append(introspectedColumn.getJavaProperty());
660             sb.setCharAt(3, Character.toUpperCase(sb.charAt(3)));
661             sb.append("Criterion(\""); //$NON-NLS-1$
662         } else {
663             sb.append("addCriterion(\""); //$NON-NLS-1$
664         }
665 
666         sb.append(MyBatis3FormattingUtilities.getAliasedActualColumnName(introspectedColumn));
667         return sb.toString();
668     }
669 
670     /**
671      * Generates methods that set between and not between conditions.
672      *
673      * @param introspectedColumn the introspected column
674      * @param betweenMethod true if between, else not between
675      * @return a generated method for the between or not between method
676      */
677     private Method getSetBetweenOrNotBetweenMethod(IntrospectedColumn introspectedColumn, boolean betweenMethod) {
678 
679         StringBuilder sb = new StringBuilder();
680         sb.append(initializeAndMethodName(introspectedColumn));
681         if (betweenMethod) {
682             sb.append("Between"); //$NON-NLS-1$
683         } else {
684             sb.append("NotBetween"); //$NON-NLS-1$
685         }
686         Method method = new Method(sb.toString());
687         method.setVisibility(JavaVisibility.PUBLIC);
688         FullyQualifiedJavaType type = introspectedColumn.getFullyQualifiedJavaType();
689 
690         method.addParameter(new Parameter(type, "value1")); //$NON-NLS-1$
691         method.addParameter(new Parameter(type, "value2")); //$NON-NLS-1$
692         method.setReturnType(FullyQualifiedJavaType.getCriteriaInstance());
693 
694         sb.setLength(0);
695         sb.append(initializeAddLine(introspectedColumn));
696         if (betweenMethod) {
697             sb.append(" between"); //$NON-NLS-1$
698         } else {
699             sb.append(" not between"); //$NON-NLS-1$
700         }
701         sb.append("\", "); //$NON-NLS-1$
702         sb.append("value1, value2"); //$NON-NLS-1$
703         sb.append(", \""); //$NON-NLS-1$
704         sb.append(introspectedColumn.getJavaProperty());
705         sb.append("\");"); //$NON-NLS-1$
706         method.addBodyLine(sb.toString());
707         method.addBodyLine("return (Criteria) this;"); //$NON-NLS-1$
708 
709         return method;
710     }
711 
712     /**
713      * Generates an In or NotIn method.
714      *
715      * @param introspectedColumn the introspected column
716      * @param inMethod
717      *            if true generates an "in" method, else generates a "not in"
718      *            method
719      * @return a generated method for the in or not in method
720      */
721     private Method getSetInOrNotInMethod(IntrospectedColumn introspectedColumn, boolean inMethod) {
722         StringBuilder sb = new StringBuilder();
723         sb.append(initializeAndMethodName(introspectedColumn));
724         if (inMethod) {
725             sb.append("In"); //$NON-NLS-1$
726         } else {
727             sb.append("NotIn"); //$NON-NLS-1$
728         }
729         Method method = new Method(sb.toString());
730         method.setVisibility(JavaVisibility.PUBLIC);
731         FullyQualifiedJavaType type = FullyQualifiedJavaType.getNewListInstance();
732         if (introspectedColumn.getFullyQualifiedJavaType().isPrimitive()) {
733             type.addTypeArgument(introspectedColumn.getFullyQualifiedJavaType().getPrimitiveTypeWrapper());
734         } else {
735             type.addTypeArgument(introspectedColumn.getFullyQualifiedJavaType());
736         }
737 
738         method.addParameter(new Parameter(type, "values")); //$NON-NLS-1$
739         method.setReturnType(FullyQualifiedJavaType.getCriteriaInstance());
740 
741         sb.setLength(0);
742         sb.append(initializeAddLine(introspectedColumn));
743         if (inMethod) {
744             sb.append(" in"); //$NON-NLS-1$
745         } else {
746             sb.append(" not in"); //$NON-NLS-1$
747         }
748         sb.append("\", values, \""); //$NON-NLS-1$
749         sb.append(introspectedColumn.getJavaProperty());
750         sb.append("\");"); //$NON-NLS-1$
751         method.addBodyLine(sb.toString());
752         method.addBodyLine("return (Criteria) this;"); //$NON-NLS-1$
753 
754         return method;
755     }
756 
757     private Method getNoValueMethod(IntrospectedColumn introspectedColumn, String nameFragment, String operator) {
758         StringBuilder sb = new StringBuilder();
759         sb.append(initializeAndMethodName(introspectedColumn));
760         sb.append(nameFragment);
761         Method method = new Method(sb.toString());
762 
763         method.setVisibility(JavaVisibility.PUBLIC);
764         method.setReturnType(FullyQualifiedJavaType.getCriteriaInstance());
765 
766         sb.setLength(0);
767         sb.append("addCriterion(\""); //$NON-NLS-1$
768         sb.append(MyBatis3FormattingUtilities.getAliasedActualColumnName(introspectedColumn));
769         sb.append(' ');
770         sb.append(operator);
771         sb.append("\");"); //$NON-NLS-1$
772         method.addBodyLine(sb.toString());
773         method.addBodyLine("return (Criteria) this;"); //$NON-NLS-1$
774 
775         return method;
776     }
777 
778     /**
779      * This method adds all the extra methods and fields required to support a
780      * user defined type handler on some column.
781      *
782      * @param introspectedColumn the introspected column
783      * @param constructor the constructor
784      * @param innerClass the enclosing class
785      * @return the name of the List added to the class by this method
786      */
787     private String addTypeHandledObjectsAndMethods(IntrospectedColumn introspectedColumn, Method constructor,
788                                                    InnerClass innerClass) {
789         StringBuilder sb = new StringBuilder();
790 
791         // add new private field and public accessor in the class
792         sb.setLength(0);
793         sb.append(introspectedColumn.getJavaProperty());
794         sb.append("Criteria"); //$NON-NLS-1$
795         String answer = sb.toString();
796 
797         Field field = new Field(answer, new FullyQualifiedJavaType("java.util.List<Criterion>")); //$NON-NLS-1$
798         field.setVisibility(JavaVisibility.PROTECTED);
799         innerClass.addField(field);
800 
801         Method method = new Method(getGetterMethodName(field.getName(), field.getType()));
802         method.setVisibility(JavaVisibility.PUBLIC);
803         method.setReturnType(field.getType());
804         sb.insert(0, "return "); //$NON-NLS-1$
805         sb.append(';');
806         method.addBodyLine(sb.toString());
807         innerClass.addMethod(method);
808 
809         // add constructor initialization
810         sb.setLength(0);
811         sb.append(field.getName());
812         sb.append(" = new ArrayList<>();"); //$NON-NLS-1$
813         constructor.addBodyLine(sb.toString());
814 
815         // now add the methods for simplifying the individual field set methods
816         sb.setLength(0);
817         sb.append("add"); //$NON-NLS-1$
818         sb.append(introspectedColumn.getJavaProperty());
819         sb.setCharAt(3, Character.toUpperCase(sb.charAt(3)));
820         sb.append("Criterion"); //$NON-NLS-1$
821         method = new Method(sb.toString());
822         method.setVisibility(JavaVisibility.PROTECTED);
823         method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); //$NON-NLS-1$
824         method.addParameter(new Parameter(FullyQualifiedJavaType.getObjectInstance(), "value")); //$NON-NLS-1$
825         method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); //$NON-NLS-1$
826         method.addBodyLine("if (value == null) {"); //$NON-NLS-1$
827         method.addBodyLine(
828                 "throw new RuntimeException(\"Value for \" + property + \" cannot be null\");"); //$NON-NLS-1$
829         method.addBodyLine("}"); //$NON-NLS-1$
830 
831         method.addBodyLine(
832                 String.format("%s.add(new Criterion(condition, value, \"%s\"));", //$NON-NLS-1$
833                         field.getName(), introspectedColumn.getTypeHandler()));
834         method.addBodyLine("allCriteria = null;"); //$NON-NLS-1$
835         innerClass.addMethod(method);
836 
837         sb.setLength(0);
838         sb.append("add"); //$NON-NLS-1$
839         sb.append(introspectedColumn.getJavaProperty());
840         sb.setCharAt(3, Character.toUpperCase(sb.charAt(3)));
841         sb.append("Criterion"); //$NON-NLS-1$
842 
843         method = new Method(sb.toString());
844         method.setVisibility(JavaVisibility.PROTECTED);
845         method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); //$NON-NLS-1$
846         method.addParameter(new Parameter(introspectedColumn.getFullyQualifiedJavaType(), "value1")); //$NON-NLS-1$
847         method.addParameter(new Parameter(introspectedColumn.getFullyQualifiedJavaType(), "value2")); //$NON-NLS-1$
848         method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); //$NON-NLS-1$
849         if (!introspectedColumn.getFullyQualifiedJavaType().isPrimitive()) {
850             method.addBodyLine("if (value1 == null || value2 == null) {"); //$NON-NLS-1$
851             method.addBodyLine(
852                     "throw new RuntimeException(\"Between values for \" + property + \"" //$NON-NLS-1$
853                     + " cannot be null\");"); //$NON-NLS-1$
854             method.addBodyLine("}"); //$NON-NLS-1$
855         }
856 
857         method.addBodyLine(
858                 String.format("%s.add(new Criterion(condition, value1, value2, \"%s\"));", //$NON-NLS-1$
859                         field.getName(), introspectedColumn.getTypeHandler()));
860 
861         method.addBodyLine("allCriteria = null;"); //$NON-NLS-1$
862         innerClass.addMethod(method);
863 
864         return answer;
865     }
866 }