@Override
  public List<CompilationUnit> getCompilationUnits() {
    FullyQualifiedTable table = introspectedTable.getFullyQualifiedTable();
    progressCallback.startTask(getString("Progress.9", table.toString())); // $NON-NLS-1$
    Plugin plugins = context.getPlugins();
    CommentGenerator commentGenerator = context.getCommentGenerator();

    TopLevelClass topLevelClass = new TopLevelClass(introspectedTable.getRecordWithBLOBsType());
    topLevelClass.setVisibility(JavaVisibility.PUBLIC);
    commentGenerator.addJavaFileComment(topLevelClass);

    topLevelClass.addJavaDocLine("/**");
    topLevelClass.addJavaDocLine("* " + table.getDomainObjectName());
    topLevelClass.addJavaDocLine("* table:" + table.getIntrospectedTableName());
    topLevelClass.addJavaDocLine("* ");
    topLevelClass.addJavaDocLine("* @author 王欣");
    topLevelClass.addJavaDocLine("* @version v1.0");
    // topLevelClass.addJavaDocLine("* @copy 鸿旭图码");
    topLevelClass.addJavaDocLine("* @copy wangxin");
    topLevelClass.addJavaDocLine(
        "* @date " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    topLevelClass.addJavaDocLine("*/");

    String rootClass = getRootClass();
    if (introspectedTable.getRules().generateBaseRecordClass()) {
      topLevelClass.setSuperClass(introspectedTable.getBaseRecordType());
    } else {
      topLevelClass.setSuperClass(introspectedTable.getPrimaryKeyType());
    }

    if (introspectedTable.isConstructorBased()) {
      addParameterizedConstructor(topLevelClass);

      if (!introspectedTable.isImmutable()) {
        addDefaultConstructor(topLevelClass);
      }
    }

    for (IntrospectedColumn introspectedColumn : introspectedTable.getBLOBColumns()) {
      if (RootClassInfo.getInstance(rootClass, warnings).containsProperty(introspectedColumn)) {
        continue;
      }

      Field field = getJavaBeansField(introspectedColumn);
      if (plugins.modelFieldGenerated(
          field,
          topLevelClass,
          introspectedColumn,
          introspectedTable,
          Plugin.ModelClassType.RECORD_WITH_BLOBS)) {
        topLevelClass.addField(field);
        topLevelClass.addImportedType(field.getType());
      }

      Method method = getJavaBeansGetter(introspectedColumn);
      if (plugins.modelGetterMethodGenerated(
          method,
          topLevelClass,
          introspectedColumn,
          introspectedTable,
          Plugin.ModelClassType.RECORD_WITH_BLOBS)) {
        topLevelClass.addMethod(method);
      }

      if (!introspectedTable.isImmutable()) {
        method = getJavaBeansSetter(introspectedColumn);
        if (plugins.modelSetterMethodGenerated(
            method,
            topLevelClass,
            introspectedColumn,
            introspectedTable,
            Plugin.ModelClassType.RECORD_WITH_BLOBS)) {
          topLevelClass.addMethod(method);
        }
      }
    }

    List<CompilationUnit> answer = new ArrayList<CompilationUnit>();
    if (context.getPlugins().modelRecordWithBLOBsClassGenerated(topLevelClass, introspectedTable)) {
      answer.add(topLevelClass);
    }
    return answer;
  }
    @Override
    public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        MyBatisClasses cls = MyBatisClasses.calculate(topLevelClass, introspectedTable);
        topLevelClass.addImportedType(sqlSession);
        if (cls.imports.mapper != null)
            topLevelClass.addImportedType(cls.imports.mapper);

        int newMethodsStart = topLevelClass.getMethods().size();

        addListMethods(topLevelClass, introspectedTable, cls);
        addGetRecordMethods(topLevelClass, introspectedTable, cls, firstMethod, firstWithBLOBsMethod, "list == null || list.isEmpty() ? null : list.get(0)");
        addGetRecordMethods(topLevelClass, introspectedTable, cls, singleMethod, singleWithBLOBsMethod, "list == null || list.size() != 1 ? null : list.get(0)");
        addGetRecordMethods(topLevelClass, introspectedTable, cls, optionalMethod, optionalWithBLOBsMethod, "list == null || list.isEmpty() ? new @result() : list.get(0)");
        addUpdateMethods(topLevelClass, introspectedTable, cls, updateMethod, updateWithBLOBsMethod, false);
        addUpdateMethods(topLevelClass, introspectedTable, cls, updateSelectiveMethod, updateSelectiveWithBLOBsMethod, true);
        addDeleteMethods(topLevelClass, introspectedTable, cls);
        addCountMethods(topLevelClass, introspectedTable, cls);
        if (mapperClass != null) {
            addUserDefinedMethods(topLevelClass, mapperClass, introspectedTable, cls);
            mapperClass = null;
            exampleClass = null;
        } else {
            exampleClass = topLevelClass;
        }

        addCriteriaMethods(topLevelClass, newMethodsStart);

        return true;
    }
    private void addCriteriaMethods(TopLevelClass topLevelClass, int newMethodsStart) {
        if (!generateCriteriaMethods) return;
        InnerClass criteria = null;
        for (InnerClass c : topLevelClass.getInnerClasses()) {
            if (c.getType().getShortName().equals("Criteria")) criteria = c;
        }
        if (criteria == null) return;
        boolean owner = false;
        for (Field f : criteria.getFields()) if (ExampleMethodsChainPlugin.OWNER.equals(f.getName())) owner = true;
        if (!owner) return;

        for (ListIterator<Method> methods = topLevelClass.getMethods().listIterator(newMethodsStart); methods.hasNext(); ) {
            Method base = methods.next();
            if (base.getVisibility() != PUBLIC || base.isStatic() || base.isConstructor()) continue;
            Method m = method(PUBLIC, base.getReturnType(), base.getName());
            StringBuilder sb = new StringBuilder();
            sb.append("return ").append(ExampleMethodsChainPlugin.OWNER).append(".").append(base.getName()).append("(");
            for (ListIterator<Parameter> params = base.getParameters().listIterator(); params.hasNext(); ) {
                if (params.hasPrevious()) sb.append(", ");
                Parameter p = params.next();
                m.addParameter(new Parameter(p.getType(), p.getName()));
                sb.append(p.getName());
            }
            sb.append(");");
            m.addBodyLine(sb.toString());
            criteria.addMethod(m);
        }
    }
  /** 添加方法 */
  protected void addMethod(TopLevelClass topLevelClass) {
    Method method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setName("setSuccess");
    method.addParameter(
        new Parameter(FullyQualifiedJavaType.getBooleanPrimitiveInstance(), "success"));
    method.addBodyLine("this.success = success;");
    topLevelClass.addMethod(method);

    method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setReturnType(FullyQualifiedJavaType.getBooleanPrimitiveInstance());
    method.setName("isSuccess");
    method.addBodyLine("return success;");
    topLevelClass.addMethod(method);

    method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setName("setMessage");
    method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "message"));
    method.addBodyLine("this.message = message;");
    topLevelClass.addMethod(method);

    method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setReturnType(FullyQualifiedJavaType.getStringInstance());
    method.setName("getMessage");
    method.addBodyLine("return message;");
    topLevelClass.addMethod(method);
  }
    private void addUserDefinedMethods(TopLevelClass exampleClass, Interface mapperClass, IntrospectedTable introspectedTable, MyBatisClasses cls) {
        for (Method action : mapperClass.getMethods()) {
            if (!userDefinedMethods.matcher(action.getName()).matches()) continue;
            StringBuilder args = new StringBuilder();
            List<Parameter> params = new ArrayList<Parameter>();
            boolean example = false;
            if (action.getParameters() != null)
                for (Parameter param : action.getParameters()) {
                    String name;
                    if (Objects.equals(param.getType(), exampleClass.getType())) {
                        example = true;
                        name = "this";
                    } else {
                        name = param.getName();
                        params.add(new Parameter(param.getType(), name));
                    }
                    if (args.length() > 0)
                        args.append(", ");
                    args.append(name);
                }
            if (!example) {
                //System.err.println("Invalid user-defined mapper method: "+action.getName());
                continue;
            }

            exampleClass.addMethod(method(
                PUBLIC, INT, action.getName(), _(sqlSession, "sql"), params.toArray(new Parameter[params.size()]), __(
                    "return sql.getMapper(" + cls.names.mapper + ".class)."+action.getName()+"("+args+");"
            )));
            exampleClass.addMethod(method(
                PUBLIC, INT, action.getName(), _(cls.types.mapper, "mapper"), params.toArray(new Parameter[params.size()]), __(
                    "return mapper."+action.getName()+"("+args+");"
            )));
        }
    }
  @Override
  public void addClassElements(TopLevelClass topLevelClass) {
    Set<String> staticImports = new TreeSet<String>();
    Set<FullyQualifiedJavaType> importedTypes = new TreeSet<FullyQualifiedJavaType>();

    staticImports.add("org.apache.ibatis.jdbc.SqlBuilder.BEGIN"); // $NON-NLS-1$
    staticImports.add("org.apache.ibatis.jdbc.SqlBuilder.UPDATE"); // $NON-NLS-1$
    staticImports.add("org.apache.ibatis.jdbc.SqlBuilder.SET"); // $NON-NLS-1$
    staticImports.add("org.apache.ibatis.jdbc.SqlBuilder.SQL"); // $NON-NLS-1$

    importedTypes.add(new FullyQualifiedJavaType("java.util.Map")); // $NON-NLS-1$

    Method method = new Method(getMethodName());
    method.setReturnType(FullyQualifiedJavaType.getStringInstance());
    method.setVisibility(JavaVisibility.PUBLIC);
    method.addParameter(
        new Parameter(
            new FullyQualifiedJavaType(
                "java.util.Map<java.lang.String, java.lang.Object>"), //$NON-NLS-1$
            "parameter")); //$NON-NLS-1$
    //        method.addJavaDocLine("根据主键更新所有字段的数据,不含BLOB字段。");
    context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

    method.addBodyLine("BEGIN();"); // $NON-NLS-1$

    method.addBodyLine(
        String.format(
            "UPDATE(\"%s\");", //$NON-NLS-1$
            escapeStringForJava(introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime())));
    method.addBodyLine(""); // $NON-NLS-1$

    for (IntrospectedColumn introspectedColumn : getColumns()) {
      StringBuilder sb = new StringBuilder();
      sb.append(getParameterClause(introspectedColumn));
      sb.insert(2, "record."); // $NON-NLS-1$

      method.addBodyLine(
          String.format(
              "SET(\"%s = %s\");", //$NON-NLS-1$
              escapeStringForJava(getAliasedEscapedColumnName(introspectedColumn)), sb.toString()));
    }

    method.addBodyLine(""); // $NON-NLS-1$

    FullyQualifiedJavaType example = new FullyQualifiedJavaType(introspectedTable.getExampleType());
    importedTypes.add(example);
    method.addBodyLine(
        String.format(
            "%s example = (%s) parameter.get(\"example\");", //$NON-NLS-1$
            example.getShortName(), example.getShortName()));

    method.addBodyLine("applyWhere(example, true);"); // $NON-NLS-1$
    method.addBodyLine("return SQL();"); // $NON-NLS-1$

    if (callPlugins(method, topLevelClass)) {
      topLevelClass.addStaticImports(staticImports);
      topLevelClass.addImportedTypes(importedTypes);
      topLevelClass.addMethod(method);
    }
  }
 private void addLimit(
     TopLevelClass topLevelClass, IntrospectedTable introspectedTable, String name) {
   CommentGenerator commentGenerator = context.getCommentGenerator();
   FullyQualifiedJavaType limitType = new FullyQualifiedJavaType("com.tommy.common.Limit");
   topLevelClass.addImportedType(limitType);
   Field field = new Field();
   field.setVisibility(JavaVisibility.PROTECTED);
   field.setType(limitType);
   field.setName(name);
   commentGenerator.addFieldComment(field, introspectedTable);
   topLevelClass.addField(field);
   char c = name.charAt(0);
   String camel = Character.toUpperCase(c) + name.substring(1);
   Method method = new Method();
   method.setVisibility(JavaVisibility.PUBLIC);
   method.setName("set" + camel);
   method.addParameter(new Parameter(limitType, name));
   method.addBodyLine("this." + name + "=" + name + ";");
   commentGenerator.addGeneralMethodComment(method, introspectedTable);
   topLevelClass.addMethod(method);
   method = new Method();
   method.setVisibility(JavaVisibility.PUBLIC);
   method.setReturnType(limitType);
   method.setName("get" + camel);
   method.addBodyLine("return " + name + ";");
   commentGenerator.addGeneralMethodComment(method, introspectedTable);
   topLevelClass.addMethod(method);
 }
  @Override
  public void addImplementationElements(TopLevelClass topLevelClass) {
    Set<FullyQualifiedJavaType> importedTypes = new TreeSet<FullyQualifiedJavaType>();
    Method method = getMethodShell(importedTypes);

    if (generateForJava5) {
      method.addSuppressTypeWarningsAnnotation();
    }

    StringBuilder sb = new StringBuilder();
    sb.append(method.getReturnType().getShortName());
    sb.append(" list = "); // $NON-NLS-1$
    sb.append(
        daoTemplate.getQueryForListMethod(
            introspectedTable.getIbatis2SqlMapNamespace(),
            introspectedTable.getSelectByExampleStatementId(),
            "example")); //$NON-NLS-1$
    method.addBodyLine(sb.toString());
    method.addBodyLine("return list;"); // $NON-NLS-1$

    if (context
        .getPlugins()
        .clientSelectByExampleWithoutBLOBsMethodGenerated(
            method, topLevelClass, introspectedTable)) {
      topLevelClass.addImportedTypes(importedTypes);
      topLevelClass.addMethod(method);
    }
  }
 /** 导入logger */
 private void addLogger(TopLevelClass topLevelClass) {
   Field field = new Field();
   field.setFinal(true);
   field.setInitializationString(
       "LoggerFactory.getLogger(" + topLevelClass.getType().getShortName() + ".class)"); // 设置值
   field.setName("logger"); // 设置变量名
   field.setStatic(true);
   field.setType(new FullyQualifiedJavaType("Logger")); // 类型
   field.setVisibility(JavaVisibility.PRIVATE);
   topLevelClass.addField(field);
 }
 private void addCountMethods(TopLevelClass topLevelClass, IntrospectedTable introspectedTable, MyBatisClasses cls) {
     if (!countMethod.startsWith(SKIP) && introspectedTable.getRules().generateCountByExample()) {
         topLevelClass.addMethod(method(
             PUBLIC, INT, countMethod, _(sqlSession, "sql"), __(
                 "return sql.getMapper(" + cls.names.mapper + ".class).countByExample(this);"
         )));
         topLevelClass.addMethod(method(
             PUBLIC, INT, countMethod, _(cls.types.mapper, "mapper"), __(
                 "return mapper.countByExample(this);"
         )));
     }
 }
 /**
  * 添加字段
  *
  * @param topLevelClass
  */
 protected void addField(TopLevelClass topLevelClass, String tableName) {
   // 添加 dao
   Field field = new Field();
   field.setName(toLowerCase(daoType.getShortName())); // 设置变量名
   topLevelClass.addImportedType(daoType);
   field.setType(daoType); // 类型
   field.setVisibility(JavaVisibility.PRIVATE);
   if (enableAnnotation) {
     field.addAnnotation("@Autowired");
   }
   topLevelClass.addField(field);
 }
  @Override
  public void addImplementationElements(TopLevelClass topLevelClass) {
    Set<FullyQualifiedJavaType> importedTypes = new TreeSet<FullyQualifiedJavaType>();
    Method method = getMethodShell(importedTypes);

    FullyQualifiedJavaType returnType = method.getReturnType();
    StringBuilder sb = new StringBuilder();

    if (returnType != null) {
      sb.append("Object newKey = "); // $NON-NLS-1$
    }

    sb.append(
        daoTemplate.getInsertMethod(
            introspectedTable.getIbatis2SqlMapNamespace(),
            introspectedTable.getInsertSelectiveStatementId(),
            "record")); //$NON-NLS-1$
    method.addBodyLine(sb.toString());

    if (returnType != null) {
      if ("Object".equals(returnType.getShortName())) { // $NON-NLS-1$
        // no need to cast if the return type is Object
        method.addBodyLine("return newKey;"); // $NON-NLS-1$
      } else {
        sb.setLength(0);

        if (returnType.isPrimitive()) {
          PrimitiveTypeWrapper ptw = returnType.getPrimitiveTypeWrapper();
          sb.append("return (("); // $NON-NLS-1$
          sb.append(ptw.getShortName());
          sb.append(") newKey"); // $NON-NLS-1$
          sb.append(")."); // $NON-NLS-1$
          sb.append(ptw.getToPrimitiveMethod());
          sb.append(';');
        } else {
          sb.append("return ("); // $NON-NLS-1$
          sb.append(returnType.getShortName());
          sb.append(") newKey;"); // $NON-NLS-1$
        }

        method.addBodyLine(sb.toString());
      }
    }

    if (context
        .getPlugins()
        .clientInsertSelectiveMethodGenerated(method, topLevelClass, introspectedTable)) {
      topLevelClass.addImportedTypes(importedTypes);
      topLevelClass.addMethod(method);
    }
  }
  protected void addDefaultNoArgConstructor(
      TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
    Method defaultNoArgConstructor = new Method();
    defaultNoArgConstructor.setVisibility(JavaVisibility.PUBLIC);
    defaultNoArgConstructor.setName(topLevelClass.getType().getShortName());
    defaultNoArgConstructor.setConstructor(true);
    defaultNoArgConstructor.addBodyLine("//Needed For JAXB serialization.");

    context
        .getCommentGenerator()
        .addGeneralMethodComment(defaultNoArgConstructor, introspectedTable);

    topLevelClass.addMethod(defaultNoArgConstructor);
  }
 /**
  * 添加字段
  *
  * @param topLevelClass
  */
 protected void addField(TopLevelClass topLevelClass) {
   // 添加 success
   Field field = new Field();
   field.setName("success"); // 设置变量名
   field.setType(FullyQualifiedJavaType.getBooleanPrimitiveInstance()); // 类型
   field.setVisibility(JavaVisibility.PRIVATE);
   addComment(field, "执行结果");
   topLevelClass.addField(field);
   // 设置结果
   field = new Field();
   field.setName("message"); // 设置变量名
   field.setType(FullyQualifiedJavaType.getStringInstance()); // 类型
   field.setVisibility(JavaVisibility.PRIVATE);
   addComment(field, "消息结果");
   topLevelClass.addField(field);
 }
  @Override
  public boolean modelBaseRecordClassGenerated(
      TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
    topLevelClass.addImportedType("java.io.Serializable");
    topLevelClass.addSuperInterface(new FullyQualifiedJavaType("java.io.Serializable"));

    Field field = new Field();
    // private static final long serialVersionUID = 1L;
    field.setName("serialVersionUID");
    field.setType(new FullyQualifiedJavaType("long"));
    field.setStatic(true);
    field.setFinal(true);
    field.setInitializationString("1L");
    topLevelClass.addField(field);
    return super.modelBaseRecordClassGenerated(topLevelClass, introspectedTable);
  }
 /** 添加方法 */
 protected void addMethod(TopLevelClass topLevelClass, String tableName) {
   Method method2 = new Method();
   for (int i = 0; i < methods.size(); i++) {
     Method method = new Method();
     method2 = methods.get(i);
     method = method2;
     method.removeAllBodyLines();
     method.removeAnnotation();
     StringBuilder sb = new StringBuilder();
     sb.append("return this.");
     sb.append(getDaoShort());
     sb.append(method.getName());
     sb.append("(");
     List<Parameter> list = method.getParameters();
     for (int j = 0; j < list.size(); j++) {
       sb.append(list.get(j).getName());
       sb.append(",");
     }
     sb.setLength(sb.length() - 1);
     sb.append(");");
     method.addBodyLine(sb.toString());
     topLevelClass.addMethod(method);
   }
   methods.clear();
 }
 private void addUpdateMethods(TopLevelClass topLevelClass, IntrospectedTable introspectedTable, MyBatisClasses cls, String base, String withBLOBs, boolean selective) {
     String record = cls.names.base;
     topLevelClass.addImportedType(cls.imports.base);
     String mapperMethod = selective ? "updateByExampleSelective" : "updateByExample";
     Rules r = introspectedTable.getRules();
     if (!base.startsWith(SKIP) && ( selective ? r.generateUpdateByExampleSelective() : r.generateUpdateByExampleWithoutBLOBs() )) {
         if (selective && r.generateRecordWithBLOBsClass()) {
             record = cls.names.blob;
             topLevelClass.addImportedType(cls.imports.blob);
         }
         topLevelClass.addMethod(method(
             PUBLIC, INT, base, _(sqlSession, "sql"), _(new FullyQualifiedJavaType(record), "record"), __(
                 "return sql.getMapper(" + cls.names.mapper + ".class)."+mapperMethod+"(record, this);"
         )));
         topLevelClass.addMethod(method(
             PUBLIC, INT, base, _(cls.types.mapper, "mapper"), _(new FullyQualifiedJavaType(record), "record"), __(
                 "return mapper."+mapperMethod+"(record, this);"
         )));
     }
     if (introspectedTable.hasBLOBColumns() && !withBLOBs.startsWith(SKIP) && !selective && r.generateUpdateByExampleWithBLOBs()) {
         if (r.generateRecordWithBLOBsClass()) {
             record = cls.names.blob;
             topLevelClass.addImportedType(cls.imports.blob);
         }
         mapperMethod = selective ? "updateByExampleSelectiveWithBLOBs" /* not supported */ : "updateByExampleWithBLOBs";
         topLevelClass.addMethod(method(
             PUBLIC, INT, withBLOBs, _(sqlSession, "sql"), _(new FullyQualifiedJavaType(record), "record"), __(
                 "return sql.getMapper(" + cls.names.mapper + ".class)."+mapperMethod+"(record, this);"
         )));
         topLevelClass.addMethod(method(
             PUBLIC, INT, withBLOBs, _(cls.types.mapper, "mapper"), _(new FullyQualifiedJavaType(record), "record"), __(
                 "return mapper."+mapperMethod+"(record, this);"
         )));
     }
 }
  /**
   * 添加给Example类序列化的方法
   *
   * @param topLevelClass
   * @param introspectedTable
   * @return
   */
  @Override
  public boolean modelExampleClassGenerated(
      TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
    makeSerializable(topLevelClass, introspectedTable);
    for (InnerClass innerClass : topLevelClass.getInnerClasses()) {
      makeSerializable(innerClass);
    }

    return true;
  }
 /** 导入需要的类 */
 private void addImport(Interface interfaces, TopLevelClass topLevelClass) {
   interfaces.addImportedType(pojoType);
   interfaces.addImportedType(pojoCriteriaType);
   interfaces.addImportedType(listType);
   topLevelClass.addImportedType(daoType);
   topLevelClass.addImportedType(interfaceType);
   topLevelClass.addImportedType(pojoType);
   topLevelClass.addImportedType(pojoCriteriaType);
   topLevelClass.addImportedType(listType);
   topLevelClass.addImportedType(slf4jLogger);
   topLevelClass.addImportedType(slf4jLoggerFactory);
   if (enableAnnotation) {
     topLevelClass.addImportedType(service);
     topLevelClass.addImportedType(autowired);
   }
 }
 private void addListMethods(TopLevelClass topLevelClass, IntrospectedTable introspectedTable, MyBatisClasses cls) {
     String returnType = "java.util.List<"+cls.names.base+">";
     topLevelClass.addImportedType(cls.imports.base);
     if (!listMethod.startsWith(SKIP) && introspectedTable.getRules().generateSelectByExampleWithoutBLOBs()) {
         topLevelClass.addMethod(method(
             PUBLIC, new FullyQualifiedJavaType(returnType), listMethod, _(sqlSession, "sql"), __(
                 "return sql.getMapper(" + cls.names.mapper + ".class).selectByExample(this);"
         )));
         topLevelClass.addMethod(method(
             PUBLIC, new FullyQualifiedJavaType(returnType), listMethod, _(cls.types.mapper, "mapper"), __(
                 "return mapper.selectByExample(this);"
         )));
     }
     if (introspectedTable.hasBLOBColumns() && !listWithBLOBsMethod.startsWith(SKIP) && introspectedTable.getRules().generateSelectByExampleWithBLOBs()) {
         if (cls.exists.blob) {
             returnType = "java.util.List<" + cls.names.blob + ">";
             topLevelClass.addImportedType(cls.imports.blob);
         }
         topLevelClass.addMethod(method(
             PUBLIC, new FullyQualifiedJavaType(returnType), listWithBLOBsMethod, _(sqlSession, "sql"), __(
                 "return sql.getMapper("+cls.names.mapper+".class).selectByExampleWithBLOBs(this);"
         )));
         topLevelClass.addMethod(method(
             PUBLIC, new FullyQualifiedJavaType(returnType), listWithBLOBsMethod, _(cls.types.mapper, "mapper"), __(
                 "return mapper.selectByExampleWithBLOBs(this);"
         )));
     }
 }
 private void addGetRecordMethods(TopLevelClass topLevelClass, IntrospectedTable introspectedTable, MyBatisClasses cls, String base, String withBLOBs, String expression) {
     String returnType = cls.names.base;
     topLevelClass.addImportedType(cls.imports.base);
     String listType = "java.util.List<"+returnType+">";
     if (!base.startsWith(SKIP) && introspectedTable.getRules().generateSelectByExampleWithoutBLOBs()) {
         topLevelClass.addMethod(method(
             PUBLIC, new FullyQualifiedJavaType(returnType), base, _(sqlSession, "sql"), __(
                 listType + " list = sql.getMapper(" + cls.names.mapper + ".class).selectByExample(this);",
                 "return "+expression.replace("@result", returnType)+";"
         )));
         topLevelClass.addMethod(method(
             PUBLIC, new FullyQualifiedJavaType(returnType), base, _(cls.types.mapper, "mapper"), __(
                 listType + " list = mapper.selectByExample(this);",
                 "return "+expression.replace("@result", returnType)+";"
         )));
     }
     if (introspectedTable.hasBLOBColumns() && !withBLOBs.startsWith(SKIP) && introspectedTable.getRules().generateSelectByExampleWithBLOBs()) {
         if (cls.exists.blob) {
             returnType = cls.names.blob;
             topLevelClass.addImportedType(cls.imports.blob);
         }
         listType = "java.util.List<"+returnType+">";
         topLevelClass.addMethod(method(
             PUBLIC, new FullyQualifiedJavaType(returnType), withBLOBs, _(sqlSession, "sql"), __(
                 listType + " list = sql.getMapper(" + cls.names.mapper + ".class).selectByExampleWithBLOBs(this);",
                 "return "+expression.replace("@result", returnType)+";"
         )));
         topLevelClass.addMethod(method(
             PUBLIC, new FullyQualifiedJavaType(returnType), withBLOBs, _(cls.types.mapper, "mapper"), __(
                 listType + " list = mapper.selectByExampleWithBLOBs(this);",
                 "return "+expression.replace("@result", returnType)+";"
         )));
     }
 }
  private void addParameterizedConstructor(TopLevelClass topLevelClass) {
    Method method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setConstructor(true);
    method.setName(topLevelClass.getType().getShortName());
    context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

    for (IntrospectedColumn introspectedColumn : introspectedTable.getAllColumns()) {
      method.addParameter(
          new Parameter(
              introspectedColumn.getFullyQualifiedJavaType(),
              introspectedColumn.getJavaProperty()));
    }

    boolean comma = false;
    StringBuilder sb = new StringBuilder();
    sb.append("super("); // $NON-NLS-1$
    for (IntrospectedColumn introspectedColumn : introspectedTable.getNonBLOBColumns()) {
      if (comma) {
        sb.append(", "); // $NON-NLS-1$
      } else {
        comma = true;
      }
      sb.append(introspectedColumn.getJavaProperty());
    }
    sb.append(");"); // $NON-NLS-1$
    method.addBodyLine(sb.toString());

    for (IntrospectedColumn introspectedColumn : introspectedTable.getBLOBColumns()) {
      sb.setLength(0);
      sb.append("this."); // $NON-NLS-1$
      sb.append(introspectedColumn.getJavaProperty());
      sb.append(" = "); // $NON-NLS-1$
      sb.append(introspectedColumn.getJavaProperty());
      sb.append(';');
      method.addBodyLine(sb.toString());
    }

    topLevelClass.addMethod(method);
  }
  protected void addDefaultAnnotationsToClass(TopLevelClass topLevelClass) {
    String thisClassName = topLevelClass.getType().getShortName();

    // Start of code to change the first letter of the Java Class name to lower case in the Xml Root
    // Element

    StringBuilder sb = new StringBuilder(thisClassName);
    sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
    sb.insert(0, "@XmlRootElement(name=\"");
    sb.append("\")");

    // End of code to change the first letter of the Java Class name to lower case in the Xml Root
    // Element

    // Add default JAXB imports
    addImportsForAnnotations(topLevelClass, "XmlAccessorType", "XmlAccessType", "XmlRootElement");

    // Add default JAXB annotations
    topLevelClass.addAnnotation(
        getXmlAccessTypeConstant()); // Returns either: @XmlAccessorType(XmlAccessType.FIELD) or
    // @XmlAccessorType(XmlAccessType.PROPERTY)
    topLevelClass.addAnnotation(sb.toString());
  }
  protected void makeSerializable(
      TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
    if (addGWTInterface) {
      topLevelClass.addImportedType(gwtSerializable);
      topLevelClass.addSuperInterface(gwtSerializable);
    }

    if (!suppressJavaInterface) {
      topLevelClass.addImportedType(serializable);
      topLevelClass.addSuperInterface(serializable);

      Field field = new Field();
      field.setFinal(true);
      field.setInitializationString("1L"); // $NON-NLS-1$
      field.setName("serialVersionUID"); // $NON-NLS-1$
      field.setStatic(true);
      field.setType(new FullyQualifiedJavaType("long")); // $NON-NLS-1$
      field.setVisibility(JavaVisibility.PRIVATE);
      context.getCommentGenerator().addFieldComment(field, introspectedTable);

      topLevelClass.addField(field);
    }
  }
  @Override
  public void addImplementationElements(TopLevelClass topLevelClass) {
    Set<FullyQualifiedJavaType> importedTypes = new TreeSet<FullyQualifiedJavaType>();
    Method method = getMethodShell(importedTypes);

    StringBuilder sb = new StringBuilder();
    sb.append("int rows = "); // $NON-NLS-1$
    sb.append(
        daoTemplate.getUpdateMethod(
            introspectedTable.getIbatis2SqlMapNamespace(),
            introspectedTable.getUpdateByPrimaryKeyWithBLOBsStatementId(),
            "record")); //$NON-NLS-1$
    method.addBodyLine(sb.toString());

    method.addBodyLine("return rows;"); // $NON-NLS-1$

    if (context
        .getPlugins()
        .clientUpdateByPrimaryKeyWithBLOBsMethodGenerated(
            method, topLevelClass, introspectedTable)) {
      topLevelClass.addImportedTypes(importedTypes);
      topLevelClass.addMethod(method);
    }
  }
 @Override
 public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
     if (topLevelClass != null)
         return false;
     if (exampleClass != null) {
         MyBatisClasses cls = MyBatisClasses.calculate(exampleClass, introspectedTable);
         int newMethodsStart = exampleClass.getMethods().size();
         addUserDefinedMethods(exampleClass, interfaze, introspectedTable, cls);
         addCriteriaMethods(exampleClass, newMethodsStart);
         exampleClass = null;
         mapperClass = null;
     } else {
         mapperClass = interfaze;
     }
     return true;
 }
 protected void addImportsForAnnotations(TopLevelClass topLevelClass, String... annotations) {
   for (String strAnnot : annotations)
     topLevelClass.addImportedType(new FullyQualifiedJavaType(IMPORT_PREFIX + strAnnot));
 }
  private InnerClass getGeneratedCriteriaInnerClass(TopLevelClass topLevelClass) {
    Field field;
    Method method;

    InnerClass answer = new InnerClass(FullyQualifiedJavaType.getGeneratedCriteriaInstance());

    answer.setVisibility(JavaVisibility.PROTECTED);
    answer.setStatic(true);
    answer.setAbstract(true);
    context.getCommentGenerator().addClassComment(answer, introspectedTable);

    method = new Method();
    method.setVisibility(JavaVisibility.PROTECTED);
    method.setName("GeneratedCriteria"); // $NON-NLS-1$
    method.setConstructor(true);
    method.addBodyLine("super();"); // $NON-NLS-1$
    method.addBodyLine("criteria = new ArrayList<Criterion>();"); // $NON-NLS-1$
    answer.addMethod(method);

    List<String> criteriaLists = new ArrayList<String>();
    criteriaLists.add("criteria"); // $NON-NLS-1$

    for (IntrospectedColumn introspectedColumn : introspectedTable.getNonBLOBColumns()) {
      if (stringHasValue(introspectedColumn.getTypeHandler())) {
        String name = addtypeHandledObjectsAndMethods(introspectedColumn, method, answer);
        criteriaLists.add(name);
      }
    }

    // now generate the isValid method
    method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setName("isValid"); // $NON-NLS-1$
    method.setReturnType(FullyQualifiedJavaType.getBooleanPrimitiveInstance());
    StringBuilder sb = new StringBuilder();
    Iterator<String> strIter = criteriaLists.iterator();
    sb.append("return "); // $NON-NLS-1$
    sb.append(strIter.next());
    sb.append(".size() > 0"); // $NON-NLS-1$
    if (!strIter.hasNext()) {
      sb.append(';');
    }
    method.addBodyLine(sb.toString());
    while (strIter.hasNext()) {
      sb.setLength(0);
      OutputUtilities.javaIndent(sb, 1);
      sb.append("|| "); // $NON-NLS-1$
      sb.append(strIter.next());
      sb.append(".size() > 0"); // $NON-NLS-1$
      if (!strIter.hasNext()) {
        sb.append(';');
      }
      method.addBodyLine(sb.toString());
    }
    answer.addMethod(method);

    // now generate the getAllCriteria method
    if (criteriaLists.size() > 1) {
      field = new Field();
      field.setName("allCriteria"); // $NON-NLS-1$
      field.setType(new FullyQualifiedJavaType("List<Criterion>")); // $NON-NLS-1$
      field.setVisibility(JavaVisibility.PROTECTED);
      answer.addField(field);
    }

    method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setName("getAllCriteria"); // $NON-NLS-1$
    method.setReturnType(new FullyQualifiedJavaType("List<Criterion>")); // $NON-NLS-1$
    if (criteriaLists.size() < 2) {
      method.addBodyLine("return criteria;"); // $NON-NLS-1$
    } else {
      method.addBodyLine("if (allCriteria == null) {"); // $NON-NLS-1$
      method.addBodyLine("allCriteria = new ArrayList<Criterion>();"); // $NON-NLS-1$

      strIter = criteriaLists.iterator();
      while (strIter.hasNext()) {
        method.addBodyLine(String.format("allCriteria.addAll(%s);", strIter.next())); // $NON-NLS-1$
      }

      method.addBodyLine("}"); // $NON-NLS-1$
      method.addBodyLine("return allCriteria;"); // $NON-NLS-1$
    }
    answer.addMethod(method);

    // now we need to generate the methods that will be used in the SqlMap
    // to generate the dynamic where clause
    topLevelClass.addImportedType(FullyQualifiedJavaType.getNewListInstance());
    topLevelClass.addImportedType(FullyQualifiedJavaType.getNewArrayListInstance());

    field = new Field();
    field.setVisibility(JavaVisibility.PROTECTED);
    FullyQualifiedJavaType listOfCriterion =
        new FullyQualifiedJavaType("java.util.List<Criterion>"); // $NON-NLS-1$
    field.setType(listOfCriterion);
    field.setName("criteria"); // $NON-NLS-1$
    answer.addField(field);

    method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setReturnType(field.getType());
    method.setName(getGetterMethodName(field.getName(), field.getType()));
    method.addBodyLine("return criteria;"); // $NON-NLS-1$
    answer.addMethod(method);

    // now add the methods for simplifying the individual field set methods
    method = new Method();
    method.setVisibility(JavaVisibility.PROTECTED);
    method.setName("addCriterion"); // $NON-NLS-1$
    method.addParameter(
        new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$
    method.addBodyLine("if (condition == null) {"); // $NON-NLS-1$
    method.addBodyLine(
        "throw new RuntimeException(\"Value for condition cannot be null\");"); //$NON-NLS-1$
    method.addBodyLine("}"); // $NON-NLS-1$
    method.addBodyLine("criteria.add(new Criterion(condition));"); // $NON-NLS-1$
    if (criteriaLists.size() > 1) {
      method.addBodyLine("allCriteria = null;"); // $NON-NLS-1$
    }
    answer.addMethod(method);

    method = new Method();
    method.setVisibility(JavaVisibility.PROTECTED);
    method.setName("addCriterion"); // $NON-NLS-1$
    method.addParameter(
        new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$
    method.addParameter(
        new Parameter(FullyQualifiedJavaType.getObjectInstance(), "value")); // $NON-NLS-1$
    method.addParameter(
        new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); // $NON-NLS-1$
    method.addBodyLine("if (value == null) {"); // $NON-NLS-1$
    method.addBodyLine(
        "throw new RuntimeException(\"Value for \" + property + \" cannot be null\");"); //$NON-NLS-1$
    method.addBodyLine("}"); // $NON-NLS-1$
    method.addBodyLine("criteria.add(new Criterion(condition, value));"); // $NON-NLS-1$
    if (criteriaLists.size() > 1) {
      method.addBodyLine("allCriteria = null;"); // $NON-NLS-1$
    }
    answer.addMethod(method);

    method = new Method();
    method.setVisibility(JavaVisibility.PROTECTED);
    method.setName("addCriterion"); // $NON-NLS-1$
    method.addParameter(
        new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$
    method.addParameter(
        new Parameter(FullyQualifiedJavaType.getObjectInstance(), "value1")); // $NON-NLS-1$
    method.addParameter(
        new Parameter(FullyQualifiedJavaType.getObjectInstance(), "value2")); // $NON-NLS-1$
    method.addParameter(
        new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); // $NON-NLS-1$
    method.addBodyLine("if (value1 == null || value2 == null) {"); // $NON-NLS-1$
    method.addBodyLine(
        "throw new RuntimeException(\"Between values for \" + property + \" cannot be null\");"); //$NON-NLS-1$
    method.addBodyLine("}"); // $NON-NLS-1$
    method.addBodyLine("criteria.add(new Criterion(condition, value1, value2));"); // $NON-NLS-1$
    if (criteriaLists.size() > 1) {
      method.addBodyLine("allCriteria = null;"); // $NON-NLS-1$
    }
    answer.addMethod(method);

    FullyQualifiedJavaType listOfDates =
        new FullyQualifiedJavaType("java.util.List<java.util.Date>"); // $NON-NLS-1$

    if (introspectedTable.hasJDBCDateColumns()) {
      topLevelClass.addImportedType(FullyQualifiedJavaType.getDateInstance());
      topLevelClass.addImportedType(FullyQualifiedJavaType.getNewIteratorInstance());
      method = new Method();
      method.setVisibility(JavaVisibility.PROTECTED);
      method.setName("addCriterionForJDBCDate"); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getDateInstance(), "value")); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); // $NON-NLS-1$
      method.addBodyLine("if (value == null) {"); // $NON-NLS-1$
      method.addBodyLine(
          "throw new RuntimeException(\"Value for \" + property + \" cannot be null\");"); //$NON-NLS-1$
      method.addBodyLine("}"); // $NON-NLS-1$
      method.addBodyLine(
          "addCriterion(condition, new java.sql.Date(value.getTime()), property);"); //$NON-NLS-1$
      answer.addMethod(method);

      method = new Method();
      method.setVisibility(JavaVisibility.PROTECTED);
      method.setName("addCriterionForJDBCDate"); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$
      method.addParameter(new Parameter(listOfDates, "values")); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); // $NON-NLS-1$
      method.addBodyLine("if (values == null || values.size() == 0) {"); // $NON-NLS-1$
      method.addBodyLine(
          "throw new RuntimeException(\"Value list for \" + property + \" cannot be null or empty\");"); //$NON-NLS-1$
      method.addBodyLine("}"); // $NON-NLS-1$
      method.addBodyLine(
          "List<java.sql.Date> dateList = new ArrayList<java.sql.Date>();"); //$NON-NLS-1$
      method.addBodyLine("Iterator<Date> iter = values.iterator();"); // $NON-NLS-1$
      method.addBodyLine("while (iter.hasNext()) {"); // $NON-NLS-1$
      method.addBodyLine("dateList.add(new java.sql.Date(iter.next().getTime()));"); // $NON-NLS-1$
      method.addBodyLine("}"); // $NON-NLS-1$
      method.addBodyLine("addCriterion(condition, dateList, property);"); // $NON-NLS-1$
      answer.addMethod(method);

      method = new Method();
      method.setVisibility(JavaVisibility.PROTECTED);
      method.setName("addCriterionForJDBCDate"); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getDateInstance(), "value1")); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getDateInstance(), "value2")); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); // $NON-NLS-1$
      method.addBodyLine("if (value1 == null || value2 == null) {"); // $NON-NLS-1$
      method.addBodyLine(
          "throw new RuntimeException(\"Between values for \" + property + \" cannot be null\");"); //$NON-NLS-1$
      method.addBodyLine("}"); // $NON-NLS-1$
      method.addBodyLine(
          "addCriterion(condition, new java.sql.Date(value1.getTime()), new java.sql.Date(value2.getTime()), property);"); //$NON-NLS-1$
      answer.addMethod(method);
    }

    if (introspectedTable.hasJDBCTimeColumns()) {
      topLevelClass.addImportedType(FullyQualifiedJavaType.getDateInstance());
      topLevelClass.addImportedType(FullyQualifiedJavaType.getNewIteratorInstance());
      method = new Method();
      method.setVisibility(JavaVisibility.PROTECTED);
      method.setName("addCriterionForJDBCTime"); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getDateInstance(), "value")); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); // $NON-NLS-1$
      method.addBodyLine("if (value == null) {"); // $NON-NLS-1$
      method.addBodyLine(
          "throw new RuntimeException(\"Value for \" + property + \" cannot be null\");"); //$NON-NLS-1$
      method.addBodyLine("}"); // $NON-NLS-1$
      method.addBodyLine(
          "addCriterion(condition, new java.sql.Time(value.getTime()), property);"); //$NON-NLS-1$
      answer.addMethod(method);

      method = new Method();
      method.setVisibility(JavaVisibility.PROTECTED);
      method.setName("addCriterionForJDBCTime"); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$
      method.addParameter(new Parameter(listOfDates, "values")); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); // $NON-NLS-1$
      method.addBodyLine("if (values == null || values.size() == 0) {"); // $NON-NLS-1$
      method.addBodyLine(
          "throw new RuntimeException(\"Value list for \" + property + \" cannot be null or empty\");"); //$NON-NLS-1$
      method.addBodyLine("}"); // $NON-NLS-1$
      method.addBodyLine(
          "List<java.sql.Time> timeList = new ArrayList<java.sql.Time>();"); //$NON-NLS-1$
      method.addBodyLine("Iterator<Date> iter = values.iterator();"); // $NON-NLS-1$
      method.addBodyLine("while (iter.hasNext()) {"); // $NON-NLS-1$
      method.addBodyLine("timeList.add(new java.sql.Time(iter.next().getTime()));"); // $NON-NLS-1$
      method.addBodyLine("}"); // $NON-NLS-1$
      method.addBodyLine("addCriterion(condition, timeList, property);"); // $NON-NLS-1$
      answer.addMethod(method);

      method = new Method();
      method.setVisibility(JavaVisibility.PROTECTED);
      method.setName("addCriterionForJDBCTime"); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getDateInstance(), "value1")); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getDateInstance(), "value2")); // $NON-NLS-1$
      method.addParameter(
          new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); // $NON-NLS-1$
      method.addBodyLine("if (value1 == null || value2 == null) {"); // $NON-NLS-1$
      method.addBodyLine(
          "throw new RuntimeException(\"Between values for \" + property + \" cannot be null\");"); //$NON-NLS-1$
      method.addBodyLine("}"); // $NON-NLS-1$
      method.addBodyLine(
          "addCriterion(condition, new java.sql.Time(value1.getTime()), new java.sql.Time(value2.getTime()), property);"); //$NON-NLS-1$
      answer.addMethod(method);
    }

    for (IntrospectedColumn introspectedColumn : introspectedTable.getNonBLOBColumns()) {
      topLevelClass.addImportedType(introspectedColumn.getFullyQualifiedJavaType());

      // here we need to add the individual methods for setting the
      // conditions for a field
      answer.addMethod(getSetNullMethod(introspectedColumn));
      answer.addMethod(getSetNotNullMethod(introspectedColumn));
      answer.addMethod(getSetEqualMethod(introspectedColumn));
      answer.addMethod(getSetNotEqualMethod(introspectedColumn));
      answer.addMethod(getSetGreaterThanMethod(introspectedColumn));
      answer.addMethod(getSetGreaterThenOrEqualMethod(introspectedColumn));
      answer.addMethod(getSetLessThanMethod(introspectedColumn));
      answer.addMethod(getSetLessThanOrEqualMethod(introspectedColumn));

      if (introspectedColumn.isJdbcCharacterColumn()) {
        answer.addMethod(getSetLikeMethod(introspectedColumn));
        answer.addMethod(getSetNotLikeMethod(introspectedColumn));
      }

      answer.addMethod(getSetInOrNotInMethod(introspectedColumn, true));
      answer.addMethod(getSetInOrNotInMethod(introspectedColumn, false));
      answer.addMethod(getSetBetweenOrNotBetweenMethod(introspectedColumn, true));
      answer.addMethod(getSetBetweenOrNotBetweenMethod(introspectedColumn, false));
    }

    return answer;
  }
  @Override
  public List<CompilationUnit> getCompilationUnits() {
    FullyQualifiedTable table = introspectedTable.getFullyQualifiedTable();
    progressCallback.startTask(getString("Progress.6", table.toString())); // $NON-NLS-1$
    CommentGenerator commentGenerator = context.getCommentGenerator();

    FullyQualifiedJavaType type = new FullyQualifiedJavaType(introspectedTable.getExampleType());
    TopLevelClass topLevelClass = new TopLevelClass(type);
    topLevelClass.setVisibility(JavaVisibility.PUBLIC);
    commentGenerator.addJavaFileComment(topLevelClass);

    // add default constructor
    Method method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setConstructor(true);
    method.setName(type.getShortName());
    method.addBodyLine("oredCriteria = new ArrayList<Criteria>();"); // $NON-NLS-1$

    commentGenerator.addGeneralMethodComment(method, introspectedTable);
    topLevelClass.addMethod(method);

    // add field, getter, setter for orderby clause
    Field field = new Field();
    field.setVisibility(JavaVisibility.PROTECTED);
    field.setType(FullyQualifiedJavaType.getStringInstance());
    field.setName("orderByClause"); // $NON-NLS-1$
    commentGenerator.addFieldComment(field, introspectedTable);
    topLevelClass.addField(field);

    method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setName("setOrderByClause"); // $NON-NLS-1$
    method.addParameter(
        new Parameter(FullyQualifiedJavaType.getStringInstance(), "orderByClause")); // $NON-NLS-1$
    method.addBodyLine("this.orderByClause = orderByClause;"); // $NON-NLS-1$
    commentGenerator.addGeneralMethodComment(method, introspectedTable);
    topLevelClass.addMethod(method);

    method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setReturnType(FullyQualifiedJavaType.getStringInstance());
    method.setName("getOrderByClause"); // $NON-NLS-1$
    method.addBodyLine("return orderByClause;"); // $NON-NLS-1$
    commentGenerator.addGeneralMethodComment(method, introspectedTable);
    topLevelClass.addMethod(method);

    // add field, getter, setter for distinct
    field = new Field();
    field.setVisibility(JavaVisibility.PROTECTED);
    field.setType(FullyQualifiedJavaType.getBooleanPrimitiveInstance());
    field.setName("distinct"); // $NON-NLS-1$
    commentGenerator.addFieldComment(field, introspectedTable);
    topLevelClass.addField(field);

    method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setName("setDistinct"); // $NON-NLS-1$
    method.addParameter(
        new Parameter(
            FullyQualifiedJavaType.getBooleanPrimitiveInstance(), "distinct")); // $NON-NLS-1$
    method.addBodyLine("this.distinct = distinct;"); // $NON-NLS-1$
    commentGenerator.addGeneralMethodComment(method, introspectedTable);
    topLevelClass.addMethod(method);

    method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setReturnType(FullyQualifiedJavaType.getBooleanPrimitiveInstance());
    method.setName("isDistinct"); // $NON-NLS-1$
    method.addBodyLine("return distinct;"); // $NON-NLS-1$
    commentGenerator.addGeneralMethodComment(method, introspectedTable);
    topLevelClass.addMethod(method);

    // add field and methods for the list of ored criteria
    field = new Field();
    field.setVisibility(JavaVisibility.PROTECTED);

    FullyQualifiedJavaType fqjt =
        new FullyQualifiedJavaType("java.util.List<Criteria>"); // $NON-NLS-1$
    field.setType(fqjt);
    field.setName("oredCriteria"); // $NON-NLS-1$
    commentGenerator.addFieldComment(field, introspectedTable);
    topLevelClass.addField(field);

    method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setReturnType(fqjt);
    method.setName("getOredCriteria"); // $NON-NLS-1$
    method.addBodyLine("return oredCriteria;"); // $NON-NLS-1$
    commentGenerator.addGeneralMethodComment(method, introspectedTable);
    topLevelClass.addMethod(method);

    method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setName("or"); // $NON-NLS-1$
    method.addParameter(
        new Parameter(FullyQualifiedJavaType.getCriteriaInstance(), "criteria")); // $NON-NLS-1$
    method.addBodyLine("oredCriteria.add(criteria);"); // $NON-NLS-1$
    commentGenerator.addGeneralMethodComment(method, introspectedTable);
    topLevelClass.addMethod(method);

    method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setName("or"); // $NON-NLS-1$
    method.setReturnType(FullyQualifiedJavaType.getCriteriaInstance());
    method.addBodyLine("Criteria criteria = createCriteriaInternal();"); // $NON-NLS-1$
    method.addBodyLine("oredCriteria.add(criteria);"); // $NON-NLS-1$
    method.addBodyLine("return criteria;"); // $NON-NLS-1$
    commentGenerator.addGeneralMethodComment(method, introspectedTable);
    topLevelClass.addMethod(method);

    method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setName("createCriteria"); // $NON-NLS-1$
    method.setReturnType(FullyQualifiedJavaType.getCriteriaInstance());
    method.addBodyLine("Criteria criteria = createCriteriaInternal();"); // $NON-NLS-1$
    method.addBodyLine("if (oredCriteria.size() == 0) {"); // $NON-NLS-1$
    method.addBodyLine("oredCriteria.add(criteria);"); // $NON-NLS-1$
    method.addBodyLine("}"); // $NON-NLS-1$
    method.addBodyLine("return criteria;"); // $NON-NLS-1$
    commentGenerator.addGeneralMethodComment(method, introspectedTable);
    topLevelClass.addMethod(method);

    method = new Method();
    method.setVisibility(JavaVisibility.PROTECTED);
    method.setName("createCriteriaInternal"); // $NON-NLS-1$
    method.setReturnType(FullyQualifiedJavaType.getCriteriaInstance());
    method.addBodyLine("Criteria criteria = new Criteria();"); // $NON-NLS-1$
    method.addBodyLine("return criteria;"); // $NON-NLS-1$
    commentGenerator.addGeneralMethodComment(method, introspectedTable);
    topLevelClass.addMethod(method);

    method = new Method();
    method.setVisibility(JavaVisibility.PUBLIC);
    method.setName("clear"); // $NON-NLS-1$
    method.addBodyLine("oredCriteria.clear();"); // $NON-NLS-1$
    method.addBodyLine("orderByClause = null;"); // $NON-NLS-1$
    method.addBodyLine("distinct = false;"); // $NON-NLS-1$
    commentGenerator.addGeneralMethodComment(method, introspectedTable);
    topLevelClass.addMethod(method);

    // now generate the inner class that holds the AND conditions
    topLevelClass.addInnerClass(getGeneratedCriteriaInnerClass(topLevelClass));

    topLevelClass.addInnerClass(getCriteriaInnerClass(topLevelClass));

    topLevelClass.addInnerClass(getCriterionInnerClass(topLevelClass));

    List<CompilationUnit> answer = new ArrayList<CompilationUnit>();
    if (context.getPlugins().modelExampleClassGenerated(topLevelClass, introspectedTable)) {
      answer.add(topLevelClass);
    }
    return answer;
  }
  /**
   * 添加实现类
   *
   * @param introspectedTable
   * @param tableName
   * @param files
   */
  protected void addServiceImpl(
      TopLevelClass topLevelClass,
      IntrospectedTable introspectedTable,
      String tableName,
      List<GeneratedJavaFile> files) {
    topLevelClass.setVisibility(JavaVisibility.PUBLIC);
    // 设置实现的接口
    topLevelClass.addSuperInterface(interfaceType);

    if (enableAnnotation) {
      topLevelClass.addAnnotation("@Service");
      topLevelClass.addImportedType(service);
    }
    // 添加引用dao
    addField(topLevelClass, tableName);
    // 添加方法
    topLevelClass.addMethod(countByExample(introspectedTable, tableName));
    topLevelClass.addMethod(selectByPrimaryKey(introspectedTable, tableName));
    topLevelClass.addMethod(selectByExample(introspectedTable, tableName));

    /** type 的意义 pojo 1 ;key 2 ;example 3 ;pojo+example 4 */
    if (enableDeleteByPrimaryKey) {
      topLevelClass.addMethod(
          getOtherInteger("deleteByPrimaryKey", introspectedTable, tableName, 2));
    }
    if (enableUpdateByPrimaryKeySelective) {
      topLevelClass.addMethod(
          getOtherInteger("updateByPrimaryKeySelective", introspectedTable, tableName, 1));
    }
    if (enableUpdateByPrimaryKey) {
      topLevelClass.addMethod(
          getOtherInteger("updateByPrimaryKey", introspectedTable, tableName, 1));
    }
    if (enableDeleteByExample) {
      topLevelClass.addMethod(getOtherInteger("deleteByExample", introspectedTable, tableName, 3));
    }
    if (enableUpdateByExampleSelective) {
      topLevelClass.addMethod(
          getOtherInteger("updateByExampleSelective", introspectedTable, tableName, 4));
    }
    if (enableUpdateByExample) {
      topLevelClass.addMethod(getOtherInteger("updateByExample", introspectedTable, tableName, 4));
    }
    if (enableInsert) {
      topLevelClass.addMethod(getOtherInsertboolean("insert", introspectedTable, tableName));
    }
    if (enableInsertSelective) {
      topLevelClass.addMethod(
          getOtherInsertboolean("insertSelective", introspectedTable, tableName));
    }
    // 生成文件
    GeneratedJavaFile file =
        new GeneratedJavaFile(
            topLevelClass,
            project,
            context.getProperty(PropertyRegistry.CONTEXT_JAVA_FILE_ENCODING),
            context.getJavaFormatter());
    files.add(file);
  }