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