diff --git a/src/main/java/xyz/zhouxy/plusone/commons/base/IWithIntCode.java b/src/main/java/xyz/zhouxy/plusone/commons/base/IWithIntCode.java
index 480ab75..dcd9b03 100644
--- a/src/main/java/xyz/zhouxy/plusone/commons/base/IWithIntCode.java
+++ b/src/main/java/xyz/zhouxy/plusone/commons/base/IWithIntCode.java
@@ -16,15 +16,12 @@
package xyz.zhouxy.plusone.commons.base;
-import xyz.zhouxy.plusone.commons.exception.BaseException;
-
/**
* 规定实现类带有 {@code getCode} 方法。
* 用于像自定义异常等需要带有 {@code code} 字段的类,
* 方便其它地方的程序判断该类的是否实现了此接口,以此获取其实例的 {@code code} 字段的值。
*
* @author ZhouXY
- * @see BaseException
*/
public interface IWithIntCode {
int getCode();
diff --git a/src/main/java/xyz/zhouxy/plusone/commons/base/IWithLongCode.java b/src/main/java/xyz/zhouxy/plusone/commons/base/IWithLongCode.java
new file mode 100644
index 0000000..759ef21
--- /dev/null
+++ b/src/main/java/xyz/zhouxy/plusone/commons/base/IWithLongCode.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2022-2023 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package xyz.zhouxy.plusone.commons.base;
+
+/**
+ * 规定实现类带有 {@code getCode} 方法。
+ * 用于像自定义异常等需要带有 {@code code} 字段的类,
+ * 方便其它地方的程序判断该类的是否实现了此接口,以此获取其实例的 {@code code} 字段的值。
+ *
+ * @author ZhouXY
+ */
+public interface IWithLongCode {
+ long getCode();
+}
diff --git a/src/main/java/xyz/zhouxy/plusone/commons/collection/AbstractMapWrapper.java b/src/main/java/xyz/zhouxy/plusone/commons/collection/AbstractMapWrapper.java
index ca6f2f5..2ab3e56 100644
--- a/src/main/java/xyz/zhouxy/plusone/commons/collection/AbstractMapWrapper.java
+++ b/src/main/java/xyz/zhouxy/plusone/commons/collection/AbstractMapWrapper.java
@@ -22,6 +22,7 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -29,6 +30,8 @@ import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
+import xyz.zhouxy.plusone.commons.util.ConcurrentHashMapUtil;
+
@Beta
public abstract class AbstractMapWrapper> {
@@ -141,12 +144,12 @@ public abstract class AbstractMapWrapper mappingFunction) {
- V v = this.map.get(key);
- if (null == v) {
- this.map.putIfAbsent(key, mappingFunction.apply(key));
- v = this.map.get(key);
+ if (this.map instanceof ConcurrentHashMap) {
+ return ConcurrentHashMapUtil.computIfAbsent(
+ (ConcurrentHashMap) this.map, key, mappingFunction);
+ } else {
+ return this.map.computeIfAbsent(key, mappingFunction);
}
- return v;
}
public final Map exportMap() {
diff --git a/src/main/java/xyz/zhouxy/plusone/commons/collection/SafeConcurrentHashMap.java b/src/main/java/xyz/zhouxy/plusone/commons/collection/SafeConcurrentHashMap.java
index 97e01bb..100c05c 100644
--- a/src/main/java/xyz/zhouxy/plusone/commons/collection/SafeConcurrentHashMap.java
+++ b/src/main/java/xyz/zhouxy/plusone/commons/collection/SafeConcurrentHashMap.java
@@ -1,14 +1,30 @@
+/*
+ * Copyright 2022-2023 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package xyz.zhouxy.plusone.commons.collection;
import java.util.Map;
-import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import javax.annotation.concurrent.ThreadSafe;
-import xyz.zhouxy.plusone.commons.base.JRE;
+import xyz.zhouxy.plusone.commons.util.ConcurrentHashMapUtil;
+// TODO 添加文档注释
@ThreadSafe
public class SafeConcurrentHashMap extends ConcurrentHashMap {
@@ -86,27 +102,6 @@ public class SafeConcurrentHashMap extends ConcurrentHashMap {
/** {@inheritDoc} */
@Override
public V computeIfAbsent(K key, Function super K, ? extends V> mappingFunction) {
- Objects.requireNonNull(mappingFunction);
- if (JRE.isJava8()) {
- V v = get(key);
- if (null == v) {
- // this bug fix methods maybe cause `mappingFunction.apply` multiple calls.
- v = mappingFunction.apply(key);
- if (null == v) {
- return null;
- }
- final V res = putIfAbsent(key, v);
- if (null != res) {
- // if pre value present, means other thread put value already,
- // and putIfAbsent not effect
- // return exist value
- return res;
- }
- // if pre value is null, means putIfAbsent effected, return current value
- }
- return v;
- } else {
- return computeIfAbsent(key, mappingFunction);
- }
+ return ConcurrentHashMapUtil.computIfAbsent(this, key, mappingFunction);
}
}
diff --git a/src/main/java/xyz/zhouxy/plusone/commons/exception/BaseException.java b/src/main/java/xyz/zhouxy/plusone/commons/exception/BaseException.java
index 27bc36e..ae976d8 100644
--- a/src/main/java/xyz/zhouxy/plusone/commons/exception/BaseException.java
+++ b/src/main/java/xyz/zhouxy/plusone/commons/exception/BaseException.java
@@ -45,7 +45,7 @@ public abstract class BaseException extends RuntimeException implements IWithInt
}
@Override
- public int getCode() {
+ public final int getCode() {
return this.code;
}
}
diff --git a/src/main/java/xyz/zhouxy/plusone/commons/util/ConcurrentHashMapUtil.java b/src/main/java/xyz/zhouxy/plusone/commons/util/ConcurrentHashMapUtil.java
new file mode 100644
index 0000000..c5ca312
--- /dev/null
+++ b/src/main/java/xyz/zhouxy/plusone/commons/util/ConcurrentHashMapUtil.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2022-2023 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package xyz.zhouxy.plusone.commons.util;
+
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+
+import xyz.zhouxy.plusone.commons.base.JRE;
+
+public class ConcurrentHashMapUtil { // TODO 添加文档注释
+
+ public static V computIfAbsent(ConcurrentHashMap map, final K key, final Function super K, ? extends V> mappingFunction) {
+ if (JRE.isJava8()) {
+ Objects.requireNonNull(mappingFunction);
+ V v = map.get(key);
+ if (null == v) {
+ v = mappingFunction.apply(key);
+ if (null == v) {
+ return null;
+ }
+ final V res = map.putIfAbsent(key, v);
+ if (null != res) {
+ return res;
+ }
+ }
+ return v;
+ } else {
+ return map.computeIfAbsent(key, mappingFunction);
+ }
+ }
+
+ private ConcurrentHashMapUtil() {
+ throw new IllegalStateException("Utility class");
+ }
+}
diff --git a/src/main/java/xyz/zhouxy/plusone/commons/util/ErrorResult.java b/src/main/java/xyz/zhouxy/plusone/commons/util/ErrorResult.java
new file mode 100644
index 0000000..7ad1726
--- /dev/null
+++ b/src/main/java/xyz/zhouxy/plusone/commons/util/ErrorResult.java
@@ -0,0 +1,40 @@
+package xyz.zhouxy.plusone.commons.util;
+
+import com.google.common.base.Strings;
+
+import xyz.zhouxy.plusone.commons.base.IWithCode;
+
+/**
+ * 错误结果
+ *
+ * @author zhouxy
+ */
+final class ErrorResult extends UnifiedResponse {
+ private static final String DEFAULT_ERR_STATUS = "9999999";
+
+ ErrorResult(String message) {
+ super(DEFAULT_ERR_STATUS, message);
+ }
+
+ ErrorResult(String message, Object data) {
+ super(DEFAULT_ERR_STATUS, message, data);
+ }
+
+ ErrorResult(Object status, String message) {
+ super(status, message);
+ }
+
+ ErrorResult(Object status, String message, Object data) {
+ super(status, message, data);
+ }
+
+ ErrorResult(Object status, Throwable e) {
+ super(status, Strings.nullToEmpty(e.getMessage()));
+ }
+
+ > ErrorResult(E e) {
+ super(e.getCode(), Strings.nullToEmpty(e.getMessage()));
+ }
+
+ private static final long serialVersionUID = -1680792957826923092L;
+}
diff --git a/src/main/java/xyz/zhouxy/plusone/commons/util/OrdinaryResult.java b/src/main/java/xyz/zhouxy/plusone/commons/util/OrdinaryResult.java
new file mode 100644
index 0000000..0659cc0
--- /dev/null
+++ b/src/main/java/xyz/zhouxy/plusone/commons/util/OrdinaryResult.java
@@ -0,0 +1,19 @@
+package xyz.zhouxy.plusone.commons.util;
+
+/**
+ * 普通结果
+ *
+ * @author zhouxy
+ */
+final class OrdinaryResult extends UnifiedResponse {
+
+ OrdinaryResult(Object status, String message) {
+ super(status, message);
+ }
+
+ OrdinaryResult(Object status, String message, Object data) {
+ super(status, message, data);
+ }
+
+ private static final long serialVersionUID = -5794887914598566589L;
+}
diff --git a/src/main/java/xyz/zhouxy/plusone/commons/util/RegexUtil.java b/src/main/java/xyz/zhouxy/plusone/commons/util/RegexUtil.java
index b566a6e..e71e391 100644
--- a/src/main/java/xyz/zhouxy/plusone/commons/util/RegexUtil.java
+++ b/src/main/java/xyz/zhouxy/plusone/commons/util/RegexUtil.java
@@ -18,9 +18,11 @@ package xyz.zhouxy.plusone.commons.util;
import java.util.Arrays;
import java.util.Map;
+import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.google.common.base.Preconditions;
@@ -28,7 +30,7 @@ import com.google.common.base.Preconditions;
import xyz.zhouxy.plusone.commons.collection.SafeConcurrentHashMap;
/**
- * 封装一些常用的正则操作,并可以缓存 {@link Pattern} 实例以复用(最多缓存 256 个)。
+ * 封装一些常用的正则操作,并可以缓存 {@link Pattern} 实例以复用(最多缓存大概 256 个)。
*
* @author ZhouXY
*
@@ -37,8 +39,8 @@ public final class RegexUtil {
private static final int DEFAULT_CACHE_INITIAL_CAPACITY = 64;
private static final int MAX_CACHE_SIZE = 256;
- private static final Map PATTERN_CACHE = new SafeConcurrentHashMap<>(
- DEFAULT_CACHE_INITIAL_CAPACITY);
+ private static final Map PATTERN_CACHE
+ = new SafeConcurrentHashMap<>(DEFAULT_CACHE_INITIAL_CAPACITY);
/**
* 获取 {@link Pattern} 实例。
@@ -49,15 +51,7 @@ public final class RegexUtil {
*/
public static Pattern getPattern(final String pattern, final boolean cachePattern) {
Preconditions.checkNotNull(pattern, "The pattern can not be null.");
- Pattern result = PATTERN_CACHE.get(pattern);
- if (result == null) {
- result = Pattern.compile(pattern);
- if (cachePattern && PATTERN_CACHE.size() < MAX_CACHE_SIZE) {
- PATTERN_CACHE.putIfAbsent(pattern, result);
- result = PATTERN_CACHE.get(pattern);
- }
- }
- return result;
+ return cachePattern ? getAndCachePatternInternal(pattern) : getPatternInternal(pattern);
}
/**
@@ -68,11 +62,7 @@ public final class RegexUtil {
*/
public static Pattern getPattern(final String pattern) {
Preconditions.checkNotNull(pattern, "The pattern can not be null.");
- Pattern result = PATTERN_CACHE.get(pattern);
- if (result == null) {
- result = Pattern.compile(pattern);
- }
- return result;
+ return getPatternInternal(pattern);
}
/**
@@ -83,10 +73,11 @@ public final class RegexUtil {
* @return {@link Pattern} 实例数组
*/
public static Pattern[] getPatterns(final String[] patterns, final boolean cachePattern) {
- Preconditions.checkNotNull(patterns, "The patterns can not be null.");
- return Arrays.stream(patterns)
- .map(pattern -> getPattern(pattern, cachePattern))
- .toArray(Pattern[]::new);
+ Preconditions.checkNotNull(patterns, "Patterns can not be null.");
+ Preconditions.checkArgument(allNotNull(patterns), "The pattern can not be null.");
+ return cachePattern
+ ? getAndCachePatternsInternal(patterns)
+ : getPatternsInternal(patterns);
}
/**
@@ -96,10 +87,9 @@ public final class RegexUtil {
* @return {@link Pattern} 实例数组
*/
public static Pattern[] getPatterns(final String[] patterns) {
- Preconditions.checkNotNull(patterns, "The patterns can not be null.");
- return Arrays.stream(patterns)
- .map(RegexUtil::getPattern)
- .toArray(Pattern[]::new);
+ Preconditions.checkNotNull(patterns, "Patterns can not be null.");
+ Preconditions.checkArgument(allNotNull(patterns), "The pattern can not be null.");
+ return getPatternsInternal(patterns);
}
/**
@@ -109,12 +99,13 @@ public final class RegexUtil {
* @return 缓存的 Pattern 实例。如果缓存已满,则返回 {@code null}。
*/
public static Pattern cachePattern(final Pattern pattern) {
+ Preconditions.checkNotNull(pattern, "The pattern can not be null.");
if (PATTERN_CACHE.size() >= MAX_CACHE_SIZE) {
return null;
}
final String patternStr = pattern.pattern();
- PATTERN_CACHE.putIfAbsent(patternStr, pattern);
- return PATTERN_CACHE.get(patternStr);
+ final Pattern pre = PATTERN_CACHE.putIfAbsent(patternStr, pattern);
+ return pre != null ? pre : pattern;
}
/**
@@ -126,7 +117,7 @@ public final class RegexUtil {
*/
public static boolean matches(@Nullable final CharSequence input, final Pattern pattern) {
Preconditions.checkNotNull(pattern, "The pattern can not be null.");
- return input != null && pattern.matcher(input).matches();
+ return matchesInternal(input, pattern);
}
/**
@@ -137,16 +128,9 @@ public final class RegexUtil {
* @return 判断结果
*/
public static boolean matchesOne(@Nullable final CharSequence input, final Pattern[] patterns) {
- Preconditions.checkNotNull(patterns, "The patterns can not be null.");
- if (input == null) {
- return false;
- }
- for (Pattern pattern : patterns) {
- if (matches(input, pattern)) {
- return true;
- }
- }
- return false;
+ Preconditions.checkNotNull(patterns, "Patterns can not be null.");
+ Preconditions.checkArgument(allNotNull(patterns), "The pattern can not be null.");
+ return matchesOneInternal(input, patterns);
}
/**
@@ -157,16 +141,9 @@ public final class RegexUtil {
* @return 判断结果
*/
public static boolean matchesAll(@Nullable final CharSequence input, final Pattern[] patterns) {
- Preconditions.checkNotNull(patterns, "The patterns can not be null.");
- if (input == null) {
- return false;
- }
- for (Pattern pattern : patterns) {
- if (!matches(input, pattern)) {
- return false;
- }
- }
- return true;
+ Preconditions.checkNotNull(patterns, "Patterns can not be null.");
+ Preconditions.checkArgument(allNotNull(patterns), "The pattern can not be null.");
+ return matchesAllInternal(input, patterns);
}
/**
@@ -179,7 +156,11 @@ public final class RegexUtil {
*/
public static boolean matches(@Nullable final CharSequence input, final String pattern,
final boolean cachePattern) {
- return matches(input, getPattern(pattern, cachePattern));
+ Preconditions.checkNotNull(pattern, "The pattern can not be null.");
+ Pattern p = cachePattern
+ ? getAndCachePatternInternal(pattern)
+ : getPatternInternal(pattern);
+ return matchesInternal(input, p);
}
/**
@@ -190,7 +171,8 @@ public final class RegexUtil {
* @return 判断结果
*/
public static boolean matches(@Nullable final CharSequence input, final String pattern) {
- return matches(input, getPattern(pattern));
+ Preconditions.checkNotNull(pattern, "The pattern can not be null.");
+ return matchesInternal(input, getPatternInternal(pattern));
}
/**
@@ -203,8 +185,12 @@ public final class RegexUtil {
*/
public static boolean matchesOne(@Nullable final CharSequence input, final String[] patterns,
final boolean cachePattern) {
- final Pattern[] patternSet = getPatterns(patterns, cachePattern);
- return matchesOne(input, patternSet);
+ Preconditions.checkNotNull(patterns, "Patterns can not be null.");
+ Preconditions.checkArgument(allNotNull(patterns), "The pattern can not be null.");
+ final Pattern[] patternSet = cachePattern
+ ? getAndCachePatternsInternal(patterns)
+ : getPatternsInternal(patterns);
+ return matchesOneInternal(input, patternSet);
}
/**
@@ -215,8 +201,10 @@ public final class RegexUtil {
* @return 判断结果
*/
public static boolean matchesOne(@Nullable final CharSequence input, final String[] patterns) {
- final Pattern[] patternSet = getPatterns(patterns);
- return matchesOne(input, patternSet);
+ Preconditions.checkNotNull(patterns, "Patterns can not be null.");
+ Preconditions.checkArgument(allNotNull(patterns), "The pattern can not be null.");
+ final Pattern[] patternSet = getPatternsInternal(patterns);
+ return matchesOneInternal(input, patternSet);
}
/**
@@ -229,8 +217,12 @@ public final class RegexUtil {
*/
public static boolean matchesAll(@Nullable final CharSequence input, final String[] patterns,
final boolean cachePattern) {
- final Pattern[] patternSet = getPatterns(patterns, cachePattern);
- return matchesAll(input, patternSet);
+ Preconditions.checkNotNull(patterns, "Patterns can not be null.");
+ Preconditions.checkArgument(allNotNull(patterns), "The pattern can not be null.");
+ final Pattern[] patternSet = cachePattern
+ ? getAndCachePatternsInternal(patterns)
+ : getPatternsInternal(patterns);
+ return matchesAllInternal(input, patternSet);
}
/**
@@ -241,25 +233,27 @@ public final class RegexUtil {
* @return 判断结果
*/
public static boolean matchesAll(@Nullable final CharSequence input, final String[] patterns) {
- final Pattern[] patternSet = getPatterns(patterns);
- return matchesAll(input, patternSet);
+ Preconditions.checkNotNull(patterns, "Patterns can not be null.");
+ Preconditions.checkArgument(allNotNull(patterns), "The pattern can not be null.");
+ final Pattern[] patternSet = getPatternsInternal(patterns);
+ return matchesAllInternal(input, patternSet);
}
/**
- * 生成匹配器。
+ * 生成 Matcher。
*
* @param input 输入
* @param pattern 正则
* @return 结果
*/
public static Matcher getMatcher(final CharSequence input, final Pattern pattern) {
- Preconditions.checkNotNull(input, "The input can not be null");
- Preconditions.checkNotNull(pattern, "The pattern can not be null");
+ Preconditions.checkNotNull(input, "The input can not be null.");
+ Preconditions.checkNotNull(pattern, "The pattern can not be null.");
return pattern.matcher(input);
}
/**
- * 生成匹配器。
+ * 生成 Matcher。
*
* @param input 输入
* @param pattern 正则表达式
@@ -267,20 +261,132 @@ public final class RegexUtil {
* @return 结果
*/
public static Matcher getMatcher(final CharSequence input, final String pattern, boolean cachePattern) {
- Preconditions.checkNotNull(input, "The input can not be null");
- return getPattern(pattern, cachePattern).matcher(input);
+ Preconditions.checkNotNull(input, "The input can not be null.");
+ Preconditions.checkNotNull(pattern, "The pattern can not be null.");
+ final Pattern p = cachePattern
+ ? getAndCachePatternInternal(pattern)
+ : getPatternInternal(pattern);
+ return p.matcher(input);
}
/**
- * 生成匹配器。不缓存 {@link Pattern} 实例。
+ * 生成 Matcher。不缓存 {@link Pattern} 实例。
*
* @param input 输入
* @param pattern 正则表达式
* @return 结果
*/
public static Matcher getMatcher(final CharSequence input, final String pattern) {
- Preconditions.checkNotNull(input, "The input can not be null");
- return getPattern(pattern).matcher(input);
+ Preconditions.checkNotNull(input, "The input can not be null.");
+ Preconditions.checkNotNull(pattern, "The pattern can not be null.");
+ return getPatternInternal(pattern).matcher(input);
+ }
+
+ // ========== internal methods ==========
+
+ /**
+ * 获取 {@link Pattern} 实例。
+ *
+ * @param pattern 正则表达式
+ * @param cachePattern 是否缓存 {@link Pattern} 实例
+ * @return {@link Pattern} 实例
+ */
+ @SuppressWarnings("null")
+ @Nonnull
+ private static Pattern getAndCachePatternInternal(@Nonnull final String pattern) {
+ if (PATTERN_CACHE.size() < MAX_CACHE_SIZE) {
+ return PATTERN_CACHE.computeIfAbsent(pattern, Pattern::compile);
+ }
+ Pattern result = PATTERN_CACHE.get(pattern);
+ if (result != null) {
+ return result;
+ }
+ return Pattern.compile(pattern);
+ }
+
+ /**
+ * 获取 {@link Pattern} 实例,不缓存。
+ *
+ * @param pattern 正则表达式
+ * @return {@link Pattern} 实例
+ */
+ @SuppressWarnings("null")
+ @Nonnull
+ private static Pattern getPatternInternal(@Nonnull final String pattern) {
+ Pattern result = PATTERN_CACHE.get(pattern);
+ if (result == null) {
+ result = Pattern.compile(pattern);
+ }
+ return result;
+ }
+
+ /**
+ * 将各个正则表达式转为 {@link Pattern} 实例。
+ *
+ * @param patterns 正则表达式
+ * @return {@link Pattern} 实例数组
+ */
+ @SuppressWarnings("null")
+ @Nonnull
+ private static Pattern[] getAndCachePatternsInternal(@Nonnull final String[] patterns) {
+ return Arrays.stream(patterns)
+ .map(RegexUtil::getAndCachePatternInternal)
+ .toArray(Pattern[]::new);
+ }
+
+ /**
+ * 将各个正则表达式转为 {@link Pattern} 实例。
+ *
+ * @param patterns 正则表达式
+ * @return {@link Pattern} 实例数组
+ */
+ @SuppressWarnings("null")
+ @Nonnull
+ private static Pattern[] getPatternsInternal(@Nonnull final String[] patterns) {
+ return Arrays.stream(patterns)
+ .map(RegexUtil::getPatternInternal)
+ .toArray(Pattern[]::new);
+ }
+
+ /**
+ * 判断 {@code input} 是否匹配 {@code pattern}。
+ *
+ * @param input 输入
+ * @param pattern 正则
+ * @return 判断结果
+ */
+ private static boolean matchesInternal(@Nullable final CharSequence input, @Nonnull final Pattern pattern) {
+ return input != null && pattern.matcher(input).matches();
+ }
+
+ @SuppressWarnings("null")
+ private static boolean matchesOneInternal(@Nullable final CharSequence input, @Nonnull final Pattern[] patterns) {
+ if (input == null) {
+ return false;
+ }
+ for (Pattern pattern : patterns) {
+ if (matchesInternal(input, pattern)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @SuppressWarnings("null")
+ private static boolean matchesAllInternal(final CharSequence input, final Pattern[] patterns) {
+ if (input == null) {
+ return false;
+ }
+ for (Pattern pattern : patterns) {
+ if (!matchesInternal(input, pattern)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean allNotNull(T[] array) {
+ return Arrays.stream(array).allMatch(Objects::nonNull);
}
private RegexUtil() {
diff --git a/src/main/java/xyz/zhouxy/plusone/commons/util/RestfulResult.java b/src/main/java/xyz/zhouxy/plusone/commons/util/RestfulResult.java
index 5a52811..d517d68 100644
--- a/src/main/java/xyz/zhouxy/plusone/commons/util/RestfulResult.java
+++ b/src/main/java/xyz/zhouxy/plusone/commons/util/RestfulResult.java
@@ -28,7 +28,9 @@ import com.google.common.base.Preconditions;
* 对返回给前端的数据进行封装
*
* @author ZhouXY
+ * @deprecated 已被 {@link UnifiedResponse} 代替。
*/
+@Deprecated
@JsonInclude(JsonInclude.Include.NON_NULL)
public class RestfulResult {
diff --git a/src/main/java/xyz/zhouxy/plusone/commons/util/SuccessResult.java b/src/main/java/xyz/zhouxy/plusone/commons/util/SuccessResult.java
new file mode 100644
index 0000000..660f82b
--- /dev/null
+++ b/src/main/java/xyz/zhouxy/plusone/commons/util/SuccessResult.java
@@ -0,0 +1,25 @@
+package xyz.zhouxy.plusone.commons.util;
+
+/**
+ * 成功结果
+ *
+ * @author zhouxy
+ */
+final class SuccessResult extends UnifiedResponse {
+ private static final String SUCCESS_STATUS = "000000";
+ private static final String DEFAULT_SUCCESS_MSG = "SUCCESS";
+
+ SuccessResult() {
+ super(SUCCESS_STATUS, DEFAULT_SUCCESS_MSG);
+ }
+
+ SuccessResult(String message) {
+ super(SUCCESS_STATUS, message);
+ }
+
+ SuccessResult(String message, Object data) {
+ super(SUCCESS_STATUS, message, data);
+ }
+
+ private static final long serialVersionUID = -7509096647748429661L;
+}
diff --git a/src/main/java/xyz/zhouxy/plusone/commons/util/UnifiedResponse.java b/src/main/java/xyz/zhouxy/plusone/commons/util/UnifiedResponse.java
new file mode 100644
index 0000000..8512079
--- /dev/null
+++ b/src/main/java/xyz/zhouxy/plusone/commons/util/UnifiedResponse.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2022-2023 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package xyz.zhouxy.plusone.commons.util;
+
+import xyz.zhouxy.plusone.commons.base.IWithCode;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.BiFunction;
+import java.util.function.BooleanSupplier;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * 统一结果,对返回给前端的数据进行封装。
+ *
+ * @author ZhouXY
+ */
+public abstract class UnifiedResponse extends HashMap {
+ private static final long serialVersionUID = -6198220274571286031L;
+
+ private static final String STATUS_KEY = "status";
+ private static final String MESSAGE_KEY = "message";
+ private static final String DATA_KEY = "data";
+
+ public static UnifiedResponse success() {
+ return new SuccessResult();
+ }
+
+ public static UnifiedResponse success(String message) {
+ return new SuccessResult(message);
+ }
+
+ public static UnifiedResponse success(String message, Object data) {
+ return new SuccessResult(message, data);
+ }
+
+ public static UnifiedResponse error(String message) {
+ return new ErrorResult(message);
+ }
+
+ public static UnifiedResponse error(String message, Object data) {
+ return new ErrorResult(message, data);
+ }
+
+ public static UnifiedResponse error(Object status, String message) {
+ return new ErrorResult(status, message);
+ }
+
+ public static UnifiedResponse error(Object status, String message, Object data) {
+ return new ErrorResult(status, message, data);
+ }
+
+ public static UnifiedResponse error(Object status, Throwable e) {
+ return new ErrorResult(status, e);
+ }
+
+ public static > UnifiedResponse error(E e) {
+ return new ErrorResult(e);
+ }
+
+ public static UnifiedResponse of(Object status, String message) {
+ return new OrdinaryResult(status, message);
+ }
+
+ public static UnifiedResponse of(Object status, String message, Object data) {
+ return new OrdinaryResult(status, message, data);
+ }
+
+ public static UnifiedResponse of(final boolean isSuccess,
+ final Supplier success, final Supplier error) {
+ Preconditions.checkNotNull(success, "Success supplier must not be null.");
+ Preconditions.checkNotNull(error, "Error supplier must not be null.");
+ return isSuccess ? success.get() : error.get();
+ }
+
+ public static UnifiedResponse of(final BooleanSupplier isSuccess,
+ final Supplier success, final Supplier error) {
+ Preconditions.checkNotNull(isSuccess, "Conditions for success must not be null.");
+ Preconditions.checkNotNull(success, "Success supplier must not be null.");
+ Preconditions.checkNotNull(error, "Error supplier must not be null.");
+ return isSuccess.getAsBoolean() ? success.get() : error.get();
+ }
+
+ protected UnifiedResponse(Object status, String message) {
+ setStatus(status);
+ setMessage(message);
+ }
+
+ protected UnifiedResponse(Object status, String message, Object data) {
+ setStatus(status);
+ setMessage(message);
+ setData(data);
+ }
+
+ private void setStatus(Object status) {
+ Objects.requireNonNull(status);
+ if (status instanceof String) {
+ super.put(STATUS_KEY, status);
+ } else {
+ super.put(STATUS_KEY, status.toString());
+ }
+ }
+
+ private void setData(Object data) {
+ super.put(DATA_KEY, Objects.requireNonNull(data));
+ }
+
+ private void setMessage(String message) {
+ super.put(MESSAGE_KEY, Objects.requireNonNull(message));
+ }
+
+ /**
+ * @deprecated Unsupported operation.
+ */
+ @Deprecated
+ @Override
+ public Object put(String key, Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated Unsupported operation.
+ */
+ @Deprecated
+ @Override
+ public void putAll(Map extends String, ?> m) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated Unsupported operation.
+ */
+ @Deprecated
+ @Override
+ public Object remove(Object key) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated Unsupported operation.
+ */
+ @Deprecated
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated Unsupported operation.
+ */
+ @Deprecated
+ @Override
+ public Object putIfAbsent(String key, Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated Unsupported operation.
+ */
+ @Deprecated
+ @Override
+ public boolean remove(Object key, Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated Unsupported operation.
+ */
+ @Deprecated
+ @Override
+ public boolean replace(String key, Object oldValue, Object newValue) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated Unsupported operation.
+ */
+ @Deprecated
+ @Override
+ public Object replace(String key, Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated Unsupported operation.
+ */
+ @Deprecated
+ @Override
+ public Object computeIfAbsent(String key, Function super String, ?> mappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated Unsupported operation.
+ */
+ @Deprecated
+ @Override
+ public Object computeIfPresent(String key, BiFunction super String, ? super Object, ?> remappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated Unsupported operation.
+ */
+ @Deprecated
+ @Override
+ public Object compute(String key, BiFunction super String, ? super Object, ?> remappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated Unsupported operation.
+ */
+ @Deprecated
+ @Override
+ public Object merge(String key, Object value, BiFunction super Object, ? super Object, ?> remappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @deprecated Unsupported operation.
+ */
+ @Deprecated
+ @Override
+ public void replaceAll(BiFunction super String, ? super Object, ?> function) {
+ throw new UnsupportedOperationException();
+ }
+}