BukkitYAML
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.BufferedWriter; | |
import java.io.File; | |
import java.io.FileWriter; | |
import java.io.IOException; | |
import java.io.Writer; | |
import org.bukkit.configuration.InvalidConfigurationException; | |
import org.bukkit.configuration.file.YamlConfiguration; | |
/* | |
* Bungee's SuperEasyConfig - Config | |
* | |
* Based off of MrFigg's SuperEasyConfig v1.2 | |
* which was inspired by codename_Bs | |
* which was inspired by md_5 | |
* which was inspired by... oh no, that's it. | |
* | |
* Includes support for Guava Library's collection types. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
* | |
* @author MrFigg | |
* @author roblabla | |
* | |
* @version 1.2 | |
*/ | |
public abstract class Config extends ConfigObject { | |
protected transient File CONFIG_FILE = null; | |
protected transient String CONFIG_HEADER = null; | |
public Config() { | |
CONFIG_HEADER = null; | |
} | |
public Config load(File file) throws InvalidConfigurationException { | |
if(file==null) throw new InvalidConfigurationException(new NullPointerException()); | |
if(!file.exists()) throw new InvalidConfigurationException(new IOException("File doesn't exist")); | |
CONFIG_FILE = file; | |
return reload(); | |
} | |
public Config reload() throws InvalidConfigurationException { | |
if(CONFIG_FILE==null) throw new InvalidConfigurationException(new NullPointerException()); | |
if(!CONFIG_FILE.exists()) throw new InvalidConfigurationException(new IOException("File doesn't exist")); | |
YamlConfiguration yamlConfig = YamlConfiguration.loadConfiguration(CONFIG_FILE); | |
try { | |
onLoad(yamlConfig); | |
yamlConfig.save(CONFIG_FILE); | |
} catch(Exception ex) { | |
throw new InvalidConfigurationException(ex); | |
} | |
return this; | |
} | |
public Config save(File file) throws InvalidConfigurationException { | |
if(file==null) throw new InvalidConfigurationException(new NullPointerException()); | |
CONFIG_FILE = file; | |
return save(); | |
} | |
public Config save() throws InvalidConfigurationException { | |
if(CONFIG_FILE==null) throw new InvalidConfigurationException(new NullPointerException()); | |
if(!CONFIG_FILE.exists()) { | |
try { | |
if(CONFIG_FILE.getParentFile() != null) CONFIG_FILE.getParentFile().mkdirs(); | |
CONFIG_FILE.createNewFile(); | |
if(CONFIG_HEADER!=null) { | |
Writer newConfig = new BufferedWriter(new FileWriter(CONFIG_FILE)); | |
for(String line : CONFIG_HEADER.split("\n")) { | |
newConfig.write("# "+line+"\n"); | |
} | |
newConfig.close(); | |
} | |
} catch(Exception ex) { | |
throw new InvalidConfigurationException(ex); | |
} | |
} | |
YamlConfiguration yamlConfig = YamlConfiguration.loadConfiguration(CONFIG_FILE); | |
try { | |
onSave(yamlConfig); | |
yamlConfig.save(CONFIG_FILE); | |
} catch(Exception ex) { | |
throw new InvalidConfigurationException(ex); | |
} | |
return this; | |
} | |
public Config init(File file) throws InvalidConfigurationException { | |
if(file==null) throw new InvalidConfigurationException(new NullPointerException()); | |
CONFIG_FILE = file; | |
return init(); | |
} | |
public Config init() throws InvalidConfigurationException { | |
if(CONFIG_FILE==null) throw new InvalidConfigurationException(new NullPointerException()); | |
if(CONFIG_FILE.exists()) return reload(); | |
else return save(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.reflect.Field; | |
import java.lang.reflect.Modifier; | |
import java.lang.reflect.ParameterizedType; | |
import java.lang.reflect.Type; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Set; | |
import org.bukkit.Bukkit; | |
import org.bukkit.Location; | |
import org.bukkit.World; | |
import org.bukkit.configuration.ConfigurationSection; | |
import org.bukkit.configuration.InvalidConfigurationException; | |
import org.bukkit.util.Vector; | |
import org.json.simple.JSONObject; | |
import org.json.simple.parser.JSONParser; | |
import com.google.common.collect.ArrayListMultimap; | |
import com.google.common.collect.HashBasedTable; | |
import com.google.common.collect.Multimap; | |
import com.google.common.collect.Table; | |
/* | |
* BukkitYAML - ConfigObject | |
* | |
* Based off of MrFigg's SuperEasyConfig v1.2 | |
* which was inspired by codename_Bs | |
* which was inspired by md_5 | |
* which was inspired by... oh no, that's it. | |
* | |
* Includes support for Guava Library's collection types. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
* | |
* @author MrFigg | |
* @author roblabla | |
* | |
* @version 1.2 | |
*/ | |
public abstract class ConfigObject { | |
/* | |
* loading and saving | |
*/ | |
protected void onLoad(ConfigurationSection cs) throws Exception { | |
for(Field field : getClass().getDeclaredFields()) { | |
String path = field.getName().replaceAll("_", "."); | |
if(doSkip(field)) { | |
// Do nothing | |
} else if(cs.isSet(path)) { | |
field.set(this, loadObject(field, cs, path)); | |
} else { | |
cs.set(path, saveObject(field.get(this), field, cs, path)); | |
} | |
} | |
} | |
protected void onSave(ConfigurationSection cs) throws Exception { | |
for(Field field : getClass().getDeclaredFields()) { | |
String path = field.getName().replaceAll("_", "."); | |
if(doSkip(field)) { | |
// Do nothing | |
} else { | |
cs.set(path, saveObject(field.get(this), field, cs, path)); | |
} | |
} | |
} | |
protected Object loadObject(Field field, ConfigurationSection cs, String path) throws Exception { | |
return loadObject(field, cs, path, 0); | |
} | |
protected Object saveObject(Object obj, Field field, ConfigurationSection cs, String path) throws Exception { | |
return saveObject(obj, field, cs, path, 0); | |
} | |
@SuppressWarnings("rawtypes") | |
protected Object loadObject(Field field, ConfigurationSection cs, String path, int depth) throws Exception { | |
Class clazz = getClassAtDepth(field.getGenericType(), depth); | |
if(ConfigObject.class.isAssignableFrom(clazz)&&isConfigurationSection(cs.get(path))) { | |
return getConfigObject(clazz, cs.getConfigurationSection(path)); | |
} else if(Location.class.isAssignableFrom(clazz)&&isJSON(cs.get(path))) { | |
return getLocation((String) cs.get(path)); | |
} else if(Vector.class.isAssignableFrom(clazz)&&isJSON(cs.get(path))) { | |
return getVector((String) cs.get(path)); | |
} else if(Map.class.isAssignableFrom(clazz)&&isConfigurationSection(cs.get(path))) { | |
return getMap(field, cs.getConfigurationSection(path), path, depth); | |
} else if(clazz.isEnum()&&isString(cs.get(path))) { | |
return getEnum(clazz, (String) cs.get(path)); | |
} else if(List.class.isAssignableFrom(clazz)&&isConfigurationSection(cs.get(path))) { | |
Class subClazz = getClassAtDepth(field.getGenericType(), depth+1); | |
if(ConfigObject.class.isAssignableFrom(subClazz)||Location.class.isAssignableFrom(subClazz)||Vector.class.isAssignableFrom(subClazz)||Map.class.isAssignableFrom(subClazz)||List.class.isAssignableFrom(subClazz)||subClazz.isEnum()) { | |
return getList(field, cs.getConfigurationSection(path), path, depth); | |
} else { | |
return cs.get(path); | |
} | |
} else { | |
return cs.get(path); | |
} | |
} | |
@SuppressWarnings("rawtypes") | |
protected Object saveObject(Object obj, Field field, ConfigurationSection cs, String path, int depth) throws Exception { | |
Class clazz = getClassAtDepth(field.getGenericType(), depth); | |
if(ConfigObject.class.isAssignableFrom(clazz)&&isConfigObject(obj)) { | |
return getConfigObject((ConfigObject) obj, path, cs); | |
} else if(Location.class.isAssignableFrom(clazz)&&isLocation(obj)) { | |
return getLocation((Location) obj); | |
} else if(Vector.class.isAssignableFrom(clazz)&&isVector(obj)) { | |
return getVector((Vector) obj); | |
} else if(Map.class.isAssignableFrom(clazz)&&isMap(obj)) { | |
return getMap((Map) obj, field, cs, path, depth); | |
} else if(clazz.isEnum()&&isEnum(clazz, obj)) { | |
return getEnum((Enum) obj); | |
} else if(List.class.isAssignableFrom(clazz)&&isList(obj)) { | |
Class subClazz = getClassAtDepth(field.getGenericType(), depth+1); | |
if(ConfigObject.class.isAssignableFrom(subClazz)||Location.class.isAssignableFrom(subClazz)||Vector.class.isAssignableFrom(subClazz)||Map.class.isAssignableFrom(subClazz)||List.class.isAssignableFrom(subClazz)||subClazz.isEnum()) { | |
return getList((List) obj, field, cs, path, depth); | |
} else { | |
return obj; | |
} | |
} else { | |
return obj; | |
} | |
} | |
/* | |
* class detection | |
*/ | |
@SuppressWarnings("rawtypes") | |
protected Class getClassAtDepth(Type type, int depth) throws Exception { | |
if(depth<=0) { | |
String className = type.toString(); | |
if(className.length()>=6&&className.substring(0, 6).equalsIgnoreCase("class ")) { | |
className = className.substring(6); | |
} | |
if(className.indexOf("<")>=0) { | |
className = className.substring(0, className.indexOf("<")); | |
} | |
try { | |
return Class.forName(className); | |
} catch(ClassNotFoundException ex) { | |
// ugly fix for primitive data types | |
if(className.equalsIgnoreCase("byte")) return Byte.class; | |
if(className.equalsIgnoreCase("short")) return Short.class; | |
if(className.equalsIgnoreCase("int")) return Integer.class; | |
if(className.equalsIgnoreCase("long")) return Long.class; | |
if(className.equalsIgnoreCase("float")) return Float.class; | |
if(className.equalsIgnoreCase("double")) return Double.class; | |
if(className.equalsIgnoreCase("char")) return Character.class; | |
if(className.equalsIgnoreCase("boolean")) return Boolean.class; | |
throw ex; | |
} | |
} | |
depth--; | |
ParameterizedType pType = (ParameterizedType) type; | |
Type[] typeArgs = pType.getActualTypeArguments(); | |
return getClassAtDepth(typeArgs[typeArgs.length-1], depth); | |
} | |
protected boolean isString(Object obj) { | |
if(obj instanceof String) { | |
return true; | |
} | |
return false; | |
} | |
protected boolean isConfigurationSection(Object o) { | |
try { | |
return (ConfigurationSection) o != null; | |
} catch (Exception e) { | |
return false; | |
} | |
} | |
protected boolean isJSON(Object obj) { | |
try { | |
if(obj instanceof String) { | |
String str = (String) obj; | |
if(str.startsWith("{")) { | |
return new JSONParser().parse(str) != null; | |
} | |
} | |
return false; | |
} catch (Exception e) { | |
return false; | |
} | |
} | |
protected boolean isConfigObject(Object obj) { | |
try { | |
return (ConfigObject) obj != null; | |
} catch (Exception e) { | |
return false; | |
} | |
} | |
@SuppressWarnings("rawtypes") | |
protected boolean isMultimap(Object obj) { | |
try { | |
return (Multimap) obj != null; | |
} catch (Exception e) { | |
return false; | |
} | |
} | |
@SuppressWarnings("rawtypes") | |
protected boolean isTable(Object obj) { | |
try { | |
return (Table) obj != null; | |
} catch (Exception e) { | |
return false; | |
} | |
} | |
protected boolean isLocation(Object obj) { | |
try { | |
return (Location) obj != null; | |
} catch (Exception e) { | |
return false; | |
} | |
} | |
protected boolean isVector(Object obj) { | |
try { | |
return (Vector) obj != null; | |
} catch (Exception e) { | |
return false; | |
} | |
} | |
@SuppressWarnings("rawtypes") | |
protected boolean isMap(Object obj) { | |
try { | |
return (Map) obj != null; | |
} catch (Exception e) { | |
return false; | |
} | |
} | |
@SuppressWarnings("rawtypes") | |
protected boolean isList(Object obj) { | |
try { | |
return (List) obj != null; | |
} catch(Exception e) { | |
return false; | |
} | |
} | |
@SuppressWarnings("rawtypes") | |
protected boolean isEnum(Class clazz, Object obj) { | |
if(!clazz.isEnum()) return false; | |
for(Object constant : clazz.getEnumConstants()) { | |
if(constant.equals(obj)) { | |
return true; | |
} | |
} | |
return false; | |
} | |
/* | |
* loading conversion | |
*/ | |
@SuppressWarnings("rawtypes") | |
protected ConfigObject getConfigObject(Class clazz, ConfigurationSection cs) throws Exception { | |
ConfigObject obj = (ConfigObject) clazz.newInstance(); | |
obj.onLoad(cs); | |
return obj; | |
} | |
@SuppressWarnings({ "unchecked", "rawtypes" }) | |
protected Multimap getMultimap(Field field, ConfigurationSection cs, String path, int depth) throws Exception { | |
depth++; | |
Set<String> keys = cs.getKeys(false); | |
Multimap multimap = ArrayListMultimap.create(); | |
if(keys != null && keys.size() > 0) { | |
for(String key : keys) { | |
Object in = cs.get(key); | |
in = loadObject(field, cs, key, depth); | |
if (in instanceof List) { | |
multimap.putAll(key, (List) in); | |
} else { | |
throw new InvalidConfigurationException(cs.getCurrentPath()+"."+key + " is not a List."); | |
} | |
} | |
} | |
return multimap; | |
} | |
protected Location getLocation(String json) throws Exception { | |
JSONObject data = (JSONObject) new JSONParser().parse(json); | |
// world | |
World world = Bukkit.getWorld((String) data.get("world")); | |
// x, y, z | |
double x = Double.parseDouble((String) data.get("x")); | |
double y = Double.parseDouble((String) data.get("y")); | |
double z = Double.parseDouble((String) data.get("z")); | |
// pitch, yaw | |
float pitch = Float.parseFloat((String) data.get("pitch")); | |
float yaw = Float.parseFloat((String) data.get("yaw")); | |
// generate Location | |
Location loc = new Location(world, x, y, z); | |
loc.setPitch(pitch); | |
loc.setYaw(yaw); | |
return loc; | |
} | |
protected Vector getVector(String json) throws Exception { | |
JSONObject data = (JSONObject) new JSONParser().parse(json); | |
// x, y, z | |
double x = Double.parseDouble((String) data.get("x")); | |
double y = Double.parseDouble((String) data.get("y")); | |
double z = Double.parseDouble((String) data.get("z")); | |
// generate Vector | |
return new Vector(x, y, z); | |
} | |
@SuppressWarnings({ "rawtypes", "unchecked" }) | |
protected Map getMap(Field field, ConfigurationSection cs, String path, int depth) throws Exception { | |
depth++; | |
Set<String> keys = cs.getKeys(false); | |
Map map = new HashMap(); | |
if(keys != null && keys.size() > 0) { | |
for(String key : keys) { | |
Object in = cs.get(key); | |
in = loadObject(field, cs, key, depth); | |
map.put(key, in); | |
} | |
} | |
return map; | |
} | |
@SuppressWarnings({ "rawtypes", "unchecked" }) | |
protected List getList(Field field, ConfigurationSection cs, String path, int depth) throws Exception { | |
depth++; | |
int listSize = cs.getKeys(false).size(); | |
String key = path; | |
if(key.lastIndexOf(".")>=0) { | |
key = key.substring(key.lastIndexOf(".")); | |
} | |
List list = new ArrayList(); | |
if(listSize > 0) { | |
int loaded = 0; | |
int i = 0; | |
while(loaded<listSize) { | |
if(cs.isSet(key+i)) { | |
Object in = cs.get(key+i); | |
in = loadObject(field, cs, key+i, depth); | |
list.add(in); | |
loaded++; | |
} | |
i++; | |
// ugly overflow guard... should only be needed if config was manually edited very badly | |
if(i>(listSize*3)) loaded = listSize; | |
} | |
} | |
return list; | |
} | |
@SuppressWarnings("rawtypes") | |
protected Enum getEnum(Class clazz, String string) throws Exception { | |
if(!clazz.isEnum()) throw new Exception("Class "+clazz.getName()+" is not an enum."); | |
for(Object constant : clazz.getEnumConstants()) { | |
if(((Enum) constant).toString().equals(string)) { | |
return (Enum) constant; | |
} | |
} | |
throw new Exception("String "+string+" not a valid enum constant for "+clazz.getName()); | |
} | |
/* | |
* saving conversion | |
*/ | |
protected ConfigurationSection getConfigObject(ConfigObject obj, String path, ConfigurationSection cs) throws Exception { | |
ConfigurationSection subCS = cs.createSection(path); | |
obj.onSave(subCS); | |
return subCS; | |
} | |
@SuppressWarnings({ "rawtypes", "unchecked" }) | |
protected ConfigurationSection getMultimap(Multimap map, Field field, ConfigurationSection cs, String path, int depth) throws Exception { | |
depth++; | |
ConfigurationSection subCS = cs.createSection(path); | |
Set<String> keys = map.keySet(); | |
if(keys != null && keys.size() > 0) { | |
for(String key : keys) { | |
Object out = map.get(key); | |
out = saveObject(out, field, cs, path+"."+key, depth); | |
subCS.set(key, out); | |
} | |
} | |
return subCS; | |
} | |
@SuppressWarnings({ "rawtypes", "unchecked" }) | |
protected ConfigurationSection getTable(Table table, Field field, ConfigurationSection cs, String path, int depth) throws Exception { | |
depth++; | |
ConfigurationSection subCS = cs.createSection(path); | |
Set<Table.Cell> keys = table.cellSet(); | |
if(keys != null && keys.size() > 0) { | |
for(Table.Cell key : keys) { | |
Object out = table.get(key.getRowKey(),key.getColumnKey()); | |
out = saveObject(out, field, cs, path+"."+key.getRowKey()+"."+key.getColumnKey(), depth); | |
subCS.set(key.getRowKey()+"."+key.getColumnKey(), out); | |
} | |
} | |
return subCS; | |
} | |
protected String getLocation(Location loc) { | |
String ret = "{"; | |
ret += "\"world\":\""+loc.getWorld().getName()+"\""; | |
ret += ",\"x\":\""+loc.getX()+"\""; | |
ret += ",\"y\":\""+loc.getY()+"\""; | |
ret += ",\"z\":\""+loc.getZ()+"\""; | |
ret += ",\"pitch\":\""+loc.getPitch()+"\""; | |
ret += ",\"yaw\":\""+loc.getYaw()+"\""; | |
ret += "}"; | |
if(!isJSON(ret)) return getLocationJSON(loc); | |
try { | |
getLocation(ret); | |
} catch(Exception ex) { | |
return getLocationJSON(loc); | |
} | |
return ret; | |
} | |
@SuppressWarnings("unchecked") | |
protected String getLocationJSON(Location loc) { | |
JSONObject data = new JSONObject(); | |
// world | |
data.put("world", loc.getWorld().getName()); | |
// x, y, z | |
data.put("x", String.valueOf(loc.getX())); | |
data.put("y", String.valueOf(loc.getY())); | |
data.put("z", String.valueOf(loc.getZ())); | |
// pitch, yaw | |
data.put("pitch", String.valueOf(loc.getPitch())); | |
data.put("yaw", String.valueOf(loc.getYaw())); | |
return data.toJSONString(); | |
} | |
protected String getVector(Vector vec) { | |
String ret = "{"; | |
ret += "\"x\":\""+vec.getX()+"\""; | |
ret += ",\"y\":\""+vec.getY()+"\""; | |
ret += ",\"z\":\""+vec.getZ()+"\""; | |
ret += "}"; | |
if(!isJSON(ret)) return getVectorJSON(vec); | |
try { | |
getVector(ret); | |
} catch(Exception ex) { | |
return getVectorJSON(vec); | |
} | |
return ret; | |
} | |
@SuppressWarnings("unchecked") | |
protected String getVectorJSON(Vector vec) { | |
JSONObject data = new JSONObject(); | |
// x, y, z | |
data.put("x", String.valueOf(vec.getX())); | |
data.put("y", String.valueOf(vec.getY())); | |
data.put("z", String.valueOf(vec.getZ())); | |
return data.toJSONString(); | |
} | |
@SuppressWarnings({ "rawtypes", "unchecked" }) | |
protected ConfigurationSection getMap(Map map, Field field, ConfigurationSection cs, String path, int depth) throws Exception { | |
depth++; | |
ConfigurationSection subCS = cs.createSection(path); | |
Set<String> keys = map.keySet(); | |
if(keys != null && keys.size() > 0) { | |
for(String key : keys) { | |
Object out = map.get(key); | |
out = saveObject(out, field, cs, path+"."+key, depth); | |
subCS.set(key, out); | |
} | |
} | |
return subCS; | |
} | |
@SuppressWarnings("rawtypes") | |
protected ConfigurationSection getList(List list, Field field, ConfigurationSection cs, String path, int depth) throws Exception { | |
depth++; | |
ConfigurationSection subCS = cs.createSection(path); | |
String key = path; | |
if(key.lastIndexOf(".")>=0) { | |
key = key.substring(key.lastIndexOf(".")); | |
} | |
if(list != null && list.size() > 0) { | |
for(int i = 0; i < list.size(); i++) { | |
Object out = list.get(i); | |
out = saveObject(out, field, cs, path+"."+key+(i+1), depth); | |
subCS.set(key+(i+1), out); | |
} | |
} | |
return subCS; | |
} | |
@SuppressWarnings("rawtypes") | |
protected String getEnum(Enum enumObj) { | |
return enumObj.toString(); | |
} | |
/* | |
* utility | |
*/ | |
protected boolean doSkip(Field field) { | |
return Modifier.isTransient(field.getModifiers()) || Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers()) || Modifier.isPrivate(field.getModifiers()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment