forked from plusone/plusone-commons
添加 UnifiedResponse 以替代 RestfulResult;重构 RegexUtil。 (#4)
Reviewed-on: plusone/plusone-commons#4feature/net-util
parent
f2aba52c4c
commit
ef43b4dd87
|
@ -16,15 +16,12 @@
|
|||
|
||||
package xyz.zhouxy.plusone.commons.base;
|
||||
|
||||
import xyz.zhouxy.plusone.commons.exception.BaseException;
|
||||
|
||||
/**
|
||||
* 规定实现类带有 {@code getCode} 方法。
|
||||
* 用于像自定义异常等需要带有 {@code code} 字段的类,
|
||||
* 方便其它地方的程序判断该类的是否实现了此接口,以此获取其实例的 {@code code} 字段的值。
|
||||
*
|
||||
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
|
||||
* @see BaseException
|
||||
*/
|
||||
public interface IWithIntCode {
|
||||
int getCode();
|
||||
|
|
|
@ -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 <a href="https://gitee.com/zhouxy108">ZhouXY</a>
|
||||
*/
|
||||
public interface IWithLongCode {
|
||||
long getCode();
|
||||
}
|
|
@ -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<K, V, T extends AbstractMapWrapper<K, V, T>> {
|
||||
|
||||
|
@ -141,12 +144,12 @@ public abstract class AbstractMapWrapper<K, V, T extends AbstractMapWrapper<K, V
|
|||
}
|
||||
|
||||
public final V computeIfAbsent(K key, Function<? super K, ? extends V> 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<K, V>) this.map, key, mappingFunction);
|
||||
} else {
|
||||
return this.map.computeIfAbsent(key, mappingFunction);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
public final Map<K, V> exportMap() {
|
||||
|
|
|
@ -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<K, V> extends ConcurrentHashMap<K, V> {
|
||||
|
||||
|
@ -86,27 +102,6 @@ public class SafeConcurrentHashMap<K, V> extends ConcurrentHashMap<K, V> {
|
|||
/** {@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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ public abstract class BaseException extends RuntimeException implements IWithInt
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getCode() {
|
||||
public final int getCode() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <K, V> V computIfAbsent(ConcurrentHashMap<K, V> 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");
|
||||
}
|
||||
}
|
|
@ -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()));
|
||||
}
|
||||
|
||||
<E extends Throwable & IWithCode<?>> ErrorResult(E e) {
|
||||
super(e.getCode(), Strings.nullToEmpty(e.getMessage()));
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = -1680792957826923092L;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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<String, Pattern> PATTERN_CACHE = new SafeConcurrentHashMap<>(
|
||||
DEFAULT_CACHE_INITIAL_CAPACITY);
|
||||
private static final Map<String, Pattern> 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 <T> boolean allNotNull(T[] array) {
|
||||
return Arrays.stream(array).allMatch(Objects::nonNull);
|
||||
}
|
||||
|
||||
private RegexUtil() {
|
||||
|
|
|
@ -28,7 +28,9 @@ import com.google.common.base.Preconditions;
|
|||
* 对返回给前端的数据进行封装
|
||||
*
|
||||
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
|
||||
* @deprecated 已被 {@link UnifiedResponse} 代替。
|
||||
*/
|
||||
@Deprecated
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class RestfulResult {
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 <a href="http://zhouxy.xyz:3000/ZhouXY108">ZhouXY</a>
|
||||
*/
|
||||
public abstract class UnifiedResponse extends HashMap<String, Object> {
|
||||
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 <E extends Throwable & IWithCode<?>> 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<SuccessResult> success, final Supplier<ErrorResult> 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<SuccessResult> success, final Supplier<ErrorResult> 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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue