001/*
002 *  Copyright (c) 2022-2025, Mybatis-Flex (fuhai999@gmail.com).
003 *  <p>
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *  <p>
008 *  http://www.apache.org/licenses/LICENSE-2.0
009 *  <p>
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package com.mybatisflex.core.query;
017
018import com.mybatisflex.core.constant.SqlConsts;
019import com.mybatisflex.core.dialect.IDialect;
020import com.mybatisflex.core.dialect.OperateType;
021import com.mybatisflex.core.exception.FlexExceptions;
022import com.mybatisflex.core.util.ObjectUtil;
023
024import java.util.List;
025import java.util.function.Supplier;
026
027/**
028 * @author michael yang (fuhai999@gmail.com)
029 * @Date: 2020/1/14
030 */
031public class Join implements CloneSupport<Join> {
032
033    private static final long serialVersionUID = 1L;
034
035
036    protected final String type;
037    protected QueryTable queryTable;
038    protected QueryCondition on;
039    protected boolean effective;
040
041    public Join(String type, QueryTable table, boolean when) {
042        this.type = type;
043        this.queryTable = table;
044        this.effective = when;
045    }
046
047    public Join(String type, QueryWrapper queryWrapper, boolean when) {
048        this.type = type;
049        this.queryTable = new SelectQueryTable(queryWrapper);
050        this.effective = when;
051    }
052
053
054    QueryTable getQueryTable() {
055        return queryTable;
056    }
057
058
059    public void on(QueryCondition condition) {
060        replaceConditionColumn(condition);
061        this.on = condition;
062    }
063
064    private void replaceConditionColumn(QueryCondition condition) {
065        if (condition != null) {
066            if (condition.checkEffective() && condition.column != null) {
067                QueryTable table = condition.column.getTable();
068                if (queryTable.isSameTable(table)) {
069                    QueryColumn newColumn = condition.column.clone();
070                    newColumn.table.alias = queryTable.alias;
071                    condition.column = newColumn;
072                }
073            } else if (condition instanceof Brackets) {
074                replaceConditionColumn(((Brackets) condition).getChildCondition());
075            } else if (condition instanceof OperatorQueryCondition) {
076                replaceConditionColumn(((OperatorQueryCondition) condition).getChildCondition());
077            } else if (condition instanceof OperatorSelectCondition) {
078                QueryWrapper qw = ((OperatorSelectCondition) condition).getQueryWrapper();
079                replaceConditionColumn(qw.whereQueryCondition);
080            }
081            replaceConditionColumn(condition.next);
082        }
083    }
084
085
086    QueryCondition getOnCondition() {
087        return on;
088    }
089
090    public boolean checkEffective() {
091        return effective;
092    }
093
094    public void when(boolean when) {
095        this.effective = when;
096    }
097
098    public void when(Supplier<Boolean> fn) {
099        this.effective = fn.get();
100    }
101
102    public String toSql(List<QueryTable> queryTables, IDialect dialect, OperateType operateType) {
103        return type + queryTable.toSql(dialect, operateType) + SqlConsts.ON + on.toSql(queryTables, dialect);
104    }
105
106    @Override
107    public Join clone() {
108        try {
109            Join clone = (Join) super.clone();
110            // deep clone ...
111            clone.queryTable = ObjectUtil.clone(this.queryTable);
112            clone.on = ObjectUtil.clone(this.on);
113            return clone;
114        } catch (CloneNotSupportedException e) {
115            throw FlexExceptions.wrap(e);
116        }
117    }
118
119}