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 LinkedHashMap<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
110        super.put(column, value);
111
112        boolean isPrimaryKey = false;
113        if (this.primaryKeys != null) {
114            for (RowKey rowKey : primaryKeys) {
115                if (rowKey.getKeyColumn().equals(column)) {
116                    isPrimaryKey = true;
117                    break;
118                }
119            }
120        }
121
122        if (!isPrimaryKey) {
123            addModifyAttr(column);
124        }
125
126        return this;
127    }
128
129    public Row set(QueryColumn queryColumn, Object value) {
130        return set(queryColumn.getName(), value);
131    }
132
133
134    public Object get(String key, Object defaultValue) {
135        Object result = super.get(key);
136        return result != null ? result : defaultValue;
137    }
138
139
140    @Override
141    public Object put(String key, Object value) {
142        if (!containsKey(key)) {
143            return super.put(key, value);
144        } else {
145            for (int i = 1; i < 100; i++) {
146                String newKey = key + RowUtil.INDEX_SEPARATOR + 1;
147                if (!containsKey(newKey)) {
148                    return super.put(newKey, value);
149                }
150            }
151        }
152        return super.put(key, value);
153    }
154
155
156    public String getString(String key) {
157        Object s = super.get(key);
158        return s != null ? s.toString() : null;
159    }
160
161
162    public String getString(String key, String defaultValue) {
163        Object s = super.get(key);
164        if (s == null) {
165            return defaultValue;
166        }
167        String r = s.toString();
168        return r.trim().length() == 0 ? defaultValue : r;
169    }
170
171    public Integer getInt(String key) {
172        return ConvertUtil.toInt(super.get(key));
173    }
174
175    public Integer getInt(String key, Integer defaultValue) {
176        Integer r = ConvertUtil.toInt(super.get(key));
177        return r != null ? r : defaultValue;
178    }
179
180    public Long getLong(String key) {
181        return ConvertUtil.toLong(super.get(key));
182    }
183
184    public Long getLong(String key, Long defaultValue) {
185        Long r = ConvertUtil.toLong(super.get(key));
186        return r != null ? r : defaultValue;
187    }
188
189    public Double getDouble(String key) {
190        return ConvertUtil.toDouble(super.get(key));
191    }
192
193    public Double getDouble(String key, Double defaultValue) {
194        Double r = ConvertUtil.toDouble(super.get(key));
195        return r != null ? r : defaultValue;
196    }
197
198
199    public Float getFloat(String key, Float defaultValue) {
200        Float r = ConvertUtil.toFloat(super.get(key));
201        return r != null ? r : defaultValue;
202    }
203
204    public Float getFloat(String key) {
205        return ConvertUtil.toFloat(super.get(key));
206    }
207
208
209    public Short getShort(String key, Short defaultValue) {
210        Short r = ConvertUtil.toShort(super.get(key));
211        return r != null ? r : defaultValue;
212    }
213
214    public Short getShort(String key) {
215        return ConvertUtil.toShort(super.get(key));
216    }
217
218    public BigInteger getBigInteger(String key) {
219        return ConvertUtil.toBigInteger(super.get(key));
220    }
221
222    public BigInteger getBigInteger(String key, BigInteger defaultValue) {
223        BigInteger r = ConvertUtil.toBigInteger(super.get(key));
224        return r != null ? r : defaultValue;
225    }
226
227    public BigDecimal getBigDecimal(String key) {
228        return ConvertUtil.toBigDecimal(super.get(key));
229    }
230
231    public BigDecimal getBigDecimal(String key, BigDecimal defaultValue) {
232        BigDecimal r = ConvertUtil.toBigDecimal(super.get(key));
233        return r != null ? r : defaultValue;
234    }
235
236    public Boolean getBoolean(String key) {
237        return ConvertUtil.toBoolean(super.get(key));
238    }
239
240    public Boolean getBoolean(String key, Boolean defaultValue) {
241        Boolean r = ConvertUtil.toBoolean(super.get(key));
242        return r != null ? r : defaultValue;
243    }
244
245    public Date getDate(String key) {
246        return ConvertUtil.toDate(super.get(key));
247    }
248
249    public Date getDate(String key, Date defaultValue) {
250        Date r = ConvertUtil.toDate(super.get(key));
251        return r != null ? r : defaultValue;
252    }
253
254    public LocalDateTime getLocalDateTime(String key) {
255        return ConvertUtil.toLocalDateTime(super.get(key));
256    }
257
258    public LocalDateTime getLocalDateTime(String key, LocalDateTime defaultValue) {
259        LocalDateTime r = ConvertUtil.toLocalDateTime(super.get(key));
260        return r != null ? r : defaultValue;
261    }
262
263    public Time getTime(String key) {
264        return (Time) super.get(key);
265    }
266
267    public Time getTime(String key, Time defaultValue) {
268        Time r = (Time) super.get(key);
269        return r != null ? r : defaultValue;
270    }
271
272    public Timestamp getTimestamp(String key) {
273        return (Timestamp) super.get(key);
274    }
275
276    public Timestamp getTimestamp(String key, Timestamp defaultValue) {
277        Timestamp r = (Timestamp) super.get(key);
278        return r != null ? r : defaultValue;
279    }
280
281    public Byte getByte(String key) {
282        return ConvertUtil.toByte(super.get(key));
283    }
284
285    public byte[] getBytes(String key) {
286        return (byte[]) super.get(key);
287    }
288
289    @Override
290    public Object remove(Object key) {
291        removeModifyAttr(key.toString());
292        return super.remove(key);
293    }
294
295    public <T> T toEntity(Class<T> entityClass) {
296        return RowUtil.toEntity(this, entityClass);
297    }
298
299    public <T> T toObject(Class<T> objectClass) {
300        return RowUtil.toObject(this, objectClass);
301    }
302
303    public Map<String, Object> toCamelKeysMap() {
304        Map<String, Object> ret = new HashMap<>();
305        for (String key : keySet()) {
306            ret.put(StringUtil.underlineToCamel(key), get(key));
307        }
308        return ret;
309    }
310
311    public Map<String, Object> toUnderlineKeysMap() {
312        Map<String, Object> ret = new HashMap<>();
313        for (String key : keySet()) {
314            ret.put(StringUtil.camelToUnderline(key), get(key));
315        }
316        return ret;
317    }
318
319
320    void keepModifyAttrs(Collection<String> attrs) {
321        if (attrs == null) {
322            throw new NullPointerException("attrs is null.");
323        }
324        clearModifyFlag();
325        modifyAttrs.addAll(attrs);
326    }
327
328    /**
329     * 获取修改的值,值需要保持顺序,返回的内容不包含主键的值
330     */
331    Object[] obtainModifyValues() {
332        Object[] values = new Object[modifyAttrs.size()];
333        int index = 0;
334        for (String modifyAttr : modifyAttrs) {
335            values[index++] = get(modifyAttr);
336        }
337        return values;
338    }
339
340
341    String[] obtainsPrimaryKeyStrings() {
342        String[] returnKeys = new String[primaryKeys.length];
343        for (int i = 0; i < primaryKeys.length; i++) {
344            returnKeys[i] = primaryKeys[i].keyColumn;
345        }
346        return returnKeys;
347    }
348
349
350    RowKey[] obtainsPrimaryKeys() {
351        return this.primaryKeys;
352    }
353
354
355    Object[] obtainsPrimaryValues() {
356        if (ArrayUtil.isEmpty(primaryKeys)) {
357            return NULL_ARGS;
358        }
359        Object[] values = new Object[primaryKeys.length];
360        for (int i = 0; i < primaryKeys.length; i++) {
361            values[i] = get(primaryKeys[i].keyColumn);
362        }
363        return values;
364    }
365
366
367    Object[] obtainAllModifyValues() {
368        return ArrayUtil.concat(obtainModifyValues(), obtainsPrimaryValues());
369    }
370
371
372
373}