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.row;
017
018import com.mybatisflex.core.javassist.ModifyAttrsRecord;
019import com.mybatisflex.core.query.QueryColumn;
020import com.mybatisflex.core.util.ArrayUtil;
021import com.mybatisflex.core.util.ConvertUtil;
022import com.mybatisflex.core.util.SqlUtil;
023import com.mybatisflex.core.util.StringUtil;
024
025import java.math.BigDecimal;
026import java.math.BigInteger;
027import java.sql.Time;
028import java.sql.Timestamp;
029import java.time.LocalDateTime;
030import java.util.*;
031
032public class Row extends HashMap<String, Object> implements ModifyAttrsRecord {
033
034    private static final Object[] NULL_ARGS = new Object[0];
035
036    //主键,多个主键用英文逗号隔开
037    private RowKey[] primaryKeys;
038
039    public static Row of(String key, Object value) {
040        Row row = new Row();
041        return row.set(key, value);
042    }
043
044
045    private Set<String> modifyAttrs = new LinkedHashSet<>();
046
047    @Override
048    public Set<String> getModifyAttrs() {
049        return modifyAttrs;
050    }
051
052
053    public static Row ofKey(String primaryKey, Object value) {
054        Row row = new Row();
055        String[] primaryKeyStrings = primaryKey.split(",");
056        row.primaryKeys = new RowKey[primaryKeyStrings.length];
057
058        for (int i = 0; i < primaryKeyStrings.length; i++) {
059            row.primaryKeys[i] = RowKey.of(primaryKeyStrings[i].trim());
060        }
061
062        if (primaryKeyStrings.length > 1 && !value.getClass().isArray()) {
063            throw new IllegalArgumentException("The type of \"" + value + "\" must be an array.");
064        }
065
066        if (primaryKeyStrings.length == 1) {
067            row.put(primaryKey.trim(), value);
068        } else {
069            Object[] values = (Object[]) value;
070            for (int i = 0; i < primaryKeyStrings.length; i++) {
071                row.put(primaryKeyStrings[i].trim(), values[i]);
072            }
073        }
074        return row;
075    }
076
077    public static Row ofKey(RowKey... rowKeys) {
078        Row row = new Row();
079        row.primaryKeys = rowKeys;
080        return row;
081    }
082
083
084    public static Row ofKey(RowKey rowKey, Object value) {
085        Row row = new Row();
086        row.primaryKeys = new RowKey[]{rowKey};
087        row.put(rowKey.keyColumn, value);
088        return row;
089    }
090
091
092    public static Row ofKey(RowKey[] rowKeys, Object[] value) {
093        Row row = new Row();
094        row.primaryKeys = rowKeys;
095        for (int i = 0; i < rowKeys.length; i++) {
096            row.put(rowKeys[i].keyColumn, value[i]);
097        }
098        return row;
099    }
100
101
102    public Row set(String column, Object value) {
103        if (StringUtil.isBlank(column)) {
104            throw new IllegalArgumentException("key column not be null or empty.");
105        }
106
107        SqlUtil.keepColumnSafely(column);
108
109        put(column, value);
110
111        boolean isPrimaryKey = false;
112        if (this.primaryKeys != null) {
113            for (RowKey rowKey : primaryKeys) {
114                if (rowKey.getKeyColumn().equals(column)) {
115                    isPrimaryKey = true;
116                    break;
117                }
118            }
119        }
120
121        if (!isPrimaryKey) {
122            addModifyAttr(column);
123        }
124
125        return this;
126    }
127
128    public Row set(QueryColumn queryColumn, Object value) {
129        return set(queryColumn.getName(), value);
130    }
131
132
133    public Object get(String key, Object defaultValue) {
134        Object result = super.get(key);
135        return result != null ? result : defaultValue;
136    }
137
138
139    public String getString(String key) {
140        Object s = super.get(key);
141        return s != null ? s.toString() : null;
142    }
143
144
145    public String getString(String key, String defaultValue) {
146        Object s = super.get(key);
147        if (s == null) {
148            return defaultValue;
149        }
150        String r = s.toString();
151        return r.trim().length() == 0 ? defaultValue : r;
152    }
153
154    public Integer getInt(String key) {
155        return ConvertUtil.toInt(super.get(key));
156    }
157
158    public Integer getInt(String key, Integer defaultValue) {
159        Integer r = ConvertUtil.toInt(super.get(key));
160        return r != null ? r : defaultValue;
161    }
162
163    public Long getLong(String key) {
164        return ConvertUtil.toLong(super.get(key));
165    }
166
167    public Long getLong(String key, Long defaultValue) {
168        Long r = ConvertUtil.toLong(super.get(key));
169        return r != null ? r : defaultValue;
170    }
171
172    public Double getDouble(String key) {
173        return ConvertUtil.toDouble(super.get(key));
174    }
175
176    public Double getDouble(String key, Double defaultValue) {
177        Double r = ConvertUtil.toDouble(super.get(key));
178        return r != null ? r : defaultValue;
179    }
180
181
182    public Float getFloat(String key, Float defaultValue) {
183        Float r = ConvertUtil.toFloat(super.get(key));
184        return r != null ? r : defaultValue;
185    }
186
187    public Float getFloat(String key) {
188        return ConvertUtil.toFloat(super.get(key));
189    }
190
191
192    public Short getShort(String key, Short defaultValue) {
193        Short r = ConvertUtil.toShort(super.get(key));
194        return r != null ? r : defaultValue;
195    }
196
197    public Short getShort(String key) {
198        return ConvertUtil.toShort(super.get(key));
199    }
200
201    public BigInteger getBigInteger(String key) {
202        return ConvertUtil.toBigInteger(super.get(key));
203    }
204
205    public BigInteger getBigInteger(String key, BigInteger defaultValue) {
206        BigInteger r = ConvertUtil.toBigInteger(super.get(key));
207        return r != null ? r : defaultValue;
208    }
209
210    public BigDecimal getBigDecimal(String key) {
211        return ConvertUtil.toBigDecimal(super.get(key));
212    }
213
214    public BigDecimal getBigDecimal(String key, BigDecimal defaultValue) {
215        BigDecimal r = ConvertUtil.toBigDecimal(super.get(key));
216        return r != null ? r : defaultValue;
217    }
218
219    public Boolean getBoolean(String key) {
220        return ConvertUtil.toBoolean(super.get(key));
221    }
222
223    public Boolean getBoolean(String key, Boolean defaultValue) {
224        Boolean r = ConvertUtil.toBoolean(super.get(key));
225        return r != null ? r : defaultValue;
226    }
227
228    public Date getDate(String key) {
229        return ConvertUtil.toDate(super.get(key));
230    }
231
232    public Date getDate(String key, Date defaultValue) {
233        Date r = ConvertUtil.toDate(super.get(key));
234        return r != null ? r : defaultValue;
235    }
236
237    public LocalDateTime getLocalDateTime(String key) {
238        return ConvertUtil.toLocalDateTime(super.get(key));
239    }
240
241    public LocalDateTime getLocalDateTime(String key, LocalDateTime defaultValue) {
242        LocalDateTime r = ConvertUtil.toLocalDateTime(super.get(key));
243        return r != null ? r : defaultValue;
244    }
245
246    public Time getTime(String key) {
247        return (Time) super.get(key);
248    }
249
250    public Time getTime(String key, Time defaultValue) {
251        Time r = (Time) super.get(key);
252        return r != null ? r : defaultValue;
253    }
254
255    public Timestamp getTimestamp(String key) {
256        return (Timestamp) super.get(key);
257    }
258
259    public Timestamp getTimestamp(String key, Timestamp defaultValue) {
260        Timestamp r = (Timestamp) super.get(key);
261        return r != null ? r : defaultValue;
262    }
263
264    public Byte getByte(String key) {
265        return ConvertUtil.toByte(super.get(key));
266    }
267
268    public byte[] getBytes(String key) {
269        return (byte[]) super.get(key);
270    }
271
272    @Override
273    public Object remove(Object key) {
274        removeModifyAttr(key.toString());
275        return super.remove(key);
276    }
277
278    public <T> T toEntity(Class<T> entityClass) {
279        return RowUtil.toEntity(this, entityClass);
280    }
281
282    public <T> T toObject(Class<T> objectClass) {
283        return RowUtil.toObject(this, objectClass);
284    }
285
286    public Map<String, Object> toCamelKeysMap() {
287        Map<String, Object> ret = new HashMap<>();
288        for (String key : keySet()) {
289            ret.put(StringUtil.underlineToCamel(key), get(key));
290        }
291        return ret;
292    }
293
294    public Map<String, Object> toUnderlineKeysMap() {
295        Map<String, Object> ret = new HashMap<>();
296        for (String key : keySet()) {
297            ret.put(StringUtil.camelToUnderline(key), get(key));
298        }
299        return ret;
300    }
301
302
303    void keepModifyAttrs(Collection<String> attrs) {
304        if (attrs == null) {
305            throw new NullPointerException("attrs is null.");
306        }
307        clearModifyFlag();
308        modifyAttrs.addAll(attrs);
309    }
310
311    /**
312     * 获取修改的值,值需要保持顺序,返回的内容不包含主键的值
313     */
314    Object[] obtainModifyValues() {
315        Object[] values = new Object[modifyAttrs.size()];
316        int index = 0;
317        for (String modifyAttr : modifyAttrs) {
318            values[index++] = get(modifyAttr);
319        }
320        return values;
321    }
322
323
324    String[] obtainsPrimaryKeyStrings() {
325        String[] returnKeys = new String[primaryKeys.length];
326        for (int i = 0; i < primaryKeys.length; i++) {
327            returnKeys[i] = primaryKeys[i].keyColumn;
328        }
329        return returnKeys;
330    }
331
332
333    RowKey[] obtainsPrimaryKeys() {
334        return this.primaryKeys;
335    }
336
337
338    Object[] obtainsPrimaryValues() {
339        if (ArrayUtil.isEmpty(primaryKeys)) {
340            return NULL_ARGS;
341        }
342        Object[] values = new Object[primaryKeys.length];
343        for (int i = 0; i < primaryKeys.length; i++) {
344            values[i] = get(primaryKeys[i].keyColumn);
345        }
346        return values;
347    }
348
349
350    Object[] obtainAllModifyValues() {
351        return ArrayUtil.concat(obtainModifyValues(), obtainsPrimaryValues());
352    }
353
354
355}