001/** 002 * Copyright (c) 2025-2026, Michael Yang 杨福海 (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.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.gnu.org/licenses/lgpl-3.0.txt 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 dev.tinyflow.core.util; 017 018import com.alibaba.fastjson.JSON; 019import com.alibaba.fastjson.serializer.SerializerFeature; 020 021import java.lang.reflect.Array; 022import java.util.Collection; 023import java.util.HashMap; 024import java.util.Map; 025import java.util.function.Function; 026 027public class Maps extends HashMap<String, Object> { 028 029 public static Maps of() { 030 return new Maps(); 031 } 032 033 public static Maps of(String key, Object value) { 034 Maps maps = Maps.of(); 035 maps.put(key, value); 036 return maps; 037 } 038 039 public static Maps ofNotNull(String key, Object value) { 040 return new Maps().setIfNotNull(key, value); 041 } 042 043 public static Maps ofNotEmpty(String key, Object value) { 044 return new Maps().setIfNotEmpty(key, value); 045 } 046 047 public static Maps ofNotEmpty(String key, Maps value) { 048 return new Maps().setIfNotEmpty(key, value); 049 } 050 051 052 public Maps set(String key, Object value) { 053 super.put(key, value); 054 return this; 055 } 056 057 public Maps setChild(String key, Object value) { 058 if (key.contains(".")) { 059 String[] keys = key.split("\\."); 060 Map<String, Object> currentMap = this; 061 for (int i = 0; i < keys.length; i++) { 062 String currentKey = keys[i].trim(); 063 if (currentKey.isEmpty()) { 064 continue; 065 } 066 if (i == keys.length - 1) { 067 currentMap.put(currentKey, value); 068 } else { 069 //noinspection unchecked 070 currentMap = (Map<String, Object>) currentMap.computeIfAbsent(currentKey, k -> Maps.of()); 071 } 072 } 073 } else { 074 super.put(key, value); 075 } 076 077 return this; 078 } 079 080 public Maps setOrDefault(String key, Object value, Object orDefault) { 081 if (isNullOrEmpty(value)) { 082 return this.set(key, orDefault); 083 } else { 084 return this.set(key, value); 085 } 086 } 087 088 public Maps setIf(boolean condition, String key, Object value) { 089 if (condition) put(key, value); 090 return this; 091 } 092 093 public Maps setIf(Function<Maps, Boolean> func, String key, Object value) { 094 if (func.apply(this)) put(key, value); 095 return this; 096 } 097 098 public Maps setIfNotNull(String key, Object value) { 099 if (value != null) put(key, value); 100 return this; 101 } 102 103 public Maps setIfNotEmpty(String key, Object value) { 104 if (!isNullOrEmpty(value)) { 105 put(key, value); 106 } 107 return this; 108 } 109 110 public Maps setIfNotEmpty(Map<String, Object> source) { 111 if (!isNullOrEmpty(source)) { 112 this.putAll(source); 113 } 114 return this; 115 } 116 117 118 public Maps setIfContainsKey(String checkKey, String key, Object value) { 119 if (this.containsKey(checkKey)) { 120 this.put(key, value); 121 } 122 return this; 123 } 124 125 public Maps setIfNotContainsKey(String checkKey, String key, Object value) { 126 if (!this.containsKey(checkKey)) { 127 this.put(key, value); 128 } 129 return this; 130 } 131 132 public String toJSON() { 133 return JSON.toJSONString(this, SerializerFeature.DisableCircularReferenceDetect); 134 } 135 136 137 private static boolean isNullOrEmpty(Object value) { 138 if (value == null) { 139 return true; 140 } 141 142 if (value instanceof Collection && ((Collection<?>) value).isEmpty()) { 143 return true; 144 } 145 146 if (value instanceof Map && ((Map<?, ?>) value).isEmpty()) { 147 return true; 148 } 149 150 if (value.getClass().isArray() && Array.getLength(value) == 0) { 151 return true; 152 } 153 154 return value instanceof String && ((String) value).trim().isEmpty(); 155 } 156}