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
018
019import com.mybatisflex.core.FlexConsts;
020import com.mybatisflex.core.constant.SqlConsts;
021import com.mybatisflex.core.dialect.DialectFactory;
022import com.mybatisflex.core.dialect.IDialect;
023import com.mybatisflex.core.dialect.impl.OracleDialect;
024import com.mybatisflex.core.util.ClassUtil;
025import com.mybatisflex.core.util.EnumWrapper;
026import com.mybatisflex.core.util.StringUtil;
027
028import java.lang.reflect.Array;
029import java.util.ArrayList;
030import java.util.Arrays;
031import java.util.Collections;
032import java.util.List;
033
034class WrapperUtil {
035
036    private WrapperUtil() {
037    }
038
039    static List<QueryWrapper> getChildQueryWrapper(QueryCondition condition) {
040        List<QueryWrapper> list = null;
041        while (condition != null) {
042            if (condition.checkEffective()) {
043                if (condition instanceof Brackets) {
044                    List<QueryWrapper> childQueryWrapper = getChildQueryWrapper(((Brackets) condition).getChildCondition());
045                    if (!childQueryWrapper.isEmpty()) {
046                        if (list == null) {
047                            list = new ArrayList<>();
048                        }
049                        list.addAll(childQueryWrapper);
050                    }
051                }
052                // not Brackets
053                else {
054                    Object value = condition.getValue();
055                    if (value instanceof QueryWrapper) {
056                        if (list == null) {
057                            list = new ArrayList<>();
058                        }
059                        list.add((QueryWrapper) value);
060                        list.addAll(((QueryWrapper) value).getChildSelect());
061                    } else if (value != null && value.getClass().isArray()) {
062                        for (int i = 0; i < Array.getLength(value); i++) {
063                            Object arrayValue = Array.get(value, i);
064                            if (arrayValue instanceof QueryWrapper) {
065                                if (list == null) {
066                                    list = new ArrayList<>();
067                                }
068                                list.add((QueryWrapper) arrayValue);
069                                list.addAll(((QueryWrapper) arrayValue).getChildSelect());
070                            }
071                        }
072                    }
073                }
074            }
075            condition = condition.next;
076        }
077        return list == null ? Collections.emptyList() : list;
078    }
079
080
081    static Object[] getValues(QueryCondition condition) {
082        if (condition == null) {
083            return FlexConsts.EMPTY_ARRAY;
084        }
085
086        List<Object> params = new ArrayList<>();
087        getValues(condition, params);
088
089        return params.isEmpty() ? FlexConsts.EMPTY_ARRAY : params.toArray();
090    }
091
092
093    private static void getValues(QueryCondition condition, List<Object> params) {
094        if (condition == null) {
095            return;
096        }
097
098        Object value = condition.getValue();
099        if (value == null
100            || value instanceof QueryColumn
101            || value instanceof RawQueryCondition) {
102            getValues(condition.next, params);
103            return;
104        }
105
106        addParam(params, value);
107        getValues(condition.next, params);
108    }
109
110    private static void addParam(List<Object> paras, Object value) {
111        if (value == null) {
112            paras.add(null);
113        } else if (ClassUtil.isArray(value.getClass())) {
114            for (int i = 0; i < Array.getLength(value); i++) {
115                addParam(paras, Array.get(value, i));
116            }
117        } else if (value instanceof QueryWrapper) {
118            Object[] valueArray = ((QueryWrapper) value).getAllValueArray();
119            paras.addAll(Arrays.asList(valueArray));
120        } else if (value.getClass().isEnum()) {
121            EnumWrapper enumWrapper = EnumWrapper.of(value.getClass());
122            if (enumWrapper.hasEnumValueAnnotation()) {
123                paras.add(enumWrapper.getEnumValue((Enum) value));
124            } else {
125                paras.add(((Enum<?>) value).name());
126            }
127        } else {
128            paras.add(value);
129        }
130
131    }
132
133    static String buildValue(List<QueryTable> queryTables, Object value) {
134        if (value instanceof Number || value instanceof Boolean) {
135            return String.valueOf(value);
136        } else if (value instanceof RawQueryCondition) {
137            return ((RawQueryCondition) value).getContent();
138        } else if (value instanceof QueryColumn) {
139            return ((QueryColumn) value).toConditionSql(queryTables, DialectFactory.getDialect());
140        } else {
141            return SqlConsts.SINGLE_QUOTE + value + SqlConsts.SINGLE_QUOTE;
142        }
143    }
144
145
146    static String withBracket(String sql) {
147        return SqlConsts.BRACKET_LEFT + sql + SqlConsts.BRACKET_RIGHT;
148    }
149
150    static String withAlias(String sql, String alias, IDialect dialect) {
151        return SqlConsts.BRACKET_LEFT + sql + SqlConsts.BRACKET_RIGHT + buildColumnAlias(alias, dialect);
152    }
153
154    static String buildAlias(String alias, IDialect dialect) {
155        return StringUtil.isBlank(alias) ? SqlConsts.EMPTY : getAsKeyWord(dialect) + dialect.wrap(alias);
156    }
157
158    static String buildColumnAlias(String alias, IDialect dialect) {
159        return StringUtil.isBlank(alias) ? SqlConsts.EMPTY : getAsKeyWord(dialect) + dialect.wrapColumnAlias(alias);
160    }
161
162    private static String getAsKeyWord(IDialect dialect) {
163        return dialect instanceof OracleDialect ? SqlConsts.BLANK : SqlConsts.AS;
164    }
165
166}