All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.objectsql.query.MultiQueryImpl Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2017 @objectsql.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.objectsql.query;

import com.objectsql.spring.SpringUtils;
import com.objectsql.support.*;
import com.objectsql.utils.ORMUtils;
import com.objectsql.annotation.RdTable;

import java.util.*;

public class MultiQueryImpl extends AbstractQueryImpl implements MultiQuery {

    private List subQueries = new ArrayList();

    private List usedAlias = new ArrayList();

    public  MultiQueryImpl(){}

    private MultiQuery parentQuery;

    public MultiQueryImpl(MultiQuery query){
        this.parentQuery = query;
    }

    private List aliasList = new ArrayList();
	private Map aliasTable = new HashMap();

	private List groups = new ArrayList();
    private List groupCountsSelectColumns = new ArrayList();

	private List joins = new ArrayList();

    private Class returnClass;
    private List returnColumns = new ArrayList();
    private List fixReturnColumns = new ArrayList();

    private Map dataColumns = new LinkedHashMap();
    private Map dataKeys = new LinkedHashMap();

	public MultiQuery createQuery(Class clazz, Column... columns) {
		this.returnClass = clazz;
        this.returnColumns.clear();
        this.fixReturnColumns.clear();
        if(columns != null) {
            for (Column column : columns) {
                returnColumns.add(column);
            }
        }
		return this;
	}

    public MultiQuery createQuery(Column... columns) {
        this.returnColumns.clear();
        this.fixReturnColumns.clear();
        if(columns != null) {
            for (Column column : columns) {
                returnColumns.add(column);
            }
        }
        return this;
    }

    public MultiQuery createQuery(Class clazz, Columns... columns){
        this.returnClass = clazz;
        this.returnColumns.clear();
        this.fixReturnColumns.clear();
        if(columns != null) {
            for (Columns column : columns) {
                List columnList = column.getColumnList();
                if(!columnList.isEmpty()) {
                    returnColumns.addAll(columnList);
                }
            }
        }
        return this;
    }

    public MultiQuery addReturnColumn(Column ... columns){
        if(columns != null) {
            for (int i = 0; i < columns.length; i++) {
                this.returnColumns.add(columns[i]);
            }
        }
        return this;
    }

    @Override
    public MultiQuery addReturnColumn(Columns ... columns) {
        if (columns != null && columns.length > 0){
            for (int i = 0; i < columns.length; i++) {
                this.returnColumns.addAll(columns[i].getColumnList());
            }
        }
        return this;
    }

    public MultiQuery clearReturnColumns(){
        this.returnColumns.clear();
        return this;
    }


    public MultiQuery addFixedReturnColumn(Column ... columns){
        if(columns != null) {
            for (int i = 0; i < columns.length; i++) {
                this.fixReturnColumns.add(columns[i]);
            }
        }
        return this;
    }

    @Override
    public MultiQuery addFixedReturnColumn(Columns ... columns) {
        if (columns != null && columns.length > 0){
            for (int i = 0; i < columns.length; i++) {
                this.fixReturnColumns.addAll(columns[i].getColumnList());
            }
        }
        return this;
    }

    public MultiQuery clearFixedReturnColumns(){
        this.fixReturnColumns.clear();
        return this;
    }

    /////////////////////////////////
    private String generateUniqueAlias(Object object){
        int i = 0;
        String prefixAlias = null;
        if(object instanceof IQuery){
            prefixAlias = "q";
        }else if(object instanceof Class){
            prefixAlias = ((Class)object).getSimpleName().substring(0, 1).toLowerCase(Locale.ROOT);
        }else{
            prefixAlias = object.toString().substring(0, 1).toLowerCase(Locale.ROOT);
        }
        String alias = prefixAlias + i;
        while(containsAlias(alias)){
            i++;
            alias = prefixAlias + i;
        }
        return alias;
    }

    public AliasTable join(IQuery query){
        String alias = generateUniqueAlias(query);
        return join(query, alias);
    }

    public AliasTable join(IQuery query, String alias){
        AliasTable table = new AliasTable(query);
        table.setAlias(alias);
        aliasTable.put(alias, query);
        addUsedAlias(alias);
        return table;
    }

    public AliasTable table(IQuery query, String alias){
        AliasTable table = new AliasTable(query);
        table.setAlias(alias);
        aliasList.add(alias);
        addUsedAlias(alias);
        aliasTable.put(alias, query);
        return table;
    }

    public AliasTable table(IQuery query){
        String alias = generateUniqueAlias(query);
        return table(query, alias);
    }

