Restored one Database method for getting the new UserData objects.

This commit is contained in:
Rsl1122 2017-08-21 20:36:01 +03:00
parent e4220574da
commit f7fca4b863
7 changed files with 67 additions and 347 deletions

View File

@ -3,23 +3,12 @@ package main.java.com.djrapitops.plan.command.commands.manage;
import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.utilities.FormattingUtils;
import com.djrapitops.plugin.utilities.player.Fetch;
import com.djrapitops.plugin.utilities.player.IOfflinePlayer;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.handling.importing.ImportUtils;
import main.java.com.djrapitops.plan.data.handling.importing.Importer;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.utilities.Check;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* This manage subcommand is used to import data from 3rd party plugins.
* <p>
@ -58,52 +47,7 @@ public class ManageImportCommand extends SubCommand {
if (!Check.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG) + " " + this.getArguments(), sender)) {
return true;
}
String importFromPlugin = args[0].toLowerCase();
Map<String, Importer> importPlugins = ImportUtils.getImporters();
if (importFromPlugin.equals("list")) {
list(importPlugins, sender);
return true;
}
if (!Check.isTrue(importPlugins.keySet().contains(importFromPlugin), Locale.get(Msg.MANAGE_FAIL_INCORRECT_PLUGIN) + importFromPlugin, sender)) {
return true;
}
if (!Check.isTrue(ImportUtils.isPluginEnabled(importFromPlugin), Locale.get(Msg.MANAGE_FAIL_PLUGIN_NOT_ENABLED) + importFromPlugin, sender)) {
return true;
}
String[] importArguments = FormattingUtils.removeFirstArgument(args);
final Importer importer = importPlugins.get(importFromPlugin);
runImportTask(sender, importer, importArguments);
// TODO Rewrite Importer
return true;
}
private void runImportTask(ISender sender, final Importer importer, String... importArguments) {
plugin.getRunnableFactory().createNew(new AbsRunnable("ImportTask") {
@Override
public void run() {
try {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_IMPORT).toString());
List<UUID> uuids = Fetch.getIOfflinePlayers().stream().map(IOfflinePlayer::getUniqueId).collect(Collectors.toList());
if (importer.importData(uuids, importArguments)) {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_SUCCESS).toString());
} else {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());
}
} finally {
this.cancel();
}
}
}).runTaskAsynchronously();
}
private void list(Map<String, Importer> importers, ISender sender) {
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).parse());
importers.forEach((string, importer) -> sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_LIST_BALL) + " " + string + ": " + importer.getInfo()));
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).parse());
}
}

View File

@ -1,54 +0,0 @@
package main.java.com.djrapitops.plan.data.handling.importing;
import com.djrapitops.pluginbridge.plan.importing.OnTimeImporter;
import main.java.com.djrapitops.plan.Log;
import java.util.HashMap;
import java.util.Map;
import static org.bukkit.Bukkit.getPluginManager;
/**
* This class is responsible for static utility methods used for importing.
*
* @author Rsl1122
* @since 3.2.0
*/
@Deprecated
public class ImportUtils {
/**
* Constructor used to hide the public constructor
*/
private ImportUtils() {
throw new IllegalStateException("Utility class");
}
/**
* Checks if a plugin is enabled.
*
* @param pluginName Name of the plugin
* @return true/false
*/
public static boolean isPluginEnabled(String pluginName) {
return "offline".equals(pluginName) || getPluginManager().isPluginEnabled(pluginName);
}
/**
* Used to get all importers for different plugins.
*
* @return Map of importers with pluginname in lowercase as key.
*/
public static Map<String, Importer> getImporters() {
Map<String, Importer> importers = new HashMap<>();
try {
importers.put("ontime", new OnTimeImporter());
importers.put("offline", new OfflinePlayerImporter());
} catch (Exception e) {
Log.toLog("ImportUtils.getImporters", e);
Log.error("Plan Plugin Bridge not included in the plugin jar.");
}
return importers;
}
}

View File

