<%_ if (position === 'import') { _%>
import <%= packageName %>.anltr.LogicExprLexer;
import <%= packageName %>.anltr.LogicExprParser;
import <%= packageName %>.anltr.CriteriaLogicExprListener;
import org.apache.commons.lang3.ClassUtils;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import tech.jhipster.service.filter.*;
import java.time.ZonedDateTime;
import cn.hutool.core.bean.DynaBean;
    <%_ if (databaseTypeSql && ormTool === 'hibernate') { _%>
import javax.persistence.metamodel.SingularAttribute;
    <%_ } _%>
<%_ } _%>
<%_ if (position === 'field') { _%>

public static Map<String, Object> specificationMap = new HashMap<>();
<%_ } _%>
<%_ if (position === 'method') { _%>
    <%_ if (databaseTypeSql) { _%>
        <%_ if (ormTool !== 'mybatis') { _%>
    // 把commonQuery转为Specification
    public Specification createSpecification(Long commonQueryId) throws ClassNotFoundException {
        CommonCondition commonCondition = commonConditionRepository.getOne(commonQueryId);
        String packageName = ClassUtils.getPackageName(CommonCondition.class);
        String servicePackageName = ClassUtils.getPackageName(this.getClass());
        Specification specification;
        if (commonCondition != null) {
            Class targetClass = Class.forName(packageName + "." + commonCondition<% if (useCommonTable) { %>.getCommonTable()<% } %>.getClazzName() + "_");
            Class targetCriteriaClass = Class.forName(servicePackageName + ".dto." + commonCondition<% if (useCommonTable) { %>.getCommonTable()<% } %>.getClazzName() + "Criteria");
            StringBuffer s = new StringBuffer();
            Set<CommonConditionItem> conditionItems = commonCondition.getItems();
            conditionItems.forEach( queryItem -> {
                String prefix = queryItem.getPrefix();
                String suffix = queryItem.getSuffix();
                if (StringUtils.isNotEmpty(prefix)) {
                    switch (prefix) {
                        case ")":
                            s.append(" )");
                            break;
                        case "(":
                            s.append(" (");
                            break;
                        case "AND":
                            s.append(" AND");
                            break;
                        case "OR":
                            s.append(" AND");
                            break;
                        default:

                    }
                }
                try {
                    Integer specId = specificationMap.size()+1;
                    specificationMap.put(queryItem.getId() + "_" + specId, createSpecificationByQueryItem(queryItem,targetClass,targetCriteriaClass));
                    s.append(" " +queryItem.getId() + "_" + specId);
                } catch (NoSuchFieldException | InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                if (StringUtils.isNotEmpty(suffix)) {
                    switch (suffix) {
                        case ")":
                            s.append(" )");
                            break;
                        case "(":
                            s.append(" (");
                            break;
                        case "AND":
                            s.append(" AND");
                            break;
                        case "OR":
                            s.append(" AND");
                            break;
                        default:
                    }
                }
            });
            ANTLRInputStream input = new ANTLRInputStream(s.toString());
            LogicExprLexer lexer = new LogicExprLexer(input);
            CommonTokenStream tokenStream = new CommonTokenStream(lexer);
            LogicExprParser parser = new LogicExprParser(tokenStream);
            LogicExprParser.StatContext parseTree = parser.stat();
            CriteriaLogicExprListener visitor = new CriteriaLogicExprListener();
            System.out.println(parseTree.toStringTree(parser)); //打印规则数
            ParseTreeWalker walker = new ParseTreeWalker();
            walker.walk(visitor, parseTree);
            specification = Specification.where(visitor.specifications.get(parseTree));
            return specification;
        } else {
            return null;
        }
    }
        <%_ } else { _%>

    // 把commonQuery转为DynamicJoinQueryWrapper
    public DynamicJoinQueryWrapper createQueryWrapper(Long commonQueryId) throws ClassNotFoundException {
        CommonCondition commonCondition = this.commonConditionRepository.selectById(commonQueryId);
        if (commonCondition != null) {
            String packageName = ClassUtils.getPackageName(CommonCondition.class);
            String servicePackageName = ClassUtils.getPackageName(this.getClass());
            Class targetClass = Class.forName(packageName + "." + commonCondition.getCommonTable().getClazzName() + "_");
            Class targetCriteriaClass = Class.forName(servicePackageName + ".dto." + commonCondition.getCommonTable().getClazzName() + "Criteria");
            <%= manyListName%><CommonConditionItem> conditionItems = commonCondition.getItems();
            StringBuffer s = new StringBuffer();
            conditionItems.forEach( queryItem -> {
                String prefix = queryItem.getPrefix();
                String suffix = queryItem.getSuffix();
                if (StringUtils.isNotEmpty(prefix)) {
                    switch (prefix) {
                        case ")":
                            s.append(" )");
                            break;
                        case "(":
                            s.append(" (");
                            break;
                        case "AND":
                            s.append(" AND");
                            break;
                        case "OR":
                            s.append(" AND");
                            break;
                        default:

                    }
                }
                try {
                    Integer specId = specificationMap.size()+1;
                    specificationMap.put(queryItem.getId() + "_" + specId, createMergeSegmentsByQueryItem(queryItem,targetClass,targetCriteriaClass));
                    s.append(" " +queryItem.getId() + "_" + specId);
                } catch (NoSuchFieldException | InstantiationException | IllegalAccessException e) {
                    e.printStackTrace();
                }
                if (StringUtils.isNotEmpty(suffix)) {
                    switch (suffix) {
                        case ")":
                            s.append(" )");
                            break;
                        case "(":
                            s.append(" (");
                            break;
                        case "AND":
                            s.append(" AND");
                            break;
                        case "OR":
                            s.append(" AND");
                            break;
                        default:
                    }
                }
            });

        /*String packageName = ClassUtils.getPackageName(CommonCondition.class);
        String servicePackageName = ClassUtils.getPackageName(this.getClass());
        Specification specification;
        if (commonCondition != null) {
            Class targetClass = Class.forName(packageName + "." + commonCondition.getCommonTable().getClazzName() + "_");
            Class targetCriteriaClass = Class.forName(servicePackageName + ".dto." + commonCondition.getCommonTable().getClazzName() + "Criteria");
            StringBuffer s = new StringBuffer();
            Set<CommonConditionItem> conditionItems = commonCondition.getItems();
            conditionItems.forEach( queryItem -> {
                String prefix = queryItem.getPrefix();
                String suffix = queryItem.getSuffix();
                if (StringUtils.isNotEmpty(prefix)) {
                    switch (prefix) {
                        case ")":
                            s.append(" )");
                            break;
                        case "(":
                            s.append(" (");
                            break;
                        case "AND":
                            s.append(" AND");
                            break;
                        case "OR":
                            s.append(" AND");
                            break;
                        default:

                    }
                }
                try {
                    Integer specId = specificationMap.size()+1;
                    specificationMap.put(queryItem.getId() + "_" + specId, createMergeSegmentsByQueryItem(queryItem,targetClass,targetCriteriaClass));
                    s.append(" " +queryItem.getId() + "_" + specId);
                } catch (NoSuchFieldException | InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                if (StringUtils.isNotEmpty(suffix)) {
                    switch (suffix) {
                        case ")":
                            s.append(" )");
                            break;
                        case "(":
                            s.append(" (");
                            break;
                        case "AND":
                            s.append(" AND");
                            break;
                        case "OR":
                            s.append(" AND");
                            break;
                        default:
                    }
                }
            });*/
            ANTLRInputStream input = new ANTLRInputStream(s.toString());
            LogicExprLexer lexer = new LogicExprLexer(input);
            CommonTokenStream tokenStream = new CommonTokenStream(lexer);
            LogicExprParser parser = new LogicExprParser(tokenStream);
            LogicExprParser.StatContext parseTree = parser.stat();
            CriteriaLogicExprListener visitor = new CriteriaLogicExprListener();
            System.out.println(parseTree.toStringTree(parser)); //打印规则数
            ParseTreeWalker walker = new ParseTreeWalker();
            walker.walk(visitor, parseTree);
            return (DynamicJoinQueryWrapper) (new DynamicJoinQueryWrapper(targetClass, null)).apply(visitor.specifications.get(parseTree).getSqlSegment());
        } else {
            return null;
        }
    }
        <%_ } _%>
        <%_ if (ormTool !== 'mybatis') { _%>

    private Specification createSpecificationByQueryItem(CommonConditionItem commonConditionItem,Class jPAMetaModelClass, Class targetCriteriaClass) throws NoSuchFieldException, IllegalAccessException, InstantiationException {
        if (StringUtils.isNotEmpty(commonConditionItem.getFieldName()) &&
            StringUtils.isNotEmpty(commonConditionItem.getOperator()) &&
            StringUtils.isNotEmpty(commonConditionItem.getValue())
        ) {
            DynaBean criteria = DynaBean.create(targetCriteriaClass.newInstance());
            DynaBean filter;
            switch (commonConditionItem.getFieldType()) {
                case "LONG":
                    filter = DynaBean.create(LongFilter.class);
                    filter.set(commonConditionItem.getOperator(), Long.parseLong(commonConditionItem.getValue()));
                    criteria.set(commonConditionItem.getFieldName(), filter.getBean());
                    return buildRangeSpecification(criteria.get(commonConditionItem.getFieldName()),
                        (SingularAttribute)jPAMetaModelClass.getField(commonConditionItem.getFieldName()).get(targetCriteriaClass));
                case "INTEGER":
                    filter = DynaBean.create(IntegerFilter.class);
                    filter.set(commonConditionItem.getOperator(), Integer.parseInt(commonConditionItem.getValue()));
                    criteria.set(commonConditionItem.getFieldName(), filter.getBean());
                    return buildRangeSpecification(criteria.get(commonConditionItem.getFieldName()),
                        (SingularAttribute)jPAMetaModelClass.getField(commonConditionItem.getFieldName()).get(targetCriteriaClass));
                case "STRING":
                    filter = DynaBean.create(new StringFilter());
                    filter.set(commonConditionItem.getOperator(),commonConditionItem.getValue());
                    criteria.set(commonConditionItem.getFieldName(), filter.getBean());
                    return buildStringSpecification(criteria.get(commonConditionItem.getFieldName()),
                        (SingularAttribute)jPAMetaModelClass.getField(commonConditionItem.getFieldName()).get(targetCriteriaClass));
                case "FLOAT":
                    filter = DynaBean.create(FloatFilter.class);
                    filter.set(commonConditionItem.getOperator(), Float.parseFloat(commonConditionItem.getValue()));
                    criteria.set(commonConditionItem.getFieldName(), filter.getBean());
                    return buildRangeSpecification(criteria.get(commonConditionItem.getFieldName()),
                        (SingularAttribute)jPAMetaModelClass.getField(commonConditionItem.getFieldName()).get(targetCriteriaClass));
                case "DOUBLE":
                    filter = DynaBean.create(DoubleFilter.class);
                    filter.set(commonConditionItem.getOperator(), Double.parseDouble(commonConditionItem.getValue()));
                    criteria.set(commonConditionItem.getFieldName(), filter.getBean());
                    return buildRangeSpecification(criteria.get(commonConditionItem.getFieldName()),
                        (SingularAttribute)jPAMetaModelClass.getField(commonConditionItem.getFieldName()).get(targetCriteriaClass));
                case "BOOLEAN":
                    filter = DynaBean.create(BooleanFilter.class);
                    filter.set(commonConditionItem.getOperator(), Boolean.parseBoolean(commonConditionItem.getValue()));
                    criteria.set(commonConditionItem.getFieldName(), filter.getBean());
                    return buildSpecification(criteria.get(commonConditionItem.getFieldName()),
                        (SingularAttribute)jPAMetaModelClass.getField(commonConditionItem.getFieldName()).get(targetCriteriaClass));
                case "ZONED_DATE_TIME":
                    filter = DynaBean.create(ZonedDateTimeFilter.class);
                    filter.set(commonConditionItem.getOperator(), ZonedDateTime.parse(commonConditionItem.getValue()));
                    criteria.set(commonConditionItem.getFieldName(), filter.getBean());
                    return buildRangeSpecification(criteria.get(commonConditionItem.getFieldName()),
                        (SingularAttribute)jPAMetaModelClass.getField(commonConditionItem.getFieldName()).get(targetCriteriaClass));
                default:
                    return null;
            }
        } else {
            return null;
        }
    }
        <%_ } else { _%>

    private MergeSegments createMergeSegmentsByQueryItem(CommonConditionItem commonConditionItem, Class jPAMetaModelClass, Class targetCriteriaClass) throws NoSuchFieldException, IllegalAccessException, InstantiationException {
        if (StringUtils.isNotEmpty(commonConditionItem.getFieldName()) &&
            StringUtils.isNotEmpty(commonConditionItem.getOperator()) &&
            StringUtils.isNotEmpty(commonConditionItem.getValue())
        ) {
            DynaBean criteria = DynaBean.create(targetCriteriaClass.newInstance());
            DynaBean filter;
            switch (commonConditionItem.getFieldType()) {
                case "LONG":
                    filter = DynaBean.create(LongFilter.class);
                    filter.set(commonConditionItem.getOperator(), Long.parseLong(commonConditionItem.getValue()));
                    criteria.set(commonConditionItem.getFieldName(), filter.getBean());
                    return buildRangeMergeSegments(criteria.get(commonConditionItem.getFieldName()),commonConditionItem.getFieldName());
                case "INTEGER":
                    filter = DynaBean.create(IntegerFilter.class);
                    filter.set(commonConditionItem.getOperator(), Integer.parseInt(commonConditionItem.getValue()));
                    criteria.set(commonConditionItem.getFieldName(), filter.getBean());
                    return buildRangeMergeSegments(criteria.get(commonConditionItem.getFieldName()),commonConditionItem.getFieldName());
                case "STRING":
                    filter = DynaBean.create(new StringFilter());
                    filter.set(commonConditionItem.getOperator(),commonConditionItem.getValue());
                    criteria.set(commonConditionItem.getFieldName(), filter.getBean());
                    return buildStringMergeSegments(criteria.get(commonConditionItem.getFieldName()),commonConditionItem.getFieldName());
                case "FLOAT":
                    filter = DynaBean.create(FloatFilter.class);
                    filter.set(commonConditionItem.getOperator(), Float.parseFloat(commonConditionItem.getValue()));
                    criteria.set(commonConditionItem.getFieldName(), filter.getBean());
                    return buildRangeMergeSegments(criteria.get(commonConditionItem.getFieldName()),commonConditionItem.getFieldName());
                case "DOUBLE":
                    filter = DynaBean.create(DoubleFilter.class);
                    filter.set(commonConditionItem.getOperator(), Double.parseDouble(commonConditionItem.getValue()));
                    criteria.set(commonConditionItem.getFieldName(), filter.getBean());
                    return buildRangeMergeSegments(criteria.get(commonConditionItem.getFieldName()),commonConditionItem.getFieldName());
                case "BOOLEAN":
                    filter = DynaBean.create(BooleanFilter.class);
                    filter.set(commonConditionItem.getOperator(), Boolean.parseBoolean(commonConditionItem.getValue()));
                    criteria.set(commonConditionItem.getFieldName(), filter.getBean());
                    return buildMergeSegments((BooleanFilter) criteria.get(commonConditionItem.getFieldName()),commonConditionItem.getFieldName());
                case "ZONED_DATE_TIME":
                    filter = DynaBean.create(ZonedDateTimeFilter.class);
                    filter.set(commonConditionItem.getOperator(), ZonedDateTime.parse(commonConditionItem.getValue()));
                    criteria.set(commonConditionItem.getFieldName(), filter.getBean());
                    return buildRangeMergeSegments(criteria.get(commonConditionItem.getFieldName()),commonConditionItem.getFieldName());
                default:
                    return null;
            }
        } else {
            return null;
        }
    }


    protected <X extends Comparable<? super X>> MergeSegments buildRangeMergeSegments(RangeFilter<X> filter, String field) {
        MergeSegments mergeSegments = new MergeSegments();
        if (filter.getEquals() != null) {
            mergeSegments.add(() -> String.valueOf(field), EQ, () -> String.valueOf(filter.getEquals()));
        } else if (filter.getIn() != null) {
            mergeSegments.add(() -> String.valueOf(field), IN, inExpression(filter.getIn()));
        }
        if (filter.getSpecified() != null) {
            if (filter.getSpecified()) {
                this.isNotNull(field);
            } else {
                this.isNull(field);
            }
        }
        if (filter.getNotEquals() != null) {
            mergeSegments.add(() -> String.valueOf(field), NE, () -> String.valueOf(filter.getNotEquals()));
        }
        if (filter.getGreaterThan() != null) {
            mergeSegments.add(() -> String.valueOf(field), GT, () -> String.valueOf(filter.getGreaterThan()));
        }
        if (filter.getGreaterThanOrEqual() != null) {
            mergeSegments.add(() -> String.valueOf(field), GE, () -> String.valueOf(filter.getGreaterThanOrEqual()));
        }
        if (filter.getLessThan() != null) {
            mergeSegments.add(() -> String.valueOf(field), LT, () -> String.valueOf(filter.getLessThan()));
        }
        if (filter.getLessThanOrEqual() != null) {
            mergeSegments.add(() -> String.valueOf(field), LE, () -> String.valueOf(filter.getLessThanOrEqual()));
        }
        return mergeSegments;
    }

    protected MergeSegments buildStringMergeSegments(StringFilter filter, String field) {
        MergeSegments mergeSegments = new MergeSegments();
        if (filter.getEquals() != null) {
            mergeSegments.add(() -> String.valueOf(field), EQ, filter::getEquals);
        } else if (filter.getIn() != null) {
            mergeSegments.add(() -> String.valueOf(field), IN, inExpression(filter.getIn()));
        } else if (filter.getContains() != null) {
            mergeSegments.add(() -> String.valueOf(field), LIKE, filter::getContains);
        } else if (filter.getDoesNotContain() != null) {
            mergeSegments.add(() -> String.valueOf(field), NOT_LIKE, filter::getDoesNotContain);
        } else if (filter.getNotEquals() != null) {
            mergeSegments.add(() -> String.valueOf(field), NE, filter::getNotEquals);
        } else if (filter.getSpecified() != null) {
            if (filter.getSpecified()) {
                this.isNotNull(field);
            } else {
                this.isNull(field);
            }
        }
        return mergeSegments;
    }

    protected <X> MergeSegments buildMergeSegments(Filter<X> filter, String field) {
        MergeSegments mergeSegments = new MergeSegments();
        if (filter.getEquals() != null) {
            mergeSegments.add(() -> String.valueOf(field), EQ, () -> String.valueOf(filter.getEquals()));
        } else if (filter.getIn() != null) {
            mergeSegments.add(() -> String.valueOf(field), IN, inExpression(filter.getIn()));
        } else if (filter.getNotEquals() != null) {
            mergeSegments.add(() -> String.valueOf(field), NE, () -> String.valueOf(filter.getNotEquals()));
        } else if (filter.getSpecified() != null) {
            if (filter.getSpecified()) {
                this.isNotNull(field);
            } else {
                this.isNull(field);
            }
        }
        return mergeSegments;
    }

    /**
     * 获取in表达式 包含括号
     *
     * @param value 集合
     */
    private ISqlSegment inExpression(Collection<?> value) {
        return () ->
            value
                .stream()
                .map(i -> formatSql("{0}", i))
                .collect(joining(StringPool.COMMA, StringPool.LEFT_BRACKET, StringPool.RIGHT_BRACKET));
    }
        <%_ } _%>
    <%_ } _%>
<%_ } _%>
