mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2025-02-16 12:21:35 +01:00
Fixed issue where empty memory sections caused nulls.
This commit is contained in:
parent
19b7d24ad4
commit
f6a676244e
@ -19,6 +19,7 @@ import java.util.UUID;
|
|||||||
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.configuration.MemorySection;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
import us.tastybento.bskyblock.BSkyBlock;
|
import us.tastybento.bskyblock.BSkyBlock;
|
||||||
@ -36,348 +37,358 @@ import us.tastybento.bskyblock.util.Util;
|
|||||||
*/
|
*/
|
||||||
public class FlatFileDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
public class FlatFileDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
||||||
|
|
||||||
private static final String DATABASE_FOLDER_NAME = "database";
|
private static final String DATABASE_FOLDER_NAME = "database";
|
||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = false;
|
||||||
public FlatFileDatabaseHandler(BSkyBlock plugin, Class<T> type, DatabaseConnecter databaseConnecter) {
|
public FlatFileDatabaseHandler(BSkyBlock plugin, Class<T> type, DatabaseConnecter databaseConnecter) {
|
||||||
super(plugin, type, databaseConnecter);
|
super(plugin, type, databaseConnecter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String createSelectQuery() {
|
protected String createSelectQuery() {
|
||||||
return ""; // not used
|
return ""; // not used
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected String createInsertQuery() {
|
protected String createInsertQuery() {
|
||||||
return ""; // not used
|
return ""; // not used
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected String createDeleteQuery() {
|
protected String createDeleteQuery() {
|
||||||
return ""; // Not used
|
return ""; // Not used
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a <T> filled with values from the corresponding
|
* Creates a <T> filled with values from the corresponding
|
||||||
* database file
|
* database file
|
||||||
*
|
*
|
||||||
* @return <T> filled with values from the corresponding database file
|
* @return <T> filled with values from the corresponding database file
|
||||||
* @throws IntrospectionException
|
* @throws IntrospectionException
|
||||||
* @throws InvocationTargetException
|
* @throws InvocationTargetException
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* @throws InstantiationException
|
* @throws InstantiationException
|
||||||
* @throws ClassNotFoundException
|
* @throws ClassNotFoundException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public T loadObject(String key) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException, ClassNotFoundException {
|
public T loadObject(String key) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException, ClassNotFoundException {
|
||||||
YamlConfiguration config = databaseConnecter.loadYamlFile(type.getSimpleName(), key);
|
YamlConfiguration config = databaseConnecter.loadYamlFile(type.getSimpleName(), key);
|
||||||
return createObject(config);
|
return createObject(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean objectExits(String key) {
|
public boolean objectExits(String key) {
|
||||||
return databaseConnecter.uniqueIdExists(type.getSimpleName(), key);
|
return databaseConnecter.uniqueIdExists(type.getSimpleName(), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all the records in this table and returns a list of them
|
* Loads all the records in this table and returns a list of them
|
||||||
* @return list of <T>
|
* @return list of <T>
|
||||||
* @throws InstantiationException
|
* @throws InstantiationException
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* @throws InvocationTargetException
|
* @throws InvocationTargetException
|
||||||
* @throws IntrospectionException
|
* @throws IntrospectionException
|
||||||
* @throws ClassNotFoundException
|
* @throws ClassNotFoundException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<T> loadObjects() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException, ClassNotFoundException {
|
public List<T> loadObjects() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException, ClassNotFoundException {
|
||||||
List<T> list = new ArrayList<T>();
|
List<T> list = new ArrayList<T>();
|
||||||
FilenameFilter ymlFilter = new FilenameFilter() {
|
FilenameFilter ymlFilter = new FilenameFilter() {
|
||||||
@Override
|
@Override
|
||||||
public boolean accept(File dir, String name) {
|
public boolean accept(File dir, String name) {
|
||||||
String lowercaseName = name.toLowerCase();
|
String lowercaseName = name.toLowerCase();
|
||||||
if (lowercaseName.endsWith(".yml")) {
|
if (lowercaseName.endsWith(".yml")) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
File dataFolder = new File(plugin.getDataFolder(), DATABASE_FOLDER_NAME);
|
File dataFolder = new File(plugin.getDataFolder(), DATABASE_FOLDER_NAME);
|
||||||
File tableFolder = new File(dataFolder, type.getSimpleName());
|
File tableFolder = new File(dataFolder, type.getSimpleName());
|
||||||
if (!tableFolder.exists()) {
|
if (!tableFolder.exists()) {
|
||||||
// Nothing there...
|
// Nothing there...
|
||||||
tableFolder.mkdirs();
|
tableFolder.mkdirs();
|
||||||
}
|
}
|
||||||
for (File file: tableFolder.listFiles(ymlFilter)) {
|
for (File file: tableFolder.listFiles(ymlFilter)) {
|
||||||
YamlConfiguration config = databaseConnecter.loadYamlFile(type.getSimpleName(), file.getName());
|
YamlConfiguration config = databaseConnecter.loadYamlFile(type.getSimpleName(), file.getName());
|
||||||
list.add(createObject(config));
|
list.add(createObject(config));
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Creates a list of <T>s filled with values from the provided ResultSet
|
* Creates a list of <T>s filled with values from the provided ResultSet
|
||||||
*
|
*
|
||||||
* @param config - YAML config file
|
* @param config - YAML config file
|
||||||
*
|
*
|
||||||
* @return <T> filled with values
|
* @return <T> filled with values
|
||||||
*
|
*
|
||||||
* @throws InstantiationException
|
* @throws InstantiationException
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* @throws IntrospectionException
|
* @throws IntrospectionException
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* @throws InvocationTargetException
|
* @throws InvocationTargetException
|
||||||
* @throws ClassNotFoundException
|
* @throws ClassNotFoundException
|
||||||
*/
|
*/
|
||||||
private T createObject(YamlConfiguration config) throws InstantiationException, IllegalAccessException, IntrospectionException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException {
|
private T createObject(YamlConfiguration config) throws InstantiationException, IllegalAccessException, IntrospectionException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException {
|
||||||
T instance = type.newInstance();
|
T instance = type.newInstance();
|
||||||
|
|
||||||
for (Field field : type.getDeclaredFields()) {
|
for (Field field : type.getDeclaredFields()) {
|
||||||
|
|
||||||
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), type);
|
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), type);
|
||||||
Method method = propertyDescriptor.getWriteMethod();
|
Method method = propertyDescriptor.getWriteMethod();
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
plugin.getLogger().info("DEBUG: " + field.getName() + ": " + propertyDescriptor.getPropertyType().getTypeName());
|
plugin.getLogger().info("DEBUG: " + field.getName() + ": " + propertyDescriptor.getPropertyType().getTypeName());
|
||||||
if (config.contains(field.getName())) {
|
if (config.contains(field.getName())) {
|
||||||
if (propertyDescriptor.getPropertyType().equals(HashMap.class)) {
|
if (propertyDescriptor.getPropertyType().equals(HashMap.class)) {
|
||||||
|
|
||||||
// Note that we have no idea what type this is
|
// Note that we have no idea what type this is
|
||||||
List<Type> collectionTypes = Util.getCollectionParameterTypes(method);
|
List<Type> collectionTypes = Util.getCollectionParameterTypes(method);
|
||||||
// collectionTypes should be 2 long
|
// collectionTypes should be 2 long
|
||||||
Type keyType = collectionTypes.get(0);
|
Type keyType = collectionTypes.get(0);
|
||||||
Type valueType = collectionTypes.get(1);
|
Type valueType = collectionTypes.get(1);
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
plugin.getLogger().info("DEBUG: is HashMap<" + keyType.getTypeName() + ", " + valueType.getTypeName() + ">");
|
plugin.getLogger().info("DEBUG: is HashMap<" + keyType.getTypeName() + ", " + valueType.getTypeName() + ">");
|
||||||
// TODO: this may not work with all keys. Further serialization may be required.
|
// TODO: this may not work with all keys. Further serialization may be required.
|
||||||
HashMap<Object,Object> value = new HashMap<Object, Object>();
|
HashMap<Object,Object> value = new HashMap<Object, Object>();
|
||||||
for (String key : config.getConfigurationSection(field.getName()).getKeys(false)) {
|
for (String key : config.getConfigurationSection(field.getName()).getKeys(false)) {
|
||||||
Object mapKey = deserialize(key,Class.forName(keyType.getTypeName()));
|
Object mapKey = deserialize(key,Class.forName(keyType.getTypeName()));
|
||||||
Object mapValue = deserialize(config.get(field.getName() + "." + key), Class.forName(valueType.getTypeName()));
|
Object mapValue = deserialize(config.get(field.getName() + "." + key), Class.forName(valueType.getTypeName()));
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
plugin.getLogger().info("DEBUG: mapKey = " + mapKey + " (" + mapKey.getClass().getCanonicalName() + ")");
|
plugin.getLogger().info("DEBUG: mapKey = " + mapKey + " (" + mapKey.getClass().getCanonicalName() + ")");
|
||||||
plugin.getLogger().info("DEBUG: mapValue = " + mapValue + " (" + mapValue.getClass().getCanonicalName() + ")");
|
plugin.getLogger().info("DEBUG: mapValue = " + mapValue + " (" + mapValue.getClass().getCanonicalName() + ")");
|
||||||
}
|
}
|
||||||
value.put(mapKey, mapValue);
|
value.put(mapKey, mapValue);
|
||||||
}
|
}
|
||||||
method.invoke(instance, value);
|
method.invoke(instance, value);
|
||||||
} else if (propertyDescriptor.getPropertyType().equals(Set.class)) {
|
} else if (propertyDescriptor.getPropertyType().equals(Set.class)) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
plugin.getLogger().info("DEBUG: is Set " + propertyDescriptor.getReadMethod().getGenericReturnType().getTypeName());
|
plugin.getLogger().info("DEBUG: is Set " + propertyDescriptor.getReadMethod().getGenericReturnType().getTypeName());
|
||||||
plugin.getLogger().info("DEBUG: adding a set");
|
plugin.getLogger().info("DEBUG: adding a set");
|
||||||
}
|
}
|
||||||
// Loop through the collection resultset
|
// Loop through the collection resultset
|
||||||
// Note that we have no idea what type this is
|
// Note that we have no idea what type this is
|
||||||
List<Type> collectionTypes = Util.getCollectionParameterTypes(method);
|
List<Type> collectionTypes = Util.getCollectionParameterTypes(method);
|
||||||
// collectionTypes should be only 1 long
|
// collectionTypes should be only 1 long
|
||||||
Type setType = collectionTypes.get(0);
|
Type setType = collectionTypes.get(0);
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
plugin.getLogger().info("DEBUG: is HashSet<" + setType.getTypeName() + ">");
|
plugin.getLogger().info("DEBUG: is HashSet<" + setType.getTypeName() + ">");
|
||||||
Set<Object> value = new HashSet<Object>();
|
Set<Object> value = new HashSet<Object>();
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
plugin.getLogger().info("DEBUG: collection type argument = " + collectionTypes);
|
plugin.getLogger().info("DEBUG: collection type argument = " + collectionTypes);
|
||||||
plugin.getLogger().info("DEBUG: setType = " + setType.getTypeName());
|
plugin.getLogger().info("DEBUG: setType = " + setType.getTypeName());
|
||||||
}
|
}
|
||||||
for (Object listValue: config.getList(field.getName())) {
|
for (Object listValue: config.getList(field.getName())) {
|
||||||
//plugin.getLogger().info("DEBUG: collectionResultSet size = " + collectionResultSet.getFetchSize());
|
//plugin.getLogger().info("DEBUG: collectionResultSet size = " + collectionResultSet.getFetchSize());
|
||||||
((Set<Object>) value).add(deserialize(listValue,Class.forName(setType.getTypeName())));
|
((Set<Object>) value).add(deserialize(listValue,Class.forName(setType.getTypeName())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this may not work with all keys. Further serialization may be required.
|
// TODO: this may not work with all keys. Further serialization may be required.
|
||||||
//Set<Object> value = new HashSet((List<Object>) config.getList(field.getName()));
|
//Set<Object> value = new HashSet((List<Object>) config.getList(field.getName()));
|
||||||
method.invoke(instance, value);
|
method.invoke(instance, value);
|
||||||
} else if (propertyDescriptor.getPropertyType().equals(ArrayList.class)) {
|
} else if (propertyDescriptor.getPropertyType().equals(ArrayList.class)) {
|
||||||
//plugin.getLogger().info("DEBUG: is Set " + propertyDescriptor.getReadMethod().getGenericReturnType().getTypeName());
|
//plugin.getLogger().info("DEBUG: is Set " + propertyDescriptor.getReadMethod().getGenericReturnType().getTypeName());
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
plugin.getLogger().info("DEBUG: adding a set");
|
plugin.getLogger().info("DEBUG: adding a set");
|
||||||
// Loop through the collection resultset
|
// Loop through the collection resultset
|
||||||
// Note that we have no idea what type this is
|
// Note that we have no idea what type this is
|
||||||
List<Type> collectionTypes = Util.getCollectionParameterTypes(method);
|
List<Type> collectionTypes = Util.getCollectionParameterTypes(method);
|
||||||
// collectionTypes should be only 1 long
|
// collectionTypes should be only 1 long
|
||||||
Type setType = collectionTypes.get(0);
|
Type setType = collectionTypes.get(0);
|
||||||
List<Object> value = new ArrayList<Object>();
|
List<Object> value = new ArrayList<Object>();
|
||||||
//plugin.getLogger().info("DEBUG: collection type argument = " + collectionTypes);
|
//plugin.getLogger().info("DEBUG: collection type argument = " + collectionTypes);
|
||||||
//plugin.getLogger().info("DEBUG: setType = " + setType.getTypeName());
|
//plugin.getLogger().info("DEBUG: setType = " + setType.getTypeName());
|
||||||
for (Object listValue: config.getList(field.getName())) {
|
for (Object listValue: config.getList(field.getName())) {
|
||||||
//plugin.getLogger().info("DEBUG: collectionResultSet size = " + collectionResultSet.getFetchSize());
|
//plugin.getLogger().info("DEBUG: collectionResultSet size = " + collectionResultSet.getFetchSize());
|
||||||
((List<Object>) value).add(deserialize(listValue,Class.forName(setType.getTypeName())));
|
((List<Object>) value).add(deserialize(listValue,Class.forName(setType.getTypeName())));
|
||||||
}
|
}
|
||||||
// TODO: this may not work with all keys. Further serialization may be required.
|
// TODO: this may not work with all keys. Further serialization may be required.
|
||||||
//Set<Object> value = new HashSet((List<Object>) config.getList(field.getName()));
|
//Set<Object> value = new HashSet((List<Object>) config.getList(field.getName()));
|
||||||
method.invoke(instance, value);
|
method.invoke(instance, value);
|
||||||
} else {
|
} else {
|
||||||
// Not a collection
|
// Not a collection
|
||||||
Object value = config.get(field.getName());
|
if (DEBUG)
|
||||||
method.invoke(instance, deserialize(value,propertyDescriptor.getPropertyType()));
|
plugin.getLogger().info("DEBUG: not a collection");
|
||||||
|
Object value = config.get(field.getName());
|
||||||
|
if (DEBUG) {
|
||||||
|
plugin.getLogger().info("DEBUG: value = " + value);
|
||||||
|
plugin.getLogger().info("DEBUG: property type = " + propertyDescriptor.getPropertyType());
|
||||||
|
plugin.getLogger().info("DEBUG: " + value.getClass());
|
||||||
|
if (value != null && !value.getClass().equals(MemorySection.class)) {
|
||||||
|
method.invoke(instance, deserialize(value,propertyDescriptor.getPropertyType()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return instance;
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
return instance;
|
||||||
* Inserts T into the corresponding database-table
|
}
|
||||||
*
|
|
||||||
* @param instance that should be inserted into the database
|
|
||||||
* @throws IllegalAccessException
|
|
||||||
* @throws IllegalArgumentException
|
|
||||||
* @throws InvocationTargetException
|
|
||||||
* @throws IntrospectionException
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public void saveObject(T instance) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException {
|
|
||||||
// This is the Yaml Configuration that will be used and saved at the end
|
|
||||||
YamlConfiguration config = new YamlConfiguration();
|
|
||||||
// The file name of the Yaml file.
|
|
||||||
String filename = "";
|
|
||||||
// Run through all the fields in the class that is being stored. EVERY field must have a get and set method
|
|
||||||
for (Field field : type.getDeclaredFields()) {
|
|
||||||
// Get the property descriptor for this field
|
|
||||||
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), type);
|
|
||||||
// Get the read method, i.e., getXXXX();
|
|
||||||
Method method = propertyDescriptor.getReadMethod();
|
|
||||||
// Invoke the read method to get the value. We have no idea what type of value it is.
|
|
||||||
Object value = method.invoke(instance);
|
|
||||||
//plugin.getLogger().info("DEBUG: writing " + field.getName());
|
|
||||||
//plugin.getLogger().info("DEBUG: property desc = " + propertyDescriptor.getPropertyType().getTypeName());
|
|
||||||
// Depending on the vale type, it'll need serializing differenty
|
|
||||||
// Check if this field is the mandatory UniqueId field. This is used to identify this instantiation of the class
|
|
||||||
if (method.getName().equals("getUniqueId")) {
|
|
||||||
// If the object does not have a unique name assigned to it already, one is created at random
|
|
||||||
//plugin.getLogger().info("DEBUG: uniqueId = " + value);
|
|
||||||
String id = (String)value;
|
|
||||||
if (id.isEmpty()) {
|
|
||||||
id = databaseConnecter.getUniqueId(type.getSimpleName());
|
|
||||||
// Set it in the class so that it will be used next time
|
|
||||||
propertyDescriptor.getWriteMethod().invoke(instance, id);
|
|
||||||
}
|
|
||||||
// Save the name for when the file is saved
|
|
||||||
filename = id;
|
|
||||||
}
|
|
||||||
// Collections need special serialization
|
|
||||||
if (propertyDescriptor.getPropertyType().equals(HashMap.class) || propertyDescriptor.getPropertyType().equals(Map.class)) {
|
|
||||||
// Maps need to have keys serialized
|
|
||||||
//plugin.getLogger().info("DEBUG: Map for " + field.getName());
|
|
||||||
Map<Object, Object> result = new HashMap<Object, Object>();
|
|
||||||
for (Entry<Object, Object> object : ((Map<Object,Object>)value).entrySet()) {
|
|
||||||
// Serialize all key types
|
|
||||||
// TODO: also need to serialize values?
|
|
||||||
result.put(serialize(object.getKey()), object.getValue());
|
|
||||||
}
|
|
||||||
// Save the list in the config file
|
|
||||||
config.set(field.getName(), result);
|
|
||||||
} else if (propertyDescriptor.getPropertyType().equals(Set.class)) {
|
|
||||||
// Sets need to be serialized as string lists
|
|
||||||
//plugin.getLogger().info("DEBUG: Set for " + field.getName());
|
|
||||||
List<Object> list = new ArrayList<Object>();
|
|
||||||
for (Object object : (Set<Object>)value) {
|
|
||||||
list.add(serialize(object));
|
|
||||||
}
|
|
||||||
// Save the list in the config file
|
|
||||||
config.set(field.getName(), list);
|
|
||||||
} else {
|
|
||||||
// For all other data that doesn't need special serialization
|
|
||||||
config.set(field.getName(), serialize(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (filename.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("No uniqueId in class");
|
|
||||||
}
|
|
||||||
// Save the file in the right folder
|
|
||||||
databaseConnecter.saveYamlFile(config, type.getSimpleName(), filename);
|
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* Inserts T into the corresponding database-table
|
||||||
|
*
|
||||||
|
* @param instance that should be inserted into the database
|
||||||
|
* @throws IllegalAccessException
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* @throws InvocationTargetException
|
||||||
|
* @throws IntrospectionException
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void saveObject(T instance) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException {
|
||||||
|
// This is the Yaml Configuration that will be used and saved at the end
|
||||||
|
YamlConfiguration config = new YamlConfiguration();
|
||||||
|
// The file name of the Yaml file.
|
||||||
|
String filename = "";
|
||||||
|
// Run through all the fields in the class that is being stored. EVERY field must have a get and set method
|
||||||
|
for (Field field : type.getDeclaredFields()) {
|
||||||
|
// Get the property descriptor for this field
|
||||||
|
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), type);
|
||||||
|
// Get the read method, i.e., getXXXX();
|
||||||
|
Method method = propertyDescriptor.getReadMethod();
|
||||||
|
// Invoke the read method to get the value. We have no idea what type of value it is.
|
||||||
|
Object value = method.invoke(instance);
|
||||||
|
//plugin.getLogger().info("DEBUG: writing " + field.getName());
|
||||||
|
//plugin.getLogger().info("DEBUG: property desc = " + propertyDescriptor.getPropertyType().getTypeName());
|
||||||
|
// Depending on the vale type, it'll need serializing differenty
|
||||||
|
// Check if this field is the mandatory UniqueId field. This is used to identify this instantiation of the class
|
||||||
|
if (method.getName().equals("getUniqueId")) {
|
||||||
|
// If the object does not have a unique name assigned to it already, one is created at random
|
||||||
|
//plugin.getLogger().info("DEBUG: uniqueId = " + value);
|
||||||
|
String id = (String)value;
|
||||||
|
if (id.isEmpty()) {
|
||||||
|
id = databaseConnecter.getUniqueId(type.getSimpleName());
|
||||||
|
// Set it in the class so that it will be used next time
|
||||||
|
propertyDescriptor.getWriteMethod().invoke(instance, id);
|
||||||
|
}
|
||||||
|
// Save the name for when the file is saved
|
||||||
|
filename = id;
|
||||||
|
}
|
||||||
|
// Collections need special serialization
|
||||||
|
if (propertyDescriptor.getPropertyType().equals(HashMap.class) || propertyDescriptor.getPropertyType().equals(Map.class)) {
|
||||||
|
// Maps need to have keys serialized
|
||||||
|
//plugin.getLogger().info("DEBUG: Map for " + field.getName());
|
||||||
|
Map<Object, Object> result = new HashMap<Object, Object>();
|
||||||
|
for (Entry<Object, Object> object : ((Map<Object,Object>)value).entrySet()) {
|
||||||
|
// Serialize all key types
|
||||||
|
// TODO: also need to serialize values?
|
||||||
|
result.put(serialize(object.getKey()), object.getValue());
|
||||||
|
}
|
||||||
|
// Save the list in the config file
|
||||||
|
config.set(field.getName(), result);
|
||||||
|
} else if (propertyDescriptor.getPropertyType().equals(Set.class)) {
|
||||||
|
// Sets need to be serialized as string lists
|
||||||
|
//plugin.getLogger().info("DEBUG: Set for " + field.getName());
|
||||||
|
List<Object> list = new ArrayList<Object>();
|
||||||
|
for (Object object : (Set<Object>)value) {
|
||||||
|
list.add(serialize(object));
|
||||||
|
}
|
||||||
|
// Save the list in the config file
|
||||||
|
config.set(field.getName(), list);
|
||||||
|
} else {
|
||||||
|
// For all other data that doesn't need special serialization
|
||||||
|
config.set(field.getName(), serialize(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (filename.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("No uniqueId in class");
|
||||||
|
}
|
||||||
|
// Save the file in the right folder
|
||||||
|
databaseConnecter.saveYamlFile(config, type.getSimpleName(), filename);
|
||||||
|
|
||||||
/**
|
}
|
||||||
* Serialize an object if required
|
|
||||||
* @param object
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private Object serialize(Object object) {
|
|
||||||
if (object == null) {
|
|
||||||
return "null";
|
|
||||||
}
|
|
||||||
//plugin.getLogger().info("DEBUG: serializing " + object.getClass().getTypeName());
|
|
||||||
if (object instanceof UUID) {
|
|
||||||
return ((UUID)object).toString();
|
|
||||||
}
|
|
||||||
if (object instanceof World) {
|
|
||||||
return ((World)object).getName();
|
|
||||||
}
|
|
||||||
if (object instanceof Location) {
|
|
||||||
return Util.getStringLocation((Location)object);
|
|
||||||
}
|
|
||||||
if (object instanceof Enum) {
|
|
||||||
//Custom enums are a child of the Enum class. Just get the names of each one.
|
|
||||||
return ((Enum<?>)object).name();
|
|
||||||
}
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object deserialize(Object value, Class<? extends Object> clazz) {
|
/**
|
||||||
if (DEBUG) {
|
* Serialize an object if required
|
||||||
plugin.getLogger().info("DEBUG: deserialize - class is " + clazz.getCanonicalName());
|
* @param object
|
||||||
plugin.getLogger().info("DEBUG: value is " + value);
|
* @return
|
||||||
if (value != null)
|
*/
|
||||||
plugin.getLogger().info("DEBUG: value class is " + value.getClass().getCanonicalName());
|
private Object serialize(Object object) {
|
||||||
}
|
if (object == null) {
|
||||||
if (value instanceof String && value.equals("null")) {
|
return "null";
|
||||||
// If the value is null as a string, return null
|
}
|
||||||
return null;
|
//plugin.getLogger().info("DEBUG: serializing " + object.getClass().getTypeName());
|
||||||
}
|
if (object instanceof UUID) {
|
||||||
// Bukkit may have deserialized the object already
|
return ((UUID)object).toString();
|
||||||
if (clazz.equals(value.getClass())) {
|
}
|
||||||
return value;
|
if (object instanceof World) {
|
||||||
}
|
return ((World)object).getName();
|
||||||
// Types that need to be deserialized
|
}
|
||||||
if (clazz.equals(Long.class) && value.getClass().equals(Integer.class)) {
|
if (object instanceof Location) {
|
||||||
return new Long((Integer)value);
|
return Util.getStringLocation((Location)object);
|
||||||
}
|
}
|
||||||
if (clazz.equals(UUID.class)) {
|
if (object instanceof Enum) {
|
||||||
value = UUID.fromString((String)value);
|
//Custom enums are a child of the Enum class. Just get the names of each one.
|
||||||
}
|
return ((Enum<?>)object).name();
|
||||||
// Bukkit Types
|
}
|
||||||
if (clazz.equals(Location.class)) {
|
return object;
|
||||||
// Get Location from String - may be null...
|
}
|
||||||
value = Util.getLocationString(((String)value));
|
|
||||||
}
|
|
||||||
if (clazz.equals(World.class)) {
|
|
||||||
// Get world by name - may be null...
|
|
||||||
value = plugin.getServer().getWorld((String)value);
|
|
||||||
}
|
|
||||||
// Enums
|
|
||||||
if (clazz.getSuperclass() != null && clazz.getSuperclass().equals(Enum.class)) {
|
|
||||||
//Custom enums are a child of the Enum class.
|
|
||||||
// Find out the value
|
|
||||||
try {
|
|
||||||
Class<Enum> enumClass = (Class<Enum>)clazz;
|
|
||||||
value = Enum.valueOf(enumClass, (String)value);
|
|
||||||
} catch (Exception e) {
|
|
||||||
// Maybe this value does not exist?
|
|
||||||
// TODO return something?
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
private Object deserialize(Object value, Class<? extends Object> clazz) {
|
||||||
public void deleteObject(T instance) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException {
|
if (DEBUG) {
|
||||||
// The file name of the Yaml file.
|
plugin.getLogger().info("DEBUG: deserialize - class is " + clazz.getCanonicalName());
|
||||||
PropertyDescriptor propertyDescriptor = new PropertyDescriptor("uniqueId", type);
|
plugin.getLogger().info("DEBUG: value is " + value);
|
||||||
Method method = propertyDescriptor.getReadMethod();
|
if (value != null)
|
||||||
String fileName = (String) method.invoke(instance);
|
plugin.getLogger().info("DEBUG: value class is " + value.getClass().getCanonicalName());
|
||||||
if (!fileName.endsWith(".yml")) {
|
}
|
||||||
fileName = fileName + ".yml";
|
if (value instanceof String && value.equals("null")) {
|
||||||
}
|
// If the value is null as a string, return null
|
||||||
File dataFolder = new File(plugin.getDataFolder(), DATABASE_FOLDER_NAME);
|
return null;
|
||||||
File tableFolder = new File(dataFolder, type.getSimpleName());
|
}
|
||||||
if (tableFolder.exists()) {
|
// Bukkit may have deserialized the object already
|
||||||
File file = new File(tableFolder, fileName);
|
if (clazz.equals(value.getClass())) {
|
||||||
file.delete();
|
return value;
|
||||||
}
|
}
|
||||||
}
|
// Types that need to be deserialized
|
||||||
|
if (clazz.equals(Long.class) && value.getClass().equals(Integer.class)) {
|
||||||
|
return new Long((Integer)value);
|
||||||
|
}
|
||||||
|
if (clazz.equals(UUID.class)) {
|
||||||
|
value = UUID.fromString((String)value);
|
||||||
|
}
|
||||||
|
// Bukkit Types
|
||||||
|
if (clazz.equals(Location.class)) {
|
||||||
|
// Get Location from String - may be null...
|
||||||
|
value = Util.getLocationString(((String)value));
|
||||||
|
}
|
||||||
|
if (clazz.equals(World.class)) {
|
||||||
|
// Get world by name - may be null...
|
||||||
|
value = plugin.getServer().getWorld((String)value);
|
||||||
|
}
|
||||||
|
// Enums
|
||||||
|
if (clazz.getSuperclass() != null && clazz.getSuperclass().equals(Enum.class)) {
|
||||||
|
//Custom enums are a child of the Enum class.
|
||||||
|
// Find out the value
|
||||||
|
try {
|
||||||
|
Class<Enum> enumClass = (Class<Enum>)clazz;
|
||||||
|
value = Enum.valueOf(enumClass, (String)value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Maybe this value does not exist?
|
||||||
|
// TODO return something?
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteObject(T instance) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException {
|
||||||
|
// The file name of the Yaml file.
|
||||||
|
PropertyDescriptor propertyDescriptor = new PropertyDescriptor("uniqueId", type);
|
||||||
|
Method method = propertyDescriptor.getReadMethod();
|
||||||
|
String fileName = (String) method.invoke(instance);
|
||||||
|
if (!fileName.endsWith(".yml")) {
|
||||||
|
fileName = fileName + ".yml";
|
||||||
|
}
|
||||||
|
File dataFolder = new File(plugin.getDataFolder(), DATABASE_FOLDER_NAME);
|
||||||
|
File tableFolder = new File(dataFolder, type.getSimpleName());
|
||||||
|
if (tableFolder.exists()) {
|
||||||
|
File file = new File(tableFolder, fileName);
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user