    public AliasTable join(Class clazz, String alias){
        ORMUtils.whenEmpty(clazz, "AliasTable join class should not be null.");
        RdTable rdTable = SpringUtils.findAnnotation(clazz, RdTable.class);
        ORMUtils.whenEmpty(rdTable, "Should annotate RdTable");
        AliasTable table = new AliasTable(clazz);
        table.setAlias(alias);
        aliasTable.put(alias, clazz);
        addUsedAlias(alias);
        return table;
    }

    @Override
    public AliasTable join(Class clazz, String clazzColumn, Column tableColumn) {
        AliasTable join = join(clazz);
        this.join(join, join.c(clazzColumn), tableColumn);
        return join;
    }

    @Override
    public AliasTable join(Class clazz, JoinType joinType, String clazzColumn, Column tableColumn) {
        AliasTable join = join(clazz);
        this.join(join, joinType, join.c(clazzColumn), tableColumn);
        return join;
    }

    @Override
    public  AliasTable join(Class clazz, LambdaQuery clazzColumn, Column tableColumn) {
        AliasTable join = join(clazz);
        this.join(join, join.c(clazzColumn), tableColumn);
        return join;
    }

    @Override
    public  AliasTable join(Class clazz, JoinType joinType, LambdaQuery clazzColumn, Column tableColumn) {
        AliasTable join = join(clazz);
        this.join(join, joinType, join.c(clazzColumn), tableColumn);
        return join;
    }

    public AliasTable join(Class clazz){
        String alias = generateUniqueAlias(clazz);
        return join(clazz, alias);
    }

    @Override
    public MultiQuery whereEqual(Column left, Object value) {
        return where(left, value, ExpressionType.CDT_EQUAL);
    }

    @Override
    public MultiQuery whereNotEqual(Column left, Object value) {
        return where(left, value, ExpressionType.CDT_NOT_EQUAL);
    }

    @Override
    public MultiQuery whereLike(Column left, String value) {
        return where(left, value, ExpressionType.CDT_LIKE);
    }

    @Override
    public MultiQuery whereNotLike(Column left, String value) {
        return where(left, value, ExpressionType.CDT_NOT_LIKE);
    }

    @Override
    public MultiQuery whereStartWith(Column left, String value) {
        return where(left, value, ExpressionType.CDT_START_WITH);
    }

    @Override
    public MultiQuery whereEndWith(Column left, String value) {
        return where(left, value, ExpressionType.CDT_END_WITH);
    }

    @Override
    public MultiQuery whereNotStartWith(Column left, String value) {
        return where(left, value, ExpressionType.CDT_NOT_START_WITH);
    }

    @Override
    public MultiQuery whereNotEndWith(Column left, String value) {
        return where(left, value, ExpressionType.CDT_NOT_END_WITH);
    }

    @Override
    public MultiQuery whereLess(Column left, Object value) {
        return where(left, value, ExpressionType.CDT_LESS);
    }

    @Override
    public MultiQuery whereLessEqual(Column left, Object value) {
        return where(left, value, ExpressionType.CDT_LESS_EQUAL);
    }

    @Override
    public MultiQuery whereMore(Column left, Object value) {
        return where(left, value, ExpressionType.CDT_MORE);
    }

    @Override
    public MultiQuery whereMoreEqual(Column left, Object value) {
        return where(left, value, ExpressionType.CDT_MORE_EQUAL);
    }


    @Override
    public MultiQuery whereIn(Column left, Collection value) {
        return where(left, value, ExpressionType.CDT_IN);
    }

    @Override
    public MultiQuery whereInValues(Column left, Object ... values){
        List temp = null;
        if(values != null){
            temp = Arrays.asList(values);
        }else{
            temp = new ArrayList();
        }
        return where(left, temp, ExpressionType.CDT_IN);
    }

    @Override
    public MultiQuery whereNotInValues(Column left, Object ... values){
        List temp = null;
        if(values != null){
            temp = Arrays.asList(values);
        }else{
            temp = new ArrayList();
        }
        return where(left, temp, ExpressionType.CDT_NOT_IN);
    }

    @Override
    public MultiQuery whereNotIn(Column left, Collection value) {
        return where(left, value, ExpressionType.CDT_NOT_IN);
    }

    @Override
    public MultiQuery whereNotInQuery(Column left, MultiQuery query) {
        return where(left, query, ExpressionType.CDT_NOT_IN);
    }

    @Override
    public MultiQuery whereBetween(Column left, Object value, Object andValue){
        if(!ORMUtils.isEmpty(value) && !ORMUtils.isEmpty(andValue)){
            Expression expression = new Expression(left, value, ExpressionType.CDT_BETWEEN);
            expression.setAndValue(andValue);
            addCondition(new Condition().and(expression));
        }
        return this;
    }

    @Override
    public MultiQuery whereInQuery(Column left, MultiQuery query) {

        return where(left, query, ExpressionType.CDT_IN);
    }

    public AliasTable table(Class clazz){
        String alias = generateUniqueAlias(clazz);
        return table(clazz, alias);
    }

    @Override
    public AliasTable table(String tableName, String alias) {
        AliasTable table = new AliasTable(tableName);
        table.setAlias(alias);
        aliasList.add(alias);
        aliasTable.put(alias, tableName);
        addUsedAlias(alias);
        return table;
    }

    @Override
    public AliasTable table(String tableName) {
        String alias = generateUniqueAlias(tableName);
        return table(tableName, alias);
    }

    public AliasTable table(Class clazz, String alias){
        if(this.returnClass == null){
            this.returnClass = clazz;
        }
        AliasTable table = null;
        if(clazz != null) {
            RdTable rdTable = SpringUtils.findAnnotation(clazz, RdTable.class);
            if(rdTable != null) {
                table = new AliasTable(clazz);
                table.setAlias(alias);
                aliasList.add(alias);
                addUsedAlias(alias);
                aliasTable.put(alias, clazz);
            }
        }
        return table;
    }

    public MultiQuery whereIsNull(Column left) {
        addCondition(new Condition().and(new Expression(left, ExpressionType.CDT_IS_NULL)));
        return this;
    }

    public MultiQuery whereIsNotNull(Column left) {
        addCondition(new Condition().and(new Expression(left, ExpressionType.CDT_IS_NOT_NULL)));
        return this;
    }

    public MultiQuery whereIsEmpty(Column left) {
        addCondition(new Condition().and(new Expression(left, ExpressionType.CDT_IS_EMPTY)));
        return this;
    }

    public MultiQuery whereIsNotEmpty(Column left) {
        addCondition(new Condition().and(new Expression(left, ExpressionType.CDT_IS_NOT_EMPTY)));
        return this;
    }

    public MultiQuery where(Column left, Object value, ExpressionType type) {
        if(ORMUtils.isEmpty(value)){
            if(type == ExpressionType.CDT_IS_NULL
                    || type == ExpressionType.CDT_IS_NOT_NULL
                    || type == ExpressionType.CDT_IS_EMPTY
                    || type == ExpressionType.CDT_IS_NOT_EMPTY){
                addCondition(new Condition().and(new Expression(left, type)));
            }
            return this;
        }
        addCondition(new Condition().and(new Expression(left, value, type)));
        return this;
    }

    public MultiQuery where(Column left, Column value) {
        addCondition(new Condition().and(new Expression(left, value)));
        return this;
    }

    public MultiQuery where(Condition condition) {
        if(condition != null) {
            addCondition(condition);
        }
        return this;
    }

    @Override
    public MultiQuery where(Expression... expressions) {
        addCondition(new Condition().and(expressions));
        return this;
    }


    public MultiQuery group(Column ... columns) {
        if(columns != null) {
            groups.addAll(Arrays.asList(columns));
        }
        return this;
    }

    public List getGroupCountSelectColumns(){
        return groupCountsSelectColumns;
    }

    public MultiQuery groupCountSelectColumn(Column ... columns) {
        if(columns != null) {
            groupCountsSelectColumns.addAll(Arrays.asList(columns));
        }
        return this;
    }


    public MultiQuery group(Columns ... columns) {
        if(columns != null) {
            for(Columns column : columns) {
                groups.addAll(column.getColumnList());
            }
        }
        return this;
    }

    public MultiQuery having(Column left, Object value, ExpressionType type) {
        if(ORMUtils.isEmpty(value)){
            return this;
        }
        addHaving(new Condition().or(new Expression(left, value, type)));
        return this;
    }

    public MultiQuery having(Column left, Column value) {
        addHaving(new Condition().and(new Expression(left, value)));
        return this;
    }

    public MultiQuery having(Condition condition) {
        if(condition != null) {
            addHaving(condition);
        }
        return this;
    }

    public MultiQuery having(Expression expression) {
        if(expression != null) {
            addHaving(new Condition().and(expression));
        }
        return this;
    }

    public MultiQuery orderDesc(Column column) {
        orders.add(new Order(column, Order.DESC));
        return this;
    }

    public MultiQuery orderAsc(Column column) {
        orders.add(new Order(column, Order.ASC));
        return this;
    }

    public MultiQuery order(Order order) {
        if (order != null) {
            orders.add(order);
        }
        return this;
    }

    public MultiQuery orders(List orderList){
        if(orderList != null){
            for(Order order : orderList){
                orders.add(order);
            }
        }
        return this;
    }

    public MultiQuery join(Join join){
        joins.add(join);
        return this;
    }

    public MultiQuery join(AliasTable table, Column left, Column right){
        return join(new Join(table).on(left, right));
    }

    public MultiQuery join(AliasTable table, JoinType joinType, Column left, Column right){
        return join(new Join(table, joinType).on(left, right));
    }

    @Override
    public MultiQuery distinct() {
        this.distinct = true;
        return this;
    }

    private boolean enableDataPermission = false;

    @Override
    public MultiQuery enableDataPermission() {
        enableDataPermission = true;
        return this;
    }

    @Override
    public MultiQuery disableDataPermission() {
        enableDataPermission = false;
        return this;
    }

    @Override
    public boolean isEnableDataPermission() {
        return enableDataPermission;
    }

    @Override
    public String dataKey(Object dataType) {
        return dataKeys.get(dataType);
    }

    @Override
    public MultiQuery dataColumn(Object dataKey, Column column) {
        dataColumns.put(dataKey, column);
        return this;
    }

    @Override
    public MultiQuery dataColumn(Object dataType, String dataKey, Column column) {
        dataColumns.put(dataType, column);
        dataKeys.put(dataType, dataKey);
        return this;
    }

    @Override
    public Column dataColumn(Object dataType) {
        return dataColumns.get(dataType);
    }

    //    @Override
//    public Map getAliasQuery() {
//        return aliasQuery;
//    }

    @Override
    public Class getTable() {
        return null;
    }

    @Override
    public boolean isDistinct() {
        return distinct;
    }

    @Override
    public List getAliasList() {
        return aliasList;
    }

    @Override
    public Map getAliasTable() {
        return aliasTable;
    }

    @Override
    public List getJoins() {
        return joins;
    }

    @Override
    public List getGroups() {
        return groups;
    }

    @Override
    public Class getReturnClass() {
        return returnClass;
    }

    @Override
    public List getReturnColumns() {
        List columnList = new ArrayList();
        if(returnColumns.isEmpty()){
            for(String alias : aliasList){
                columnList.add(new Column(alias, Column.ALL));
            }
        }else{
            columnList.addAll(returnColumns);
        }
        return columnList;
    }

    @Override
    public List getFinalReturnColumns() {
        List columnList = new ArrayList();
        columnList.addAll(getReturnColumns());
        columnList.addAll(fixReturnColumns);
        return columnList;
    }

    @Override
    public List getFixedReturnColumns() {
        return fixReturnColumns;
    }

    public void addUsedAlias(String alias){
        if(parentQuery == null) {
            usedAlias.add(alias);
        }else{
            MultiQuery temp = parentQuery;
            while (temp != null){
                if(temp.parentQuery() == null){
                    temp.addUsedAlias(alias);
                }
                temp = temp.parentQuery();
            }
        }
    }

    public boolean containsAlias(String alias){
        if(parentQuery == null){
            return usedAlias.contains(alias);
        }
        MultiQuery temp = parentQuery;
        boolean hasC = false;
        while (temp != null){
            if(temp.parentQuery() == null){
                hasC = temp.containsAlias(alias);
                break;
            }
            temp = temp.parentQuery();
        }
        return hasC;
    }

    @Override
    public MultiQuery newMultiQuery() {
        MultiQuery query = new MultiQueryImpl(this);
        query.setTextTransformType(this.textTransformType());
        if(this.isLessDatePlus235959()){
            query.enableLessDatePlus235959();
        }
        if (this.isLessEqualDatePlus235959()){
            query.enableLessEqualDatePlus235959();
        }
        subQueries.add(query);
        return query;
    }

    @Override
    public MultiQuery parentQuery() {
        return this.parentQuery;
    }

    @Override
    public void setOptions(Options options) {
        this.options = options;
        for (MultiQuery query : this.subQueries){
            query.setOptions(options);
        }
    }

    @Override
    public QueryInfo doQuery() {
        if(parentQuery != null) {
            return parentQuery.getOptions().doQuery(this, getPageable());
        }else{
            return options.doQuery(this, getPageable());
        }
    }

    @Override
    public QueryInfo doQueryCount() {
        if(parentQuery != null) {
            return parentQuery.getOptions().doQueryCount(this);
        }else{
            return options.doQueryCount(this);
        }
    }

    @Override
    public MultiQuery whereExists(MultiQuery query) {
        addCondition(new Condition().and(new Expression(ExpressionType.CDT_EXISTS, query)));
        return this;
    }

    @Override
    public MultiQuery whereNotExists(MultiQuery query) {
        addCondition(new Condition().and(new Expression(ExpressionType.CDT_NOT_EXISTS, query)));
        return this;
    }


}