1
0
mirror of https://e.coding.net/circlecloud/YumCore.git synced 2024-11-21 01:38:51 +00:00

feat: 添加自动配置转换解析

Signed-off-by: 502647092 <admin@yumc.pw>
This commit is contained in:
502647092 2016-10-17 00:41:06 +08:00
parent 7711cb3d74
commit 7ee5fc9b40
5 changed files with 209 additions and 130 deletions

View File

@ -30,7 +30,7 @@ import pw.yumc.YumCore.bukkit.Log;
* @version 1.0 * @version 1.0
* @since 2015年11月7日 下午2:36:07 * @since 2015年11月7日 下午2:36:07
*/ */
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({"unchecked"})
public class FileConfig extends AbstractConfig { public class FileConfig extends AbstractConfig {
protected static String VERSION = "Version"; protected static String VERSION = "Version";
@ -67,8 +67,7 @@ public class FileConfig extends AbstractConfig {
/** /**
* 从文件载入配置 * 从文件载入配置
* *
* @param file * @param file 配置文件名称
* 配置文件名称
*/ */
public FileConfig(File file) { public FileConfig(File file) {
Validate.notNull(file, FILE_NOT_BE_NULL); Validate.notNull(file, FILE_NOT_BE_NULL);
@ -78,10 +77,8 @@ public class FileConfig extends AbstractConfig {
/** /**
* 从文件载入配置 * 从文件载入配置
* *
* @param parent * @param parent 文件夹
* 文件夹 * @param filename 配置文件名称
* @param filename
* 配置文件名称
*/ */
public FileConfig(File parent, String filename) { public FileConfig(File parent, String filename) {
init(new File(parent, filename), true); init(new File(parent, filename), true);
@ -90,8 +87,7 @@ public class FileConfig extends AbstractConfig {
/** /**
* 从数据流载入配置文件 * 从数据流载入配置文件
* *
* @param stream * @param stream 数据流
* 数据流
*/ */
public FileConfig(InputStream stream) { public FileConfig(InputStream stream) {
init(stream); init(stream);
@ -100,8 +96,7 @@ public class FileConfig extends AbstractConfig {
/** /**
* 从文件载入配置 * 从文件载入配置
* *
* @param filename * @param filename 配置文件名称
* 配置文件名称
*/ */
public FileConfig(String filename) { public FileConfig(String filename) {
init(new File(plugin.getDataFolder(), filename), true); init(new File(plugin.getDataFolder(), filename), true);
@ -110,10 +105,8 @@ public class FileConfig extends AbstractConfig {
/** /**
* 从文件载入配置 * 从文件载入配置
* *
* @param parent * @param parent 文件夹
* 文件夹 * @param filename 配置文件名称
* @param filename
* 配置文件名称
*/ */
public FileConfig(String parent, String filename) { public FileConfig(String parent, String filename) {
init(new File(parent, filename), true); init(new File(parent, filename), true);
@ -122,12 +115,9 @@ public class FileConfig extends AbstractConfig {
/** /**
* 添加到List末尾 * 添加到List末尾
* *
* @param <E> * @param <E> List内容类型
* List内容类型 * @param path 路径
* @param path * @param obj 对象
* 路径
* @param obj
* 对象
* @return {@link FileConfig} * @return {@link FileConfig}
*/ */
public <E> FileConfig addToList(String path, E obj) { public <E> FileConfig addToList(String path, E obj) {
@ -142,10 +132,8 @@ public class FileConfig extends AbstractConfig {
/** /**
* 添加到StringList末尾 * 添加到StringList末尾
* *
* @param path * @param path 路径
* 路径 * @param obj 字符串
* @param obj
* 字符串
* @return {@link FileConfig} * @return {@link FileConfig}
*/ */
public FileConfig addToStringList(String path, String obj) { public FileConfig addToStringList(String path, String obj) {
@ -156,12 +144,9 @@ public class FileConfig extends AbstractConfig {
/** /**
* 添加到StringList末尾 * 添加到StringList末尾
* *
* @param path * @param path 路径
* 路径 * @param obj 字符串
* @param obj * @param allowrepeat 是否允许重复
* 字符串
* @param allowrepeat
* 是否允许重复
* @return {@link FileConfig} * @return {@link FileConfig}
*/ */
public FileConfig addToStringList(String path, String obj, boolean allowrepeat) { public FileConfig addToStringList(String path, String obj, boolean allowrepeat) {
@ -179,8 +164,7 @@ public class FileConfig extends AbstractConfig {
/** /**
* 获得已颜色转码的文本 * 获得已颜色转码的文本
* *
* @param cfgmsg * @param cfgmsg 待转码的List
* 待转码的List
* @return 颜色转码后的文本 * @return 颜色转码后的文本
*/ */
public List<String> getColorList(List<String> cfgmsg) { public List<String> getColorList(List<String> cfgmsg) {
@ -206,8 +190,7 @@ public class FileConfig extends AbstractConfig {
/** /**
* 获得Location * 获得Location
* *
* @param key * @param key
*
* @return {@link Location} * @return {@link Location}
*/ */
public Location getLocation(String key) { public Location getLocation(String key) {
@ -217,10 +200,8 @@ public class FileConfig extends AbstractConfig {
/** /**
* 获得Location * 获得Location
* *
* @param path * @param path
* * @param def 默认地点
* @param def
* 默认地点
* @return {@link Location} * @return {@link Location}
*/ */
public Location getLocation(String path, Location def) { public Location getLocation(String path, Location def) {
@ -231,8 +212,7 @@ public class FileConfig extends AbstractConfig {
/** /**
* 获得已颜色转码的文本 * 获得已颜色转码的文本
* *
* @param path * @param path 配置路径
* 配置路径
* @return 颜色转码后的文本 * @return 颜色转码后的文本
*/ */
public String getMessage(String path) { public String getMessage(String path) {
@ -242,10 +222,8 @@ public class FileConfig extends AbstractConfig {
/** /**
* 获得已颜色转码的文本 * 获得已颜色转码的文本
* *
* @param path * @param path 配置路径
* 配置路径 * @param def 默认文本
* @param def
* 默认文本
* @return 颜色转码后的文本 * @return 颜色转码后的文本
*/ */
public String getMessage(String path, String def) { public String getMessage(String path, String def) {
@ -259,8 +237,7 @@ public class FileConfig extends AbstractConfig {
/** /**
* 获得已颜色转码的文本 * 获得已颜色转码的文本
* *
* @param path * @param path 配置路径
* 配置路径
* @return 颜色转码后的文本 * @return 颜色转码后的文本
*/ */
public List<String> getMessageList(String path) { public List<String> getMessageList(String path) {
@ -277,8 +254,7 @@ public class FileConfig extends AbstractConfig {
/** /**
* 获得字符串数组 * 获得字符串数组
* *
* @param path * @param path 配置路径
* 配置路径
* @return 字符串数组 * @return 字符串数组
*/ */
public String[] getStringArray(String path) { public String[] getStringArray(String path) {
@ -300,10 +276,8 @@ public class FileConfig extends AbstractConfig {
/** /**
* 比较版本号 * 比较版本号
* *
* @param newver * @param newver 新版本
* 新版本 * @param oldver 旧版本
* @param oldver
* 旧版本
* @return 是否需要更新 * @return 是否需要更新
*/ */
public boolean needUpdate(String newver, String oldver) { public boolean needUpdate(String newver, String oldver) {
@ -340,12 +314,9 @@ public class FileConfig extends AbstractConfig {
/** /**
* 从List移除对象 * 从List移除对象
* *
* @param <E> * @param <E> List内容对象类型
* List内容对象类型 * @param path 路径
* @param path * @param obj 对象
* 路径
* @param obj
* 对象
* @return {@link FileConfig} * @return {@link FileConfig}
*/ */
public <E> FileConfig removeFromList(String path, E obj) { public <E> FileConfig removeFromList(String path, E obj) {
@ -359,10 +330,8 @@ public class FileConfig extends AbstractConfig {
/** /**
* 从StringList移除对象 * 从StringList移除对象
* *
* @param path * @param path 路径
* 路径 * @param obj 对象
* @param obj
* 对象
* @return {@link FileConfig} * @return {@link FileConfig}
*/ */
public FileConfig removeFromStringList(String path, String obj) { public FileConfig removeFromStringList(String path, String obj) {
@ -436,8 +405,7 @@ public class FileConfig extends AbstractConfig {
/** /**
* 备份配置文件 * 备份配置文件
* *
* @param oldcfg * @param oldcfg 配置文件
* 配置文件
*/ */
protected void backupConfig(FileConfig oldcfg) { protected void backupConfig(FileConfig oldcfg) {
String filename = oldcfg.getConfigName(); String filename = oldcfg.getConfigName();
@ -455,8 +423,7 @@ public class FileConfig extends AbstractConfig {
/** /**
* 检查配置文件 * 检查配置文件
* *
* @param file * @param file 配置文件
* 配置文件
*/ */
protected void check(File file) { protected void check(File file) {
String filename = file.getName(); String filename = file.getName();
@ -509,8 +476,7 @@ public class FileConfig extends AbstractConfig {
/** /**
* 初始化FileConfig * 初始化FileConfig
* *
* @param file * @param file 配置文件
* 配置文件
* @return FileConfig * @return FileConfig
*/ */
protected FileConfig init(File file) { protected FileConfig init(File file) {
@ -521,10 +487,8 @@ public class FileConfig extends AbstractConfig {
/** /**
* 初始化FileConfig * 初始化FileConfig
* *
* @param file * @param file 配置文件
* 配置文件 * @param check 是否检查文件
* @param check
* 是否检查文件
* @return FileConfig * @return FileConfig
*/ */
protected FileConfig init(File file, boolean check) { protected FileConfig init(File file, boolean check) {
@ -544,8 +508,7 @@ public class FileConfig extends AbstractConfig {
/** /**
* 初始化FileConfig * 初始化FileConfig
* *
* @param stream * @param stream 输入流
* 输入流
* @return FileConfig * @return FileConfig
*/ */
protected FileConfig init(InputStream stream) { protected FileConfig init(InputStream stream) {
@ -571,10 +534,8 @@ public class FileConfig extends AbstractConfig {
/** /**
* 检查配置文件版本 * 检查配置文件版本
* *
* @param newcfg * @param newcfg 新配置文件
* 新配置文件 * @param oldcfg 旧配置文件
* @param oldcfg
* 旧配置文件
* @return 是否需要升级 * @return 是否需要升级
*/ */
protected boolean needUpdate(FileConfig newcfg, FileConfig oldcfg) { protected boolean needUpdate(FileConfig newcfg, FileConfig oldcfg) {
@ -584,10 +545,8 @@ public class FileConfig extends AbstractConfig {
/** /**
* 更新配置文件 * 更新配置文件
* *
* @param newcfg * @param newcfg 新配置文件
* 新配置文件 * @param oldcfg 旧配置文件
* @param oldcfg
* 旧配置文件
* @return 更新以后的配置文件 * @return 更新以后的配置文件
*/ */
protected FileConfig updateConfig(FileConfig newCfg, FileConfig oldCfg) { protected FileConfig updateConfig(FileConfig newCfg, FileConfig oldCfg) {
@ -597,12 +556,9 @@ public class FileConfig extends AbstractConfig {
/** /**
* 更新配置文件 * 更新配置文件
* *
* @param newCfg * @param newCfg 新的配置文件
* 新的配置文件 * @param oldCfg 老的配置文件
* @param oldCfg * @param force 是否强制更新
* 老的配置文件
* @param force
* 是否强制更新
* @return 更新以后的配置文件 * @return 更新以后的配置文件
*/ */
protected FileConfig updateConfig(FileConfig newCfg, FileConfig oldCfg, boolean force) { protected FileConfig updateConfig(FileConfig newCfg, FileConfig oldCfg, boolean force) {
@ -621,7 +577,8 @@ public class FileConfig extends AbstractConfig {
// 复制旧的数据 // 复制旧的数据
for (String string : oldConfigKeys) { for (String string : oldConfigKeys) {
Object var = oldCfg.get(string); Object var = oldCfg.get(string);
if (var != null && !(var instanceof MemorySection)) { // 需要进行节点检查 还有类型检查 不同类型情况下 使用新配置
if (var != null && !(var instanceof MemorySection) && newCfg.get(string).getClass().equals(var.getClass())) {
Log.debug(String.format(CONFIG_UPDATE_VALUE, string, var)); Log.debug(String.format(CONFIG_UPDATE_VALUE, string, var));
newCfg.set(string, var); newCfg.set(string, var);
} }

View File

@ -0,0 +1,22 @@
package pw.yumc.YumCore.config.exception;
/**
* 配置注入解析异常
*
* @author
* @since 2016年10月5日 下午5:15:43
*/
public class ConfigParseException extends RuntimeException {
public ConfigParseException(Exception e) {
super(e);
}
public ConfigParseException(String string) {
super(string);
}
public ConfigParseException(String string, Exception e) {
super(string, e);
}
}

View File

@ -12,23 +12,27 @@ import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import pw.yumc.YumCore.bukkit.Log; import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.commands.exception.CommandParseException;
import pw.yumc.YumCore.config.annotation.ConfigNode; import pw.yumc.YumCore.config.annotation.ConfigNode;
import pw.yumc.YumCore.config.annotation.Default; import pw.yumc.YumCore.config.annotation.Default;
import pw.yumc.YumCore.config.annotation.Nullable; import pw.yumc.YumCore.config.annotation.Nullable;
import pw.yumc.YumCore.config.exception.ConfigParseException;
/** /**
* 抽象注入配置 * 抽象注入配置
* *
* @since 2016年7月5日 上午10:11:22
* @author * @author
* @since 2016年7月5日 上午10:11:22
*/ */
public abstract class AbstractInjectConfig { public abstract class AbstractInjectConfig {
private static String INJECT_TYPE_ERROR = "配置节点 %s 数据类型不匹配 应该为: %s 但实际为: %s!"; private static String INJECT_TYPE_ERROR = "配置节点 %s 数据类型不匹配 应该为: %s 但实际为: %s!";
private static String INJECT_ERROR = "自动注入配置失败 可能造成插件运行错误 %s: %s!"; private static String INJECT_ERROR = "自动注入配置失败 可能造成插件运行错误 %s: %s!";
private static String DATE_PARSE_ERROR = "配置节点 {0} 日期解析失败 格式应该为: {1} 但输入值为: {2}!";
private static String PATH_NOT_FOUND = "配置节点 %s 丢失 将使用默认值!"; private static String PATH_NOT_FOUND = "配置节点 %s 丢失 将使用默认值!";
private static String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; private static String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
private static SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT); private static SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT);
static {
}
private ConfigurationSection config; private ConfigurationSection config;
/** /**
@ -122,17 +126,9 @@ public abstract class AbstractInjectConfig {
* @throws NoSuchMethodException * @throws NoSuchMethodException
* @throws SecurityException * @throws SecurityException
*/ */
private Object convertType(Class<?> type, String path, Object value) throws ParseException, IllegalAccessException, IllegalArgumentException, InstantiationException, InvocationTargetException, NoSuchMethodException, SecurityException { private Object convertType(Class<?> type, String path, Object value) throws CommandParseException, IllegalAccessException, IllegalArgumentException, InstantiationException, InvocationTargetException, NoSuchMethodException, SecurityException {
switch (type.getName()) { Object result = InjectParse.parse(type, config, path);
case "java.util.Date": return result == null ? hanldeDefault(type, path, value) : result;
return df.parse((String) value);
case "java.util.List":
return config.getList(path);
case "java.util.Map":
return config.getConfigurationSection(path).getValues(true);
default:
return hanldeDefault(type, path, value);
}
} }
/** /**
@ -179,7 +175,7 @@ public abstract class AbstractInjectConfig {
* @throws IllegalArgumentException * @throws IllegalArgumentException
* @throws IllegalAccessException * @throws IllegalAccessException
*/ */
private void hanldeValue(String path, Field field, Object value) throws IllegalAccessException, IllegalArgumentException, InstantiationException, InvocationTargetException, NoSuchMethodException, SecurityException, ParseException { private void hanldeValue(String path, Field field, Object value) throws IllegalAccessException, IllegalArgumentException, InstantiationException, InvocationTargetException, NoSuchMethodException, SecurityException, ConfigParseException {
Class<?> type = field.getType(); Class<?> type = field.getType();
if (!type.equals(value.getClass())) { if (!type.equals(value.getClass())) {
value = convertType(type, path, value); value = convertType(type, path, value);
@ -232,10 +228,10 @@ public abstract class AbstractInjectConfig {
} }
hanldeValue(path, field, value); hanldeValue(path, field, value);
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
Log.w(INJECT_TYPE_ERROR, path, field.getType().getName(), value.getClass().getName()); Log.w(INJECT_TYPE_ERROR, path, field.getType().getName(), value != null ? value.getClass().getName() : "空指针");
Log.debug(ex); Log.debug(ex);
} catch (ParseException e) { } catch (ConfigParseException e) {
Log.w(DATE_PARSE_ERROR, path, DATE_FORMAT, value); Log.w(e.getMessage());
} catch (InstantiationException | InvocationTargetException | NoSuchMethodException | SecurityException | IllegalAccessException ex) { } catch (InstantiationException | InvocationTargetException | NoSuchMethodException | SecurityException | IllegalAccessException ex) {
Log.w(INJECT_ERROR, ex.getClass().getName(), ex.getMessage()); Log.w(INJECT_ERROR, ex.getClass().getName(), ex.getMessage());
Log.debug(ex); Log.debug(ex);

View File

@ -0,0 +1,90 @@
package pw.yumc.YumCore.config.inject;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bukkit.configuration.ConfigurationSection;
import pw.yumc.YumCore.config.exception.ConfigParseException;
/**
* 注入配置类解析
*
* @author
* @since 2016年10月16日 下午3:26:48
*/
public class InjectParse {
private static String DATE_PARSE_ERROR = "配置节点 {0} 日期解析失败 格式应该为: {1} 但输入值为: {2}!";
private static String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
private static SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT);
private static Map<Class, Parse> allparse = new HashMap<>();
static {
new ListParse();
new MapParse();
new DateParse();
}
public static Object parse(Class clazz, ConfigurationSection config, String path) {
return allparse.containsKey(clazz) ? allparse.get(clazz).parse(config, path) : null;
}
/**
* 配置解析注册
*
* @param clazz
*
* @param parse
* 解析类
*/
public static void register(Class clazz, Parse parse) {
allparse.put(clazz, parse);
}
public static class DateParse implements Parse<Date> {
public DateParse() {
allparse.put(Date.class, this);
}
@Override
public Date parse(ConfigurationSection config, String path) {
String value = "0000-00-00 00:00:00";
try {
value = config.getString(path);
return df.parse(value);
} catch (ParseException e) {
throw new ConfigParseException(String.format(DATE_PARSE_ERROR, path, DATE_FORMAT, value), e);
}
}
}
public static class ListParse implements Parse<List> {
public ListParse() {
allparse.put(List.class, this);
}
@Override
public List parse(ConfigurationSection config, String path) {
return config.getList(path);
}
}
public static class MapParse implements Parse<Map> {
public MapParse() {
allparse.put(Map.class, this);
}
@Override
public Map parse(ConfigurationSection config, String path) {
return config.getConfigurationSection(path).getValues(true);
}
}
public static interface Parse<FC> {
public FC parse(ConfigurationSection config, String path);
}
}

View File

@ -15,6 +15,9 @@ import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import pw.yumc.YumCore.bukkit.Log; import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.bukkit.P;
import pw.yumc.YumCore.config.inject.InjectParse;
import pw.yumc.YumCore.config.inject.InjectParse.Parse;
import pw.yumc.YumCore.sql.core.DataBaseCore; import pw.yumc.YumCore.sql.core.DataBaseCore;
import pw.yumc.YumCore.sql.core.KeyValue; import pw.yumc.YumCore.sql.core.KeyValue;
import pw.yumc.YumCore.sql.core.MySQLCore; import pw.yumc.YumCore.sql.core.MySQLCore;
@ -231,29 +234,6 @@ public class DataBase {
} }
// @SuppressWarnings("unchecked")
// public <M> List<M> dbSelect( Class<? extends Model<?>> model, KeyValue selCondition) {
// List<M> modellist = new ArrayList<>();
// String sql = "SELECT " + toKeys(model) + " FROM `" + model.getAnnotation(Entity.class).name() + "`" + (selCondition == null ? "" : " WHERE " + selCondition.toWhereString());
// try {
// ResultSet dbresult = this.dataBaseCore.execute(sql);
// while (dbresult.next()) {
// M m = (M) model.newInstance();
// Field[] fields = model.getDeclaredFields();
// for ( Field col : fields) {
// col.set(m, dbresult.getObject(col.getName()));
// }
// modellist.add(m);
// }
// } catch ( InstantiationException e) {
// info("模型类实例化失败!");
// e.printStackTrace();
// } catch ( Exception e) {
// sqlerr(sql, e);
// }
// return modellist;
// }
/** /**
* 对数据库表进行选择操作 * 对数据库表进行选择操作
* *
@ -283,6 +263,29 @@ public class DataBase {
return kvlist; return kvlist;
} }
// @SuppressWarnings("unchecked")
// public <M> List<M> dbSelect( Class<? extends Model<?>> model, KeyValue selCondition) {
// List<M> modellist = new ArrayList<>();
// String sql = "SELECT " + toKeys(model) + " FROM `" + model.getAnnotation(Entity.class).name() + "`" + (selCondition == null ? "" : " WHERE " + selCondition.toWhereString());
// try {
// ResultSet dbresult = this.dataBaseCore.execute(sql);
// while (dbresult.next()) {
// M m = (M) model.newInstance();
// Field[] fields = model.getDeclaredFields();
// for ( Field col : fields) {
// col.set(m, dbresult.getObject(col.getName()));
// }
// modellist.add(m);
// }
// } catch ( InstantiationException e) {
// info("模型类实例化失败!");
// e.printStackTrace();
// } catch ( Exception e) {
// sqlerr(sql, e);
// }
// return modellist;
// }
/** /**
* 对数据库表进行选择操作 * 对数据库表进行选择操作
* *
@ -489,6 +492,17 @@ public class DataBase {
Log.info(info); Log.info(info);
} }
public static class DataBaseParse implements Parse<DataBase> {
public DataBaseParse() {
InjectParse.register(DataBase.class, this);
}
@Override
public DataBase parse(ConfigurationSection config, String path) {
return DataBase.create(P.instance, config.getConfigurationSection(path));
}
}
// private String toKeys( Class<? extends Model<?>> model) { // private String toKeys( Class<? extends Model<?>> model) {
// Field[] fields = model.getDeclaredFields(); // Field[] fields = model.getDeclaredFields();
// StringBuilder sb = new StringBuilder(); // StringBuilder sb = new StringBuilder();