This commit is contained in:
Looly 2024-07-11 10:33:30 +08:00
parent b0d443e8e9
commit dc561b12e3
14 changed files with 397 additions and 363 deletions

View File

@ -13,6 +13,7 @@
package org.dromara.hutool.core.bean;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;
@ -23,6 +24,7 @@ import java.util.Map;
* @since 6.0.0
*/
public interface BeanDesc extends Serializable {
/**
* 获取字段名-字段属性Map
*
@ -36,7 +38,9 @@ public interface BeanDesc extends Serializable {
*
* @return {@link PropDesc} 列表
*/
Collection<PropDesc> getProps();
default Collection<PropDesc> getProps() {
return getPropMap(false).values();
}
/**
* 获取属性如果不存在返回null
@ -44,5 +48,29 @@ public interface BeanDesc extends Serializable {
* @param fieldName 字段名
* @return {@link PropDesc}
*/
PropDesc getProp(final String fieldName);
default PropDesc getProp(final String fieldName) {
return getPropMap(false).get(fieldName);
}
/**
* 获取Getter方法如果不存在返回null
*
* @param fieldName 字段名
* @return Getter方法
*/
default Method getGetter(final String fieldName) {
final PropDesc desc = getProp(fieldName);
return null == desc ? null : desc.getGetter();
}
/**
* 获取Setter方法如果不存在返回null
*
* @param fieldName 字段名
* @return Setter方法
*/
default Method getSetter(final String fieldName) {
final PropDesc desc = getProp(fieldName);
return null == desc ? null : desc.getSetter();
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2024. 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:
* https://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.bean;
import org.dromara.hutool.core.map.reference.WeakConcurrentMap;
import java.util.function.Supplier;
/**
* Bean描述信息工厂类<br>
* 通过不同的类和策略生成对应的{@link BeanDesc}策略包括
* <ul>
* <li>当类为Record时生成{@link RecordBeanDesc}</li>
* <li>当类为普通Bean时生成{@link StrictBeanDesc}</li>
* </ul>
*
* @author Looly
* @since 6.0.0
*/
public class BeanDescFactory {
private static final WeakConcurrentMap<Class<?>, BeanDesc> bdCache = new WeakConcurrentMap<>();
/**
* 获取{@link BeanDesc} Bean描述信息使用Weak缓存
*
* @param clazz Bean类
* @return {@link BeanDesc}
*/
public static BeanDesc getBeanDesc(final Class<?> clazz) {
return getBeanDesc(clazz, () -> getBeanDescWithoutCache(clazz));
}
/**
* 获取{@link BeanDesc} Bean描述信息不使用缓存
*
* @param clazz Bean类
* @return {@link BeanDesc}
*/
public static BeanDesc getBeanDescWithoutCache(final Class<?> clazz) {
if (RecordUtil.isRecord(clazz)) {
return new RecordBeanDesc(clazz);
} else {
return new StrictBeanDesc(clazz);
}
}
/**
* 清空全局的Bean属性缓存
*
* @since 5.7.21
*/
public static void clearCache() {
bdCache.clear();
}
/**
* 获得属性名和{@link BeanDesc}Map映射
*
* @param beanClass Bean的类
* @param supplier 对象不存在时创建对象的函数
* @param <T> BeanDesc子类
* @return 属性名和 {@link BeanDesc}映射
* @since 5.4.2
*/
@SuppressWarnings("unchecked")
private static <T extends BeanDesc> T getBeanDesc(final Class<?> beanClass, final Supplier<T> supplier) {
return (T) bdCache.computeIfAbsent(beanClass, (key) -> supplier.get());
}
}

View File

@ -17,8 +17,6 @@ import org.dromara.hutool.core.bean.copier.BeanCopier;
import org.dromara.hutool.core.bean.copier.CopyOptions;
import org.dromara.hutool.core.bean.copier.ValueProvider;
import org.dromara.hutool.core.bean.path.BeanPath;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.collection.set.SetUtil;
import org.dromara.hutool.core.convert.Convert;
import org.dromara.hutool.core.convert.impl.RecordConverter;
@ -77,14 +75,13 @@ public class BeanUtil {
}
/**
* 获取{@link StrictBeanDesc} Bean描述信息
* 获取{@link BeanDesc} Bean描述信息
*
* @param clazz Bean类
* @return {@link StrictBeanDesc}
* @since 3.1.2
* @return {@link BeanDesc}
*/
public static StrictBeanDesc getBeanDesc(final Class<?> clazz) {
return BeanDescCache.INSTANCE.getBeanDesc(clazz, () -> new StrictBeanDesc(clazz));
public static BeanDesc getBeanDesc(final Class<?> clazz) {
return BeanDescFactory.getBeanDesc(clazz);
}
/**
@ -99,6 +96,7 @@ public class BeanUtil {
}
// region ----- getPropertyDescriptor
/**
* 获得Bean字段描述数组
*
@ -177,76 +175,6 @@ public class BeanUtil {
}
// endregion
/**
* 获得字段值通过反射直接获得字段值并不调用getXXX方法<br>
* 对象同样支持Map类型fieldNameOrIndex即为key
*
* <ul>
* <li>Map: fieldNameOrIndex需为key获取对应value</li>
* <li>Collection: fieldNameOrIndex当为数字返回index对应值非数字遍历集合返回子bean对应name值</li>
* <li>Array: fieldNameOrIndex当为数字返回index对应值非数字遍历数组返回子bean对应name值</li>
* </ul>
*
* @param bean Bean对象
* @param fieldNameOrIndex 字段名或序号序号支持负数
* @return 字段值
*/
public static Object getFieldValue(final Object bean, final String fieldNameOrIndex) {
if (null == bean || null == fieldNameOrIndex) {
return null;
}
if (bean instanceof Map) {
return ((Map<?, ?>) bean).get(fieldNameOrIndex);
} else if (bean instanceof Collection) {
try {
return CollUtil.get((Collection<?>) bean, Integer.parseInt(fieldNameOrIndex));
} catch (final NumberFormatException e) {
// 非数字see pr#254@Gitee
return CollUtil.map((Collection<?>) bean, (beanEle) -> getFieldValue(beanEle, fieldNameOrIndex), false);
}
} else if (ArrayUtil.isArray(bean)) {
try {
return ArrayUtil.get(bean, Integer.parseInt(fieldNameOrIndex));
} catch (final NumberFormatException e) {
// 非数字see pr#254@Gitee
return ArrayUtil.map(bean, Object.class, (beanEle) -> getFieldValue(beanEle, fieldNameOrIndex));
}
} else {// 普通Bean对象
return FieldUtil.getFieldValue(bean, fieldNameOrIndex);
}
}
/**
* 设置字段值通过反射设置字段值并不调用setXXX方法<br>
* 对象同样支持Map类型fieldNameOrIndex即为key支持
* <ul>
* <li>Map</li>
* <li>List</li>
* <li>Bean</li>
* </ul>
*
* @param bean Bean
* @param fieldNameOrIndex 字段名或序号序号支持负数
* @param value
* @return bean当为数组时返回一个新的数组
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static Object setFieldValue(final Object bean, final String fieldNameOrIndex, final Object value) {
if (bean instanceof Map) {
((Map) bean).put(fieldNameOrIndex, value);
} else if (bean instanceof List) {
ListUtil.setOrPadding((List) bean, Convert.toInt(fieldNameOrIndex), value);
} else if (ArrayUtil.isArray(bean)) {
// issue#3008追加产生新数组此处返回新数组
return ArrayUtil.setOrPadding(bean, Convert.toInt(fieldNameOrIndex), value);
} else {
// 普通Bean对象
FieldUtil.setFieldValue(bean, fieldNameOrIndex, value);
}
return bean;
}
/**
* 获取Bean中的属性值
*
@ -279,6 +207,7 @@ public class BeanUtil {
}
// region ----- toBean
/**
* 对象或Map转Bean
*
@ -327,6 +256,7 @@ public class BeanUtil {
// endregion
// region ----- fillBean
/**
* 填充Bean的核心方法
*
@ -362,6 +292,7 @@ public class BeanUtil {
// endregion
// region ----- beanToMap
/**
* 将bean的部分属性转换成map<br>
* 可选拷贝哪些属性值默认是不忽略值为{@code null}的值的
@ -747,7 +678,7 @@ public class BeanUtil {
return false;
}
// issue#I9VTZG排除定义setXXX的预定义类
if(Dict.class == clazz){
if (Dict.class == clazz) {
return false;
}
@ -755,6 +686,7 @@ public class BeanUtil {
}
// region ----- hasXXX
/**
* 判断是否有Setter方法<br>
* 判定方法是否存在只有一个参数的setXXX方法

View File

@ -0,0 +1,67 @@
/*
* 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:
* https://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.bean;
import org.dromara.hutool.core.bean.path.AbstractBeanDesc;
import org.dromara.hutool.core.reflect.FieldUtil;
import org.dromara.hutool.core.reflect.ModifierUtil;
import org.dromara.hutool.core.reflect.method.MethodUtil;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
/**
* 针对Reccord类的Bean描述<br>
* Bean描述包括Record自定义字段及对应方法getter方法与字段名同名不支持setter
*
* @author looly
* @since 3.1.2
*/
public class RecordBeanDesc extends AbstractBeanDesc {
private static final long serialVersionUID = 1L;
/**
* 构造
*
* @param beanClass Bean类
*/
public RecordBeanDesc(final Class<?> beanClass) {
super(beanClass);
initForRecord();
}
// ------------------------------------------------------------------------------------------------------ Private method start
/**
* 针对Record类的反射初始化
*/
private void initForRecord() {
final Class<?> beanClass = this.beanClass;
final Map<String, PropDesc> propMap = this.propMap;
final Method[] getters = MethodUtil.getPublicMethods(beanClass, method -> 0 == method.getParameterCount());
// 排除静态属性和对象子类
final Field[] fields = FieldUtil.getFields(beanClass, field -> !ModifierUtil.isStatic(field) && !FieldUtil.isOuterClassField(field));
for (final Field field : fields) {
for (final Method getter : getters) {
if (field.getName().equals(getter.getName())) {
//record对象getter方法与字段同名
final PropDesc prop = new PropDesc(field, getter, null);
propMap.putIfAbsent(prop.getFieldName(), prop);
}
}
}
}
// ------------------------------------------------------------------------------------------------------ Private method end
}

View File

@ -24,15 +24,15 @@ import java.lang.reflect.Method;
import java.util.Map;
/**
* 严格的Bean信息描述做为BeanInfo替代方案此对象持有JavaBean中的setters和getters等相关信息描述<br>
* 查找Getter和Setter方法时会
* 严格的Bean信息描述做为BeanInfo替代方案此对象持有JavaBean中的setters和getters等相关信息描述<br>
* 在获取Bean属性的时候要求字段必须存在并严格匹配查找Getter和Setter方法时会
*
* <pre>
* 1. 忽略字段和方法名的大小写
* 2. Getter查找getXXXisXXXgetIsXXX
* 3. Setter查找setXXXsetIsXXX
* 4. Setter忽略参数值与字段值不匹配的情况因此有多个参数类型的重载时会调用首次匹配的
* </pre>
* <ol>
* <li>忽略字段和方法名的大小写</li>
* <li>Getter查找getXXXisXXXgetIsXXX</li>
* <li>Setter查找setXXXsetIsXXX</li>
* <li>Setter忽略参数值与字段值不匹配的情况因此有多个参数类型的重载时会调用首次匹配的</li>
* </ol>
*
* @author looly
* @since 3.1.2
@ -53,42 +53,10 @@ public class StrictBeanDesc extends AbstractBeanDesc {
// ------------------------------------------------------------------------------------------------------ Private method start
/**
* 初始化<br>
* 普通Bean初始化<br>
* 只有与属性关联的相关Getter和Setter方法才会被读取无关的getXXX和setXXX都被忽略
*/
private void init() {
if (RecordUtil.isRecord(getBeanClass())) {
initForRecord();
} else{
initForBean();
}
}
/**
* 针对Record类的反射初始化
*/
private void initForRecord() {
final Class<?> beanClass = this.beanClass;
final Map<String, PropDesc> propMap = this.propMap;
final Method[] getters = MethodUtil.getPublicMethods(beanClass, method -> 0 == method.getParameterCount());
// 排除静态属性和对象子类
final Field[] fields = FieldUtil.getFields(beanClass, field -> !ModifierUtil.isStatic(field) && !FieldUtil.isOuterClassField(field));
for (final Field field : fields) {
for (final Method getter : getters) {
if (field.getName().equals(getter.getName())) {
//record对象getter方法与字段同名
final PropDesc prop = new PropDesc(field, getter, null);
propMap.putIfAbsent(prop.getFieldName(), prop);
}
}
}
}
/**
* 普通Bean初始化
*/
private void initForBean() {
final Class<?> beanClass = this.beanClass;
final Map<String, PropDesc> propMap = this.propMap;

View File

@ -12,7 +12,7 @@
package org.dromara.hutool.core.bean.copier.provider;
import org.dromara.hutool.core.bean.StrictBeanDesc;
import org.dromara.hutool.core.bean.BeanDesc;
import org.dromara.hutool.core.bean.BeanUtil;
import org.dromara.hutool.core.bean.PropDesc;
import org.dromara.hutool.core.bean.copier.ValueProvider;
@ -28,7 +28,7 @@ import java.lang.reflect.Type;
public class BeanValueProvider implements ValueProvider<String> {
private final Object bean;
private final StrictBeanDesc beanDesc;
private final BeanDesc beanDesc;
/**
* 构造

View File

@ -18,8 +18,6 @@ import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.map.CaseInsensitiveMap;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
@ -83,16 +81,6 @@ public abstract class AbstractBeanDesc implements BeanDesc {
return ignoreCase ? new CaseInsensitiveMap<>(1, this.propMap) : this.propMap;
}
@Override
public Collection<PropDesc> getProps() {
return this.propMap.values();
}
@Override
public PropDesc getProp(final String fieldName) {
return this.propMap.get(fieldName);
}
/**
* 获得字段名对应的字段对象如果不存在返回null
*
@ -103,26 +91,4 @@ public abstract class AbstractBeanDesc implements BeanDesc {
final PropDesc desc = this.propMap.get(fieldName);
return null == desc ? null : desc.getField();
}
/**
* 获取Getter方法如果不存在返回null
*
* @param fieldName 字段名
* @return Getter方法
*/
public Method getGetter(final String fieldName) {
final PropDesc desc = this.propMap.get(fieldName);
return null == desc ? null : desc.getGetter();
}
/**
* 获取Setter方法如果不存在返回null
*
* @param fieldName 字段名
* @return Setter方法
*/
public Method getSetter(final String fieldName) {
final PropDesc desc = this.propMap.get(fieldName);
return null == desc ? null : desc.getSetter();
}
}

View File

@ -2045,7 +2045,7 @@ public class CollUtil {
* @return 分组列表
*/
public static <T> List<List<T>> groupByField(final Collection<T> collection, final String fieldName) {
return groupByFunc(collection, t -> BeanUtil.getFieldValue(t, fieldName));
return groupByFunc(collection, t -> BeanUtil.getProperty(t, fieldName));
}
/**

View File

@ -13,11 +13,10 @@
package org.dromara.hutool.core.text.placeholder.template;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.bean.StrictBeanDesc;
import org.dromara.hutool.core.bean.BeanDesc;
import org.dromara.hutool.core.bean.BeanUtil;
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.exception.HutoolException;
import org.dromara.hutool.core.func.LambdaUtil;
import org.dromara.hutool.core.lang.Assert;
@ -26,7 +25,6 @@ import org.dromara.hutool.core.text.StrPool;
import org.dromara.hutool.core.text.placeholder.StrTemplate;
import org.dromara.hutool.core.text.placeholder.segment.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.function.*;
@ -344,7 +342,7 @@ public class NamedPlaceholderStrTemplate extends StrTemplate {
if (beanOrMap instanceof Map) {
return format((Map<String, ?>) beanOrMap);
} else if (BeanUtil.isReadableBean(beanOrMap.getClass())) {
final StrictBeanDesc beanDesc = BeanUtil.getBeanDesc(beanOrMap.getClass());
final BeanDesc beanDesc = BeanUtil.getBeanDesc(beanOrMap.getClass());
return format(fieldName -> {
final Method getterMethod = beanDesc.getGetter(fieldName);
if (getterMethod == null) {
@ -353,7 +351,7 @@ public class NamedPlaceholderStrTemplate extends StrTemplate {
return LambdaUtil.buildGetter(getterMethod).apply(beanOrMap);
});
}
return format(fieldName -> BeanUtil.getFieldValue(beanOrMap, fieldName));
return format(fieldName -> BeanUtil.getProperty(beanOrMap, fieldName));
}
/**
@ -552,22 +550,12 @@ public class NamedPlaceholderStrTemplate extends StrTemplate {
if (obj instanceof Map) {
@SuppressWarnings("unchecked") final Map<String, String> map = (Map<String, String>) obj;
matchesByKey(str, map::put);
} else if (BeanUtil.isReadableBean(obj.getClass())) {
final StrictBeanDesc beanDesc = BeanUtil.getBeanDesc(obj.getClass());
matchesByKey(str, (key, value) -> {
final Field field = beanDesc.getField(key);
final Method setterMethod = beanDesc.getSetter(key);
if (field == null || setterMethod == null) {
return;
}
final Object convert = Convert.convert(field.getType(), value);
LambdaUtil.buildSetter(setterMethod).accept(obj, convert);
});
} else if (BeanUtil.isWritableBean(obj.getClass())) {
matchesByKey(str, (key, value) -> BeanUtil.setProperty(obj, key, value));
}
return obj;
}
// endregion
// endregion
/**
* 创建 builder

View File

@ -12,6 +12,7 @@
package org.dromara.hutool.core.bean;
import org.dromara.hutool.core.bean.path.AbstractBeanDesc;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -25,10 +26,12 @@ public class BeanDescTest {
@Test
public void propDescTes() {
final StrictBeanDesc desc = BeanUtil.getBeanDesc(User.class);
Assertions.assertEquals("User", desc.getSimpleName());
final BeanDesc desc = BeanUtil.getBeanDesc(User.class);
if(desc instanceof AbstractBeanDesc){
Assertions.assertEquals("User", ((AbstractBeanDesc) desc).getSimpleName());
}
Assertions.assertEquals("age", desc.getField("age").getName());
Assertions.assertEquals("age", desc.getProp("age").getFieldName());
Assertions.assertEquals("getAge", desc.getGetter("age").getName());
Assertions.assertEquals("setAge", desc.getSetter("age").getName());
Assertions.assertEquals(1, desc.getSetter("age").getParameterTypes().length);
@ -38,7 +41,7 @@ public class BeanDescTest {
@Test
public void propDescTes2() {
final StrictBeanDesc desc = BeanUtil.getBeanDesc(User.class);
final BeanDesc desc = BeanUtil.getBeanDesc(User.class);
final PropDesc prop = desc.getProp("name");
Assertions.assertEquals("name", prop.getFieldName());
@ -50,7 +53,7 @@ public class BeanDescTest {
@Test
public void propDescOfBooleanTest() {
final StrictBeanDesc desc = BeanUtil.getBeanDesc(User.class);
final BeanDesc desc = BeanUtil.getBeanDesc(User.class);
Assertions.assertEquals("isAdmin", desc.getGetter("isAdmin").getName());
Assertions.assertEquals("setAdmin", desc.getSetter("isAdmin").getName());
@ -60,7 +63,7 @@ public class BeanDescTest {
@Test
public void propDescOfBooleanTest2() {
final StrictBeanDesc desc = BeanUtil.getBeanDesc(User.class);
final BeanDesc desc = BeanUtil.getBeanDesc(User.class);
Assertions.assertEquals("isIsSuper", desc.getGetter("isSuper").getName());
Assertions.assertEquals("setIsSuper", desc.getSetter("isSuper").getName());
@ -68,7 +71,7 @@ public class BeanDescTest {
@Test
public void propDescOfBooleanTest3() {
final StrictBeanDesc desc = BeanUtil.getBeanDesc(User.class);
final BeanDesc desc = BeanUtil.getBeanDesc(User.class);
Assertions.assertEquals("setLastPage", desc.getSetter("lastPage").getName());
Assertions.assertEquals("setIsLastPage", desc.getSetter("isLastPage").getName());
@ -76,7 +79,7 @@ public class BeanDescTest {
@Test
public void getSetTest() {
final StrictBeanDesc desc = BeanUtil.getBeanDesc(User.class);
final BeanDesc desc = BeanUtil.getBeanDesc(User.class);
final User user = new User();
desc.getProp("name").setValue(user, "张三");

View File

@ -745,7 +745,7 @@ public class BeanUtilTest {
new LinkedHashMap<>(),
false,
entry -> {
if(!Arrays.asList("id", "name", "code", "sortOrder").contains(entry.getKey())){
if(!ArrayUtil.contains(new String[]{"id", "name", "code", "sortOrder"}, entry.getKey())){
entry.setKey(null);
}
return entry;

View File

@ -20,7 +20,7 @@ public class BeanWithReturnThisTest {
@Test
public void setValueTest() {
final BeanWithRetuenThis bean = new BeanWithRetuenThis();
final StrictBeanDesc beanDesc = BeanUtil.getBeanDesc(BeanWithRetuenThis.class);
final BeanDesc beanDesc = BeanUtil.getBeanDesc(BeanWithRetuenThis.class);
final PropDesc prop = beanDesc.getProp("a");
prop.setValue(bean, "123");

View File

@ -19,7 +19,7 @@ public class Issue3096Test {
@Test
void beanDescTest() {
final StrictBeanDesc desc = BeanUtil.getBeanDesc(User.class);
final BeanDesc desc = BeanUtil.getBeanDesc(User.class);
// https://github.com/dromara/hutool/issues/3096
// 新修改的规则中isLastPage字段优先匹配setIsLastPage这个顺序固定

View File

@ -31,6 +31,8 @@ import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* test for {@link StrTemplate}
*
@ -57,19 +59,19 @@ public class StrTemplateTest {
public void namedPlaceholderFormatSequenceTest() {
final String text = "select * from #[tableName] where id = #[id]";
final NamedPlaceholderStrTemplate strTemplate = StrTemplate.ofNamed(text).prefix("#[").suffix("]").build();
Assertions.assertEquals(
assertEquals(
"select * from user where id = 1001",
strTemplate.formatSequence("user", 1001)
);
Assertions.assertEquals(
assertEquals(
"select * from user where id = 1001",
strTemplate.formatArraySequence(new String[]{"user", "1001"})
);
Assertions.assertEquals(
assertEquals(
"select * from 123 where id = 456",
strTemplate.formatArraySequence(new int[]{123, 456})
);
Assertions.assertEquals(
assertEquals(
"select * from user where id = 1001",
strTemplate.formatSequence(ListUtil.of("user", 1001))
);
@ -80,23 +82,23 @@ public class StrTemplateTest {
final String text = "select * from #[1] where id = #[2]";
final NamedPlaceholderStrTemplate strTemplate = StrTemplate.ofNamed(text).prefix("#[").suffix("]").build();
Assertions.assertEquals(
assertEquals(
"select * from user where id = 1001",
strTemplate.formatIndexed("hutool", "user", 1001)
);
Assertions.assertEquals(
assertEquals(
"select * from user where id = 1001",
strTemplate.formatArrayIndexed(new String[]{"hutool", "user", "1001"})
);
Assertions.assertEquals(
assertEquals(
"select * from 123 where id = 456",
strTemplate.formatArrayIndexed(new int[]{666, 123, 456})
);
Assertions.assertEquals(
assertEquals(
"select * from user where id = 1001",
strTemplate.formatIndexed(ListUtil.of("hutool", "user", 1001))
);
Assertions.assertEquals(
assertEquals(
"select * from user where id = ?",
strTemplate.formatIndexed(ListUtil.of("hutool", "user"), idx -> "?")
);
@ -108,22 +110,22 @@ public class StrTemplateTest {
final NamedPlaceholderStrTemplate strTemplate = StrTemplate.ofNamed(text).prefix("#[").suffix("]").build();
final Map<String, Object> map = MapUtil.<String, Object>builder().put("tableName", "user").put("id", 1001).build();
Assertions.assertEquals(
assertEquals(
"select * from user where id = 1001",
strTemplate.format(map)
);
Assertions.assertEquals(
assertEquals(
"select * from user where id = 1001",
strTemplate.format((Object) map)
);
FormatEntity entity = new FormatEntity().setTableName("user").setId(1001);
Assertions.assertEquals(
assertEquals(
"select * from user where id = 1001",
strTemplate.format(entity)
);
entity = new FormatEntity().setTableName("user").setId(1001);
Assertions.assertEquals(
assertEquals(
"select * from user where id = 1001",
strTemplate.format(entity)
);
@ -143,19 +145,19 @@ public class StrTemplateTest {
String text = "i {a}{m} a {jvav} programmer";
NamedPlaceholderStrTemplate.Builder strTemplate = StrTemplate.ofNamed(text)
.addFeatures(StrTemplate.Feature.FORMAT_MISSING_KEY_PRINT_DEFAULT_VALUE);
Assertions.assertEquals(
assertEquals(
"i a programmer",
strTemplate.defaultValue(s -> "")
.build()
.formatSequence()
);
Assertions.assertEquals(
assertEquals(
"i ?? a ? programmer",
strTemplate.defaultValue(s -> "?")
.build()
.formatSequence()
);
Assertions.assertEquals(
assertEquals(
"i $$$$$$ a $$$ programmer",
strTemplate.defaultValue(s -> "$$$")
.build()
@ -164,26 +166,26 @@ public class StrTemplateTest {
text = "select * from #[tableName] where id = #[id]";
strTemplate = StrTemplate.ofNamed(text).prefix("#[").suffix("]");
Assertions.assertEquals(
assertEquals(
"select * from user where id = 1001",
strTemplate.defaultValue(s -> "?")
.build()
.formatSequence("user", 1001)
);
Assertions.assertEquals(
assertEquals(
"select * from user where id = ?",
strTemplate.defaultValue(s -> "?")
.addFeatures(StrTemplate.Feature.FORMAT_MISSING_KEY_PRINT_DEFAULT_VALUE)
.build()
.formatSequence("user")
);
Assertions.assertEquals(
assertEquals(
"select * from user where id = ?",
strTemplate.defaultValue(s -> "?")
.build()
.formatArraySequence(new String[]{"user"})
);
Assertions.assertEquals(
assertEquals(
"select * from user where id = ?",
strTemplate.defaultValue(s -> "?")
.build()
@ -192,19 +194,19 @@ public class StrTemplateTest {
text = "select * from #[1] where id = #[2]";
strTemplate = StrTemplate.ofNamed(text).prefix("#[").suffix("]").addFeatures(StrTemplate.Feature.FORMAT_MISSING_KEY_PRINT_DEFAULT_VALUE);
Assertions.assertEquals(
assertEquals(
"select * from user where id = ?",
strTemplate.defaultValue(s -> "?")
.build()
.formatIndexed("hutool", "user")
);
Assertions.assertEquals(
assertEquals(
"select * from user where id = ?",
strTemplate.defaultValue(s -> "?")
.build()
.formatArrayIndexed(new String[]{"hutool", "user"})
);
Assertions.assertEquals(
assertEquals(
"select * from user where id = ?",
strTemplate.defaultValue(s -> "?")
.build()
@ -218,13 +220,13 @@ public class StrTemplateTest {
// 转义符
String text = "select * from \\#[tableName] where id = \\#[id]";
NamedPlaceholderStrTemplate strTemplate = StrTemplate.ofNamed(text).prefix("#[").suffix("]").build();
Assertions.assertEquals(
assertEquals(
"select * from #[tableName] where id = #[id]",
strTemplate.format(map)
);
text = "select * from \\#[tableName] where id = #[id\\]]";
strTemplate = StrTemplate.ofNamed(text).prefix("#[").suffix("]").build();
Assertions.assertEquals(
assertEquals(
"select * from #[tableName] where id = 1001",
strTemplate.format(MapUtil.<String, Object>builder().put("tableName", "user").put("id]", 1001).build())
);
@ -232,25 +234,25 @@ public class StrTemplateTest {
// 转义 转义符
text = "select * from \\\\#[tableName] where id = #[id]";
strTemplate = StrTemplate.ofNamed(text).prefix("#[").suffix("]").build();
Assertions.assertEquals(
assertEquals(
"select * from \\user where id = 1001",
strTemplate.format(map)
);
text = "select * from \\\\#[tableName] where id = \\\\#[id]";
strTemplate = StrTemplate.ofNamed(text).prefix("#[").suffix("]").build();
Assertions.assertEquals(
assertEquals(
"select * from \\user where id = \\1001",
strTemplate.format(map)
);
text = "select * from \\\\#[tableName] where id = #[id\\\\]";
strTemplate = StrTemplate.ofNamed(text).prefix("#[").suffix("]").build();
Assertions.assertEquals(
assertEquals(
"select * from \\user where id = 1001",
strTemplate.format(MapUtil.<String, Object>builder().put("tableName", "user").put("id\\", 1001).build())
);
text = "select * from #[tableName\\\\] where id = #[id\\\\]";
strTemplate = StrTemplate.ofNamed(text).prefix("#[").suffix("]").build();
Assertions.assertEquals(
assertEquals(
"select * from user where id = 1001",
strTemplate.format(MapUtil.<String, Object>builder().put("tableName\\", "user").put("id\\", 1001).build())
);
@ -258,19 +260,19 @@ public class StrTemplateTest {
// 自定义 转义符
text = "select * from /#[tableName] where id = /#[id]";
strTemplate = StrTemplate.ofNamed(text).prefix("#[").suffix("]").escape('/').build();
Assertions.assertEquals(
assertEquals(
"select * from #[tableName] where id = #[id]",
strTemplate.format(map)
);
text = "select * from //#[tableName] where id = //#[id]";
strTemplate = StrTemplate.ofNamed(text).prefix("#[").suffix("]").escape('/').build();
Assertions.assertEquals(
assertEquals(
"select * from /user where id = /1001",
strTemplate.format(map)
);
text = "select * from /#[tableName] where id = #[id/]]";
strTemplate = StrTemplate.ofNamed(text).prefix("#[").suffix("]").escape('/').build();
Assertions.assertEquals(
assertEquals(
"select * from #[tableName] where id = 1001",
strTemplate.format(MapUtil.<String, Object>builder().put("tableName", "user").put("id]", 1001).build())
);
@ -286,21 +288,21 @@ public class StrTemplateTest {
// 普通使用
Assertions.assertEquals("this is a for 666",
assertEquals("this is a for 666",
template.format("a", 666)
);
Assertions.assertEquals("this is a for 666",
assertEquals("this is a for 666",
template.format(ListUtil.of("a", 666))
);
Assertions.assertEquals("this is 123 for 456",
assertEquals("this is 123 for 456",
template.formatArray(new int[]{123, 456})
);
Assertions.assertEquals("this is 123 for 456",
assertEquals("this is 123 for 456",
template.formatArray(new Integer[]{123, 456})
);
// 转义占位符
Assertions.assertEquals("this is " + placeholder + " for a",
assertEquals("this is " + placeholder + " for a",
StrTemplate.of("this is " + escape + placeholder + " for " + placeholder)
.placeholder(placeholder)
.escape(escape)
@ -308,7 +310,7 @@ public class StrTemplateTest {
.format("a", "b")
);
// 转义"转义符"
Assertions.assertEquals("this is " + escape + "a for b",
assertEquals("this is " + escape + "a for b",
StrTemplate.of("this is " + escape + escape + placeholder + " for " + placeholder)
.placeholder(placeholder)
.escape(escape)
@ -316,15 +318,15 @@ public class StrTemplateTest {
.format("a", "b")
);
// 填充null值
Assertions.assertEquals("this is " + null + " for b",
assertEquals("this is " + null + " for b",
template.format(null, "b")
);
Assertions.assertEquals("this is a for null",
assertEquals("this is a for null",
template.format("a", null)
);
// 序列化参数 小于 占位符数量
Assertions.assertEquals("this is a for " + placeholder,
assertEquals("this is a for " + placeholder,
template.format("a")
);
@ -334,12 +336,12 @@ public class StrTemplateTest {
.escape(escape)
.addFeatures(StrTemplate.Feature.FORMAT_MISSING_KEY_PRINT_DEFAULT_VALUE);
Assertions.assertEquals("this is a for ",
assertEquals("this is a for ",
builder.defaultValue("")
.build()
.format("a")
);
Assertions.assertEquals("this is a for 666",
assertEquals("this is a for 666",
builder.defaultValue("666")
.build()
.format("a")
@ -349,41 +351,41 @@ public class StrTemplateTest {
.placeholder(placeholder)
.escape(escape)
.addFeatures(StrTemplate.Feature.FORMAT_MISSING_KEY_PRINT_DEFAULT_VALUE);
Assertions.assertEquals("this is a for ",
assertEquals("this is a for ",
builder.defaultValue(s -> "")
.build()
.format("a")
);
Assertions.assertEquals("this is a for 666",
assertEquals("this is a for 666",
builder.defaultValue(s -> "666")
.build()
.format("a")
);
// 序列化参数 超过 占位符数量
Assertions.assertEquals("this is a for b",
assertEquals("this is a for b",
builder.build()
.format("a", "b", "c")
);
// 残缺的占位符
if (placeholder.length() >= 2) {
Assertions.assertEquals("this is " + placeholder.charAt(0) + " for a",
assertEquals("this is " + placeholder.charAt(0) + " for a",
StrTemplate.of("this is " + placeholder.charAt(0) + " for " + placeholder)
.placeholder(placeholder)
.escape(escape)
.build()
.format("a")
);
Assertions.assertEquals("this is " + placeholder.charAt(1) + " for a",
assertEquals("this is " + placeholder.charAt(1) + " for a",
StrTemplate.of("this is " + placeholder.charAt(1) + " for " + placeholder)
.placeholder(placeholder)
.escape(escape)
.build()
.format("a")
);
Assertions.assertEquals("this is " + placeholder.charAt(0) + ' ' + placeholder.charAt(1) + " for a",
assertEquals("this is " + placeholder.charAt(0) + ' ' + placeholder.charAt(1) + " for a",
StrTemplate.of("this is " + placeholder.charAt(0) + ' ' + placeholder.charAt(1) + " for " + placeholder)
.placeholder(placeholder)
.escape(escape)
@ -440,127 +442,127 @@ public class StrTemplateTest {
@Test
public void singlePlaceholderMatchesTest() {
SinglePlaceholderStrTemplate strTemplate = StrTemplate.of("this is {} for {}").build();
Assertions.assertEquals(ListUtil.of("a", "b"), strTemplate.matches("this is a for b"));
Assertions.assertEquals(ListUtil.of("aaa", "666"), strTemplate.matches("this is aaa for 666"));
Assertions.assertEquals(ListUtil.of("a", "b "), strTemplate.matches("this is a for b "));
Assertions.assertEquals(ListUtil.of("a x", "b"), strTemplate.matches("this is a x for b"));
Assertions.assertEquals(ListUtil.of("{}", "{}"), strTemplate.matches("this is {} for {}"));
Assertions.assertEquals(ListUtil.of("{ }", "{}"), strTemplate.matches("this is { } for {}"));
Assertions.assertEquals(ListUtil.of("{ }", "{ }"), strTemplate.matches("this is { } for { }"));
Assertions.assertEquals(ListUtil.of(" a", "b"), strTemplate.matches("this is a for b"));
Assertions.assertEquals(ListUtil.of(" a", " b"), strTemplate.matches("this is a for b"));
Assertions.assertEquals(ListUtil.of("a ", "b"), strTemplate.matches("this is a for b"));
Assertions.assertEquals(ListUtil.of("a", null), strTemplate.matches("this is a for "));
Assertions.assertEquals(ListUtil.of(null, "b"), strTemplate.matches("this is for b"));
Assertions.assertEquals(ListUtil.of(null, null), strTemplate.matches("this is for "));
assertEquals(ListUtil.of("a", "b"), strTemplate.matches("this is a for b"));
assertEquals(ListUtil.of("aaa", "666"), strTemplate.matches("this is aaa for 666"));
assertEquals(ListUtil.of("a", "b "), strTemplate.matches("this is a for b "));
assertEquals(ListUtil.of("a x", "b"), strTemplate.matches("this is a x for b"));
assertEquals(ListUtil.of("{}", "{}"), strTemplate.matches("this is {} for {}"));
assertEquals(ListUtil.of("{ }", "{}"), strTemplate.matches("this is { } for {}"));
assertEquals(ListUtil.of("{ }", "{ }"), strTemplate.matches("this is { } for { }"));
assertEquals(ListUtil.of(" a", "b"), strTemplate.matches("this is a for b"));
assertEquals(ListUtil.of(" a", " b"), strTemplate.matches("this is a for b"));
assertEquals(ListUtil.of("a ", "b"), strTemplate.matches("this is a for b"));
assertEquals(ListUtil.of("a", null), strTemplate.matches("this is a for "));
assertEquals(ListUtil.of(null, "b"), strTemplate.matches("this is for b"));
assertEquals(ListUtil.of(null, null), strTemplate.matches("this is for "));
final List<Object> emptyList = Collections.emptyList();
Assertions.assertEquals(emptyList, strTemplate.matches(""));
Assertions.assertEquals(emptyList, strTemplate.matches(" "));
Assertions.assertEquals(emptyList, strTemplate.matches(" \r\n \n "));
Assertions.assertEquals(emptyList, strTemplate.matches(" this is a for b"));
Assertions.assertEquals(emptyList, strTemplate.matches("this is a forb"));
Assertions.assertEquals(emptyList, strTemplate.matches("this is a for b"));
Assertions.assertEquals(emptyList, strTemplate.matches("this are a for b"));
Assertions.assertEquals(emptyList, strTemplate.matches("that is a for b"));
assertEquals(emptyList, strTemplate.matches(""));
assertEquals(emptyList, strTemplate.matches(" "));
assertEquals(emptyList, strTemplate.matches(" \r\n \n "));
assertEquals(emptyList, strTemplate.matches(" this is a for b"));
assertEquals(emptyList, strTemplate.matches("this is a forb"));
assertEquals(emptyList, strTemplate.matches("this is a for b"));
assertEquals(emptyList, strTemplate.matches("this are a for b"));
assertEquals(emptyList, strTemplate.matches("that is a for b"));
strTemplate = StrTemplate.of("{}, this is for {}").build();
Assertions.assertEquals(ListUtil.of("Cleveland", "you"), strTemplate.matches("Cleveland, this is for you"));
Assertions.assertEquals(ListUtil.of(" Cleveland", "you"), strTemplate.matches(" Cleveland, this is for you"));
Assertions.assertEquals(ListUtil.of("Cleveland ", "you"), strTemplate.matches("Cleveland , this is for you"));
Assertions.assertEquals(ListUtil.of("Cleveland", "you "), strTemplate.matches("Cleveland, this is for you "));
Assertions.assertEquals(ListUtil.of("Cleveland", " you"), strTemplate.matches("Cleveland, this is for you"));
Assertions.assertEquals(ListUtil.of("Cleveland", " you "), strTemplate.matches("Cleveland, this is for you "));
Assertions.assertEquals(ListUtil.of("Cleveland", "you ?"), strTemplate.matches("Cleveland, this is for you ?"));
Assertions.assertEquals(ListUtil.of(":)Cleveland", "you:("), strTemplate.matches(":)Cleveland, this is for you:("));
assertEquals(ListUtil.of("Cleveland", "you"), strTemplate.matches("Cleveland, this is for you"));
assertEquals(ListUtil.of(" Cleveland", "you"), strTemplate.matches(" Cleveland, this is for you"));
assertEquals(ListUtil.of("Cleveland ", "you"), strTemplate.matches("Cleveland , this is for you"));
assertEquals(ListUtil.of("Cleveland", "you "), strTemplate.matches("Cleveland, this is for you "));
assertEquals(ListUtil.of("Cleveland", " you"), strTemplate.matches("Cleveland, this is for you"));
assertEquals(ListUtil.of("Cleveland", " you "), strTemplate.matches("Cleveland, this is for you "));
assertEquals(ListUtil.of("Cleveland", "you ?"), strTemplate.matches("Cleveland, this is for you ?"));
assertEquals(ListUtil.of(":)Cleveland", "you:("), strTemplate.matches(":)Cleveland, this is for you:("));
Assertions.assertEquals(emptyList, strTemplate.matches("Cleveland, this is for you"));
Assertions.assertEquals(emptyList, strTemplate.matches("Cleveland, this is for you"));
Assertions.assertEquals(emptyList, strTemplate.matches("Cleveland, this is for you"));
Assertions.assertEquals(emptyList, strTemplate.matches("Cleveland, this is four you"));
Assertions.assertEquals(emptyList, strTemplate.matches("Cleveland, this are for you"));
Assertions.assertEquals(emptyList, strTemplate.matches("Cleveland, that is for you"));
assertEquals(emptyList, strTemplate.matches("Cleveland, this is for you"));
assertEquals(emptyList, strTemplate.matches("Cleveland, this is for you"));
assertEquals(emptyList, strTemplate.matches("Cleveland, this is for you"));
assertEquals(emptyList, strTemplate.matches("Cleveland, this is four you"));
assertEquals(emptyList, strTemplate.matches("Cleveland, this are for you"));
assertEquals(emptyList, strTemplate.matches("Cleveland, that is for you"));
}
@Test
public void namedPlaceholderMatchesSequenceTest() {
NamedPlaceholderStrTemplate strTemplate = StrTemplate.ofNamed("this is {a} for {b}").build();
Assertions.assertEquals(ListUtil.of("a", "b"), strTemplate.matchesSequence("this is a for b"));
Assertions.assertEquals(ListUtil.of("aaa", "666"), strTemplate.matchesSequence("this is aaa for 666"));
Assertions.assertEquals(ListUtil.of("a", "b "), strTemplate.matchesSequence("this is a for b "));
Assertions.assertEquals(ListUtil.of("a x", "b"), strTemplate.matchesSequence("this is a x for b"));
Assertions.assertEquals(ListUtil.of("{}", "{}"), strTemplate.matchesSequence("this is {} for {}"));
Assertions.assertEquals(ListUtil.of("{ }", "{}"), strTemplate.matchesSequence("this is { } for {}"));
Assertions.assertEquals(ListUtil.of("{ }", "{ }"), strTemplate.matchesSequence("this is { } for { }"));
Assertions.assertEquals(ListUtil.of(" a", "b"), strTemplate.matchesSequence("this is a for b"));
Assertions.assertEquals(ListUtil.of(" a", " b"), strTemplate.matchesSequence("this is a for b"));
Assertions.assertEquals(ListUtil.of("a ", "b"), strTemplate.matchesSequence("this is a for b"));
Assertions.assertEquals(ListUtil.of("a", null), strTemplate.matchesSequence("this is a for "));
Assertions.assertEquals(ListUtil.of(null, "b"), strTemplate.matchesSequence("this is for b"));
Assertions.assertEquals(ListUtil.of(null, null), strTemplate.matchesSequence("this is for "));
assertEquals(ListUtil.of("a", "b"), strTemplate.matchesSequence("this is a for b"));
assertEquals(ListUtil.of("aaa", "666"), strTemplate.matchesSequence("this is aaa for 666"));
assertEquals(ListUtil.of("a", "b "), strTemplate.matchesSequence("this is a for b "));
assertEquals(ListUtil.of("a x", "b"), strTemplate.matchesSequence("this is a x for b"));
assertEquals(ListUtil.of("{}", "{}"), strTemplate.matchesSequence("this is {} for {}"));
assertEquals(ListUtil.of("{ }", "{}"), strTemplate.matchesSequence("this is { } for {}"));
assertEquals(ListUtil.of("{ }", "{ }"), strTemplate.matchesSequence("this is { } for { }"));
assertEquals(ListUtil.of(" a", "b"), strTemplate.matchesSequence("this is a for b"));
assertEquals(ListUtil.of(" a", " b"), strTemplate.matchesSequence("this is a for b"));
assertEquals(ListUtil.of("a ", "b"), strTemplate.matchesSequence("this is a for b"));
assertEquals(ListUtil.of("a", null), strTemplate.matchesSequence("this is a for "));
assertEquals(ListUtil.of(null, "b"), strTemplate.matchesSequence("this is for b"));
assertEquals(ListUtil.of(null, null), strTemplate.matchesSequence("this is for "));
final List<Object> emptyList = Collections.emptyList();
Assertions.assertEquals(emptyList, strTemplate.matchesSequence(""));
Assertions.assertEquals(emptyList, strTemplate.matchesSequence(" "));
Assertions.assertEquals(emptyList, strTemplate.matchesSequence(" \r\n \n "));
Assertions.assertEquals(emptyList, strTemplate.matchesSequence(" this is a for b"));
Assertions.assertEquals(emptyList, strTemplate.matchesSequence("this is a forb"));
Assertions.assertEquals(emptyList, strTemplate.matchesSequence("this is a for b"));
Assertions.assertEquals(emptyList, strTemplate.matchesSequence("this are a for b"));
Assertions.assertEquals(emptyList, strTemplate.matchesSequence("that is a for b"));
assertEquals(emptyList, strTemplate.matchesSequence(""));
assertEquals(emptyList, strTemplate.matchesSequence(" "));
assertEquals(emptyList, strTemplate.matchesSequence(" \r\n \n "));
assertEquals(emptyList, strTemplate.matchesSequence(" this is a for b"));
assertEquals(emptyList, strTemplate.matchesSequence("this is a forb"));
assertEquals(emptyList, strTemplate.matchesSequence("this is a for b"));
assertEquals(emptyList, strTemplate.matchesSequence("this are a for b"));
assertEquals(emptyList, strTemplate.matchesSequence("that is a for b"));
strTemplate = StrTemplate.ofNamed("{a}, this is for {b}").build();
Assertions.assertEquals(ListUtil.of("Cleveland", "you"), strTemplate.matchesSequence("Cleveland, this is for you"));
Assertions.assertEquals(ListUtil.of(" Cleveland", "you"), strTemplate.matchesSequence(" Cleveland, this is for you"));
Assertions.assertEquals(ListUtil.of("Cleveland ", "you"), strTemplate.matchesSequence("Cleveland , this is for you"));
Assertions.assertEquals(ListUtil.of("Cleveland", "you "), strTemplate.matchesSequence("Cleveland, this is for you "));
Assertions.assertEquals(ListUtil.of("Cleveland", " you"), strTemplate.matchesSequence("Cleveland, this is for you"));
Assertions.assertEquals(ListUtil.of("Cleveland", " you "), strTemplate.matchesSequence("Cleveland, this is for you "));
Assertions.assertEquals(ListUtil.of("Cleveland", "you ?"), strTemplate.matchesSequence("Cleveland, this is for you ?"));
Assertions.assertEquals(ListUtil.of(":)Cleveland", "you:("), strTemplate.matchesSequence(":)Cleveland, this is for you:("));
assertEquals(ListUtil.of("Cleveland", "you"), strTemplate.matchesSequence("Cleveland, this is for you"));
assertEquals(ListUtil.of(" Cleveland", "you"), strTemplate.matchesSequence(" Cleveland, this is for you"));
assertEquals(ListUtil.of("Cleveland ", "you"), strTemplate.matchesSequence("Cleveland , this is for you"));
assertEquals(ListUtil.of("Cleveland", "you "), strTemplate.matchesSequence("Cleveland, this is for you "));
assertEquals(ListUtil.of("Cleveland", " you"), strTemplate.matchesSequence("Cleveland, this is for you"));
assertEquals(ListUtil.of("Cleveland", " you "), strTemplate.matchesSequence("Cleveland, this is for you "));
assertEquals(ListUtil.of("Cleveland", "you ?"), strTemplate.matchesSequence("Cleveland, this is for you ?"));
assertEquals(ListUtil.of(":)Cleveland", "you:("), strTemplate.matchesSequence(":)Cleveland, this is for you:("));
Assertions.assertEquals(emptyList, strTemplate.matchesSequence("Cleveland, this is for you"));
Assertions.assertEquals(emptyList, strTemplate.matchesSequence("Cleveland, this is for you"));
Assertions.assertEquals(emptyList, strTemplate.matchesSequence("Cleveland, this is for you"));
Assertions.assertEquals(emptyList, strTemplate.matchesSequence("Cleveland, this is four you"));
Assertions.assertEquals(emptyList, strTemplate.matchesSequence("Cleveland, this are for you"));
Assertions.assertEquals(emptyList, strTemplate.matchesSequence("Cleveland, that is for you"));
assertEquals(emptyList, strTemplate.matchesSequence("Cleveland, this is for you"));
assertEquals(emptyList, strTemplate.matchesSequence("Cleveland, this is for you"));
assertEquals(emptyList, strTemplate.matchesSequence("Cleveland, this is for you"));
assertEquals(emptyList, strTemplate.matchesSequence("Cleveland, this is four you"));
assertEquals(emptyList, strTemplate.matchesSequence("Cleveland, this are for you"));
assertEquals(emptyList, strTemplate.matchesSequence("Cleveland, that is for you"));
}
@Test
public void namedPlaceholderMatchesIndexedTest() {
NamedPlaceholderStrTemplate strTemplate = StrTemplate.ofNamed("this is {2} for {1}").build();
Assertions.assertEquals(ListUtil.of(null, "b", "a"), strTemplate.matchesIndexed("this is a for b", null));
Assertions.assertEquals(ListUtil.of(null, "666", "aaa"), strTemplate.matchesIndexed("this is aaa for 666", null));
Assertions.assertEquals(ListUtil.of(null, "b", null), strTemplate.matchesIndexed("this is for b", null));
Assertions.assertEquals(ListUtil.of(null, null, "aaa"), strTemplate.matchesIndexed("this is aaa for ", null));
Assertions.assertEquals(ListUtil.of(null, null, null), strTemplate.matchesIndexed("this is for ", null));
assertEquals(ListUtil.of(null, "b", "a"), strTemplate.matchesIndexed("this is a for b", null));
assertEquals(ListUtil.of(null, "666", "aaa"), strTemplate.matchesIndexed("this is aaa for 666", null));
assertEquals(ListUtil.of(null, "b", null), strTemplate.matchesIndexed("this is for b", null));
assertEquals(ListUtil.of(null, null, "aaa"), strTemplate.matchesIndexed("this is aaa for ", null));
assertEquals(ListUtil.of(null, null, null), strTemplate.matchesIndexed("this is for ", null));
strTemplate = StrTemplate.ofNamed("this is {2} for {1}")
.addFeatures(StrTemplate.Feature.MATCH_EMPTY_VALUE_TO_DEFAULT_VALUE)
.build();
Assertions.assertEquals(ListUtil.of(null, "b", "a"), strTemplate.matchesIndexed("this is a for b", idx -> "?"));
Assertions.assertEquals(ListUtil.of(null, "666", "aaa"), strTemplate.matchesIndexed("this is aaa for 666", idx -> "?"));
Assertions.assertEquals(ListUtil.of(null, "b", "?"), strTemplate.matchesIndexed("this is for b", idx -> "?"));
Assertions.assertEquals(ListUtil.of(null, "?", "aaa"), strTemplate.matchesIndexed("this is aaa for ", idx -> "?"));
Assertions.assertEquals(ListUtil.of(null, "?", "?"), strTemplate.matchesIndexed("this is for ", idx -> "?"));
assertEquals(ListUtil.of(null, "b", "a"), strTemplate.matchesIndexed("this is a for b", idx -> "?"));
assertEquals(ListUtil.of(null, "666", "aaa"), strTemplate.matchesIndexed("this is aaa for 666", idx -> "?"));
assertEquals(ListUtil.of(null, "b", "?"), strTemplate.matchesIndexed("this is for b", idx -> "?"));
assertEquals(ListUtil.of(null, "?", "aaa"), strTemplate.matchesIndexed("this is aaa for ", idx -> "?"));
assertEquals(ListUtil.of(null, "?", "?"), strTemplate.matchesIndexed("this is for ", idx -> "?"));
strTemplate = StrTemplate.ofNamed("this is {2} for {1}").build();
final List<Object> emptyList = Collections.emptyList();
Assertions.assertEquals(emptyList, strTemplate.matchesIndexed("", null));
Assertions.assertEquals(emptyList, strTemplate.matchesIndexed(" ", null));
Assertions.assertEquals(emptyList, strTemplate.matchesIndexed(" \r\n \n ", null));
Assertions.assertEquals(emptyList, strTemplate.matchesIndexed(" this is a for b", null));
Assertions.assertEquals(emptyList, strTemplate.matchesIndexed("this is a forb", null));
Assertions.assertEquals(emptyList, strTemplate.matchesIndexed("this is a for b", null));
Assertions.assertEquals(emptyList, strTemplate.matchesIndexed("this are a for b", null));
Assertions.assertEquals(emptyList, strTemplate.matchesIndexed("that is a for b", null));
assertEquals(emptyList, strTemplate.matchesIndexed("", null));
assertEquals(emptyList, strTemplate.matchesIndexed(" ", null));
assertEquals(emptyList, strTemplate.matchesIndexed(" \r\n \n ", null));
assertEquals(emptyList, strTemplate.matchesIndexed(" this is a for b", null));
assertEquals(emptyList, strTemplate.matchesIndexed("this is a forb", null));
assertEquals(emptyList, strTemplate.matchesIndexed("this is a for b", null));
assertEquals(emptyList, strTemplate.matchesIndexed("this are a for b", null));
assertEquals(emptyList, strTemplate.matchesIndexed("that is a for b", null));
Assertions.assertEquals(emptyList, strTemplate.matchesIndexed(" this is a for b", idx -> "?"));
Assertions.assertEquals(emptyList, strTemplate.matchesIndexed("this is a forb", idx -> "?"));
Assertions.assertEquals(emptyList, strTemplate.matchesIndexed("this is a for b", idx -> "?"));
Assertions.assertEquals(emptyList, strTemplate.matchesIndexed("this are a for b", idx -> "?"));
Assertions.assertEquals(emptyList, strTemplate.matchesIndexed("that is a for b", idx -> "?"));
assertEquals(emptyList, strTemplate.matchesIndexed(" this is a for b", idx -> "?"));
assertEquals(emptyList, strTemplate.matchesIndexed("this is a forb", idx -> "?"));
assertEquals(emptyList, strTemplate.matchesIndexed("this is a for b", idx -> "?"));
assertEquals(emptyList, strTemplate.matchesIndexed("this are a for b", idx -> "?"));
assertEquals(emptyList, strTemplate.matchesIndexed("that is a for b", idx -> "?"));
}
@ -568,19 +570,19 @@ public class StrTemplateTest {
public void namedPlaceholderMatchesTest() {
final NamedPlaceholderStrTemplate strTemplate = StrTemplate.ofNamed("this is {tableName} for {id}").build();
final Supplier<Map<String, String>> mapSupplier = HashMap::new;
Assertions.assertEquals(MapUtil.builder("tableName", "aaa").put("id", "666").build(), strTemplate.matches("this is aaa for 666", mapSupplier));
Assertions.assertEquals(MapUtil.builder("tableName", null).put("id", "666").build(), strTemplate.matches("this is for 666", mapSupplier));
Assertions.assertEquals(MapUtil.builder("tableName", "aaa").put("id", null).build(), strTemplate.matches("this is aaa for ", mapSupplier));
Assertions.assertEquals(MapUtil.builder("tableName", null).put("id", null).build(), strTemplate.matches("this is for ", mapSupplier));
Assertions.assertEquals(Collections.emptyMap(), strTemplate.matches("", mapSupplier));
assertEquals(MapUtil.builder("tableName", "aaa").put("id", "666").build(), strTemplate.matches("this is aaa for 666", mapSupplier));
assertEquals(MapUtil.builder("tableName", null).put("id", "666").build(), strTemplate.matches("this is for 666", mapSupplier));
assertEquals(MapUtil.builder("tableName", "aaa").put("id", null).build(), strTemplate.matches("this is aaa for ", mapSupplier));
assertEquals(MapUtil.builder("tableName", null).put("id", null).build(), strTemplate.matches("this is for ", mapSupplier));
assertEquals(Collections.emptyMap(), strTemplate.matches("", mapSupplier));
final Supplier<FormatEntity> beanSupplier = FormatEntity::new;
Assertions.assertEquals(new FormatEntity("aaa", 666), strTemplate.matches("this is aaa for 666", beanSupplier));
Assertions.assertEquals(new FormatEntity(null, 666), strTemplate.matches("this is for 666", beanSupplier));
Assertions.assertEquals(new FormatEntity("aaa", null), strTemplate.matches("this is aaa for ", beanSupplier));
Assertions.assertEquals(new FormatEntity(null, null), strTemplate.matches("this is for ", beanSupplier));
Assertions.assertEquals(new FormatEntity(), strTemplate.matches("", beanSupplier));
assertEquals(new FormatEntity("aaa", 666), strTemplate.matches("this is aaa for 666", beanSupplier));
assertEquals(new FormatEntity(null, 666), strTemplate.matches("this is for 666", beanSupplier));
assertEquals(new FormatEntity("aaa", null), strTemplate.matches("this is aaa for ", beanSupplier));
assertEquals(new FormatEntity(null, null), strTemplate.matches("this is for ", beanSupplier));
assertEquals(new FormatEntity(), strTemplate.matches("", beanSupplier));
}
@Test
@ -603,7 +605,7 @@ public class StrTemplateTest {
final NamedPlaceholderStrTemplate template2 = StrTemplate.ofNamed(commonTemplate)
.removeFeatures(StrTemplate.Feature.FORMAT_MISSING_KEY_PRINT_WHOLE_PLACEHOLDER)
.build();
Assertions.assertEquals("this is aaa for 666", template2.format(MapUtil.builder("tableName", "aaa").put("id", "666").build()));
assertEquals("this is aaa for 666", template2.format(MapUtil.builder("tableName", "aaa").put("id", "666").build()));
Assertions.assertThrows(HutoolException.class, () -> template2.format(MapUtil.builder("tableName", "aaa").build()));
// ##### 空字符串策略 #####
@ -611,73 +613,73 @@ public class StrTemplateTest {
// 解析时空字符串 转为 null值
.addFeatures(StrTemplate.Feature.FORMAT_MISSING_KEY_PRINT_EMPTY, StrTemplate.Feature.MATCH_EMPTY_VALUE_TO_NULL)
.build();
Assertions.assertEquals("this is aaa for ", template.format(MapUtil.builder("tableName", "aaa").build()));
Assertions.assertEquals(MapUtil.builder("tableName", "aaa").put("id", null).build(), template.matches("this is aaa for null"));
assertEquals("this is aaa for ", template.format(MapUtil.builder("tableName", "aaa").build()));
assertEquals(MapUtil.builder("tableName", "aaa").put("id", null).build(), template.matches("this is aaa for null"));
// 解析时空字符串 转为 默认值
template = StrTemplate.ofNamed(commonTemplate)
.addFeatures(StrTemplate.Feature.FORMAT_MISSING_KEY_PRINT_EMPTY, StrTemplate.Feature.MATCH_EMPTY_VALUE_TO_DEFAULT_VALUE)
.defaultValue("?")
.build();
Assertions.assertEquals("this is aaa for ", template.format(MapUtil.builder("tableName", "aaa").build()));
Assertions.assertEquals(MapUtil.builder("tableName", "aaa").put("id", "?").build(), template.matches("this is aaa for "));
assertEquals("this is aaa for ", template.format(MapUtil.builder("tableName", "aaa").build()));
assertEquals(MapUtil.builder("tableName", "aaa").put("id", "?").build(), template.matches("this is aaa for "));
// 默认值 空字符串解析时空字符串 转为 默认值
template = StrTemplate.ofNamed(commonTemplate)
.addFeatures(StrTemplate.Feature.FORMAT_MISSING_KEY_PRINT_EMPTY, StrTemplate.Feature.MATCH_EMPTY_VALUE_TO_DEFAULT_VALUE)
.defaultValue("")
.build();
Assertions.assertEquals("this is aaa for ", template.format(MapUtil.builder("tableName", "aaa").build()));
Assertions.assertEquals(MapUtil.builder("tableName", "aaa").put("id", "").build(), template.matches("this is aaa for "));
assertEquals("this is aaa for ", template.format(MapUtil.builder("tableName", "aaa").build()));
assertEquals(MapUtil.builder("tableName", "aaa").put("id", "").build(), template.matches("this is aaa for "));
// ##### null值策略 #####
// 解析时null字符串 转为 null值
template = StrTemplate.ofNamed(commonTemplate)
.addFeatures(StrTemplate.Feature.FORMAT_MISSING_KEY_PRINT_NULL, StrTemplate.Feature.MATCH_NULL_STR_TO_NULL)
.build();
Assertions.assertEquals("this is aaa for null", template.format(MapUtil.builder("tableName", "aaa").build()));
Assertions.assertEquals(MapUtil.builder("tableName", "aaa").put("id", null).build(), template.matches("this is aaa for null"));
assertEquals("this is aaa for null", template.format(MapUtil.builder("tableName", "aaa").build()));
assertEquals(MapUtil.builder("tableName", "aaa").put("id", null).build(), template.matches("this is aaa for null"));
// 格式化时null值 转为 默认值 解析时null字符串 转为 null值
template = StrTemplate.ofNamed(commonTemplate)
.addFeatures(StrTemplate.Feature.FORMAT_MISSING_KEY_PRINT_DEFAULT_VALUE, StrTemplate.Feature.MATCH_NULL_STR_TO_NULL)
.defaultValue("null")
.build();
Assertions.assertEquals("this is aaa for null", template.format(MapUtil.builder("tableName", "aaa").build()));
Assertions.assertEquals(MapUtil.builder("tableName", "aaa").put("id", null).build(), template.matches("this is aaa for null"));
assertEquals("this is aaa for null", template.format(MapUtil.builder("tableName", "aaa").build()));
assertEquals(MapUtil.builder("tableName", "aaa").put("id", null).build(), template.matches("this is aaa for null"));
// 解析时忽略 null字符串
template = StrTemplate.ofNamed(commonTemplate)
.addFeatures(StrTemplate.Feature.FORMAT_MISSING_KEY_PRINT_NULL, StrTemplate.Feature.MATCH_IGNORE_NULL_STR)
.build();
Assertions.assertEquals("this is aaa for null", template.format(MapUtil.builder("tableName", "aaa").build()));
Assertions.assertEquals(MapUtil.builder("tableName", "aaa").build(), template.matches("this is aaa for null"));
assertEquals("this is aaa for null", template.format(MapUtil.builder("tableName", "aaa").build()));
assertEquals(MapUtil.builder("tableName", "aaa").build(), template.matches("this is aaa for null"));
// 格式化时null值 转为 默认值 解析时忽略 null字符串
template = StrTemplate.ofNamed(commonTemplate)
.addFeatures(StrTemplate.Feature.FORMAT_MISSING_KEY_PRINT_DEFAULT_VALUE, StrTemplate.Feature.MATCH_IGNORE_NULL_STR)
.defaultValue("null")
.build();
Assertions.assertEquals("this is aaa for null", template.format(MapUtil.builder("tableName", "aaa").build()));
Assertions.assertEquals(MapUtil.builder("tableName", "aaa").build(), template.matches("this is aaa for null"));
assertEquals("this is aaa for null", template.format(MapUtil.builder("tableName", "aaa").build()));
assertEquals(MapUtil.builder("tableName", "aaa").build(), template.matches("this is aaa for null"));
// 解析时null字符串 依然为 "null"字符串
template = StrTemplate.ofNamed(commonTemplate)
.addFeatures(StrTemplate.Feature.FORMAT_MISSING_KEY_PRINT_NULL, StrTemplate.Feature.MATCH_KEEP_NULL_STR)
.build();
Assertions.assertEquals("this is aaa for null", template.format(MapUtil.builder("tableName", "aaa").build()));
Assertions.assertEquals(MapUtil.builder("tableName", "aaa").put("id", "null").build(), template.matches("this is aaa for null"));
assertEquals("this is aaa for null", template.format(MapUtil.builder("tableName", "aaa").build()));
assertEquals(MapUtil.builder("tableName", "aaa").put("id", "null").build(), template.matches("this is aaa for null"));
}
private void testFeature(final NamedPlaceholderStrTemplate template) {
// 格式化
Assertions.assertEquals("this is aaa for 666", template.format(MapUtil.builder("tableName", "aaa").put("id", "666").build()));
Assertions.assertEquals("this is aaa for ", template.format(MapUtil.builder("tableName", "aaa").build()));
Assertions.assertEquals("this is for 666", template.format(MapUtil.builder("id", "666").build()));
Assertions.assertEquals("this is for ", template.format(MapUtil.builder().build()));
assertEquals("this is aaa for 666", template.format(MapUtil.builder("tableName", "aaa").put("id", "666").build()));
assertEquals("this is aaa for ", template.format(MapUtil.builder("tableName", "aaa").build()));
assertEquals("this is for 666", template.format(MapUtil.builder("id", "666").build()));
assertEquals("this is for ", template.format(MapUtil.builder().build()));
// 解析
Assertions.assertEquals(MapUtil.builder("tableName", "aaa").put("id", "666").build(), template.matches("this is aaa for 666"));
Assertions.assertEquals(MapUtil.builder("tableName", "aaa").build(), template.matches("this is aaa for "));
Assertions.assertEquals(MapUtil.builder("id", "666").build(), template.matches("this is for 666"));
Assertions.assertEquals(MapUtil.builder().build(), template.matches("this is for "));
assertEquals(MapUtil.builder("tableName", "aaa").put("id", "666").build(), template.matches("this is aaa for 666"));
assertEquals(MapUtil.builder("tableName", "aaa").build(), template.matches("this is aaa for "));
assertEquals(MapUtil.builder("id", "666").build(), template.matches("this is for 666"));
assertEquals(MapUtil.builder().build(), template.matches("this is for "));
}
}