@ -1,153 +1,11 @@
package main.java.com.djrapitops.plan.data.handling.importing;
import com.djrapitops.plugin.utilities.player.Fetch;
import com.djrapitops.plugin.utilities.player.IOfflinePlayer;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DataCache;
import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo;
import main.java.com.djrapitops.plan.data.handling.info.InfoType;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import main.java.com.djrapitops.plan.utilities.NewPlayerCreator;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* Abstract class used for importing data from other plugins.
*
* @author Rsl1122
* @since 3.2.0
* @since 4.0.0
*/
@Deprecated
public abstract class Importer {
private String info;
/**
* Constructor.
*/
public Importer() {
info = "No info specified";
}
/**
* Method used for the import.
* <p>
* Creates UserData for players that have not been saved to the database.
*
* @param uuids UUIDs to be imported
* @param args arguments for the import
* @return success
*/
public boolean importData(Collection<UUID> uuids, String... args) {
Plan plan = Plan.getInstance();
plan.getAnalysisCache().disableAnalysisTemporarily();
String processName = "Import, " + getClass().getSimpleName();
try {
DataCache handler = plan.getHandler();
Database db = plan.getDB();
Benchmark.start(processName);
Set<UUID> saved;
saved = db.getSavedUUIDs();
List<UUID> unSaved = new ArrayList<>(uuids);
unSaved.removeAll(saved);
int amount = unSaved.size();
String createUserObjects = "Creating " + amount + " new UserData objects";
Log.debug(processName, createUserObjects);
Map<UUID, IOfflinePlayer> offlinePlayers = Fetch.getIOfflinePlayers().stream().collect(Collectors.toMap(IOfflinePlayer::getUuid, Function.identity()));
Benchmark.start(createUserObjects);
List<UserData> newUsers = new ArrayList<>();
List<IOfflinePlayer> offlineP = unSaved
.stream()
.map(offlinePlayers::get)
.collect(Collectors.toList());
AtomicInteger currentUser = new AtomicInteger(0);
AtomicInteger currentPercent = new AtomicInteger(0);
int fivePercent = amount / 20;
//Using Set because of better Collection#contains() performance
Set<Integer> milestones = IntStream.rangeClosed(1, 20)
.mapToObj(i -> i * fivePercent)
.collect(Collectors.toSet());
offlineP.parallelStream()
.map(NewPlayerCreator::createNewOfflinePlayer)
.forEach(newPlayer -> {
newUsers.add(newPlayer);
if (milestones.contains(currentUser.incrementAndGet())) {
Log.debug(processName, "Creating new UserData objects: " + currentPercent.addAndGet(5) + "%");
}
});
Benchmark.stop(processName, createUserObjects);
Log.debug(processName, "Save new UserData objects (" + amount + ")");
plan.getDB().saveMultipleUserData(newUsers);
for (UUID uuid : uuids) {
Plan.getInstance().addToProcessQueue(importData(uuid, args));
}
} catch (SQLException ex) {
Log.toLog(this.getClass().getName(), ex);
return false;
} finally {
plan.getAnalysisCache().enableAnalysis();
Log.logDebug(processName, Benchmark.stop(processName, processName));
}
return true;
}
/**
* Returns the info for import command.
*
* @return Information about the import options
* @since 3.5.0
*/
public final String getInfo() {
return info;
}
/**
* Set the info for import command.
*
* @param info Information about the import options
* @since 3.5.0
*/
public final void setInfo(String info) {
this.info = info;
}
/**
* Method used for getting the HandlingInfo object for the import data.
*
* @param uuid UUID of the player
* @param args Arguments for import
* @return HandlingInfo object that modifies the UserData so that the data
* is imported.
* @since 3.5.0
*/
public HandlingInfo importData(UUID uuid, String... args) {
return new HandlingInfo(uuid, InfoType.OTHER, 0) {
@Override
public void process(UserData uData) {
}
};
}
}
// TODO write new Importer
}

View File

@ -1,24 +1,15 @@
package main.java.com.djrapitops.plan.data.handling.importing;
import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo;
import java.util.UUID;
/**
* Imports all players who have not joined since Plan was installed.
*
* @author Rsl1122
* @since 3.5.0
*/
@Deprecated
public class OfflinePlayerImporter extends Importer {
public OfflinePlayerImporter() {
super.setInfo("Import all players who have not joined since Plan was installed.");
// TODO Rewrite
}
@Override
public HandlingInfo importData(UUID uuid, String... args) {
return null;
}
}

View File

@ -2,7 +2,6 @@ package main.java.com.djrapitops.plan.database;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.database.tables.*;
import java.sql.SQLException;
@ -111,32 +110,6 @@ public abstract class Database {
return false;
}
/**
* Used to give Database processors to call with UserData after they have
* been fetched from the database.
* <p>
* This method is a shortcut method for multiple parameters.
*
* @param uuid UUID of the player.
* @param processors Processors to call with the UserData after the fetch is
* complete.
* @throws SQLException If a database error occurs.
*/
public void giveUserDataToProcessors(UUID uuid, DBCallableProcessor... processors) throws SQLException {
giveUserDataToProcessors(uuid, Arrays.asList(processors));
}
/**
* Used to give Database processors to call with UserData after they have
* been fetched from the database.
*
* @param uuid UUID of the player.
* @param processors Processors to call with the UserData after the fetch is
* complete.
* @throws SQLException If a database error occurs.
*/
public abstract void giveUserDataToProcessors(UUID uuid, Collection<DBCallableProcessor> processors) throws SQLException;
/**
* Used to get all UserData for multiple UUIDs.
* <p>
@ -148,22 +121,6 @@ public abstract class Database {
*/
public abstract List<UserData> getUserDataForUUIDS(Collection<UUID> uuids) throws SQLException;
/**
* Used to save UserData object of a user.
*
* @param data UserData of the Player.
* @throws SQLException If a database error occurs.
*/
public abstract void saveUserData(UserData data) throws SQLException;
/**
* Used to save UserData object of multiple users.
*
* @param data Collection of UserData objects.
* @throws SQLException If a database error occurs.
*/
public abstract void saveMultipleUserData(Collection<UserData> data) throws SQLException;
/**
* Check if the user is saved in the database.
*

View File

@ -3,17 +3,20 @@ package main.java.com.djrapitops.plan.database.databases;
import com.djrapitops.plugin.task.AbsRunnable;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.KillData;
import main.java.com.djrapitops.plan.data.SessionData;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.database.tables.*;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import main.java.com.djrapitops.plan.utilities.FormatUtils;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import java.net.InetAddress;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Set;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;
/**
* Class containing main logic for different data related save & load functionality.
@ -96,7 +99,6 @@ public abstract class SQLDB extends Database {
if (!checkConnection()) {
return false;
}
convertBukkitDataToDB();
clean();
return true;
} catch (SQLException e) {
@ -179,40 +181,6 @@ public abstract class SQLDB extends Database {
}
}
/**
*
*/
public void convertBukkitDataToDB() {
plugin.getRunnableFactory().createNew(new AbsRunnable("BukkitDataConversionTask") {
@Override
public void run() {
try {
Benchmark.start("Convert BukkitData to DB data");
Log.debug("Database", "Bukkit Data Conversion");
Set<UUID> uuids = usersTable.getSavedUUIDs();
uuids.removeAll(usersTable.getContainsBukkitData(uuids));
if (uuids.isEmpty()) {
Log.debug("Database", "No conversion necessary.");
return;
}
Log.info("Beginning Bukkit Data -> DB Conversion for " + uuids.size() + " players");
int id = plugin.getBootAnalysisTaskID();
if (id != -1) {
Log.info("Analysis | Cancelled Boot Analysis Due to conversion.");
plugin.getServer().getScheduler().cancelTask(id);
}
saveMultipleUserData(getUserDataForUUIDS(uuids));
Log.info("Conversion complete, took: " + FormatUtils.formatTimeAmount(Benchmark.stop("Database", "Convert BukkitData to DB data")) + " ms");
} catch (SQLException ex) {
Log.toLog(this.getClass().getName(), ex);
} finally {
setAvailable();
this.cancel();
}
}
}).runTaskAsynchronously();
}
/**
* @return
*/
@ -369,6 +337,56 @@ public abstract class SQLDB extends Database {
return success;
}
@Override
public List<UserData> getUserDataForUUIDS(Collection<UUID> uuidsCol) throws SQLException {
if (uuidsCol == null || uuidsCol.isEmpty()) {
return new ArrayList<>();
}
setStatus("Get userdata (multiple) for: " + uuidsCol.size());
Benchmark.start("Get UserData for " + uuidsCol.size());
Map<UUID, Integer> userIds = usersTable.getAllUserIds();
Set<UUID> remove = uuidsCol.stream()
.filter(uuid -> !userIds.containsKey(uuid))
.collect(Collectors.toSet());
List<UUID> uuids = new ArrayList<>(uuidsCol);
Log.debug("Database", "Data not found for: " + remove.size());
uuids.removeAll(remove);
Benchmark.start("Create UserData objects for " + userIds.size());
List<UserData> data = usersTable.getUserData(uuids);
Benchmark.stop("Database", "Create UserData objects for " + userIds.size());
if (data.isEmpty()) {
return data;
}
Map<Integer, UUID> idUuidRel = userIds.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
List<Integer> ids = userIds.entrySet().stream().filter(e -> uuids.contains(e.getKey())).map(Map.Entry::getValue).collect(Collectors.toList());
Log.debug("Database", "Using IDs: " + ids.size());
Map<Integer, List<String>> nicknames = nicknamesTable.getNicknames(ids);
Map<Integer, Set<InetAddress>> ipList = ipsTable.getIPList(ids);
Map<Integer, List<KillData>> playerKills = killsTable.getPlayerKills(ids, idUuidRel);
Map<Integer, List<SessionData>> sessionData = sessionsTable.getSessionData(ids);
Map<Integer, Map<String, Long>> worldTimes = worldTimesTable.getWorldTimes(ids);
Log.debug("Database",
"Data found for:",
" UUIDs: " + uuids.size(),
" IDs: " + userIds.size(),
" UserData: " + data.size(),
" Nicknames: " + nicknames.size(),
" IPs: " + ipList.size(),
" Kills: " + playerKills.size(),
" Sessions: " + sessionData.size(),
" World Times: " + worldTimes.size()
);
for (UserData uData : data) {
// TODO add extra data
}
Benchmark.stop("Database", "Get UserData for " + uuidsCol.size());
setAvailable();
return data;
}
/**
* @return
*/

View File

@ -1,6 +1,7 @@
package main.java.com.djrapitops.plan.database.tables;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.database.databases.SQLDB;
import main.java.com.djrapitops.plan.database.sql.Sql;
import main.java.com.djrapitops.plan.database.sql.TableSqlParser;
@ -368,4 +369,9 @@ public class UsersTable extends Table {
close(statement);
}
}
public List<UserData> getUserData(List<UUID> uuids) {
// TODO Rewrite method for new UserData objects.
return null;
}
}