mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2025-02-25 16:51:59 +01:00
Adds saveObjectAsync with a CompletableFuture return for databases (#1308)
Deprecates the saveObject() method
This commit is contained in:
parent
97341ce657
commit
fe58159db3
@ -4,6 +4,7 @@ import java.beans.IntrospectionException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
@ -143,7 +144,7 @@ public abstract class AbstractDatabaseHandler<T> {
|
||||
*
|
||||
* @param instance that should be inserted into the database
|
||||
*/
|
||||
public abstract void saveObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException ;
|
||||
public abstract CompletableFuture<Boolean> saveObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException ;
|
||||
|
||||
/**
|
||||
* Deletes the object with the unique id from the database. If the object does not exist, it will fail silently.
|
||||
|
@ -4,6 +4,7 @@ import java.beans.IntrospectionException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
@ -82,18 +83,32 @@ public class Database<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save config object. Saving may be done async.
|
||||
* Save object async. Saving may be done sync, depending on the underlying database.
|
||||
* @param instance to save
|
||||
* @return true if no immediate errors. If async, errors may occur later.
|
||||
* @since 1.13.0
|
||||
*/
|
||||
public boolean saveObject(T instance) {
|
||||
public CompletableFuture<Boolean> saveObjectAsync(T instance) {
|
||||
try {
|
||||
handler.saveObject(instance);
|
||||
return handler.saveObject(instance);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException
|
||||
| IntrospectionException e) {
|
||||
logger.severe(() -> "Could not save object to database! Error: " + e.getMessage());
|
||||
return false;
|
||||
return new CompletableFuture<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save object. Saving may be done async or sync, depending on the underlying database.
|
||||
* @param instance to save
|
||||
* @return true - always.
|
||||
* @deprecated As of 1.13.0. Use {@link #saveObjectAsync(Object)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean saveObject(T instance) {
|
||||
saveObjectAsync(instance).thenAccept(r -> {
|
||||
if (!r) logger.severe(() -> "Could not save object to database!");
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -137,4 +152,4 @@ public class Database<T> {
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
|
||||
@ -97,15 +98,18 @@ public class JSONDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
|
||||
public CompletableFuture<Boolean> saveObject(T instance) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
CompletableFuture<Boolean> completableFuture = new CompletableFuture<>();
|
||||
// Null check
|
||||
if (instance == null) {
|
||||
plugin.logError("JSON database request to store a null. ");
|
||||
return;
|
||||
completableFuture.complete(false);
|
||||
return completableFuture;
|
||||
}
|
||||
if (!(instance instanceof DataObject)) {
|
||||
plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
|
||||
return;
|
||||
completableFuture.complete(false);
|
||||
return completableFuture;
|
||||
}
|
||||
String path = DATABASE_FOLDER_NAME + File.separator + dataObject.getSimpleName();
|
||||
|
||||
@ -123,14 +127,15 @@ public class JSONDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
|
||||
String toStore = getGson().toJson(instance);
|
||||
if (plugin.isEnabled()) {
|
||||
// Async
|
||||
processQueue.add(() -> store(toStore, file, tableFolder, fileName));
|
||||
processQueue.add(() -> store(completableFuture, toStore, file, tableFolder, fileName));
|
||||
} else {
|
||||
// Sync
|
||||
store(toStore, file, tableFolder, fileName);
|
||||
store(completableFuture, toStore, file, tableFolder, fileName);
|
||||
}
|
||||
return completableFuture;
|
||||
}
|
||||
|
||||
private void store(String toStore, File file, File tableFolder, String fileName) {
|
||||
private void store(CompletableFuture<Boolean> completableFuture, String toStore, File file, File tableFolder, String fileName) {
|
||||
try (FileWriter fileWriter = new FileWriter(file)) {
|
||||
File tmpFile = new File(tableFolder, fileName + ".bak");
|
||||
if (file.exists()) {
|
||||
@ -139,8 +144,10 @@ public class JSONDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
|
||||
}
|
||||
fileWriter.write(toStore);
|
||||
Files.deleteIfExists(tmpFile.toPath());
|
||||
completableFuture.complete(true);
|
||||
} catch (IOException e) {
|
||||
plugin.logError("Could not save JSON file: " + tableFolder.getName() + " " + fileName + " " + e.getMessage());
|
||||
completableFuture.complete(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package world.bentobox.bentobox.database.mongodb;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.bson.conversions.Bson;
|
||||
@ -106,15 +107,18 @@ public class MongoDBDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveObject(T instance) {
|
||||
public CompletableFuture<Boolean> saveObject(T instance) {
|
||||
CompletableFuture<Boolean> completableFuture = new CompletableFuture<>();
|
||||
// Null check
|
||||
if (instance == null) {
|
||||
plugin.logError("MongoDB database request to store a null. ");
|
||||
return;
|
||||
completableFuture.complete(false);
|
||||
return completableFuture;
|
||||
}
|
||||
if (!(instance instanceof DataObject)) {
|
||||
plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
|
||||
return;
|
||||
completableFuture.complete(false);
|
||||
return completableFuture;
|
||||
}
|
||||
DataObject dataObj = (DataObject)instance;
|
||||
try {
|
||||
@ -129,10 +133,12 @@ public class MongoDBDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
|
||||
// Set the options to upsert (update or insert if doc is not there)
|
||||
FindOneAndReplaceOptions options = new FindOneAndReplaceOptions().upsert(true);
|
||||
// Do the deed
|
||||
collection.findOneAndReplace(filter, document, options);
|
||||
completableFuture.complete(collection.findOneAndReplace(filter, document, options) != null);
|
||||
} catch (Exception e) {
|
||||
plugin.logError("Could not save object " + instance.getClass().getName() + " " + e.getMessage());
|
||||
completableFuture.complete(false);
|
||||
}
|
||||
return completableFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -9,6 +9,7 @@ import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
@ -144,29 +145,34 @@ public class SQLDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveObject(T instance) {
|
||||
public CompletableFuture<Boolean> saveObject(T instance) {
|
||||
CompletableFuture<Boolean> completableFuture = new CompletableFuture<>();
|
||||
// Null check
|
||||
if (instance == null) {
|
||||
plugin.logError("SQL database request to store a null. ");
|
||||
return;
|
||||
completableFuture.complete(false);
|
||||
return completableFuture;
|
||||
}
|
||||
if (!(instance instanceof DataObject)) {
|
||||
plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
|
||||
return;
|
||||
completableFuture.complete(false);
|
||||
return completableFuture;
|
||||
}
|
||||
// This has to be on the main thread to avoid concurrent modification errors
|
||||
String toStore = getGson().toJson(instance);
|
||||
// Async
|
||||
processQueue.add(() -> store(instance.getClass().getName(), toStore, sqlConfig.getSaveObjectSQL()));
|
||||
processQueue.add(() -> store(completableFuture, instance.getClass().getName(), toStore, sqlConfig.getSaveObjectSQL()));
|
||||
return completableFuture;
|
||||
}
|
||||
|
||||
private void store(String name, String toStore, String sb) {
|
||||
private void store(CompletableFuture<Boolean> completableFuture, String name, String toStore, String sb) {
|
||||
try (PreparedStatement preparedStatement = connection.prepareStatement(sb)) {
|
||||
preparedStatement.setString(1, toStore);
|
||||
preparedStatement.setString(2, toStore);
|
||||
preparedStatement.execute();
|
||||
completableFuture.complete(preparedStatement.execute());
|
||||
} catch (SQLException e) {
|
||||
plugin.logError("Could not save object " + name + " " + e.getMessage());
|
||||
completableFuture.complete(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package world.bentobox.bentobox.database.sql.postgresql;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
@ -51,15 +52,18 @@ public class PostgreSQLDatabaseHandler<T> extends SQLDatabaseHandler<T> {
|
||||
* @see world.bentobox.bentobox.database.sql.SQLDatabaseHandler#saveObject(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public void saveObject(T instance) {
|
||||
public CompletableFuture<Boolean> saveObject(T instance) {
|
||||
CompletableFuture<Boolean> completableFuture = new CompletableFuture<>();
|
||||
// Null check
|
||||
if (instance == null) {
|
||||
plugin.logError("Postgres database request to store a null. ");
|
||||
return;
|
||||
plugin.logError("PostgreSQL database request to store a null. ");
|
||||
completableFuture.complete(false);
|
||||
return completableFuture;
|
||||
}
|
||||
if (!(instance instanceof DataObject)) {
|
||||
plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
|
||||
return;
|
||||
completableFuture.complete(false);
|
||||
return completableFuture;
|
||||
}
|
||||
Gson gson = getGson();
|
||||
String toStore = gson.toJson(instance);
|
||||
@ -69,10 +73,12 @@ public class PostgreSQLDatabaseHandler<T> extends SQLDatabaseHandler<T> {
|
||||
preparedStatement.setString(1, uniqueId); // INSERT
|
||||
preparedStatement.setString(2, toStore); // INSERT
|
||||
preparedStatement.setString(3, toStore); // ON CONFLICT
|
||||
preparedStatement.execute();
|
||||
completableFuture.complete(preparedStatement.execute());
|
||||
} catch (SQLException e) {
|
||||
plugin.logError("Could not save object " + instance.getClass().getName() + " " + e.getMessage());
|
||||
completableFuture.complete(false);
|
||||
}
|
||||
});
|
||||
return completableFuture;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package world.bentobox.bentobox.database.sql.sqlite;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
|
||||
@ -39,15 +40,18 @@ public class SQLiteDatabaseHandler<T> extends SQLDatabaseHandler<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveObject(T instance) {
|
||||
public CompletableFuture<Boolean> saveObject(T instance) {
|
||||
CompletableFuture<Boolean> completableFuture = new CompletableFuture<>();
|
||||
// Null check
|
||||
if (instance == null) {
|
||||
plugin.logError("MySQL database request to store a null. ");
|
||||
return;
|
||||
plugin.logError("SQLite database request to store a null. ");
|
||||
completableFuture.complete(false);
|
||||
return completableFuture;
|
||||
}
|
||||
if (!(instance instanceof DataObject)) {
|
||||
plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
|
||||
return;
|
||||
completableFuture.complete(false);
|
||||
return completableFuture;
|
||||
}
|
||||
Gson gson = getGson();
|
||||
String toStore = gson.toJson(instance);
|
||||
@ -56,11 +60,13 @@ public class SQLiteDatabaseHandler<T> extends SQLDatabaseHandler<T> {
|
||||
preparedStatement.setString(1, toStore);
|
||||
preparedStatement.setString(2, ((DataObject)instance).getUniqueId());
|
||||
preparedStatement.setString(3, toStore);
|
||||
preparedStatement.execute();
|
||||
completableFuture.complete(preparedStatement.execute());
|
||||
} catch (SQLException e) {
|
||||
plugin.logError("Could not save object " + instance.getClass().getName() + " " + e.getMessage());
|
||||
completableFuture.complete(false);
|
||||
}
|
||||
});
|
||||
return completableFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3,6 +3,7 @@ package world.bentobox.bentobox.database.transition;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
@ -83,9 +84,9 @@ public class TransitionDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
||||
* @see world.bentobox.bentobox.database.AbstractDatabaseHandler#saveObject(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public void saveObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
|
||||
public CompletableFuture<Boolean> saveObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
|
||||
// Save only in the destination database
|
||||
toHandler.saveObject(instance);
|
||||
return toHandler.saveObject(instance);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -116,7 +116,7 @@ public class YamlDatabaseConnector implements DatabaseConnector {
|
||||
}
|
||||
}
|
||||
|
||||
public void saveYamlFile(String data, String tableName, String fileName, Map<String, String> commentMap) {
|
||||
boolean saveYamlFile(String data, String tableName, String fileName, Map<String, String> commentMap) {
|
||||
String name = fileName.endsWith(YML) ? fileName : fileName + YML;
|
||||
File tableFolder = new File(plugin.getDataFolder(), tableName);
|
||||
File file = new File(tableFolder, name);
|
||||
@ -127,11 +127,12 @@ public class YamlDatabaseConnector implements DatabaseConnector {
|
||||
writer.write(data);
|
||||
} catch (IOException e) {
|
||||
plugin.logError("Could not save yml file: " + tableName + " " + fileName + " " + e.getMessage());
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (commentMap != null && !commentMap.isEmpty()) {
|
||||
commentFile(new File(tableFolder, name), commentMap);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,6 +22,7 @@ import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
@ -325,19 +326,22 @@ public class YamlDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
||||
* Inserts T into the corresponding database-table
|
||||
*
|
||||
* @param instance that should be inserted into the database
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void saveObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
|
||||
public CompletableFuture<Boolean> saveObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
|
||||
CompletableFuture<Boolean> completableFuture = new CompletableFuture<>();
|
||||
// Null check
|
||||
if (instance == null) {
|
||||
plugin.logError("YAML database request to store a null.");
|
||||
return;
|
||||
completableFuture.complete(false);
|
||||
return completableFuture;
|
||||
}
|
||||
// DataObject check
|
||||
if (!(instance instanceof DataObject)) {
|
||||
plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
|
||||
return;
|
||||
completableFuture.complete(false);
|
||||
return completableFuture;
|
||||
}
|
||||
// This is the Yaml Configuration that will be used and saved at the end
|
||||
YamlConfiguration config = new YamlConfiguration();
|
||||
@ -414,16 +418,19 @@ public class YamlDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
|
||||
}
|
||||
|
||||
// Save
|
||||
save(filename, config.saveToString(), path, yamlComments);
|
||||
save(completableFuture, filename, config.saveToString(), path, yamlComments);
|
||||
return completableFuture;
|
||||
}
|
||||
|
||||
private void save(String name, String data, String path, Map<String, String> yamlComments) {
|
||||
private void save(CompletableFuture<Boolean> completableFuture, String name, String data, String path, Map<String, String> yamlComments) {
|
||||
if (plugin.isEnabled()) {
|
||||
// Async
|
||||
processQueue.add(() -> ((YamlDatabaseConnector)databaseConnector).saveYamlFile(data, path, name, yamlComments));
|
||||
processQueue.add(() -> completableFuture.complete(
|
||||
((YamlDatabaseConnector)databaseConnector).saveYamlFile(data, path, name, yamlComments)));
|
||||
} else {
|
||||
// Sync for shutdown
|
||||
((YamlDatabaseConnector)databaseConnector).saveYamlFile(data, path, name, yamlComments);
|
||||
completableFuture.complete(
|
||||
((YamlDatabaseConnector)databaseConnector).saveYamlFile(data, path, name, yamlComments));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ public class IslandDeletionManager implements Listener {
|
||||
// Store location
|
||||
inDeletion.add(e.getDeletedIslandInfo().getLocation());
|
||||
// Save to database
|
||||
handler.saveObject(e.getDeletedIslandInfo());
|
||||
handler.saveObjectAsync(e.getDeletedIslandInfo());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
|
@ -340,7 +340,7 @@ public class IslandsManager {
|
||||
// Set the delete flag which will prevent it from being loaded even if database deletion fails
|
||||
island.setDeleted(true);
|
||||
// Save the island
|
||||
handler.saveObject(island);
|
||||
handler.saveObjectAsync(island);
|
||||
// Delete the island
|
||||
handler.deleteObject(island);
|
||||
// Remove players from island
|
||||
@ -900,7 +900,7 @@ public class IslandsManager {
|
||||
plugin.logError(toQuarantine.size() + " islands could not be loaded successfully; moving to trash bin.");
|
||||
plugin.logError(unowned + " are unowned, " + owned + " are owned.");
|
||||
|
||||
toQuarantine.forEach(handler::saveObject);
|
||||
toQuarantine.forEach(handler::saveObjectAsync);
|
||||
// Check if there are any islands with duplicate islands
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
Set<UUID> duplicatedUUIDRemovedSet = new HashSet<>();
|
||||
@ -1004,7 +1004,7 @@ public class IslandsManager {
|
||||
public void removePlayer(World world, UUID uuid) {
|
||||
Island island = islandCache.removePlayer(world, uuid);
|
||||
if (island != null) {
|
||||
handler.saveObject(island);
|
||||
handler.saveObjectAsync(island);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1037,7 +1037,7 @@ public class IslandsManager {
|
||||
Collection<Island> collection = islandCache.getIslands();
|
||||
for(Island island : collection){
|
||||
try {
|
||||
handler.saveObject(island);
|
||||
handler.saveObjectAsync(island);
|
||||
} catch (Exception e) {
|
||||
plugin.logError("Could not save island to database when running sync! " + e.getMessage());
|
||||
}
|
||||
@ -1072,7 +1072,7 @@ public class IslandsManager {
|
||||
teamIsland.addMember(playerUUID);
|
||||
islandCache.addPlayer(playerUUID, teamIsland);
|
||||
// Save the island
|
||||
handler.saveObject(teamIsland);
|
||||
handler.saveObjectAsync(teamIsland);
|
||||
}
|
||||
|
||||
public void setLast(Location last) {
|
||||
@ -1198,7 +1198,7 @@ public class IslandsManager {
|
||||
* @param island - island
|
||||
*/
|
||||
public void save(Island island) {
|
||||
handler.saveObject(island);
|
||||
handler.saveObjectAsync(island);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1290,10 +1290,9 @@ public class IslandsManager {
|
||||
// Put old island into trash
|
||||
quarantineCache.computeIfAbsent(target, k -> new ArrayList<>()).add(oldIsland);
|
||||
// Save old island
|
||||
if (!handler.saveObject(oldIsland)) {
|
||||
plugin.logError("Could not save trashed island in database");
|
||||
return false;
|
||||
}
|
||||
handler.saveObjectAsync(oldIsland).thenAccept(result -> {
|
||||
if (!result) plugin.logError("Could not save trashed island in database");
|
||||
});
|
||||
}
|
||||
// Restore island from trash
|
||||
island.setDoNotLoad(false);
|
||||
@ -1303,10 +1302,9 @@ public class IslandsManager {
|
||||
return false;
|
||||
}
|
||||
// Save new island
|
||||
if (!handler.saveObject(island)) {
|
||||
plugin.logError("Could not save recovered island to database");
|
||||
return false;
|
||||
}
|
||||
handler.saveObjectAsync(island).thenAccept(result -> {
|
||||
if (!result) plugin.logError("Could not save recovered island to database");
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ public class PlayersManager {
|
||||
* Save all players
|
||||
*/
|
||||
public void saveAll(){
|
||||
Collections.unmodifiableCollection(playerCache.values()).forEach(handler::saveObject);
|
||||
Collections.unmodifiableCollection(playerCache.values()).forEach(handler::saveObjectAsync);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -281,7 +281,7 @@ public class PlayersManager {
|
||||
playerCache.get(user.getUniqueId()).setPlayerName(user.getName());
|
||||
Names newName = new Names(user.getName(), user.getUniqueId());
|
||||
// Add to names database
|
||||
names.saveObject(newName);
|
||||
names.saveObjectAsync(newName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -425,7 +425,7 @@ public class PlayersManager {
|
||||
*/
|
||||
public void save(UUID playerUUID) {
|
||||
if (playerCache.containsKey(playerUUID)) {
|
||||
handler.saveObject(playerCache.get(playerUUID));
|
||||
handler.saveObjectAsync(playerCache.get(playerUUID));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,13 @@ package world.bentobox.bentobox.database;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.framework;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.beans.IntrospectionException;
|
||||
@ -11,6 +17,7 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ -21,7 +28,6 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
@ -66,17 +72,22 @@ public class DatabaseTest {
|
||||
PowerMockito.mockStatic(DatabaseSetup.class);
|
||||
dbSetup = mock(DatabaseSetup.class);
|
||||
handler = mock(AbstractDatabaseHandler.class);
|
||||
when(dbSetup.getHandler(Mockito.any())).thenReturn(handler);
|
||||
when(dbSetup.getHandler(any())).thenReturn(handler);
|
||||
// Set the internal state of the static database variable to null for each test
|
||||
Whitebox.setInternalState(Database.class, "databaseSetup", dbSetup);
|
||||
|
||||
when(handler.loadObject(Mockito.anyString())).thenReturn(island);
|
||||
when(handler.loadObject(anyString())).thenReturn(island);
|
||||
objectList = new ArrayList<>();
|
||||
objectList.add(mock(Island.class));
|
||||
objectList.add(mock(Island.class));
|
||||
objectList.add(mock(Island.class));
|
||||
objectList.add(mock(Island.class));
|
||||
when(handler.loadObjects()).thenReturn(objectList);
|
||||
|
||||
CompletableFuture<Boolean> completetableFuture = new CompletableFuture<>();
|
||||
// Complete immediately in a positive way
|
||||
completetableFuture.complete(true);
|
||||
when(handler.saveObject(any())).thenReturn(completetableFuture);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -85,7 +96,7 @@ public class DatabaseTest {
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
dbSetup = null;
|
||||
Mockito.framework().clearInlineMocks();
|
||||
framework().clearInlineMocks();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,7 +105,7 @@ public class DatabaseTest {
|
||||
*/
|
||||
private void checkSevereLog(String stringToCheck) {
|
||||
// This magic obtains the lambda from an argument
|
||||
Mockito.verify(logger).severe(registerMessageLambdaCaptor.capture());
|
||||
verify(logger).severe(registerMessageLambdaCaptor.capture());
|
||||
Supplier<String> lambda = registerMessageLambdaCaptor.getValue();
|
||||
assertEquals(stringToCheck,lambda.get());
|
||||
}
|
||||
@ -104,8 +115,8 @@ public class DatabaseTest {
|
||||
@Test
|
||||
public void testDatabaseBentoBoxClassOfT() {
|
||||
new Database<Island>(plugin, Island.class);
|
||||
Mockito.verify(plugin).getLogger();
|
||||
Mockito.verify(dbSetup).getHandler(Mockito.any());
|
||||
verify(plugin).getLogger();
|
||||
verify(dbSetup).getHandler(any());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -114,8 +125,8 @@ public class DatabaseTest {
|
||||
@Test
|
||||
public void testDatabaseAddonClassOfT() {
|
||||
new Database<Island>(addon, Island.class);
|
||||
Mockito.verify(addon).getLogger();
|
||||
Mockito.verify(dbSetup).getHandler(Mockito.any());
|
||||
verify(addon).getLogger();
|
||||
verify(dbSetup).getHandler(any());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -131,7 +142,7 @@ public class DatabaseTest {
|
||||
public void testLoadObjects() throws InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException, NoSuchMethodException, IntrospectionException {
|
||||
Database<Island> db = new Database<Island>(plugin, Island.class);
|
||||
assertEquals(objectList, db.loadObjects());
|
||||
Mockito.verify(handler).loadObjects();
|
||||
verify(handler).loadObjects();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -148,7 +159,7 @@ public class DatabaseTest {
|
||||
when(handler.loadObjects()).thenThrow(new IllegalAccessException("No bad dog! No biscuit!"));
|
||||
Database<Island> db = new Database<Island>(plugin, Island.class);
|
||||
db.loadObjects();
|
||||
Mockito.verify(handler).loadObjects();
|
||||
verify(handler).loadObjects();
|
||||
checkSevereLog("Could not load objects from database! Error: No bad dog! No biscuit!");
|
||||
|
||||
}
|
||||
@ -167,7 +178,7 @@ public class DatabaseTest {
|
||||
Database<Island> db = new Database<Island>(plugin, Island.class);
|
||||
String uniqueId = UUID.randomUUID().toString();
|
||||
assertEquals(island, db.loadObject(uniqueId));
|
||||
Mockito.verify(handler).loadObject(Mockito.eq(uniqueId));
|
||||
verify(handler).loadObject(eq(uniqueId));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -179,8 +190,9 @@ public class DatabaseTest {
|
||||
@Test
|
||||
public void testSaveObject() throws IllegalAccessException, InvocationTargetException, IntrospectionException {
|
||||
Database<Island> db = new Database<Island>(plugin, Island.class);
|
||||
assertTrue(db.saveObject(island));
|
||||
Mockito.verify(handler).saveObject(Mockito.eq(island));
|
||||
db.saveObjectAsync(island);
|
||||
verify(handler).saveObject(eq(island));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -190,10 +202,10 @@ public class DatabaseTest {
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
@Test
|
||||
public void testSaveObjectFail() throws IllegalAccessException, InvocationTargetException, IntrospectionException {
|
||||
Mockito.doThrow(new IntrospectionException("No means no!")).when(handler).saveObject(Mockito.any(Island.class));
|
||||
public void testSaveObjectException() throws IllegalAccessException, InvocationTargetException, IntrospectionException {
|
||||
doThrow(new IntrospectionException("No means no!")).when(handler).saveObject(any(Island.class));
|
||||
Database<Island> db = new Database<Island>(plugin, Island.class);
|
||||
assertFalse(db.saveObject(island));
|
||||
db.saveObjectAsync(island);
|
||||
checkSevereLog("Could not save object to database! Error: No means no!");
|
||||
}
|
||||
|
||||
@ -202,8 +214,8 @@ public class DatabaseTest {
|
||||
*/
|
||||
@Test
|
||||
public void testObjectExists() {
|
||||
when(handler.objectExists(Mockito.eq("test"))).thenReturn(false);
|
||||
when(handler.objectExists(Mockito.eq("exists"))).thenReturn(true);
|
||||
when(handler.objectExists(eq("test"))).thenReturn(false);
|
||||
when(handler.objectExists(eq("exists"))).thenReturn(true);
|
||||
Database<Island> db = new Database<Island>(plugin, Island.class);
|
||||
assertFalse(db.objectExists("test"));
|
||||
assertTrue(db.objectExists("exists"));
|
||||
@ -216,7 +228,7 @@ public class DatabaseTest {
|
||||
public void testDeleteID() {
|
||||
Database<Island> db = new Database<Island>(plugin, Island.class);
|
||||
db.deleteID("test");
|
||||
Mockito.verify(handler).deleteID(Mockito.eq("test"));
|
||||
verify(handler).deleteID(eq("test"));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -229,7 +241,7 @@ public class DatabaseTest {
|
||||
public void testDeleteObject() throws IllegalAccessException, InvocationTargetException, IntrospectionException {
|
||||
Database<Island> db = new Database<Island>(plugin, Island.class);
|
||||
db.deleteObject(island);
|
||||
Mockito.verify(handler).deleteObject(Mockito.eq(island));
|
||||
verify(handler).deleteObject(eq(island));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -240,7 +252,7 @@ public class DatabaseTest {
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteObjectFail() throws IllegalAccessException, InvocationTargetException, IntrospectionException {
|
||||
Mockito.doThrow(new IllegalArgumentException("Wot?!")).when(handler).deleteObject(Mockito.any());
|
||||
doThrow(new IllegalArgumentException("Wot?!")).when(handler).deleteObject(any());
|
||||
Database<Island> db = new Database<Island>(plugin, Island.class);
|
||||
db.deleteObject(island);
|
||||
checkSevereLog("Could not delete object! Error: Wot?!");
|
||||
@ -254,7 +266,7 @@ public class DatabaseTest {
|
||||
public void testClose() {
|
||||
Database<Island> db = new Database<Island>(plugin, Island.class);
|
||||
db.close();
|
||||
Mockito.verify(handler).close();
|
||||
verify(handler).close();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package world.bentobox.bentobox.database.yaml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isA;
|
||||
import static org.mockito.Mockito.framework;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.beans.IntrospectionException;
|
||||
@ -35,7 +38,6 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
@ -91,11 +93,11 @@ public class YamlDatabaseHandlerTest {
|
||||
PowerMockito.mockStatic(Bukkit.class);
|
||||
when(Bukkit.getScheduler()).thenReturn(scheduler);
|
||||
|
||||
when(scheduler.runTaskAsynchronously(Mockito.any(), Mockito.any(Runnable.class))).thenReturn(task);
|
||||
when(scheduler.runTaskAsynchronously(any(), any(Runnable.class))).thenReturn(task);
|
||||
Server server = mock(Server.class);
|
||||
World world = mock(World.class);
|
||||
when(world.getName()).thenReturn("cleanroom");
|
||||
when(server.getWorld(Mockito.anyString())).thenReturn(world);
|
||||
when(server.getWorld(anyString())).thenReturn(world);
|
||||
when(Bukkit.getServer()).thenReturn(server);
|
||||
|
||||
// A YAML file representing island
|
||||
@ -105,11 +107,11 @@ public class YamlDatabaseHandlerTest {
|
||||
config.loadFromString(getYaml(uuid));
|
||||
YamlConfiguration config2 = new YamlConfiguration();
|
||||
config2.loadFromString(getYaml2(uuid2));
|
||||
when(dbConnector.loadYamlFile(Mockito.anyString(), Mockito.anyString())).thenReturn(config, config2);
|
||||
when(dbConnector.loadYamlFile(anyString(), anyString())).thenReturn(config, config2);
|
||||
|
||||
// Flags Manager
|
||||
FlagsManager fm = mock(FlagsManager.class);
|
||||
when(fm.getFlag(Mockito.anyString())).thenReturn(Optional.empty());
|
||||
when(fm.getFlag(anyString())).thenReturn(Optional.empty());
|
||||
when(plugin.getFlagsManager()).thenReturn(fm);
|
||||
|
||||
// Island
|
||||
@ -138,7 +140,7 @@ public class YamlDatabaseHandlerTest {
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.map(Path::toFile)
|
||||
.forEach(File::delete);
|
||||
Mockito.framework().clearInlineMocks();
|
||||
framework().clearInlineMocks();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,7 +191,7 @@ public class YamlDatabaseHandlerTest {
|
||||
Location center = mock(Location.class);
|
||||
is.setCenter(center);
|
||||
handler.saveObject(is);
|
||||
Mockito.verify(dbConnector).saveYamlFile(Mockito.anyString(), Mockito.eq("database/Island"), Mockito.eq("unique"), Mockito.isA(Map.class));
|
||||
verify(dbConnector).saveYamlFile(anyString(), eq("database/Island"), eq("unique"), isA(Map.class));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -201,7 +203,7 @@ public class YamlDatabaseHandlerTest {
|
||||
@Test
|
||||
public void testSaveObjectNull() throws IllegalAccessException, InvocationTargetException, IntrospectionException {
|
||||
handler.saveObject(null);
|
||||
Mockito.verify(plugin).logError("YAML database request to store a null.");
|
||||
verify(plugin).logError("YAML database request to store a null.");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -215,7 +217,7 @@ public class YamlDatabaseHandlerTest {
|
||||
YamlDatabaseHandler<String> h = new YamlDatabaseHandler<String>(plugin, String.class, dbConnector);
|
||||
String test = "";
|
||||
h.saveObject(test);
|
||||
Mockito.verify(plugin).logError("This class is not a DataObject: java.lang.String");
|
||||
verify(plugin).logError("This class is not a DataObject: java.lang.String");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -238,7 +240,7 @@ public class YamlDatabaseHandlerTest {
|
||||
@Test
|
||||
public void testDeleteObjectNull() throws IllegalAccessException, InvocationTargetException, IntrospectionException {
|
||||
handler.deleteObject(null);
|
||||
Mockito.verify(plugin).logError("YAML database request to delete a null.");
|
||||
verify(plugin).logError("YAML database request to delete a null.");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -252,7 +254,7 @@ public class YamlDatabaseHandlerTest {
|
||||
YamlDatabaseHandler<String> h = new YamlDatabaseHandler<String>(plugin, String.class, dbConnector);
|
||||
String test = "";
|
||||
h.deleteObject(test);
|
||||
Mockito.verify(plugin).logError("This class is not a DataObject: java.lang.String");
|
||||
verify(plugin).logError("This class is not a DataObject: java.lang.String");
|
||||
|
||||
}
|
||||
|
||||
@ -261,7 +263,7 @@ public class YamlDatabaseHandlerTest {
|
||||
*/
|
||||
@Test
|
||||
public void testObjectExists() {
|
||||
when(dbConnector.uniqueIdExists(Mockito.eq(Island.class.getSimpleName()), Mockito.eq(uuid.toString()))).thenReturn(true);
|
||||
when(dbConnector.uniqueIdExists(eq(Island.class.getSimpleName()), eq(uuid.toString()))).thenReturn(true);
|
||||
assertTrue(handler.objectExists(uuid.toString()));
|
||||
assertFalse(handler.objectExists("nope"));
|
||||
}
|
||||
@ -301,12 +303,12 @@ public class YamlDatabaseHandlerTest {
|
||||
*/
|
||||
@Test
|
||||
public void testYamlDatabaseHandler() {
|
||||
Mockito.verify(scheduler).runTaskAsynchronously(Mockito.eq(plugin), registerLambdaCaptor.capture());
|
||||
verify(scheduler).runTaskAsynchronously(eq(plugin), registerLambdaCaptor.capture());
|
||||
Runnable lamda = registerLambdaCaptor.getValue();
|
||||
// Cannot run with true otherwise it'll infinite loop
|
||||
when(plugin.isShutdown()).thenReturn(true);
|
||||
lamda.run();
|
||||
Mockito.verify(task).cancel();
|
||||
verify(task).cancel();
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user