实用工具

这里总结了一些比较实用的工具类。

SQL 字符串高亮工具

com.github.chengyuxing.sql.util.SqlHighlighter

在支持 XTERM 的终端中,可输出带有语法高亮的 SQL 字符串:

String highlightIfAnsiCapable(String sql);
String ansi(String sql);

或者通过此方法自己实现 HTML 高亮:

String highlight(String sql, BiFunction<TAG, String, String> replacer);

replacer 会迭代各种类型,通过此方法包裹 HTML 标签。

元组

com.github.chengyuxing.common.tuple

框架内提供了一元组到十元组,通过静态类 Tuples.of(...) 来快捷使用:

DataRow

继承自 LinkedHashMap<String, Object> 的一个实用数据类,提供了一些常用方法。

输入不定常的键值对数据来构建一个 Map :

DataRow of(Object... input);

将实体转为 Map :

DataRow ofEntity(Object entity);

获取一个值并进行转换,如果值为 null ,则依次选择候选者直到不为 null

根据键名:

<T> T getAs(String name, T... defaults);

按顺序取直:

<T> T getAs(int index, T... defaults);

强制转换类型:

String getString(String name, String... defaults);

挑出一些 key 来生成一新的 DataRow:

DataRow pick(String name, String... more);

转为实体:

<T> T toEntity(@NotNull Class<T> clazz, Object... constructorParameters)

日期时间工具

com.github.chengyuxing.common.MostDateTime

字符串转日期时间类型:

MostDateTime of(String datetime)

字符串日期格式支持:

时间部分的加减操作:

MostDateTime minus(long amount, TemporalUnit unit);
MostDateTime plus(long amount, TemporalUnit unit);

格式化:

String toString(String format);

转换为各种类型的日期时间:

Instant toInstant(String datetime);
long toEpochMilli(String datetime);
...

字符串模版格式化工具

com.github.chengyuxing.common.StringFormatter

格式化带有模版占位参数的字符串:

String format(String template, Map<String, ?> data);

例如:

select ${ fields } from test.user
  where ${  cnd}
  and id in (${!idArr})
  or id = ${!idArr.1}

变量:

{
  fields: "id, name",
  cnd: "name = 'cyx'",
  idArr: ["a", "b", "c"]
  }

结果:

select id, name from test.user
  where name = 'cyx'
  and id in ('a', 'b', 'c')
  or id = 'b'

未检查自动关闭接口

com.github.chengyuxing.common.UncheckedCloseable

从里到外依次对实现了 Closeable 的对象进行自动关闭。

构造一个对象:

UncheckedCloseable wrap(AutoCloseable closeable);

继续嵌套:

UncheckedCloseable nest(AutoCloseable closeable);

对象值工具

com.github.chengyuxing.common.util.ValueUtils

平铺 IF-ELSE-ELSE-IF-ELSE 值比较返回满足的值,效果类似 Oracle 的 decode 函数:

Object decode(Object value, Object equal, Object result, Object... more);

从一组候选者中获取第一个不为 null 的值:

<T> T coalesce(T... values);

如果2个值相等则返回 null

Object nullif(Object a, Object b);

使用路径表达式 /a/b/0/name 获取一个深度嵌套对象值:

Object walkDeepValue(Object obj, @NotNull String path);

使用对象表达式 user.name 获取一个深度嵌套对象值:

Object getDeepValue(Object obj, @NotNull String propertyChains);

反射工具

com.github.chengyuxing.common.util.ReflectUtils

判断对象是否是基本的值类型(包括包装类):

boolean isBasicType(Object value);

根据构造函数参数个数和类型获取一个类的实例:

<T> T getInstance(Class<T> clazz, Object... constructorParameters);

字符串工具

com.github.chengyuxing.common.util.StringUtils

使用带有分隔符捕获组的正则表达式对字符串进行分割,返回分割后的字符串集合和分隔符集合:

Pair<List<String>, List<String>> regexSplit(final String s, @Language("Regexp") final String regex, final String groupName);

替换所有匹配的项,并返回替换后的字符串和被替换的内容集合:

graph LR
A["Hello world"] --H|w--> B["#$0#"];
B --> C["#H#ello #w#orld"]
B --> D["H, w"]
Pair<String, List<String>> replaceAll(final String s, @Language("Regexp") final String regex, final String replacement);

判断是否以一组关键字任意一个开头:

boolean startsWiths(String str, String... keywords);

不区分大小写的 indexOf 方法:

int indexOfIgnoreCase(String source, String target);

摘要算法:

String hash(String content, String algorithm);

文件读取工具

com.github.chengyuxing.common.io.FileResource

路径支持 URI 和 Classpath下的资源:

FileResource(@Subst("uri or classpath") String path);

流程控制脚本引擎

com.github.chengyuxing.common.script.parser.FlowControlParser

可在字符串模版中用来根据条件动态生成不同的内容,Rabbit SQL 框架中的动态 SQL 就是基于此进行定制实现。

If 表达式:

#if expression1
     #if expression2
     ...
     #fi
     #if expression3
     ...
     #else
     ...
     #fi
#fi

Guard 表达式:

#guard expression
...
#throw 'message'

Choose 表达式:

#choose
     #when expression1
     ...
     #break
     #when expression2
     ...
     #break
     ...
     #default
     ...
     #break
#end

Switch 表达式:

#switch :key [| pipe1 | pipeN | ...]
     #case var1[, var2, varN,...]
     ...
     #break
     #case var3
     ...
     #break
     ...
     #default
     ...
     #break
#end

For 循环表达式:

  #for item[,idx] of :list [| pipe1 | pipeN | ... ] [delimiter ','] [open ''] [close '']
      ...
  #done

布尔条件表达式:

!(:id >= 0 || :name | length <= 3) && :age > 21