diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/util/CoordinateUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/data/CoordinateUtil.java
similarity index 99%
rename from hutool-core/src/main/java/org/dromara/hutool/core/util/CoordinateUtil.java
rename to hutool-core/src/main/java/org/dromara/hutool/core/data/CoordinateUtil.java
index 4494a7f70..8cf7d7552 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/util/CoordinateUtil.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/data/CoordinateUtil.java
@@ -10,7 +10,7 @@
* See the Mulan PSL v2 for more details.
*/
-package org.dromara.hutool.core.util;
+package org.dromara.hutool.core.data;
import java.io.Serializable;
import java.util.Objects;
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/util/CreditCodeUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/data/CreditCodeUtil.java
similarity index 98%
rename from hutool-core/src/main/java/org/dromara/hutool/core/util/CreditCodeUtil.java
rename to hutool-core/src/main/java/org/dromara/hutool/core/data/CreditCodeUtil.java
index 1727dddfe..1be2324be 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/util/CreditCodeUtil.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/data/CreditCodeUtil.java
@@ -10,12 +10,13 @@
* See the Mulan PSL v2 for more details.
*/
-package org.dromara.hutool.core.util;
+package org.dromara.hutool.core.data;
import org.dromara.hutool.core.map.SafeConcurrentHashMap;
import org.dromara.hutool.core.regex.PatternPool;
import org.dromara.hutool.core.regex.ReUtil;
import org.dromara.hutool.core.text.StrUtil;
+import org.dromara.hutool.core.util.RandomUtil;
import java.util.Map;
import java.util.regex.Pattern;
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/text/MaskingUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/data/MaskingUtil.java
similarity index 99%
rename from hutool-core/src/main/java/org/dromara/hutool/core/text/MaskingUtil.java
rename to hutool-core/src/main/java/org/dromara/hutool/core/data/MaskingUtil.java
index 1b9b7915f..0c9064ac4 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/text/MaskingUtil.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/data/MaskingUtil.java
@@ -10,8 +10,9 @@
* See the Mulan PSL v2 for more details.
*/
-package org.dromara.hutool.core.text;
+package org.dromara.hutool.core.data;
+import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.CharUtil;
/**
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/text/PasswdStrength.java b/hutool-core/src/main/java/org/dromara/hutool/core/data/PasswdStrength.java
similarity index 99%
rename from hutool-core/src/main/java/org/dromara/hutool/core/text/PasswdStrength.java
rename to hutool-core/src/main/java/org/dromara/hutool/core/data/PasswdStrength.java
index 504fc7f86..78e15b28a 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/text/PasswdStrength.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/data/PasswdStrength.java
@@ -10,7 +10,9 @@
* See the Mulan PSL v2 for more details.
*/
-package org.dromara.hutool.core.text;
+package org.dromara.hutool.core.data;
+
+import org.dromara.hutool.core.text.StrUtil;
/**
* 检测密码强度
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/util/PhoneUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/data/PhoneUtil.java
similarity index 99%
rename from hutool-core/src/main/java/org/dromara/hutool/core/util/PhoneUtil.java
rename to hutool-core/src/main/java/org/dromara/hutool/core/data/PhoneUtil.java
index 9602bbea7..8b31f1272 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/util/PhoneUtil.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/data/PhoneUtil.java
@@ -10,7 +10,7 @@
* See the Mulan PSL v2 for more details.
*/
-package org.dromara.hutool.core.util;
+package org.dromara.hutool.core.data;
import org.dromara.hutool.core.regex.PatternPool;
import org.dromara.hutool.core.lang.Validator;
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/data/package-info.java b/hutool-core/src/main/java/org/dromara/hutool/core/data/package-info.java
new file mode 100644
index 000000000..e9b74b3ce
--- /dev/null
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/data/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2023 looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+/**
+ * 数据相关封装和工具类
+ * 在Hutool中,“数据”是指社会属性的内容
+ * 如电话、统一社会信用代码、密码、坐标系、数据脱敏等。
+ *
+ * @author looly
+ */
+package org.dromara.hutool.core.data;
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/lang/Validator.java b/hutool-core/src/main/java/org/dromara/hutool/core/lang/Validator.java
index 34bc1b499..df99c2751 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/lang/Validator.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/lang/Validator.java
@@ -17,7 +17,7 @@ import org.dromara.hutool.core.exceptions.ValidateException;
import org.dromara.hutool.core.regex.PatternPool;
import org.dromara.hutool.core.regex.RegexPool;
import org.dromara.hutool.core.util.CharsetUtil;
-import org.dromara.hutool.core.util.CreditCodeUtil;
+import org.dromara.hutool.core.data.CreditCodeUtil;
import org.dromara.hutool.core.math.NumberUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.core.regex.ReUtil;
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/text/CharSequenceUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/text/CharSequenceUtil.java
index eb9054c14..f9fd0d2e5 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/text/CharSequenceUtil.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/text/CharSequenceUtil.java
@@ -23,6 +23,7 @@ import org.dromara.hutool.core.text.finder.CharFinder;
import org.dromara.hutool.core.text.finder.CharMatcherFinder;
import org.dromara.hutool.core.text.finder.Finder;
import org.dromara.hutool.core.text.finder.StrFinder;
+import org.dromara.hutool.core.text.placeholder.StrFormatter;
import org.dromara.hutool.core.text.replacer.RangeReplacerByChar;
import org.dromara.hutool.core.text.replacer.RangeReplacerByStr;
import org.dromara.hutool.core.text.replacer.SearchReplacer;
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/text/StrUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/text/StrUtil.java
index b2460c884..b44a0cbdb 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/text/StrUtil.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/text/StrUtil.java
@@ -13,6 +13,7 @@
package org.dromara.hutool.core.text;
import org.dromara.hutool.core.array.ArrayUtil;
+import org.dromara.hutool.core.text.placeholder.StrFormatter;
import org.dromara.hutool.core.util.CharsetUtil;
import java.io.StringReader;
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/text/PlaceholderParser.java b/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/PlaceholderParser.java
similarity index 98%
rename from hutool-core/src/main/java/org/dromara/hutool/core/text/PlaceholderParser.java
rename to hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/PlaceholderParser.java
index 9f5b4b970..7ba625970 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/text/PlaceholderParser.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/PlaceholderParser.java
@@ -10,10 +10,11 @@
* See the Mulan PSL v2 for more details.
*/
-package org.dromara.hutool.core.text;
+package org.dromara.hutool.core.text.placeholder;
import org.dromara.hutool.core.exceptions.UtilException;
import org.dromara.hutool.core.lang.Assert;
+import org.dromara.hutool.core.text.StrChecker;
import org.dromara.hutool.core.util.CharUtil;
import java.util.Objects;
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/text/StrFormatter.java b/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/StrFormatter.java
similarity index 97%
rename from hutool-core/src/main/java/org/dromara/hutool/core/text/StrFormatter.java
rename to hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/StrFormatter.java
index e543a4eec..ce3f7a24d 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/text/StrFormatter.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/StrFormatter.java
@@ -10,10 +10,10 @@
* See the Mulan PSL v2 for more details.
*/
-package org.dromara.hutool.core.text;
+package org.dromara.hutool.core.text.placeholder;
import org.dromara.hutool.core.array.ArrayUtil;
-import org.dromara.hutool.core.text.placeholder.StrTemplate;
+import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.text.placeholder.template.NamedPlaceholderStrTemplate;
import java.util.Map;
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/text/StrMatcher.java b/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/StrMatcher.java
similarity index 97%
rename from hutool-core/src/main/java/org/dromara/hutool/core/text/StrMatcher.java
rename to hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/StrMatcher.java
index b27896fd6..42e115eda 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/text/StrMatcher.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/StrMatcher.java
@@ -10,9 +10,10 @@
* See the Mulan PSL v2 for more details.
*/
-package org.dromara.hutool.core.text;
+package org.dromara.hutool.core.text.placeholder;
import org.dromara.hutool.core.map.MapUtil;
+import org.dromara.hutool.core.text.StrUtil;
import java.util.ArrayList;
import java.util.HashMap;
diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/StrTemplate.java b/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/StrTemplate.java
index f503ea419..ac3d7af71 100644
--- a/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/StrTemplate.java
+++ b/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/StrTemplate.java
@@ -32,1008 +32,1008 @@ import static org.dromara.hutool.core.text.placeholder.StrTemplate.Feature.*;
* @since 6.0.0
*/
public abstract class StrTemplate {
- // region 静态属性和方法
- // ################################################## 静态属性和方法 ##################################################
- /**
- * 转义符 默认值
- */
- public static final char DEFAULT_ESCAPE = CharPool.BACKSLASH;
-
- /**
- * 全局默认策略,一旦修改,对所有模板对象都生效
- *
该值 是每个模板对象创建时的 策略初始值,因此,修改全局默认策略,不影响已经创建的模板对象
- */ - protected static int globalFeatures = Feature.of(FORMAT_MISSING_KEY_PRINT_WHOLE_PLACEHOLDER, FORMAT_NULL_VALUE_TO_STR, - MATCH_KEEP_DEFAULT_VALUE, MATCH_EMPTY_VALUE_TO_NULL, MATCH_NULL_STR_TO_NULL); - - /** - * 全局默认值处理器,一旦修改,对所有模板对象都生效 - *根据 占位符变量 返回 默认值
- */ - protected static UnaryOperator例如,"{}", "?", "$$$"
- * - * @param template 字符串模板 - * @return 单占位符 模板对象的 Builder - */ - public static SinglePlaceholderStrTemplate.Builder of(String template) { - return SinglePlaceholderStrTemplate.builder(template); - } - - /** - * 创建 有前缀和后缀的占位符模板对象的 Builder - *例如,"{0}", "{name}", "#{name}"
- * - * @param template 字符串模板 - * @return 有前缀和后缀的占位符模板对象的 Builder - */ - public static NamedPlaceholderStrTemplate.Builder ofNamed(String template) { - return NamedPlaceholderStrTemplate.builder(template); - } - - /** - * 设置 全局默认策略,一旦修改,对所有模板对象都生效 - *该值 是每个模板对象创建时的 策略初始值,因此,修改全局默认策略,不影响已经创建的模板对象
- * - * @param globalFeatures 全局默认策略 - */ - public static void setGlobalFeatures(final Feature... globalFeatures) { - StrTemplate.globalFeatures = Feature.of(globalFeatures); - } - - /** - * 设置 全局默认值处理器,一旦修改,对所有模板对象都生效 - * - * @param globalDefaultValueHandler 全局默认处理器,根据 占位符变量 返回 默认值 - */ - public static void setGlobalDefaultValue(final UnaryOperator转义符如果标记在 占位符的开始或者结束 之前,则该占位符无效,属于普通字符串的一部分
- * 例如,转义符为 {@literal '/'},占位符为 "{}":
- * 当字符串模板为 {@literal "I am /{}"} 时,该模板中没有任何需要替换的占位符,格式化结果为 {@literal "I am {}"}
- *
如果要打印转义符,使用双转义符即可,例如,转义符为 {@literal '/'},占位符为 "{}":
- * 当字符串模板为 {@literal "I am //{}"} ,格式化参数为 {@literal "student"}, 格式化结果为 {@literal "I am /student"}
- *
例如,{@literal "{}"->"{}"、"{name}"->"name"}
- * - * @return 所有占位变量名称列表 - */ - public List例如,{@literal "{}"->"{}"、"{name}"->"{name}"}
- * - * @return 所有占位符的完整文本列表 - */ - public List依次遍历模板中的 占位符,根据 占位符 返回 需要序列化的值
- *不对 占位符 和 参数值 做任何处理,由用户抉择
- * - * @param valueSupplier 根据 占位符 返回 需要序列化的值的字符串形式,例如:依次遍历模板中的 占位符,根据 占位符 返回 需要序列化的值
- *不对 占位符 和 参数值 做任何处理,由用户抉择
- * - * @param valueSupplier 根据 占位符 返回 需要序列化的值的字符串形式,例如:依次遍历模板中的 占位符,根据 占位符 返回 需要序列化的值
- * - * @param valueSupplier 根据 占位符 返回 需要序列化的值,如果返回值不是 {@link String},则使用 {@link StrUtil#utf8Str(Object)} - * 方法转为字符串 - * @return 模板格式化之后的结果 - */ - protected String formatBySegment(final Function例如,map中没有 占位符变量 这个key;基于下标的参数中,找不到 占位符下标 对应的 列表元素
- * - * @param segment 占位符 - * @return 参数中找不到占位符时的默认值 - */ - protected String formatMissingKey(final AbstractPlaceholderSegment segment) { - final int features = getFeatures(); - if (FORMAT_MISSING_KEY_PRINT_WHOLE_PLACEHOLDER.contains(features)) { - return segment.getText(); - } else if (FORMAT_MISSING_KEY_PRINT_DEFAULT_VALUE.contains(features)) { - return getDefaultValue(segment); - } else if (FORMAT_MISSING_KEY_PRINT_NULL.contains(features)) { - return "null"; - } else if (FORMAT_MISSING_KEY_PRINT_EMPTY.contains(features)) { - return ""; - } else if (FORMAT_MISSING_KEY_PRINT_VARIABLE_NAME.contains(features)) { - return segment.getPlaceholder(); - } else if (FORMAT_MISSING_KEY_THROWS.contains(features)) { - throw new UtilException("There is no value associated with key: '" + segment.getPlaceholder() + "'"); - } - throw new UtilException("There is no value associated with key: '" + segment.getPlaceholder() + - "'. You should define some Feature for missing key when building."); - } - - /** - * 根据 策略 返回 占位符 对应的值为 {@code null} 时的返回值 - * - * @param segment 占位符 - * @return 占位符对应的值为 {@code null} 时的返回值 - */ - protected String formatNullValue(final AbstractPlaceholderSegment segment) { - final int features = getFeatures(); - if (FORMAT_NULL_VALUE_TO_STR.contains(features)) { - return "null"; - } else if (FORMAT_NULL_VALUE_TO_EMPTY.contains(features)) { - return ""; - } else if (FORMAT_NULL_VALUE_TO_WHOLE_PLACEHOLDER.contains(features)) { - return segment.getText(); - } else if (FORMAT_NULL_VALUE_TO_DEFAULT_VALUE.contains(features)) { - return getDefaultValue(segment); - } - throw new UtilException("There is a NULL value cannot resolve. You should define a Feature for null value when building or filter null value."); - } - // endregion - - // region 解析方法 - // ################################################## 解析方法 ################################################## - - // region 原始数据的解析方法 - // 不对 占位符 和 解析得到的值 做任何处理,由用户抉择 - // ############################# 原始数据的解析方法 ############################# - - /** - * 原始数据的解析方法 - *不对 占位符 和 解析得到的值 做任何处理,由用户抉择
- * - * @param str 待解析的字符串 - * @param keyValueConsumer 消费 占位符变量名称 和 占位符对应的解析得到的字符串值,例如:不对 占位符 和 解析得到的值 做任何处理,由用户抉择
- * - * @param str 待解析的字符串 - * @param keyValueConsumer 消费 占位符 和 占位符对应的解析得到的字符串值,例如:根据定义的默认值、默认值提供者、全局默认值提供者,返回默认值
- * - * @param segment 占位符 - * @return 默认值 - */ - protected String getDefaultValue(final AbstractPlaceholderSegment segment) { - if (defaultValue != null) { - return defaultValue; - } else if (defaultValueHandler != null) { - return StrUtil.utf8Str(defaultValueHandler.apply(segment.getPlaceholder())); - } else if (globalDefaultValueHandler != null) { - return StrUtil.utf8Str(globalDefaultValueHandler.apply(segment.getPlaceholder())); - } - throw new UtilException("There is no default value for key: '" + segment.getPlaceholder() + - "'. You should define a 'defaultValue' or 'defaultValueHandler' or 'globalDefaultValueHandler' when building."); - } - - /** - * 一些公共的初始化代码 - *由于此时子类还没构造完成,所以只能由子类构造方法调用
- */ - protected void afterInit() { - // 解析 并 优化 segment 列表 - this.segments = optimizeSegments(parseSegments(template)); - - // 计算 固定文本segment 的 数量 和 文本总长度 - int literalSegmentSize = 0, fixedTextTotalLength = 0; - for (StrTemplateSegment segment : this.segments) { - if (segment instanceof LiteralSegment) { - ++literalSegmentSize; - fixedTextTotalLength += segment.getText().length(); - } - } - this.fixedTextTotalLength = fixedTextTotalLength; - - // 获取 占位符segment 列表 - final int placeholderSegmentsSize = segments.size() - literalSegmentSize; - if (placeholderSegmentsSize == 0) { - this.placeholderSegments = ListUtil.zero(); - } else { - List移除空文本节点,合并连续的文本节点
- * - * @param segments 节点列表 - * @return 不占用多余空间的节点列表 - */ - private List同组内的策略是互斥的,一但设置为组内的某个新策略,就会清除之前的同组策略,仅保留新策略
- * - * @param appendFeatures 需要新增的策略 - * @return builder子对象 - */ - public BuilderChild addFeatures(final Feature... appendFeatures) { - if (ArrayUtil.isNotEmpty(appendFeatures)) { - for (Feature feature : appendFeatures) { - this.features = feature.set(this.features); - } - } - return self(); - } - - /** - * 从 策略值 中 删除策略 - *删除的策略 可以 不存在
- * - * @param removeFeatures 需要删除的策略 - * @return builder子对象 - */ - public BuilderChild removeFeatures(final Feature... removeFeatures) { - if (ArrayUtil.isNotEmpty(removeFeatures)) { - for (Feature feature : removeFeatures) { - this.features = feature.clear(this.features); - } - } - return self(); - } - - /** - * 设置 默认值 - *不可能为 {@code null},可以为 {@code "null"}
- * - * @param defaultValue 默认值 - * @return builder子对象 - */ - public BuilderChild defaultValue(final String defaultValue) { - this.defaultValue = Objects.requireNonNull(defaultValue); - return self(); - } - - /** - * 设置 默认值处理器 - * - * @param defaultValueHandler 默认值处理器,根据 占位变量 返回 默认值 - * @return builder子对象 - */ - public BuilderChild defaultValue(final UnaryOperator同组内的策略是互斥的,一但设置为组内的某个新策略,就会清除之前的同组策略,仅保留新策略
- */ - public enum Feature { - // region 格式化策略 - // ======================================== 格式化策略 ======================================== - - // region 占位符没有对应值策略组 - // 传递的格式化参数中找不到 占位变量,例如:占位符有三个,格式化时仅传入两个值;map中不包含占位符变量这个key;按下标格式化时,传入的列表不包含这个下标时; - // ==================== 占位符没有对应值策略组 ==================== - /** - * 格式化时,如果 占位符 没有 对应的值,则打印完整占位符默认策略
- */ - FORMAT_MISSING_KEY_PRINT_WHOLE_PLACEHOLDER(0, 0, 6), - /** - * 格式化时,如果 占位符 没有 对应的值,则打印 默认值,如果 没有默认值,则抛出异常该策略意味着 模板存在默认值,且为 空字符串
- */ - FORMAT_MISSING_KEY_PRINT_EMPTY(3, 0, 6), - /** - * 格式化时,如果 占位符 没有 对应的值:默认策略
- */ - FORMAT_NULL_VALUE_TO_STR(6, 6, 4), - /** - * 格式化时,如果 占位符 对应的值为 {@code null},则打印 {@code ""} 空字符串 - */ - FORMAT_NULL_VALUE_TO_EMPTY(7, 6, 4), - /** - * 格式化时,如果 占位符 对应的值为 {@code null},则原样打印占位符默认策略
- */ - MATCH_KEEP_DEFAULT_VALUE(16, 16, 3), - /** - * 解析时,结果中 不包含 默认值,只要等于默认值,都忽略 - *即,返回的结果 map 中 不会包含 这个key
- *在 基于下标的解析方法中 不生效,基于下标的解析结果只区分是否为 {@code null},元素数量是固定的
- */ - MATCH_IGNORE_DEFAULT_VALUE(17, 16, 3), - /** - * 解析时,在 结果中 将 默认值 转为 {@code null} - *返回的结果 map 中 包含 这个key
- */ - MATCH_DEFAULT_VALUE_TO_NULL(18, 16, 3), - // endregion - - // region 空字符串策略组 - // 占位符 位置的值是 空字符串 - // ==================== 空字符串策略组 ==================== - /** - * 解析时,占位符 对应的值为 空字符串,将 这个空字符串 转为 {@code null} - *默认策略
- */ - MATCH_EMPTY_VALUE_TO_NULL(19, 19, 4), - /** - * 解析时,占位符 对应的值为 空字符串,将 这个空字符串 转为 默认值,如果 没有默认值,则转为 {@code null} - */ - MATCH_EMPTY_VALUE_TO_DEFAULT_VALUE(20, 19, 4), - /** - * 解析时,占位符 对应的值为 空字符串,结果中 不包含 这个空字符串 - *即,返回的结果 map 中 不会包含 这个key
- *在 基于下标的解析方法中 不生效,基于下标的解析结果只区分是否为 {@code null},元素数量是固定的
- */ - MATCH_IGNORE_EMPTY_VALUE(21, 19, 4), - /** - * 解析时,占位符 对应的值为 空字符串,结果中 依然保留 这个空字符串 - */ - MATCH_KEEP_VALUE_EMPTY(22, 19, 4), - // endregion - - // region null值策略组 - // ==================== null值策略组 ==================== - /** - * 解析时,占位符 对应的值为 {@code "null"} 字符串,在 结果中 转为 {@code null} - *默认策略
- */ - MATCH_NULL_STR_TO_NULL(23, 23, 3), - /** - * 解析时,占位符 对应的值为 {@code "null"} 字符串,在 结果中 保留字符串形式 {@code "null"} - */ - MATCH_KEEP_NULL_STR(24, 23, 3), - /** - * 解析时,占位符 对应的值为 {@code "null"} 字符串,结果中 不包含 这个值 - *即,返回的结果 map 中 不会包含 这个key
- *在 基于下标的解析方法中 不生效,基于下标的解析结果只区分是否为 {@code null},元素数量是固定的
- */ - MATCH_IGNORE_NULL_STR(25, 23, 3), - // endregion - // endregion - ; - /** - * 掩码 - */ - private final int mask; - /** - * 清除掩码的二进制值 - */ - private final int clearMask; - - /** - * 策略构造方法 - * - * @param bitPos 位数,掩码中哪一位需要置为1,从0开始 - * @param bitStart 同组第一个策略的掩码位数 - * @param bitLen 同组策略数量 - */ - Feature(int bitPos, int bitStart, int bitLen) { - this.mask = 1 << bitPos; - this.clearMask = (-1 << (bitStart + bitLen)) | ((1 << bitStart) - 1); - } - - /** - * 是否为当前策略 - * - * @param features 外部的策略值 - * @return 是否为当前策略 - */ - public boolean contains(int features) { - return (features & mask) != 0; - } - - /** - * 在 策略值 中添加 当前策略 - * - * @param features 外部的策略值 - * @return 添加后的策略值 - */ - public int set(int features) { - return (features & clearMask) | mask; - } - - /** - * 在 策略值 中移除 当前策略 - * - * @param features 外部的策略值 - * @return 移除后的策略值 - */ - public int clear(int features) { - return (features & clearMask); - } - - /** - * 计算 总的策略值 - * - * @param features 策略枚举数组 - * @return 总的策略值 - */ - public static int of(Feature... features) { - if (features == null) { - return 0; - } - - int value = 0; - for (Feature feature : features) { - value = feature.set(value); - } - - return value; - } - } + // region 静态属性和方法 + // ################################################## 静态属性和方法 ################################################## + /** + * 转义符 默认值 + */ + public static final char DEFAULT_ESCAPE = CharPool.BACKSLASH; + + /** + * 全局默认策略,一旦修改,对所有模板对象都生效 + *该值 是每个模板对象创建时的 策略初始值,因此,修改全局默认策略,不影响已经创建的模板对象
+ */ + protected static int globalFeatures = Feature.of(FORMAT_MISSING_KEY_PRINT_WHOLE_PLACEHOLDER, FORMAT_NULL_VALUE_TO_STR, + MATCH_KEEP_DEFAULT_VALUE, MATCH_EMPTY_VALUE_TO_NULL, MATCH_NULL_STR_TO_NULL); + + /** + * 全局默认值处理器,一旦修改,对所有模板对象都生效 + *根据 占位符变量 返回 默认值
+ */ + protected static UnaryOperator例如,"{}", "?", "$$$"
+ * + * @param template 字符串模板 + * @return 单占位符 模板对象的 Builder + */ + public static SinglePlaceholderStrTemplate.Builder of(String template) { + return SinglePlaceholderStrTemplate.builder(template); + } + + /** + * 创建 有前缀和后缀的占位符模板对象的 Builder + *例如,"{0}", "{name}", "#{name}"
+ * + * @param template 字符串模板 + * @return 有前缀和后缀的占位符模板对象的 Builder + */ + public static NamedPlaceholderStrTemplate.Builder ofNamed(String template) { + return NamedPlaceholderStrTemplate.builder(template); + } + + /** + * 设置 全局默认策略,一旦修改,对所有模板对象都生效 + *该值 是每个模板对象创建时的 策略初始值,因此,修改全局默认策略,不影响已经创建的模板对象
+ * + * @param globalFeatures 全局默认策略 + */ + public static void setGlobalFeatures(final Feature... globalFeatures) { + StrTemplate.globalFeatures = Feature.of(globalFeatures); + } + + /** + * 设置 全局默认值处理器,一旦修改,对所有模板对象都生效 + * + * @param globalDefaultValueHandler 全局默认处理器,根据 占位符变量 返回 默认值 + */ + public static void setGlobalDefaultValue(final UnaryOperator转义符如果标记在 占位符的开始或者结束 之前,则该占位符无效,属于普通字符串的一部分
+ * 例如,转义符为 {@literal '/'},占位符为 "{}":
+ * 当字符串模板为 {@literal "I am /{}"} 时,该模板中没有任何需要替换的占位符,格式化结果为 {@literal "I am {}"}
+ *
如果要打印转义符,使用双转义符即可,例如,转义符为 {@literal '/'},占位符为 "{}":
+ * 当字符串模板为 {@literal "I am //{}"} ,格式化参数为 {@literal "student"}, 格式化结果为 {@literal "I am /student"}
+ *
例如,{@literal "{}"->"{}"、"{name}"->"name"}
+ * + * @return 所有占位变量名称列表 + */ + public List例如,{@literal "{}"->"{}"、"{name}"->"{name}"}
+ * + * @return 所有占位符的完整文本列表 + */ + public List依次遍历模板中的 占位符,根据 占位符 返回 需要序列化的值
+ *不对 占位符 和 参数值 做任何处理,由用户抉择
+ * + * @param valueSupplier 根据 占位符 返回 需要序列化的值的字符串形式,例如:依次遍历模板中的 占位符,根据 占位符 返回 需要序列化的值
+ *不对 占位符 和 参数值 做任何处理,由用户抉择
+ * + * @param valueSupplier 根据 占位符 返回 需要序列化的值的字符串形式,例如:依次遍历模板中的 占位符,根据 占位符 返回 需要序列化的值
+ * + * @param valueSupplier 根据 占位符 返回 需要序列化的值,如果返回值不是 {@link String},则使用 {@link StrUtil#utf8Str(Object)} + * 方法转为字符串 + * @return 模板格式化之后的结果 + */ + protected String formatBySegment(final Function例如,map中没有 占位符变量 这个key;基于下标的参数中,找不到 占位符下标 对应的 列表元素
+ * + * @param segment 占位符 + * @return 参数中找不到占位符时的默认值 + */ + protected String formatMissingKey(final AbstractPlaceholderSegment segment) { + final int features = getFeatures(); + if (FORMAT_MISSING_KEY_PRINT_WHOLE_PLACEHOLDER.contains(features)) { + return segment.getText(); + } else if (FORMAT_MISSING_KEY_PRINT_DEFAULT_VALUE.contains(features)) { + return getDefaultValue(segment); + } else if (FORMAT_MISSING_KEY_PRINT_NULL.contains(features)) { + return "null"; + } else if (FORMAT_MISSING_KEY_PRINT_EMPTY.contains(features)) { + return ""; + } else if (FORMAT_MISSING_KEY_PRINT_VARIABLE_NAME.contains(features)) { + return segment.getPlaceholder(); + } else if (FORMAT_MISSING_KEY_THROWS.contains(features)) { + throw new UtilException("There is no value associated with key: '" + segment.getPlaceholder() + "'"); + } + throw new UtilException("There is no value associated with key: '" + segment.getPlaceholder() + + "'. You should define some Feature for missing key when building."); + } + + /** + * 根据 策略 返回 占位符 对应的值为 {@code null} 时的返回值 + * + * @param segment 占位符 + * @return 占位符对应的值为 {@code null} 时的返回值 + */ + protected String formatNullValue(final AbstractPlaceholderSegment segment) { + final int features = getFeatures(); + if (FORMAT_NULL_VALUE_TO_STR.contains(features)) { + return "null"; + } else if (FORMAT_NULL_VALUE_TO_EMPTY.contains(features)) { + return ""; + } else if (FORMAT_NULL_VALUE_TO_WHOLE_PLACEHOLDER.contains(features)) { + return segment.getText(); + } else if (FORMAT_NULL_VALUE_TO_DEFAULT_VALUE.contains(features)) { + return getDefaultValue(segment); + } + throw new UtilException("There is a NULL value cannot resolve. You should define a Feature for null value when building or filter null value."); + } + // endregion + + // region 解析方法 + // ################################################## 解析方法 ################################################## + + // region 原始数据的解析方法 + // 不对 占位符 和 解析得到的值 做任何处理,由用户抉择 + // ############################# 原始数据的解析方法 ############################# + + /** + * 原始数据的解析方法 + *不对 占位符 和 解析得到的值 做任何处理,由用户抉择
+ * + * @param str 待解析的字符串 + * @param keyValueConsumer 消费 占位符变量名称 和 占位符对应的解析得到的字符串值,例如:不对 占位符 和 解析得到的值 做任何处理,由用户抉择
+ * + * @param str 待解析的字符串 + * @param keyValueConsumer 消费 占位符 和 占位符对应的解析得到的字符串值,例如:根据定义的默认值、默认值提供者、全局默认值提供者,返回默认值
+ * + * @param segment 占位符 + * @return 默认值 + */ + protected String getDefaultValue(final AbstractPlaceholderSegment segment) { + if (defaultValue != null) { + return defaultValue; + } else if (defaultValueHandler != null) { + return StrUtil.utf8Str(defaultValueHandler.apply(segment.getPlaceholder())); + } else if (globalDefaultValueHandler != null) { + return StrUtil.utf8Str(globalDefaultValueHandler.apply(segment.getPlaceholder())); + } + throw new UtilException("There is no default value for key: '" + segment.getPlaceholder() + + "'. You should define a 'defaultValue' or 'defaultValueHandler' or 'globalDefaultValueHandler' when building."); + } + + /** + * 一些公共的初始化代码 + *由于此时子类还没构造完成,所以只能由子类构造方法调用
+ */ + protected void afterInit() { + // 解析 并 优化 segment 列表 + this.segments = optimizeSegments(parseSegments(template)); + + // 计算 固定文本segment 的 数量 和 文本总长度 + int literalSegmentSize = 0, fixedTextTotalLength = 0; + for (StrTemplateSegment segment : this.segments) { + if (segment instanceof LiteralSegment) { + ++literalSegmentSize; + fixedTextTotalLength += segment.getText().length(); + } + } + this.fixedTextTotalLength = fixedTextTotalLength; + + // 获取 占位符segment 列表 + final int placeholderSegmentsSize = segments.size() - literalSegmentSize; + if (placeholderSegmentsSize == 0) { + this.placeholderSegments = ListUtil.zero(); + } else { + List移除空文本节点,合并连续的文本节点
+ * + * @param segments 节点列表 + * @return 不占用多余空间的节点列表 + */ + private List同组内的策略是互斥的,一但设置为组内的某个新策略,就会清除之前的同组策略,仅保留新策略
+ * + * @param appendFeatures 需要新增的策略 + * @return builder子对象 + */ + public BuilderChild addFeatures(final Feature... appendFeatures) { + if (ArrayUtil.isNotEmpty(appendFeatures)) { + for (Feature feature : appendFeatures) { + this.features = feature.set(this.features); + } + } + return self(); + } + + /** + * 从 策略值 中 删除策略 + *删除的策略 可以 不存在
+ * + * @param removeFeatures 需要删除的策略 + * @return builder子对象 + */ + public BuilderChild removeFeatures(final Feature... removeFeatures) { + if (ArrayUtil.isNotEmpty(removeFeatures)) { + for (Feature feature : removeFeatures) { + this.features = feature.clear(this.features); + } + } + return self(); + } + + /** + * 设置 默认值 + *不可能为 {@code null},可以为 {@code "null"}
+ * + * @param defaultValue 默认值 + * @return builder子对象 + */ + public BuilderChild defaultValue(final String defaultValue) { + this.defaultValue = Objects.requireNonNull(defaultValue); + return self(); + } + + /** + * 设置 默认值处理器 + * + * @param defaultValueHandler 默认值处理器,根据 占位变量 返回 默认值 + * @return builder子对象 + */ + public BuilderChild defaultValue(final UnaryOperator同组内的策略是互斥的,一但设置为组内的某个新策略,就会清除之前的同组策略,仅保留新策略
+ */ + public enum Feature { + // region 格式化策略 + // ======================================== 格式化策略 ======================================== + + // region 占位符没有对应值策略组 + // 传递的格式化参数中找不到 占位变量,例如:占位符有三个,格式化时仅传入两个值;map中不包含占位符变量这个key;按下标格式化时,传入的列表不包含这个下标时; + // ==================== 占位符没有对应值策略组 ==================== + /** + * 格式化时,如果 占位符 没有 对应的值,则打印完整占位符默认策略
+ */ + FORMAT_MISSING_KEY_PRINT_WHOLE_PLACEHOLDER(0, 0, 6), + /** + * 格式化时,如果 占位符 没有 对应的值,则打印 默认值,如果 没有默认值,则抛出异常该策略意味着 模板存在默认值,且为 空字符串
+ */ + FORMAT_MISSING_KEY_PRINT_EMPTY(3, 0, 6), + /** + * 格式化时,如果 占位符 没有 对应的值:默认策略
+ */ + FORMAT_NULL_VALUE_TO_STR(6, 6, 4), + /** + * 格式化时,如果 占位符 对应的值为 {@code null},则打印 {@code ""} 空字符串 + */ + FORMAT_NULL_VALUE_TO_EMPTY(7, 6, 4), + /** + * 格式化时,如果 占位符 对应的值为 {@code null},则原样打印占位符默认策略
+ */ + MATCH_KEEP_DEFAULT_VALUE(16, 16, 3), + /** + * 解析时,结果中 不包含 默认值,只要等于默认值,都忽略 + *即,返回的结果 map 中 不会包含 这个key
+ *在 基于下标的解析方法中 不生效,基于下标的解析结果只区分是否为 {@code null},元素数量是固定的
+ */ + MATCH_IGNORE_DEFAULT_VALUE(17, 16, 3), + /** + * 解析时,在 结果中 将 默认值 转为 {@code null} + *返回的结果 map 中 包含 这个key
+ */ + MATCH_DEFAULT_VALUE_TO_NULL(18, 16, 3), + // endregion + + // region 空字符串策略组 + // 占位符 位置的值是 空字符串 + // ==================== 空字符串策略组 ==================== + /** + * 解析时,占位符 对应的值为 空字符串,将 这个空字符串 转为 {@code null} + *默认策略
+ */ + MATCH_EMPTY_VALUE_TO_NULL(19, 19, 4), + /** + * 解析时,占位符 对应的值为 空字符串,将 这个空字符串 转为 默认值,如果 没有默认值,则转为 {@code null} + */ + MATCH_EMPTY_VALUE_TO_DEFAULT_VALUE(20, 19, 4), + /** + * 解析时,占位符 对应的值为 空字符串,结果中 不包含 这个空字符串 + *即,返回的结果 map 中 不会包含 这个key
+ *在 基于下标的解析方法中 不生效,基于下标的解析结果只区分是否为 {@code null},元素数量是固定的
+ */ + MATCH_IGNORE_EMPTY_VALUE(21, 19, 4), + /** + * 解析时,占位符 对应的值为 空字符串,结果中 依然保留 这个空字符串 + */ + MATCH_KEEP_VALUE_EMPTY(22, 19, 4), + // endregion + + // region null值策略组 + // ==================== null值策略组 ==================== + /** + * 解析时,占位符 对应的值为 {@code "null"} 字符串,在 结果中 转为 {@code null} + *默认策略
+ */ + MATCH_NULL_STR_TO_NULL(23, 23, 3), + /** + * 解析时,占位符 对应的值为 {@code "null"} 字符串,在 结果中 保留字符串形式 {@code "null"} + */ + MATCH_KEEP_NULL_STR(24, 23, 3), + /** + * 解析时,占位符 对应的值为 {@code "null"} 字符串,结果中 不包含 这个值 + *即,返回的结果 map 中 不会包含 这个key
+ *在 基于下标的解析方法中 不生效,基于下标的解析结果只区分是否为 {@code null},元素数量是固定的
+ */ + MATCH_IGNORE_NULL_STR(25, 23, 3), + // endregion + // endregion + ; + /** + * 掩码 + */ + private final int mask; + /** + * 清除掩码的二进制值 + */ + private final int clearMask; + + /** + * 策略构造方法 + * + * @param bitPos 位数,掩码中哪一位需要置为1,从0开始 + * @param bitStart 同组第一个策略的掩码位数 + * @param bitLen 同组策略数量 + */ + Feature(int bitPos, int bitStart, int bitLen) { + this.mask = 1 << bitPos; + this.clearMask = (-1 << (bitStart + bitLen)) | ((1 << bitStart) - 1); + } + + /** + * 是否为当前策略 + * + * @param features 外部的策略值 + * @return 是否为当前策略 + */ + public boolean contains(int features) { + return (features & mask) != 0; + } + + /** + * 在 策略值 中添加 当前策略 + * + * @param features 外部的策略值 + * @return 添加后的策略值 + */ + public int set(int features) { + return (features & clearMask) | mask; + } + + /** + * 在 策略值 中移除 当前策略 + * + * @param features 外部的策略值 + * @return 移除后的策略值 + */ + public int clear(int features) { + return (features & clearMask); + } + + /** + * 计算 总的策略值 + * + * @param features 策略枚举数组 + * @return 总的策略值 + */ + public static int of(Feature... features) { + if (features == null) { + return 0; + } + + int value = 0; + for (Feature feature : features) { + value = feature.set(value); + } + + return value; + } + } } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/package-info.java b/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/package-info.java new file mode 100644 index 000000000..375a40c17 --- /dev/null +++ b/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/package-info.java @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2023 looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +/** + * 字符串占位符相关封装,包括占位符替换变量和解析变量 + */ +package org.dromara.hutool.core.text.placeholder; diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/template/NamedPlaceholderStrTemplate.java b/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/template/NamedPlaceholderStrTemplate.java index e5c954890..9ba13a261 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/template/NamedPlaceholderStrTemplate.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/template/NamedPlaceholderStrTemplate.java @@ -7,8 +7,8 @@ import org.dromara.hutool.core.collection.CollUtil; import org.dromara.hutool.core.collection.ListUtil; import org.dromara.hutool.core.convert.Convert; import org.dromara.hutool.core.exceptions.UtilException; +import org.dromara.hutool.core.func.LambdaUtil; import org.dromara.hutool.core.lang.Assert; -import org.dromara.hutool.core.lang.func.LambdaUtil; import org.dromara.hutool.core.math.NumberUtil; import org.dromara.hutool.core.text.StrPool; import org.dromara.hutool.core.text.placeholder.StrTemplate; diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/util/CoordinateUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/data/CoordinateUtilTest.java similarity index 79% rename from hutool-core/src/test/java/org/dromara/hutool/core/util/CoordinateUtilTest.java rename to hutool-core/src/test/java/org/dromara/hutool/core/data/CoordinateUtilTest.java index 7df504613..9cdcbb750 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/util/CoordinateUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/data/CoordinateUtilTest.java @@ -1,4 +1,16 @@ -package org.dromara.hutool.core.util; +/* + * Copyright (c) 2023 looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.data; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/util/CreditCodeUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/data/CreditCodeUtilTest.java similarity index 61% rename from hutool-core/src/test/java/org/dromara/hutool/core/util/CreditCodeUtilTest.java rename to hutool-core/src/test/java/org/dromara/hutool/core/data/CreditCodeUtilTest.java index 0a81875ce..906fd50c2 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/util/CreditCodeUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/data/CreditCodeUtilTest.java @@ -1,5 +1,18 @@ -package org.dromara.hutool.core.util; +/* + * Copyright (c) 2023 looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +package org.dromara.hutool.core.data; + +import org.dromara.hutool.core.data.CreditCodeUtil; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/util/MaskingUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/data/MaskingUtilTest.java similarity index 88% rename from hutool-core/src/test/java/org/dromara/hutool/core/util/MaskingUtilTest.java rename to hutool-core/src/test/java/org/dromara/hutool/core/data/MaskingUtilTest.java index 968932f5c..8d3636a96 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/util/MaskingUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/data/MaskingUtilTest.java @@ -1,6 +1,18 @@ -package org.dromara.hutool.core.util; +/* + * Copyright (c) 2023 looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ -import org.dromara.hutool.core.text.MaskingUtil; +package org.dromara.hutool.core.data; + +import org.dromara.hutool.core.data.MaskingUtil; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/data/PasswdStrengthTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/data/PasswdStrengthTest.java new file mode 100644 index 000000000..976a88da6 --- /dev/null +++ b/hutool-core/src/test/java/org/dromara/hutool/core/data/PasswdStrengthTest.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.data; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class PasswdStrengthTest { + @Test + public void strengthTest(){ + final String passwd = "2hAj5#mne-ix.86H"; + Assertions.assertEquals(13, PasswdStrength.check(passwd)); + } + + @Test + public void strengthNumberTest(){ + final String passwd = "9999999999999"; + Assertions.assertEquals(0, PasswdStrength.check(passwd)); + } +} diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/util/PhoneUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/data/PhoneUtilTest.java similarity index 84% rename from hutool-core/src/test/java/org/dromara/hutool/core/util/PhoneUtilTest.java rename to hutool-core/src/test/java/org/dromara/hutool/core/data/PhoneUtilTest.java index 8bcdc5228..0eeaf1b8c 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/util/PhoneUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/data/PhoneUtilTest.java @@ -1,5 +1,18 @@ -package org.dromara.hutool.core.util; +/* + * Copyright (c) 2023 looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +package org.dromara.hutool.core.data; + +import org.dromara.hutool.core.data.PhoneUtil; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/lang/StrFormatterTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/lang/StrFormatterTest.java index f110fa573..f649d541e 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/lang/StrFormatterTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/lang/StrFormatterTest.java @@ -1,6 +1,6 @@ package org.dromara.hutool.core.lang; -import org.dromara.hutool.core.text.StrFormatter; +import org.dromara.hutool.core.text.placeholder.StrFormatter; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/text/PasswdStrengthTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/text/PasswdStrengthTest.java deleted file mode 100644 index f66987a71..000000000 --- a/hutool-core/src/test/java/org/dromara/hutool/core/text/PasswdStrengthTest.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.dromara.hutool.core.text; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class PasswdStrengthTest { - @Test - public void strengthTest(){ - final String passwd = "2hAj5#mne-ix.86H"; - Assertions.assertEquals(13, PasswdStrength.check(passwd)); - } - - @Test - public void strengthNumberTest(){ - final String passwd = "9999999999999"; - Assertions.assertEquals(0, PasswdStrength.check(passwd)); - } -} diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/text/PlaceholderParserTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/text/PlaceholderParserTest.java index 23b7baa13..eea266c1e 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/text/PlaceholderParserTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/text/PlaceholderParserTest.java @@ -1,5 +1,6 @@ package org.dromara.hutool.core.text; +import org.dromara.hutool.core.text.placeholder.PlaceholderParser; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/text/StrMatcherTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/text/StrMatcherTest.java index ccf2aee62..373915cbb 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/text/StrMatcherTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/text/StrMatcherTest.java @@ -1,5 +1,6 @@ package org.dromara.hutool.core.text; +import org.dromara.hutool.core.text.placeholder.StrMatcher; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test;