001/*
002 *  Copyright (c) 2022-2023, 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.SqlConnector;
019import com.mybatisflex.core.dialect.IDialect;
020import com.mybatisflex.core.util.ObjectUtil;
021import com.mybatisflex.core.util.StringUtil;
022
023import java.util.List;
024
025/**
026 * 括号
027 */
028public class Brackets extends QueryCondition {
029
030    private QueryCondition childCondition;
031
032    public Brackets(QueryCondition childCondition) {
033        this.childCondition = childCondition;
034    }
035
036    @Override
037    public QueryColumn getColumn() {
038        return childCondition.getColumn();
039    }
040
041    @Override
042    public void setColumn(QueryColumn column) {
043        childCondition.setColumn(column);
044    }
045
046    @Override
047    public void setValue(Object value) {
048        childCondition.setValue(value);
049    }
050
051    @Override
052    public String getLogic() {
053        return childCondition.getLogic();
054    }
055
056    @Override
057    public void setLogic(String logic) {
058        childCondition.setLogic(logic);
059    }
060
061    @Override
062    protected QueryCondition getNextEffectiveCondition() {
063        return childCondition.getNextEffectiveCondition();
064    }
065
066    @Override
067    public QueryCondition and(QueryCondition nextCondition) {
068        connectToChild(nextCondition, SqlConnector.AND);
069        return this;
070    }
071
072    @Override
073    public QueryCondition or(QueryCondition nextCondition) {
074        connectToChild(nextCondition, SqlConnector.OR);
075        return this;
076    }
077
078    protected void connectToChild(QueryCondition nextCondition, SqlConnector connector) {
079        childCondition.connect(nextCondition, connector);
080    }
081
082    @Override
083    public Object getValue() {
084        return checkEffective() ? WrapperUtil.getValues(childCondition) : null;
085    }
086
087    public QueryCondition getChildCondition() {
088        return childCondition;
089    }
090
091    @Override
092    public boolean checkEffective() {
093        boolean effective = super.checkEffective();
094        if (!effective) {
095            return false;
096        }
097        QueryCondition condition = this.childCondition;
098        while (condition != null) {
099            if (condition.checkEffective()) {
100                return true;
101            }
102            condition = condition.next;
103        }
104        return false;
105    }
106
107    @Override
108    public String toSql(List<QueryTable> queryTables, IDialect dialect) {
109
110        String sqlNext = next == null ? null : next.toSql(queryTables, dialect);
111
112        StringBuilder sql = new StringBuilder();
113        if (checkEffective()) {
114            String childSql = childCondition.toSql(queryTables, dialect);
115            if (StringUtil.isNotBlank(childSql)) {
116                QueryCondition prevEffectiveCondition = getPrevEffectiveCondition();
117                if (prevEffectiveCondition != null) {
118                    childSql = prevEffectiveCondition.connector + "(" + childSql + ")";
119                } else if (StringUtil.isNotBlank(sqlNext)) {
120                    childSql = "(" + childSql + ")";
121                }
122                sql.append(childSql);
123            } else {
124                //all child conditions are not effective
125                //fixed gitee #I6W89G
126                this.effective = false;
127            }
128        }
129
130        return sqlNext != null ? sql + sqlNext : sql.toString();
131    }
132
133
134    @Override
135    boolean containsTable(String... tables) {
136        if (childCondition != null && childCondition.containsTable(tables)) {
137            return true;
138        }
139        return nextContainsTable(tables);
140    }
141
142    @Override
143    public String toString() {
144        return "Brackets{" +
145            "childCondition=" + childCondition +
146            '}';
147    }
148
149    @Override
150    public Brackets clone() {
151        Brackets clone = (Brackets) super.clone();
152        // deep clone ...
153        clone.childCondition = ObjectUtil.clone(this.childCondition);
154        return clone;
155    }
156
157}