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.*; 025 026import java.math.BigDecimal; 027import java.math.BigInteger; 028import java.sql.Time; 029import java.sql.Timestamp; 030import java.time.LocalDateTime; 031import java.util.*; 032import java.util.function.BooleanSupplier; 033import java.util.function.Predicate; 034 035public class Row extends LinkedHashMap<String, Object> implements UpdateWrapper<Row> { 036 037 //主键,多个主键用英文逗号隔开 038 private Set<RowKey> primaryKeys; 039 040 public static Row of(String key, Object value) { 041 Row row = new Row(); 042 return row.set(key, value); 043 } 044 045 @Override 046 public Map<String, Object> getUpdates() { 047 return this; 048 } 049 050 public static Row ofKey(String primaryKey, Object value) { 051 Row row = new Row(); 052 String[] primaryKeyStrings = primaryKey.split(","); 053 row.primaryKeys = new HashSet<>(primaryKeyStrings.length); 054 055 for (String primaryKeyString : primaryKeyStrings) { 056 row.primaryKeys.add(RowKey.of(primaryKeyString.trim())); 057 } 058 059 if (primaryKeyStrings.length > 1 && !value.getClass().isArray()) { 060 throw new IllegalArgumentException("The type of \"" + value + "\" must be an array."); 061 } 062 063 if (primaryKeyStrings.length == 1) { 064 row.put(primaryKey.trim(), value); 065 } else { 066 Object[] values = (Object[]) value; 067 for (int i = 0; i < primaryKeyStrings.length; i++) { 068 row.put(primaryKeyStrings[i].trim(), values[i]); 069 } 070 } 071 return row; 072 } 073 074 public static Row ofKey(RowKey... rowKeys) { 075 Row row = new Row(); 076 row.getPrimaryKeys().addAll(Arrays.asList(rowKeys)); 077 return row; 078 } 079 080 081 public static Row ofKey(RowKey rowKey, Object value) { 082 Row row = new Row(); 083 row.getPrimaryKeys().add(rowKey); 084 row.put(rowKey.keyColumn, value); 085 return row; 086 } 087 088 089 public static Row ofKey(RowKey[] rowKeys, Object[] value) { 090 Row row = new Row(); 091 row.getPrimaryKeys().addAll(Arrays.asList(rowKeys)); 092 for (int i = 0; i < rowKeys.length; i++) { 093 row.put(rowKeys[i].keyColumn, value[i]); 094 } 095 return row; 096 } 097 098 @Override 099 public Row set(String property, Object value, boolean isEffective) { 100 if (!isEffective) { 101 return this; 102 } 103 104 if (StringUtil.isBlank(property)) { 105 throw new IllegalArgumentException("key column not be null or empty."); 106 } 107 108 SqlUtil.keepColumnSafely(property); 109 110 if (value instanceof QueryWrapper || value instanceof QueryCondition || value instanceof QueryColumn) { 111 super.put(property, new RawValue(value)); 112 } else { 113 super.put(property, value); 114 } 115 116 return this; 117 } 118 119 @Override 120 public Row set(QueryColumn property, Object value, boolean isEffective) { 121 if (!isEffective) { 122 return this; 123 } 124 125 if (value instanceof QueryWrapper || value instanceof QueryCondition || value instanceof QueryColumn) { 126 super.put(property.getName(), new RawValue(value)); 127 } else { 128 super.put(property.getName(), value); 129 } 130 131 return this; 132 } 133 134 @Override 135 public <T> Row set(LambdaGetter<T> property, Object value, boolean isEffective) { 136 if (!isEffective) { 137 return this; 138 } 139 140 if (value instanceof QueryWrapper || value instanceof QueryCondition || value instanceof QueryColumn) { 141 super.put(LambdaUtil.getFieldName(property), new RawValue(value)); 142 } else { 143 super.put(LambdaUtil.getFieldName(property), value); 144 } 145 146 return this; 147 } 148 149 @Override 150 public Row setRaw(String property, Object value, boolean isEffective) { 151 return (Row) UpdateWrapper.super.setRaw(property, value, isEffective); 152 } 153 154 @Override 155 public Row setRaw(QueryColumn property, Object value, boolean isEffective) { 156 return (Row) UpdateWrapper.super.setRaw(property, value, isEffective); 157 } 158 159 @Override 160 public <T> Row setRaw(LambdaGetter<T> property, Object value, boolean isEffective) { 161 return (Row) UpdateWrapper.super.setRaw(property, value, isEffective); 162 } 163 164 165 @Override 166 public Row set(String property, Object value) { 167 return set(property, value, true); 168 } 169 170 @Override 171 public Row set(String property, Object value, BooleanSupplier isEffective) { 172 return set(property, value, isEffective.getAsBoolean()); 173 } 174 175 @Override 176 public <V> Row set(String property, V value, Predicate<V> isEffective) { 177 return set(property, value, isEffective.test(value)); 178 } 179 180 @Override 181 public Row set(QueryColumn property, Object value) { 182 return set(property, value, true); 183 } 184 185 @Override 186 public Row set(QueryColumn property, Object value, BooleanSupplier isEffective) { 187 return set(property, value, isEffective.getAsBoolean()); 188 } 189 190 @Override 191 public <V> Row set(QueryColumn property, V value, Predicate<V> isEffective) { 192 return set(property, value, isEffective.test(value)); 193 } 194 195 @Override 196 public <T> Row set(LambdaGetter<T> property, Object value) { 197 return set(property, value, true); 198 } 199 200 @Override 201 public <T> Row set(LambdaGetter<T> property, Object value, BooleanSupplier isEffective) { 202 return set(property, value, isEffective.getAsBoolean()); 203 } 204 205 @Override 206 public <T, V> Row set(LambdaGetter<T> property, V value, Predicate<V> isEffective) { 207 return set(property, value, isEffective.test(value)); 208 } 209 210 @Override 211 public Row setRaw(String property, Object value) { 212 return setRaw(property, value, true); 213 } 214 215 @Override 216 public Row setRaw(String property, Object value, BooleanSupplier isEffective) { 217 return setRaw(property, value, isEffective.getAsBoolean()); 218 } 219 220 @Override 221 public <V> Row setRaw(String property, V value, Predicate<V> isEffective) { 222 return setRaw(property, value, isEffective.test(value)); 223 } 224 225 @Override 226 public Row setRaw(QueryColumn property, Object value) { 227 return setRaw(property, value, true); 228 } 229 230 @Override 231 public Row setRaw(QueryColumn property, Object value, BooleanSupplier isEffective) { 232 return setRaw(property, value, isEffective.getAsBoolean()); 233 } 234 235 @Override 236 public <V> Row setRaw(QueryColumn property, V value, Predicate<V> isEffective) { 237 return setRaw(property, value, isEffective.test(value)); 238 } 239 240 @Override 241 public <T> Row setRaw(LambdaGetter<T> property, Object value) { 242 return setRaw(property, value, true); 243 } 244 245 @Override 246 public <T> Row setRaw(LambdaGetter<T> property, Object value, BooleanSupplier isEffective) { 247 return setRaw(property, value, isEffective.getAsBoolean()); 248 } 249 250 @Override 251 public <T, V> Row setRaw(LambdaGetter<T> property, V value, Predicate<V> isEffective) { 252 return setRaw(property, value, isEffective.test(value)); 253 } 254 255 public Object get(String key, Object defaultValue) { 256 Object result = super.get(key); 257 return result != null ? result : defaultValue; 258 } 259 260 public Object getIgnoreCase(String key) { 261 String camelKey = null; 262 if (key.contains("_")) { 263 camelKey = StringUtil.deleteChar(key, '_'); 264 } 265 for (String innerKey : keySet()) { 266 if (innerKey.equalsIgnoreCase(key) || (camelKey != null && camelKey.equalsIgnoreCase(innerKey))) { 267 return super.get(innerKey); 268 } 269 } 270 return null; 271 } 272 273 274 public Object getIgnoreCase(String key, Object defaultValue) { 275 Object result = getIgnoreCase(key); 276 return result != null ? result : defaultValue; 277 } 278 279 280 @Override 281 public Object put(String key, Object value) { 282 if (!containsKey(key)) { 283 return super.put(key, value); 284 } else { 285 for (int i = 1; i < 100; i++) { 286 String newKey = key + RowUtil.INDEX_SEPARATOR + 1; 287 if (!containsKey(newKey)) { 288 return super.put(newKey, value); 289 } 290 } 291 } 292 return super.put(key, value); 293 } 294 295 296 public String getString(String key) { 297 Object s = super.get(key); 298 return s != null ? s.toString() : null; 299 } 300 301 302 public String getString(String key, String defaultValue) { 303 Object s = super.get(key); 304 if (s == null) { 305 return defaultValue; 306 } 307 String r = s.toString(); 308 return r.trim().length() == 0 ? defaultValue : r; 309 } 310 311 public Integer getInt(String key) { 312 return ConvertUtil.toInt(super.get(key)); 313 } 314 315 public Integer getInt(String key, Integer defaultValue) { 316 Integer r = ConvertUtil.toInt(super.get(key)); 317 return r != null ? r : defaultValue; 318 } 319 320 public Long getLong(String key) { 321 return ConvertUtil.toLong(super.get(key)); 322 } 323 324 public Long getLong(String key, Long defaultValue) { 325 Long r = ConvertUtil.toLong(super.get(key)); 326 return r != null ? r : defaultValue; 327 } 328 329 public Double getDouble(String key) { 330 return ConvertUtil.toDouble(super.get(key)); 331 } 332 333 public Double getDouble(String key, Double defaultValue) { 334 Double r = ConvertUtil.toDouble(super.get(key)); 335 return r != null ? r : defaultValue; 336 } 337 338 public Float getFloat(String key, Float defaultValue) { 339 Float r = ConvertUtil.toFloat(super.get(key)); 340 return r != null ? r : defaultValue; 341 } 342 343 public Float getFloat(String key) { 344 return ConvertUtil.toFloat(super.get(key)); 345 } 346 347 348 public Short getShort(String key, Short defaultValue) { 349 Short r = ConvertUtil.toShort(super.get(key)); 350 return r != null ? r : defaultValue; 351 } 352 353 public Short getShort(String key) { 354 return ConvertUtil.toShort(super.get(key)); 355 } 356 357 public BigInteger getBigInteger(String key) { 358 return ConvertUtil.toBigInteger(super.get(key)); 359 } 360 361 public BigInteger getBigInteger(String key, BigInteger defaultValue) { 362 BigInteger r = ConvertUtil.toBigInteger(super.get(key)); 363 return r != null ? r : defaultValue; 364 } 365 366 public BigDecimal getBigDecimal(String key) { 367 return ConvertUtil.toBigDecimal(super.get(key)); 368 } 369 370 public BigDecimal getBigDecimal(String key, BigDecimal defaultValue) { 371 BigDecimal r = ConvertUtil.toBigDecimal(super.get(key)); 372 return r != null ? r : defaultValue; 373 } 374 375 public Boolean getBoolean(String key) { 376 return ConvertUtil.toBoolean(super.get(key)); 377 } 378 379 public Boolean getBoolean(String key, Boolean defaultValue) { 380 Boolean r = ConvertUtil.toBoolean(super.get(key)); 381 return r != null ? r : defaultValue; 382 } 383 384 public Date getDate(String key) { 385 return ConvertUtil.toDate(super.get(key)); 386 } 387 388 public Date getDate(String key, Date defaultValue) { 389 Date r = ConvertUtil.toDate(super.get(key)); 390 return r != null ? r : defaultValue; 391 } 392 393 public LocalDateTime getLocalDateTime(String key) { 394 return ConvertUtil.toLocalDateTime(super.get(key)); 395 } 396 397 public LocalDateTime getLocalDateTime(String key, LocalDateTime defaultValue) { 398 LocalDateTime r = ConvertUtil.toLocalDateTime(super.get(key)); 399 return r != null ? r : defaultValue; 400 } 401 402 public Time getTime(String key) { 403 return (Time) super.get(key); 404 } 405 406 public Time getTime(String key, Time defaultValue) { 407 Time r = (Time) super.get(key); 408 return r != null ? r : defaultValue; 409 } 410 411 public Timestamp getTimestamp(String key) { 412 return (Timestamp) super.get(key); 413 } 414 415 public Timestamp getTimestamp(String key, Timestamp defaultValue) { 416 Timestamp r = (Timestamp) super.get(key); 417 return r != null ? r : defaultValue; 418 } 419 420 public Byte getByte(String key) { 421 return ConvertUtil.toByte(super.get(key)); 422 } 423 424 public byte[] getBytes(String key) { 425 return (byte[]) super.get(key); 426 } 427 428 @Override 429 public Object remove(Object key) { 430 for (String innerKey : keySet()) { 431 if (innerKey.equalsIgnoreCase((String) key)) { 432 return super.remove(innerKey); 433 } 434 } 435 return null; 436 } 437 438 public <T> T toEntity(Class<T> entityClass) { 439 return RowUtil.toEntity(this, entityClass); 440 } 441 442 public <T> T toObject(Class<T> objectClass) { 443 return RowUtil.toObject(this, objectClass); 444 } 445 446 public Map<String, Object> toCamelKeysMap() { 447 Map<String, Object> ret = new HashMap<>(); 448 for (String key : keySet()) { 449 ret.put(StringUtil.underlineToCamel(key), get(key)); 450 } 451 return ret; 452 } 453 454 public Map<String, Object> toUnderlineKeysMap() { 455 Map<String, Object> ret = new HashMap<>(); 456 for (String key : keySet()) { 457 ret.put(StringUtil.camelToUnderline(key), get(key)); 458 } 459 return ret; 460 } 461 462 public Set<RowKey> getPrimaryKeys() { 463 if (primaryKeys == null) { 464 primaryKeys = new HashSet<>(); 465 } 466 return primaryKeys; 467 } 468 469 public void setPrimaryKeys(Set<RowKey> primaryKeys) { 470 this.primaryKeys = primaryKeys; 471 } 472 473 public void keep(String... columns) { 474 entrySet().removeIf(entry -> !ArrayUtil.contains(columns, entry.getKey())); 475 } 476 477 478 public void keep(Set<String> columns) { 479 entrySet().removeIf(entry -> !columns.contains(entry.getKey())); 480 } 481 482 483 Set<String> getModifyAttrs() { 484 int pkCount = primaryKeys != null ? primaryKeys.size() : 0; 485 if (pkCount == 0) { 486 return keySet(); 487 } 488 489 Set<String> attrs = new LinkedHashSet<>(keySet()); 490 attrs.removeIf(this::isPk); 491 return attrs; 492 } 493 494 Map<String, RawValue> getRawValueMap() { 495 Map<String, RawValue> map = new HashMap<>(); 496 forEach((s, o) -> { 497 if (o instanceof RawValue) { 498 map.put(s, (RawValue) o); 499 } 500 }); 501 return map; 502 } 503 504 505 /** 506 * 获取修改的值,值需要保持顺序,返回的内容不包含主键的值 507 */ 508 Object[] obtainModifyValuesWithoutPk() { 509 List<Object> values = new ArrayList<>(); 510 for (String key : keySet()) { 511 Object value = get(key); 512 if (!isPk(key) && !(value instanceof RawValue)) { 513 values.add(value); 514 } 515 } 516 return values.toArray(); 517 } 518 519 520 String[] obtainsPrimaryKeyStrings() { 521 String[] returnKeys = new String[primaryKeys.size()]; 522 int index = 0; 523 for (RowKey primaryKey : primaryKeys) { 524 returnKeys[index++] = primaryKey.keyColumn; 525 } 526 return returnKeys; 527 } 528 529 530 RowKey[] obtainsPrimaryKeys() { 531 return getPrimaryKeys().toArray(new RowKey[0]); 532 } 533 534 535 Object[] obtainsPrimaryValues() { 536 if (CollectionUtil.isEmpty(primaryKeys)) { 537 return FlexConsts.EMPTY_ARRAY; 538 } 539 Object[] values = new Object[primaryKeys.size()]; 540 541 int index = 0; 542 for (RowKey primaryKey : primaryKeys) { 543 values[index++] = get(primaryKey.keyColumn); 544 } 545 return values; 546 } 547 548 549 Object[] obtainAllModifyValues() { 550 return ArrayUtil.concat(obtainModifyValuesWithoutPk(), obtainsPrimaryValues()); 551 } 552 553 554 public Object[] obtainInsertValues() { 555 List<Object> values = new ArrayList<>(); 556 if (primaryKeys != null && !primaryKeys.isEmpty()) { 557 for (RowKey primaryKey : primaryKeys) { 558 if (primaryKey.before) { 559 values.add(get(primaryKey.keyColumn)); 560 } 561 } 562 } 563 564 for (String key : keySet()) { 565 Object value = get(key); 566 if (!isPk(key) && !(value instanceof RawValue)) { 567 values.add(value); 568 } 569 } 570 571 return values.toArray(); 572 } 573 574 public Set<String> getInsertAttrs() { 575 Set<String> attrs = new LinkedHashSet<>(); 576 if (primaryKeys != null && !primaryKeys.isEmpty()) { 577 for (RowKey primaryKey : primaryKeys) { 578 if (primaryKey.before) { 579 attrs.add(primaryKey.keyColumn); 580 } 581 } 582 } 583 attrs.addAll(keySet()); 584 return attrs; 585 } 586 587 private boolean isPk(String attr) { 588 if (primaryKeys != null && !primaryKeys.isEmpty()) { 589 for (RowKey primaryKey : primaryKeys) { 590 if (primaryKey.keyColumn.equalsIgnoreCase(attr)) { 591 return true; 592 } 593 } 594 } 595 return false; 596 } 597 598 599}