cn.hutool.setting.GroupedSet Maven / Gradle / Ivy
package cn.hutool.setting;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* 分组化的Set集合类
* 在配置文件中可以用中括号分隔不同的分组,每个分组会放在独立的Set中,用group区别
* 无分组的集合和`[]`分组集合会合并成员,重名的分组也会合并成员
* 分组配置文件如下:
*
*
* [group1]
* aaa
* bbb
* ccc
*
* [group2]
* aaa
* ccc
* ddd
*
*
* @author Looly
* @since 3.1.0
*/
public class GroupedSet extends HashMap> {
private static final long serialVersionUID = -8430706353275835496L;
// private final static Log log = StaticLog.get();
/** 注释符号(当有此符号在行首,表示此行为注释) */
private final static String COMMENT_FLAG_PRE = "#";
/** 分组行识别的环绕标记 */
private final static char[] GROUP_SURROUND = { '[', ']' };
/** 本设置对象的字符集 */
private Charset charset;
/** 设定文件的URL */
private URL groupedSetUrl;
/**
* 基本构造
* 需自定义初始化配置文件
*
* @param charset 字符集
*/
public GroupedSet(Charset charset) {
this.charset = charset;
}
/**
* 构造,使用相对于Class文件根目录的相对路径
*
* @param pathBaseClassLoader 相对路径(相对于当前项目的classes路径)
* @param charset 字符集
*/
public GroupedSet(String pathBaseClassLoader, Charset charset) {
if (null == pathBaseClassLoader) {
pathBaseClassLoader = StrUtil.EMPTY;
}
final URL url = URLUtil.getURL(pathBaseClassLoader);
if (url == null) {
throw new RuntimeException(StrUtil.format("Can not find GroupSet file: [{}]", pathBaseClassLoader));
}
this.init(url, charset);
}
/**
* 构造
*
* @param configFile 配置文件对象
* @param charset 字符集
*/
public GroupedSet(File configFile, Charset charset) {
if (configFile == null) {
throw new RuntimeException("Null GroupSet file!");
}
final URL url = URLUtil.getURL(configFile);
this.init(url, charset);
}
/**
* 构造,相对于classes读取文件
*
* @param path 相对路径
* @param clazz 基准类
* @param charset 字符集
*/
public GroupedSet(String path, Class> clazz, Charset charset) {
final URL url = URLUtil.getURL(path, clazz);
if (url == null) {
throw new RuntimeException(StrUtil.format("Can not find GroupSet file: [{}]", path));
}
this.init(url, charset);
}
/**
* 构造
*
* @param url 设定文件的URL
* @param charset 字符集
*/
public GroupedSet(URL url, Charset charset) {
if (url == null) {
throw new RuntimeException("Null url define!");
}
this.init(url, charset);
}
/**
* 构造
*
* @param pathBaseClassLoader 相对路径(相对于当前项目的classes路径)
*/
public GroupedSet(String pathBaseClassLoader) {
this(pathBaseClassLoader, CharsetUtil.CHARSET_UTF_8);
}
/*--------------------------公有方法 start-------------------------------*/
/**
* 初始化设定文件
*
* @param groupedSetUrl 设定文件的URL
* @param charset 字符集
* @return 成功初始化与否
*/
public boolean init(URL groupedSetUrl, Charset charset) {
if (groupedSetUrl == null) {
throw new RuntimeException("Null GroupSet url or charset define!");
}
this.charset = charset;
this.groupedSetUrl = groupedSetUrl;
return this.load(groupedSetUrl);
}
/**
* 加载设置文件
*
* @param groupedSetUrl 配置文件URL
* @return 加载是否成功
*/
synchronized public boolean load(URL groupedSetUrl) {
if (groupedSetUrl == null) {
throw new RuntimeException("Null GroupSet url define!");
}
// log.debug("Load GroupSet file [{}]", groupedSetUrl.getPath());
InputStream settingStream = null;
try {
settingStream = groupedSetUrl.openStream();
load(settingStream);
} catch (IOException e) {
// log.error(e, "Load GroupSet error!");
return false;
} finally {
IoUtil.close(settingStream);
}
return true;
}
/**
* 重新加载配置文件
*/
public void reload() {
this.load(groupedSetUrl);
}
/**
* 加载设置文件。 此方法不会关闭流对象
*
* @param settingStream 文件流
* @return 加载成功与否
* @throws IOException IO异常
*/
public boolean load(InputStream settingStream) throws IOException {
super.clear();
BufferedReader reader = null;
try {
reader = IoUtil.getReader(settingStream, charset);
// 分组
String group;
LinkedHashSet valueSet = null;
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
line = line.trim();
// 跳过注释行和空行
if (StrUtil.isBlank(line) || line.startsWith(COMMENT_FLAG_PRE)) {
// 空行和注释忽略
continue;
} else if (line.startsWith(StrUtil.BACKSLASH + COMMENT_FLAG_PRE)) {
// 对于值中出现开头为#的字符串,需要转义处理,在此做反转义
line = line.substring(1);
}
// 记录分组名
if (line.charAt(0) == GROUP_SURROUND[0] && line.charAt(line.length() - 1) == GROUP_SURROUND[1]) {
// 开始新的分组取值,当出现重名分组时候,合并分组值
group = line.substring(1, line.length() - 1).trim();
valueSet = super.get(group);
if (null == valueSet) {
valueSet = new LinkedHashSet<>();
}
super.put(group, valueSet);
continue;
}
// 添加值
if (null == valueSet) {
// 当出现无分组值的时候,会导致valueSet为空,此时group为""
valueSet = new LinkedHashSet<>();
super.put(StrUtil.EMPTY, valueSet);
}
valueSet.add(line);
}
} finally {
IoUtil.close(reader);
}
return true;
}
/**
* @return 获得设定文件的路径
*/
public String getPath() {
return groupedSetUrl.getPath();
}
/**
* @return 获得所有分组名
*/
public Set getGroups() {
return super.keySet();
}
/**
* 获得对应分组的所有值
*
* @param group 分组名
* @return 分组的值集合
*/
public LinkedHashSet getValues(String group) {
if (group == null) {
group = StrUtil.EMPTY;
}
return super.get(group);
}
/**
* 是否在给定分组的集合中包含指定值
* 如果给定分组对应集合不存在,则返回false
*
* @param group 分组名
* @param value 测试的值
* @param otherValues 其他值
* @return 是否包含
*/
public boolean contains(String group, String value, String... otherValues) {
if (ArrayUtil.isNotEmpty(otherValues)) {
// 需要测试多个值的情况
final List valueList = ListUtil.toList(otherValues);
valueList.add(value);
return contains(group, valueList);
} else {
// 测试单个值
final LinkedHashSet valueSet = getValues(group);
if (CollectionUtil.isEmpty(valueSet)) {
return false;
}
return valueSet.contains(value);
}
}
/**
* 是否在给定分组的集合中全部包含指定值集合
* 如果给定分组对应集合不存在,则返回false
*
* @param group 分组名
* @param values 测试的值集合
* @return 是否包含
*/
public boolean contains(String group, Collection values) {
final LinkedHashSet valueSet = getValues(group);
if (CollectionUtil.isEmpty(values) || CollectionUtil.isEmpty(valueSet)) {
return false;
}
return valueSet.containsAll(values);
}
}