mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2025-02-06 15:31:46 +01:00
MySQL and Flatfile databases now store and retrieve objects.
This commit is contained in:
parent
a541ea3e25
commit
c1c00648d9
@ -2,6 +2,7 @@ package us.tastybento.bskyblock;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -14,7 +15,6 @@ import us.tastybento.bskyblock.config.BSBLocale;
|
|||||||
import us.tastybento.bskyblock.config.PluginConfig;
|
import us.tastybento.bskyblock.config.PluginConfig;
|
||||||
import us.tastybento.bskyblock.config.Settings;
|
import us.tastybento.bskyblock.config.Settings;
|
||||||
import us.tastybento.bskyblock.database.BSBDatabase;
|
import us.tastybento.bskyblock.database.BSBDatabase;
|
||||||
import us.tastybento.bskyblock.database.BSBDatabase.DatabaseType;
|
|
||||||
import us.tastybento.bskyblock.database.managers.IslandsManager;
|
import us.tastybento.bskyblock.database.managers.IslandsManager;
|
||||||
import us.tastybento.bskyblock.database.managers.OfflineHistoryMessages;
|
import us.tastybento.bskyblock.database.managers.OfflineHistoryMessages;
|
||||||
import us.tastybento.bskyblock.database.managers.PlayersManager;
|
import us.tastybento.bskyblock.database.managers.PlayersManager;
|
||||||
@ -83,6 +83,7 @@ public class BSkyBlock extends JavaPlugin{
|
|||||||
|
|
||||||
// Test: Create a random island and save it
|
// Test: Create a random island and save it
|
||||||
// TODO: ideally this should be in a test class!
|
// TODO: ideally this should be in a test class!
|
||||||
|
/*
|
||||||
UUID owner = UUID.fromString("ddf561c5-72b6-4ec6-a7ea-8b50a893beb2");
|
UUID owner = UUID.fromString("ddf561c5-72b6-4ec6-a7ea-8b50a893beb2");
|
||||||
|
|
||||||
Island island = islandsManager.createIsland(new Location(getServer().getWorld("world"),0,0,0,0,0), owner);
|
Island island = islandsManager.createIsland(new Location(getServer().getWorld("world"),0,0,0,0,0), owner);
|
||||||
@ -109,17 +110,21 @@ public class BSkyBlock extends JavaPlugin{
|
|||||||
|
|
||||||
getLogger().info("DEBUG: ************ Finished saving, now loading *************");
|
getLogger().info("DEBUG: ************ Finished saving, now loading *************");
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
playersManager.load();
|
playersManager.load();
|
||||||
islandsManager.load();
|
islandsManager.load();
|
||||||
|
/*
|
||||||
|
*DEBUG CODE
|
||||||
Island loadedIsland = islandsManager.getIsland(owner);
|
Island loadedIsland = islandsManager.getIsland(owner);
|
||||||
getLogger().info("Island name = " + loadedIsland.getName());
|
getLogger().info("Island name = " + loadedIsland.getName());
|
||||||
getLogger().info("Island locked = " + loadedIsland.getLocked());
|
getLogger().info("Island locked = " + loadedIsland.getLocked());
|
||||||
//getLogger().info("Random set = " + randomSet);
|
//getLogger().info("Random set = " + randomSet);
|
||||||
getLogger().info("Island coops = " + loadedIsland.getCoops());
|
getLogger().info("Island coops = " + loadedIsland.getCoops());
|
||||||
|
for (Entry<SettingsFlag, Boolean> flag: loadedIsland.getFlags().entrySet()) {
|
||||||
|
getLogger().info("Flag " + flag.getKey().name() + " = " + flag.getValue());
|
||||||
|
}
|
||||||
|
*/
|
||||||
// Save islands & players data asynchronously every X minutes
|
// Save islands & players data asynchronously every X minutes
|
||||||
Settings.databaseBackupPeriod = 10 * 60 * 20;
|
Settings.databaseBackupPeriod = 10 * 60 * 20;
|
||||||
plugin.getServer().getScheduler().runTaskTimer(plugin, new Runnable() {
|
plugin.getServer().getScheduler().runTaskTimer(plugin, new Runnable() {
|
||||||
|
@ -7,18 +7,24 @@ import java.io.FilenameFilter;
|
|||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
import us.tastybento.bskyblock.BSkyBlock;
|
import us.tastybento.bskyblock.BSkyBlock;
|
||||||
import us.tastybento.bskyblock.database.DatabaseConnecter;
|
import us.tastybento.bskyblock.database.DatabaseConnecter;
|
||||||
import us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler;
|
import us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler;
|
||||||
|
import us.tastybento.bskyblock.util.Util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that creates a list of <T>s filled with values from the corresponding
|
* Class that creates a list of <T>s filled with values from the corresponding
|
||||||
@ -53,9 +59,10 @@ public class FlatFileDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
|||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* @throws InstantiationException
|
* @throws InstantiationException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public T selectObject(String key) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException {
|
public T selectObject(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);
|
||||||
}
|
}
|
||||||
@ -68,9 +75,10 @@ public class FlatFileDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
|||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* @throws InvocationTargetException
|
* @throws InvocationTargetException
|
||||||
* @throws IntrospectionException
|
* @throws IntrospectionException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<T> selectObjects() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException {
|
public List<T> selectObjects() 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
|
||||||
@ -108,49 +116,73 @@ public class FlatFileDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
|||||||
* @throws IntrospectionException
|
* @throws IntrospectionException
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* @throws InvocationTargetException
|
* @throws InvocationTargetException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
*/
|
*/
|
||||||
private T createObject(YamlConfiguration config) throws InstantiationException, IllegalAccessException, IntrospectionException, IllegalArgumentException, InvocationTargetException {
|
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()) {
|
||||||
|
|
||||||
/* We assume the table-column-names exactly match the variable-names of T */
|
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), type);
|
||||||
// TODO: depending on the data type, it'll need deserializing
|
Method method = propertyDescriptor.getWriteMethod();
|
||||||
try {
|
//plugin.getLogger().info("DEBUG: " + field.getName() + ": " + propertyDescriptor.getPropertyType().getTypeName());
|
||||||
|
if (propertyDescriptor.getPropertyType().equals(HashMap.class)) {
|
||||||
|
|
||||||
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), type);
|
// Note that we have no idea what type this is
|
||||||
Method method = propertyDescriptor.getWriteMethod();
|
List<Type> collectionTypes = Util.getCollectionParameterTypes(method);
|
||||||
plugin.getLogger().info("DEBUG: " + field.getName() + ": " + propertyDescriptor.getPropertyType().getTypeName());
|
// collectionTypes should be 2 long
|
||||||
if (propertyDescriptor.getPropertyType().equals(HashMap.class)) {
|
Type keyType = collectionTypes.get(0);
|
||||||
plugin.getLogger().info("DEBUG: is HashMap");
|
Type valueType = collectionTypes.get(1);
|
||||||
// TODO: this may not work with all keys. Further serialization may be required.
|
//plugin.getLogger().info("DEBUG: is HashMap<" + keyType.getTypeName() + ", " + valueType.getTypeName() + ">");
|
||||||
HashMap<Object,Object> value = new HashMap<Object, Object>();
|
// TODO: this may not work with all keys. Further serialization may be required.
|
||||||
for (String key : config.getConfigurationSection(field.getName()).getKeys(false)) {
|
HashMap<Object,Object> value = new HashMap<Object, Object>();
|
||||||
value.put(key, config.get(field.getName() + "." + key));
|
for (String key : config.getConfigurationSection(field.getName()).getKeys(false)) {
|
||||||
}
|
Object mapKey = deserialize(key,Class.forName(keyType.getTypeName()));
|
||||||
method.invoke(instance, value);
|
Object mapValue = deserialize(config.get(field.getName() + "." + key), Class.forName(valueType.getTypeName()));
|
||||||
} else if (propertyDescriptor.getPropertyType().equals(Set.class)) {
|
value.put(mapKey, mapValue);
|
||||||
plugin.getLogger().info("DEBUG: is Set " + propertyDescriptor.getReadMethod().getGenericReturnType().getTypeName());
|
|
||||||
|
|
||||||
// TODO: this may not work with all keys. Further serialization may be required.
|
|
||||||
Set<Object> value = new HashSet((List<Object>) config.getList(field.getName()));
|
|
||||||
|
|
||||||
method.invoke(instance, value);
|
|
||||||
} else if (propertyDescriptor.getPropertyType().equals(UUID.class)) {
|
|
||||||
plugin.getLogger().info("DEBUG: is UUID");
|
|
||||||
String uuid = (String)config.get(field.getName());
|
|
||||||
if (uuid == null || uuid.equals("null")) {
|
|
||||||
method.invoke(instance, (Object)null);
|
|
||||||
} else {
|
|
||||||
Object value = UUID.fromString(uuid);
|
|
||||||
method.invoke(instance, value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Object value = config.get(field.getName());
|
|
||||||
method.invoke(instance, value);
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
method.invoke(instance, value);
|
||||||
e.printStackTrace();
|
} else if (propertyDescriptor.getPropertyType().equals(Set.class)) {
|
||||||
|
//plugin.getLogger().info("DEBUG: is Set " + propertyDescriptor.getReadMethod().getGenericReturnType().getTypeName());
|
||||||
|
//plugin.getLogger().info("DEBUG: adding a set");
|
||||||
|
// Loop through the collection resultset
|
||||||
|
// Note that we have no idea what type this is
|
||||||
|
List<Type> collectionTypes = Util.getCollectionParameterTypes(method);
|
||||||
|
// collectionTypes should be only 1 long
|
||||||
|
Type setType = collectionTypes.get(0);
|
||||||
|
//plugin.getLogger().info("DEBUG: is HashSet<" + setType.getTypeName() + ">");
|
||||||
|
Set<Object> value = new HashSet<Object>();
|
||||||
|
//plugin.getLogger().info("DEBUG: collection type argument = " + collectionTypes);
|
||||||
|
//plugin.getLogger().info("DEBUG: setType = " + setType.getTypeName());
|
||||||
|
for (Object listValue: config.getList(field.getName())) {
|
||||||
|
//plugin.getLogger().info("DEBUG: collectionResultSet size = " + collectionResultSet.getFetchSize());
|
||||||
|
((Set<Object>) value).add(deserialize(listValue,Class.forName(setType.getTypeName())));
|
||||||
|
}
|
||||||
|
// TODO: this may not work with all keys. Further serialization may be required.
|
||||||
|
//Set<Object> value = new HashSet((List<Object>) config.getList(field.getName()));
|
||||||
|
method.invoke(instance, value);
|
||||||
|
} else if (propertyDescriptor.getPropertyType().equals(ArrayList.class)) {
|
||||||
|
//plugin.getLogger().info("DEBUG: is Set " + propertyDescriptor.getReadMethod().getGenericReturnType().getTypeName());
|
||||||
|
//plugin.getLogger().info("DEBUG: adding a set");
|
||||||
|
// Loop through the collection resultset
|
||||||
|
// Note that we have no idea what type this is
|
||||||
|
List<Type> collectionTypes = Util.getCollectionParameterTypes(method);
|
||||||
|
// collectionTypes should be only 1 long
|
||||||
|
Type setType = collectionTypes.get(0);
|
||||||
|
List<Object> value = new ArrayList<Object>();
|
||||||
|
//plugin.getLogger().info("DEBUG: collection type argument = " + collectionTypes);
|
||||||
|
//plugin.getLogger().info("DEBUG: setType = " + setType.getTypeName());
|
||||||
|
for (Object listValue: config.getList(field.getName())) {
|
||||||
|
//plugin.getLogger().info("DEBUG: collectionResultSet size = " + collectionResultSet.getFetchSize());
|
||||||
|
((List<Object>) value).add(deserialize(listValue,Class.forName(setType.getTypeName())));
|
||||||
|
}
|
||||||
|
// TODO: this may not work with all keys. Further serialization may be required.
|
||||||
|
//Set<Object> value = new HashSet((List<Object>) config.getList(field.getName()));
|
||||||
|
method.invoke(instance, value);
|
||||||
|
} else {
|
||||||
|
// Not a collection
|
||||||
|
Object value = config.get(field.getName());
|
||||||
|
method.invoke(instance, deserialize(value,propertyDescriptor.getPropertyType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -182,8 +214,8 @@ public class FlatFileDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
|||||||
Method method = propertyDescriptor.getReadMethod();
|
Method method = propertyDescriptor.getReadMethod();
|
||||||
// Invoke the read method to get the value. We have no idea what type of value it is.
|
// Invoke the read method to get the value. We have no idea what type of value it is.
|
||||||
Object value = method.invoke(instance);
|
Object value = method.invoke(instance);
|
||||||
plugin.getLogger().info("DEBUG: writing " + field.getName());
|
//plugin.getLogger().info("DEBUG: writing " + field.getName());
|
||||||
plugin.getLogger().info("DEBUG: property desc = " + propertyDescriptor.getPropertyType().getTypeName());
|
//plugin.getLogger().info("DEBUG: property desc = " + propertyDescriptor.getPropertyType().getTypeName());
|
||||||
// Depending on the vale type, it'll need serializing differenty
|
// 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
|
// 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 (method.getName().equals("getUniqueId")) {
|
||||||
@ -199,36 +231,98 @@ public class FlatFileDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
|||||||
filename = id;
|
filename = id;
|
||||||
}
|
}
|
||||||
// UUID's need special serialization
|
// UUID's need special serialization
|
||||||
if (propertyDescriptor.getPropertyType().equals(UUID.class)) {
|
if (propertyDescriptor.getPropertyType().equals(HashMap.class) || propertyDescriptor.getPropertyType().equals(Map.class)) {
|
||||||
plugin.getLogger().info("DEBUG: writing UUID for " + field.getName());
|
// Maps need to have keys serialized
|
||||||
if (value != null) {
|
//plugin.getLogger().info("DEBUG: Map for " + field.getName());
|
||||||
config.set(field.getName(), ((UUID)value).toString());
|
Map<Object, Object> result = new HashMap<Object, Object>();
|
||||||
} else {
|
for (Entry<Object, Object> object : ((Map<Object,Object>)value).entrySet()) {
|
||||||
// UUID's can be null, so they need to be saved as the string "null"
|
// Serialize all key types
|
||||||
config.set(field.getName(), "null");
|
// 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)) {
|
} else if (propertyDescriptor.getPropertyType().equals(Set.class)) {
|
||||||
// Sets need to be serialized as string lists
|
// Sets need to be serialized as string lists
|
||||||
plugin.getLogger().info("DEBUG: Set for " + field.getName());
|
//plugin.getLogger().info("DEBUG: Set for " + field.getName());
|
||||||
|
|
||||||
List<Object> list = new ArrayList<Object>();
|
List<Object> list = new ArrayList<Object>();
|
||||||
for (Object object : (Set<Object>)value) {
|
for (Object object : (Set<Object>)value) {
|
||||||
if (object instanceof UUID) {
|
list.add(serialize(object));
|
||||||
list.add(((UUID)object).toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Save the list in the config file
|
// Save the list in the config file
|
||||||
config.set(field.getName(), list);
|
config.set(field.getName(), list);
|
||||||
} else {
|
} else {
|
||||||
// For all other data that doesn't need special serialization
|
// For all other data that doesn't need special serialization
|
||||||
config.set(field.getName(), value);
|
config.set(field.getName(), serialize(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (filename.isEmpty()) {
|
if (filename.isEmpty()) {
|
||||||
throw new IllegalArgumentException("No UUID in class");
|
throw new IllegalArgumentException("No uniqueId in class");
|
||||||
}
|
}
|
||||||
// Save the file in the right folder
|
// Save the file in the right folder
|
||||||
databaseConnecter.saveYamlFile(config, type.getSimpleName(), filename);
|
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) {
|
||||||
|
//plugin.getLogger().info("DEBUG: deserialize - class is " + clazz.getCanonicalName());
|
||||||
|
if (value instanceof String && value.equals("null")) {
|
||||||
|
// If the value is null as a string, return null
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// Types that need to be deserialized
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -108,8 +108,9 @@ public abstract class AbstractDatabaseHandler<T> {
|
|||||||
* @throws IntrospectionException
|
* @throws IntrospectionException
|
||||||
* @throws SecurityException
|
* @throws SecurityException
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
*/
|
*/
|
||||||
protected abstract List<T> selectObjects() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException, SQLException, SecurityException;
|
protected abstract List<T> selectObjects() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException, SQLException, SecurityException, ClassNotFoundException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a <T> filled with values from the corresponding
|
* Creates a <T> filled with values from the corresponding
|
||||||
@ -122,8 +123,10 @@ public abstract class AbstractDatabaseHandler<T> {
|
|||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* @throws InstantiationException
|
* @throws InstantiationException
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
* @throws SecurityException
|
||||||
*/
|
*/
|
||||||
protected abstract T selectObject(String uniqueId) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException, SQLException;
|
protected abstract T selectObject(String uniqueId) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException, SQLException, SecurityException, ClassNotFoundException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts T into the corresponding database-table
|
* Inserts T into the corresponding database-table
|
||||||
|
@ -249,29 +249,6 @@ public class MySQLDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
|||||||
return columns;
|
return columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a list of parameter types for the collection argument in this method
|
|
||||||
* @param writeMethod
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private List<Type> getCollectionParameterTypes(Method writeMethod) {
|
|
||||||
List<Type> result = new ArrayList<Type>();
|
|
||||||
// Get the return type
|
|
||||||
// This uses a trick to extract what the arguments are of the writeMethod of the field.
|
|
||||||
// In this way, we can deduce what type needs to be written at runtime.
|
|
||||||
Type[] genericParameterTypes = writeMethod.getGenericParameterTypes();
|
|
||||||
// There could be more than one argument, so step through them
|
|
||||||
for (int i = 0; i < genericParameterTypes.length; i++) {
|
|
||||||
// If the argument is a parameter, then do something - this should always be true if the parameter is a collection
|
|
||||||
if( genericParameterTypes[i] instanceof ParameterizedType ) {
|
|
||||||
// Get the actual type arguments of the parameter
|
|
||||||
Type[] parameters = ((ParameterizedType)genericParameterTypes[i]).getActualTypeArguments();
|
|
||||||
result.addAll(Arrays.asList(parameters));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler#createSelectQuery()
|
* @see us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler#createSelectQuery()
|
||||||
@ -504,12 +481,13 @@ public class MySQLDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
|||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* @throws IntrospectionException
|
* @throws IntrospectionException
|
||||||
* @throws InvocationTargetException
|
* @throws InvocationTargetException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<T> selectObjects() throws SQLException,
|
public List<T> selectObjects() throws SQLException,
|
||||||
SecurityException, IllegalArgumentException,
|
SecurityException, IllegalArgumentException,
|
||||||
InstantiationException, IllegalAccessException,
|
InstantiationException, IllegalAccessException,
|
||||||
IntrospectionException, InvocationTargetException {
|
IntrospectionException, InvocationTargetException, ClassNotFoundException {
|
||||||
|
|
||||||
Connection connection = null;
|
Connection connection = null;
|
||||||
Statement statement = null;
|
Statement statement = null;
|
||||||
@ -535,7 +513,7 @@ public class MySQLDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
|||||||
@Override
|
@Override
|
||||||
protected T selectObject(String uniqueId) throws InstantiationException,
|
protected T selectObject(String uniqueId) throws InstantiationException,
|
||||||
IllegalAccessException, IllegalArgumentException,
|
IllegalAccessException, IllegalArgumentException,
|
||||||
InvocationTargetException, IntrospectionException, SQLException {
|
InvocationTargetException, IntrospectionException, SQLException, SecurityException, ClassNotFoundException {
|
||||||
Connection connection = null;
|
Connection connection = null;
|
||||||
Statement statement = null;
|
Statement statement = null;
|
||||||
ResultSet resultSet = null;
|
ResultSet resultSet = null;
|
||||||
@ -578,13 +556,14 @@ public class MySQLDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
|||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* @throws IntrospectionException
|
* @throws IntrospectionException
|
||||||
* @throws InvocationTargetException
|
* @throws InvocationTargetException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private List<T> createObjects(ResultSet resultSet)
|
private List<T> createObjects(ResultSet resultSet)
|
||||||
throws SecurityException, IllegalArgumentException,
|
throws SecurityException, IllegalArgumentException,
|
||||||
SQLException, InstantiationException,
|
SQLException, InstantiationException,
|
||||||
IllegalAccessException, IntrospectionException,
|
IllegalAccessException, IntrospectionException,
|
||||||
InvocationTargetException {
|
InvocationTargetException, ClassNotFoundException {
|
||||||
|
|
||||||
List<T> list = new ArrayList<T>();
|
List<T> list = new ArrayList<T>();
|
||||||
// The database can return multiple results in one go, e.g., all the islands in the database
|
// The database can return multiple results in one go, e.g., all the islands in the database
|
||||||
@ -633,7 +612,7 @@ public class MySQLDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
|||||||
//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 = 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);
|
||||||
value = new HashSet<Object>();
|
value = new HashSet<Object>();
|
||||||
@ -641,13 +620,13 @@ public class MySQLDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
|||||||
//plugin.getLogger().info("DEBUG: setType = " + setType.getTypeName());
|
//plugin.getLogger().info("DEBUG: setType = " + setType.getTypeName());
|
||||||
while (collectionResultSet.next()) {
|
while (collectionResultSet.next()) {
|
||||||
//plugin.getLogger().info("DEBUG: collectionResultSet size = " + collectionResultSet.getFetchSize());
|
//plugin.getLogger().info("DEBUG: collectionResultSet size = " + collectionResultSet.getFetchSize());
|
||||||
((Set<Object>) value).add(deserialize(collectionResultSet.getObject(1),setType.getClass()));
|
((Set<Object>) value).add(deserialize(collectionResultSet.getObject(1),Class.forName(setType.getTypeName())));
|
||||||
}
|
}
|
||||||
} else if (propertyDescriptor.getPropertyType().equals(ArrayList.class)) {
|
} else if (propertyDescriptor.getPropertyType().equals(ArrayList.class)) {
|
||||||
//plugin.getLogger().info("DEBUG: Adding a list ");
|
//plugin.getLogger().info("DEBUG: Adding a list ");
|
||||||
// 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 = 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);
|
||||||
value = new ArrayList<Object>();
|
value = new ArrayList<Object>();
|
||||||
@ -655,14 +634,14 @@ public class MySQLDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
|||||||
while (collectionResultSet.next()) {
|
while (collectionResultSet.next()) {
|
||||||
//plugin.getLogger().info("DEBUG: adding to the list");
|
//plugin.getLogger().info("DEBUG: adding to the list");
|
||||||
//plugin.getLogger().info("DEBUG: collectionResultSet size = " + collectionResultSet.getFetchSize());
|
//plugin.getLogger().info("DEBUG: collectionResultSet size = " + collectionResultSet.getFetchSize());
|
||||||
((List<Object>) value).add(deserialize(collectionResultSet.getObject(1),setType.getClass()));
|
((List<Object>) value).add(deserialize(collectionResultSet.getObject(1),Class.forName(setType.getTypeName())));
|
||||||
}
|
}
|
||||||
} else if (propertyDescriptor.getPropertyType().equals(Map.class) ||
|
} else if (propertyDescriptor.getPropertyType().equals(Map.class) ||
|
||||||
propertyDescriptor.getPropertyType().equals(HashMap.class)) {
|
propertyDescriptor.getPropertyType().equals(HashMap.class)) {
|
||||||
//plugin.getLogger().info("DEBUG: Adding a map ");
|
//plugin.getLogger().info("DEBUG: Adding a map ");
|
||||||
// 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 = 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);
|
||||||
@ -673,9 +652,9 @@ public class MySQLDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
|||||||
//plugin.getLogger().info("DEBUG: collectionResultSet size = " + collectionResultSet.getFetchSize());
|
//plugin.getLogger().info("DEBUG: collectionResultSet size = " + collectionResultSet.getFetchSize());
|
||||||
// Work through the columns
|
// Work through the columns
|
||||||
// Key
|
// Key
|
||||||
Object key = (deserialize(collectionResultSet.getObject(1),keyType.getClass()));
|
Object key = deserialize(collectionResultSet.getObject(1),Class.forName(keyType.getTypeName()));
|
||||||
//plugin.getLogger().info("DEBUG: key = " + key);
|
//plugin.getLogger().info("DEBUG: key = " + key);
|
||||||
Object mapValue = (deserialize(collectionResultSet.getObject(2),valueType.getClass()));
|
Object mapValue = deserialize(collectionResultSet.getObject(2),Class.forName(valueType.getTypeName()));
|
||||||
//plugin.getLogger().info("DEBUG: value = " + mapValue);
|
//plugin.getLogger().info("DEBUG: value = " + mapValue);
|
||||||
((Map<Object,Object>) value).put(key,mapValue);
|
((Map<Object,Object>) value).put(key,mapValue);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
package us.tastybento.bskyblock.util;
|
package us.tastybento.bskyblock.util;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
@ -113,4 +119,27 @@ public class Util {
|
|||||||
}
|
}
|
||||||
return location.getWorld().getName() + ":" + location.getBlockX() + ":" + location.getBlockY() + ":" + location.getBlockZ() + ":" + Float.floatToIntBits(location.getYaw()) + ":" + Float.floatToIntBits(location.getPitch());
|
return location.getWorld().getName() + ":" + location.getBlockX() + ":" + location.getBlockY() + ":" + location.getBlockZ() + ":" + Float.floatToIntBits(location.getYaw()) + ":" + Float.floatToIntBits(location.getPitch());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of parameter types for the collection argument in this method
|
||||||
|
* @param writeMethod
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static List<Type> getCollectionParameterTypes(Method writeMethod) {
|
||||||
|
List<Type> result = new ArrayList<Type>();
|
||||||
|
// Get the return type
|
||||||
|
// This uses a trick to extract what the arguments are of the writeMethod of the field.
|
||||||
|
// In this way, we can deduce what type needs to be written at runtime.
|
||||||
|
Type[] genericParameterTypes = writeMethod.getGenericParameterTypes();
|
||||||
|
// There could be more than one argument, so step through them
|
||||||
|
for (int i = 0; i < genericParameterTypes.length; i++) {
|
||||||
|
// If the argument is a parameter, then do something - this should always be true if the parameter is a collection
|
||||||
|
if( genericParameterTypes[i] instanceof ParameterizedType ) {
|
||||||
|
// Get the actual type arguments of the parameter
|
||||||
|
Type[] parameters = ((ParameterizedType)genericParameterTypes[i]).getActualTypeArguments();
|
||||||
|
result.addAll(Arrays.asList(parameters));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user