mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2024-11-24 11:45:31 +01:00
Added JSON (flatfile) database type
This commit is contained in:
parent
10000b71f6
commit
db5ac2d0e5
@ -2,6 +2,7 @@ package world.bentobox.bentobox.database;
|
|||||||
|
|
||||||
import world.bentobox.bentobox.BentoBox;
|
import world.bentobox.bentobox.BentoBox;
|
||||||
import world.bentobox.bentobox.database.flatfile.FlatFileDatabase;
|
import world.bentobox.bentobox.database.flatfile.FlatFileDatabase;
|
||||||
|
import world.bentobox.bentobox.database.json.JSONDatabase;
|
||||||
import world.bentobox.bentobox.database.mongodb.MongoDBDatabase;
|
import world.bentobox.bentobox.database.mongodb.MongoDBDatabase;
|
||||||
import world.bentobox.bentobox.database.mysql.MySQLDatabase;
|
import world.bentobox.bentobox.database.mysql.MySQLDatabase;
|
||||||
|
|
||||||
@ -9,7 +10,7 @@ public interface DatabaseSetup {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the type of database being used.
|
* Gets the type of database being used.
|
||||||
* Currently supported options are FLATFILE, MYSQL and MONGODB.
|
* Currently supported options are FLATFILE, JSON, MYSQL and MONGODB.
|
||||||
* Default is FLATFILE.
|
* Default is FLATFILE.
|
||||||
* @return Database type
|
* @return Database type
|
||||||
*/
|
*/
|
||||||
@ -24,6 +25,7 @@ public interface DatabaseSetup {
|
|||||||
|
|
||||||
enum DatabaseType {
|
enum DatabaseType {
|
||||||
FLATFILE(new FlatFileDatabase()),
|
FLATFILE(new FlatFileDatabase()),
|
||||||
|
JSON(new JSONDatabase()),
|
||||||
MYSQL(new MySQLDatabase()),
|
MYSQL(new MySQLDatabase()),
|
||||||
MONGODB(new MongoDBDatabase());
|
MONGODB(new MongoDBDatabase());
|
||||||
|
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
package world.bentobox.bentobox.database.json;
|
||||||
|
|
||||||
|
import world.bentobox.bentobox.BentoBox;
|
||||||
|
import world.bentobox.bentobox.database.AbstractDatabaseHandler;
|
||||||
|
import world.bentobox.bentobox.database.DatabaseSetup;
|
||||||
|
|
||||||
|
public class JSONDatabase implements DatabaseSetup {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> AbstractDatabaseHandler<T> getHandler(Class<T> dataObjectClass) {
|
||||||
|
return new JSONDatabaseHandler<>(BentoBox.getInstance(), dataObjectClass, new JSONDatabaseConnector(BentoBox.getInstance()));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package world.bentobox.bentobox.database.json;
|
||||||
|
|
||||||
|
import world.bentobox.bentobox.BentoBox;
|
||||||
|
import world.bentobox.bentobox.database.DatabaseConnector;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class JSONDatabaseConnector implements DatabaseConnector {
|
||||||
|
|
||||||
|
private static final int MAX_LOOPS = 100;
|
||||||
|
private static final String DATABASE_FOLDER_NAME = "database";
|
||||||
|
private final BentoBox plugin;
|
||||||
|
private final File dataFolder;
|
||||||
|
|
||||||
|
public JSONDatabaseConnector(BentoBox plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
dataFolder = new File(plugin.getDataFolder(), DATABASE_FOLDER_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUniqueId(String tableName) {
|
||||||
|
UUID uuid = UUID.randomUUID();
|
||||||
|
File file = new File(dataFolder, tableName + File.separator + uuid.toString() + ".json");
|
||||||
|
int limit = 0;
|
||||||
|
while (file.exists() && limit++ < MAX_LOOPS) {
|
||||||
|
uuid = UUID.randomUUID();
|
||||||
|
file = new File(dataFolder, tableName + File.separator + uuid.toString() + ".json");
|
||||||
|
}
|
||||||
|
return uuid.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean uniqueIdExists(String tableName, String key) {
|
||||||
|
File file = new File(dataFolder, tableName + File.separator + key + ".json");
|
||||||
|
return file.exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object createConnection() {
|
||||||
|
return null; // Not used
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getConnectionUrl() {
|
||||||
|
return null; // Not used
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeConnection() {
|
||||||
|
// Not used
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,153 @@
|
|||||||
|
package world.bentobox.bentobox.database.json;
|
||||||
|
|
||||||
|
import world.bentobox.bentobox.BentoBox;
|
||||||
|
import world.bentobox.bentobox.database.DatabaseConnector;
|
||||||
|
|
||||||
|
import java.beans.IntrospectionException;
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class JSONDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param plugin
|
||||||
|
* @param type The type of the objects that should be created and filled with
|
||||||
|
* values from the database or inserted into the database
|
||||||
|
* @param databaseConnector Contains the settings to create a connection to the database
|
||||||
|
*/
|
||||||
|
JSONDatabaseHandler(BentoBox plugin, Class<T> type, DatabaseConnector databaseConnector) {
|
||||||
|
super(plugin, type, databaseConnector);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<T> loadObjects() {
|
||||||
|
// In this case, all the objects of a specific type are being loaded.
|
||||||
|
List<T> list = new ArrayList<>();
|
||||||
|
|
||||||
|
// The path is the simple name of the class
|
||||||
|
String path = dataObject.getSimpleName();
|
||||||
|
|
||||||
|
// The database folder name is in the plugin's data folder
|
||||||
|
File dataFolder = new File(plugin.getDataFolder(), DATABASE_FOLDER_NAME);
|
||||||
|
// The folder for the objects (tables in database terminology) is here
|
||||||
|
File tableFolder = new File(dataFolder, path);
|
||||||
|
if (!tableFolder.exists()) {
|
||||||
|
// Nothing there...
|
||||||
|
tableFolder.mkdirs();
|
||||||
|
}
|
||||||
|
// Load each object from the file system, filtered, non-null
|
||||||
|
for (File file: Objects.requireNonNull(tableFolder.listFiles((dir, name) -> name.toLowerCase(Locale.ENGLISH).endsWith(".json")))) {
|
||||||
|
try {
|
||||||
|
list.add(getGson().fromJson(new FileReader(file), dataObject));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
plugin.logError("Could not load file '" + file.getName() + "': File not found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T loadObject(String uniqueId) {
|
||||||
|
// Objects are loaded from a folder named after the simple name of the class being stored
|
||||||
|
String path = DATABASE_FOLDER_NAME + File.separator + dataObject.getSimpleName();
|
||||||
|
|
||||||
|
String fileName = path + File.separator + uniqueId;
|
||||||
|
if (!fileName.endsWith(".json")) {
|
||||||
|
fileName = fileName + ".json";
|
||||||
|
}
|
||||||
|
|
||||||
|
T result = null;
|
||||||
|
try {
|
||||||
|
result = getGson().fromJson(new FileReader(new File(plugin.getDataFolder(), fileName)), dataObject);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
plugin.logError("Could not load file '" + fileName + "': File not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
|
||||||
|
String path = DATABASE_FOLDER_NAME + File.separator + dataObject.getSimpleName();
|
||||||
|
|
||||||
|
// Obtain the value of uniqueId within the instance (which must be a DataObject)
|
||||||
|
PropertyDescriptor propertyDescriptor = new PropertyDescriptor("uniqueId", dataObject);
|
||||||
|
Method method = propertyDescriptor.getReadMethod();
|
||||||
|
String fileName = (String) method.invoke(instance);
|
||||||
|
|
||||||
|
File tableFolder = new File(plugin.getDataFolder(), path);
|
||||||
|
File file = new File(tableFolder, fileName);
|
||||||
|
if (!tableFolder.exists()) {
|
||||||
|
tableFolder.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
String toStore = getGson().toJson(instance);
|
||||||
|
|
||||||
|
try {
|
||||||
|
File tmpFile = new File(tableFolder, fileName + ".bak");
|
||||||
|
if (file.exists()) {
|
||||||
|
// Make a backup of file
|
||||||
|
Files.copy(file.toPath(), tmpFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
}
|
||||||
|
FileWriter fileWriter = new FileWriter(file);
|
||||||
|
fileWriter.write(toStore);
|
||||||
|
fileWriter.close();
|
||||||
|
Files.deleteIfExists(tmpFile.toPath());
|
||||||
|
} catch (IOException e) {
|
||||||
|
plugin.logError("Could not save json file: " + path + " " + fileName + " " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
|
||||||
|
// Obtain the value of uniqueId within the instance (which must be a DataObject)
|
||||||
|
PropertyDescriptor propertyDescriptor = new PropertyDescriptor("uniqueId", dataObject);
|
||||||
|
Method method = propertyDescriptor.getReadMethod();
|
||||||
|
String fileName = (String) method.invoke(instance);
|
||||||
|
|
||||||
|
// The filename of the JSON file is the value of uniqueId field plus .json. Sometimes the .json is already appended.
|
||||||
|
if (!fileName.endsWith(".json")) {
|
||||||
|
fileName = fileName + ".json";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the database and table folders
|
||||||
|
File dataFolder = new File(plugin.getDataFolder(), DATABASE_FOLDER_NAME);
|
||||||
|
File tableFolder = new File(dataFolder, dataObject.getSimpleName());
|
||||||
|
if (tableFolder.exists()) {
|
||||||
|
// Obtain the file and delete it
|
||||||
|
File file = new File(tableFolder, fileName);
|
||||||
|
try {
|
||||||
|
Files.delete(file.toPath());
|
||||||
|
} catch (IOException e) {
|
||||||
|
plugin.logError("Could not delete json database object! " + file.getName() + " - " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean objectExists(String uniqueId) {
|
||||||
|
// Check if the uniqueId (key) exists in the file system
|
||||||
|
return databaseConnector.uniqueIdExists(dataObject.getSimpleName(), uniqueId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
// Not used
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user