mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-30 21:17:49 +01:00
Transaction for removing unsatisfied Conditional data:
This is one of the most complex queries I have made. - Select all fulfilled conditions for all players (conditionName when true and not_conditionName when false) - Left join with player value & provider tables when uuids match, and when condition matches a condition in the query above. - Filter the join query for values where the condition did not match any provided condition in the join (Is null) - Delete all player values with IDs that are returned by the left join query after filtering In addition: - Added test for the transaction - Added extension data removal to RemoveEverythingTransaction - Added unregister method to ExtensionService
This commit is contained in:
parent
09ac2dce09
commit
47a6a9b2aa
@ -58,6 +58,16 @@ public interface ExtensionService {
|
|||||||
*/
|
*/
|
||||||
void register(DataExtension extension);
|
void register(DataExtension extension);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister your {@link DataExtension} implementation.
|
||||||
|
* <p>
|
||||||
|
* This method should be used if calling methods on the DataExtension suddenly becomes unavailable, due to
|
||||||
|
* plugin disable for example.
|
||||||
|
*
|
||||||
|
* @param extension Your DataExtension implementation that was registered before.
|
||||||
|
*/
|
||||||
|
void unregister(DataExtension extension);
|
||||||
|
|
||||||
class ExtensionServiceHolder {
|
class ExtensionServiceHolder {
|
||||||
static ExtensionService API;
|
static ExtensionService API;
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import com.djrapitops.plan.db.access.transactions.init.CreateIndexTransaction;
|
|||||||
import com.djrapitops.plan.db.access.transactions.init.CreateTablesTransaction;
|
import com.djrapitops.plan.db.access.transactions.init.CreateTablesTransaction;
|
||||||
import com.djrapitops.plan.db.access.transactions.init.OperationCriticalTransaction;
|
import com.djrapitops.plan.db.access.transactions.init.OperationCriticalTransaction;
|
||||||
import com.djrapitops.plan.db.patches.*;
|
import com.djrapitops.plan.db.patches.*;
|
||||||
|
import com.djrapitops.plan.system.DebugChannels;
|
||||||
import com.djrapitops.plan.system.locale.Locale;
|
import com.djrapitops.plan.system.locale.Locale;
|
||||||
import com.djrapitops.plan.system.settings.config.PlanConfig;
|
import com.djrapitops.plan.system.settings.config.PlanConfig;
|
||||||
import com.djrapitops.plan.system.settings.paths.TimeSettings;
|
import com.djrapitops.plan.system.settings.paths.TimeSettings;
|
||||||
@ -219,6 +220,7 @@ public abstract class SQLDB extends AbstractDatabase {
|
|||||||
|
|
||||||
return CompletableFuture.supplyAsync(() -> {
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
accessLock.checkAccess(transaction);
|
accessLock.checkAccess(transaction);
|
||||||
|
logger.getDebugLogger().logOn(DebugChannels.SQL, "Executing: " + transaction.getClass().getSimpleName());
|
||||||
transaction.executeTransaction(this);
|
transaction.executeTransaction(this);
|
||||||
return CompletableFuture.completedFuture(null);
|
return CompletableFuture.completedFuture(null);
|
||||||
}, getTransactionExecutor()).handle(errorHandler(origin));
|
}, getTransactionExecutor()).handle(errorHandler(origin));
|
||||||
|
@ -44,6 +44,11 @@ public class RemoveEverythingTransaction extends Transaction {
|
|||||||
clearTable(TPSTable.TABLE_NAME);
|
clearTable(TPSTable.TABLE_NAME);
|
||||||
clearTable(SecurityTable.TABLE_NAME);
|
clearTable(SecurityTable.TABLE_NAME);
|
||||||
clearTable(ServerTable.TABLE_NAME);
|
clearTable(ServerTable.TABLE_NAME);
|
||||||
|
clearTable(ExtensionPlayerValueTable.TABLE_NAME);
|
||||||
|
clearTable(ExtensionProviderTable.TABLE_NAME);
|
||||||
|
clearTable(ExtensionTabTable.TABLE_NAME);
|
||||||
|
clearTable(ExtensionPluginTable.TABLE_NAME);
|
||||||
|
clearTable(ExtensionIconTable.TABLE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearTable(String tableName) {
|
private void clearTable(String tableName) {
|
||||||
|
@ -27,6 +27,7 @@ import com.djrapitops.plan.db.access.transactions.commands.RemovePlayerTransacti
|
|||||||
import com.djrapitops.plan.db.sql.tables.PingTable;
|
import com.djrapitops.plan.db.sql.tables.PingTable;
|
||||||
import com.djrapitops.plan.db.sql.tables.SessionsTable;
|
import com.djrapitops.plan.db.sql.tables.SessionsTable;
|
||||||
import com.djrapitops.plan.db.sql.tables.TPSTable;
|
import com.djrapitops.plan.db.sql.tables.TPSTable;
|
||||||
|
import com.djrapitops.plan.extension.implementation.storage.transactions.results.RemoveUnsatisfiedConditionalResultsTransaction;
|
||||||
import com.djrapitops.plan.system.locale.Locale;
|
import com.djrapitops.plan.system.locale.Locale;
|
||||||
import com.djrapitops.plan.system.locale.lang.PluginLang;
|
import com.djrapitops.plan.system.locale.lang.PluginLang;
|
||||||
import com.djrapitops.plugin.api.TimeAmount;
|
import com.djrapitops.plugin.api.TimeAmount;
|
||||||
@ -73,6 +74,9 @@ public class CleanTransaction extends Transaction {
|
|||||||
execute(cleanTPSTable(allTimePeak.orElse(-1)));
|
execute(cleanTPSTable(allTimePeak.orElse(-1)));
|
||||||
execute(cleanPingTable());
|
execute(cleanPingTable());
|
||||||
|
|
||||||
|
// Clean DataExtension data
|
||||||
|
executeOther(new RemoveUnsatisfiedConditionalResultsTransaction());
|
||||||
|
|
||||||
int removed = cleanOldPlayers();
|
int removed = cleanOldPlayers();
|
||||||
if (removed > 0) {
|
if (removed > 0) {
|
||||||
logger.info(locale.getString(PluginLang.DB_NOTIFY_CLEAN, removed));
|
logger.info(locale.getString(PluginLang.DB_NOTIFY_CLEAN, removed));
|
||||||
|
@ -31,6 +31,7 @@ public class Sql {
|
|||||||
public static final String INNER_JOIN = " INNER JOIN ";
|
public static final String INNER_JOIN = " INNER JOIN ";
|
||||||
public static final String LEFT_JOIN = " LEFT JOIN ";
|
public static final String LEFT_JOIN = " LEFT JOIN ";
|
||||||
public static final String AND = " AND ";
|
public static final String AND = " AND ";
|
||||||
|
public static final String OR = " OR ";
|
||||||
|
|
||||||
private Sql() {
|
private Sql() {
|
||||||
throw new IllegalStateException("Variable Class");
|
throw new IllegalStateException("Variable Class");
|
||||||
|
@ -95,6 +95,16 @@ public class ExtensionServiceImplementation implements ExtensionService {
|
|||||||
logger.getDebugLogger().logOn(DebugChannels.DATA_EXTENSIONS, pluginName + " extension registered.");
|
logger.getDebugLogger().logOn(DebugChannels.DATA_EXTENSIONS, pluginName + " extension registered.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregister(DataExtension extension) {
|
||||||
|
DataProviderExtractor extractor = new DataProviderExtractor(extension);
|
||||||
|
String pluginName = extractor.getPluginName();
|
||||||
|
if (extensionGatherers.remove(pluginName) != null) {
|
||||||
|
logger.getDebugLogger().logOn(DebugChannels.DATA_EXTENSIONS, pluginName + " extension unregistered.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private boolean shouldNotAllowRegistration(String pluginName) {
|
private boolean shouldNotAllowRegistration(String pluginName) {
|
||||||
PluginsConfigSection pluginsConfig = config.getPluginsConfigSection();
|
PluginsConfigSection pluginsConfig = config.getPluginsConfigSection();
|
||||||
|
|
||||||
@ -118,7 +128,11 @@ public class ExtensionServiceImplementation implements ExtensionService {
|
|||||||
public void updatePlayerValues(UUID playerUUID, String playerName) {
|
public void updatePlayerValues(UUID playerUUID, String playerName) {
|
||||||
for (Map.Entry<String, ProviderValueGatherer> gatherer : extensionGatherers.entrySet()) {
|
for (Map.Entry<String, ProviderValueGatherer> gatherer : extensionGatherers.entrySet()) {
|
||||||
try {
|
try {
|
||||||
|
logger.getDebugLogger().logOn(DebugChannels.DATA_EXTENSIONS, "Gathering values for: " + playerName);
|
||||||
|
|
||||||
gatherer.getValue().updateValues(playerUUID, playerName);
|
gatherer.getValue().updateValues(playerUUID, playerName);
|
||||||
|
|
||||||
|
logger.getDebugLogger().logOn(DebugChannels.DATA_EXTENSIONS, "Gathering completed: " + playerName);
|
||||||
} catch (Exception | NoClassDefFoundError | NoSuchMethodError | NoSuchFieldError e) {
|
} catch (Exception | NoClassDefFoundError | NoSuchMethodError | NoSuchFieldError e) {
|
||||||
logger.warn(gatherer.getKey() + " ran into (but failed safely) " + e.getClass().getSimpleName() +
|
logger.warn(gatherer.getKey() + " ran into (but failed safely) " + e.getClass().getSimpleName() +
|
||||||
" when updating value for '" + playerName +
|
" when updating value for '" + playerName +
|
||||||
|
@ -75,7 +75,6 @@ public class ProviderValueGatherer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
database.executeTransaction(new RemoveInvalidResultsTransaction(pluginName, serverUUID, extractor.getInvalidatedMethods()));
|
database.executeTransaction(new RemoveInvalidResultsTransaction(pluginName, serverUUID, extractor.getInvalidatedMethods()));
|
||||||
// TODO remove data in db that are updated with a 'false' condition
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateValues(UUID playerUUID, String playerName) {
|
public void updateValues(UUID playerUUID, String playerName) {
|
||||||
|
@ -135,4 +135,11 @@ public class ExtensionTabData implements Comparable<ExtensionTabData> {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ExtensionTabData{" +
|
||||||
|
"available=" + order +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Player Analytics (Plan).
|
||||||
|
*
|
||||||
|
* Plan is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License v3 as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Plan is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.djrapitops.plan.extension.implementation.storage.transactions.results;
|
||||||
|
|
||||||
|
import com.djrapitops.plan.db.DBType;
|
||||||
|
import com.djrapitops.plan.db.access.ExecStatement;
|
||||||
|
import com.djrapitops.plan.db.access.Executable;
|
||||||
|
import com.djrapitops.plan.db.access.transactions.Transaction;
|
||||||
|
import com.djrapitops.plan.db.sql.tables.ExtensionPlayerValueTable;
|
||||||
|
import com.djrapitops.plan.db.sql.tables.ExtensionProviderTable;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import static com.djrapitops.plan.db.sql.parsing.Sql.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction to remove older results that violate an updated condition value.
|
||||||
|
* <p>
|
||||||
|
* How it works:
|
||||||
|
* - Select all fulfilled conditions for all players (conditionName when true and not_conditionName when false)
|
||||||
|
* - Left join with player value & provider tables when uuids match, and when condition matches a condition in the query above.
|
||||||
|
* - Filter the join query for values where the condition did not match any provided condition in the join (Is null)
|
||||||
|
* - Delete all player values with IDs that are returned by the left join query after filtering
|
||||||
|
*
|
||||||
|
* @author Rsl1122
|
||||||
|
*/
|
||||||
|
public class RemoveUnsatisfiedConditionalResultsTransaction extends Transaction {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void performOperations() {
|
||||||
|
execute(deleteUnsatisfied());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Executable deleteUnsatisfied() {
|
||||||
|
String reversedCondition = dbType == DBType.SQLITE ? "'not_' || " + ExtensionProviderTable.PROVIDED_CONDITION : "CONCAT('not_'," + ExtensionProviderTable.PROVIDED_CONDITION + ')';
|
||||||
|
|
||||||
|
String providerTable = ExtensionProviderTable.TABLE_NAME;
|
||||||
|
String playerValueTable = ExtensionPlayerValueTable.TABLE_NAME;
|
||||||
|
|
||||||
|
String selectSatisfiedPositiveConditions = SELECT +
|
||||||
|
ExtensionProviderTable.PROVIDED_CONDITION + ',' +
|
||||||
|
ExtensionPlayerValueTable.USER_UUID +
|
||||||
|
FROM + playerValueTable +
|
||||||
|
INNER_JOIN + providerTable + " on " + providerTable + '.' + ExtensionProviderTable.ID + "=" + ExtensionPlayerValueTable.PROVIDER_ID +
|
||||||
|
WHERE + ExtensionPlayerValueTable.BOOLEAN_VALUE + "=?" +
|
||||||
|
AND + ExtensionProviderTable.PROVIDED_CONDITION + " IS NOT NULL";
|
||||||
|
String selectSatisfiedNegativeConditions = SELECT +
|
||||||
|
reversedCondition + " as " + ExtensionProviderTable.PROVIDED_CONDITION + ',' +
|
||||||
|
ExtensionPlayerValueTable.USER_UUID +
|
||||||
|
FROM + playerValueTable +
|
||||||
|
INNER_JOIN + providerTable + " on " + providerTable + '.' + ExtensionProviderTable.ID + "=" + ExtensionPlayerValueTable.PROVIDER_ID +
|
||||||
|
WHERE + ExtensionPlayerValueTable.BOOLEAN_VALUE + "=?" +
|
||||||
|
AND + ExtensionProviderTable.PROVIDED_CONDITION + " IS NOT NULL";
|
||||||
|
|
||||||
|
String selectSatisfiedConditions = '(' + selectSatisfiedPositiveConditions + " UNION " + selectSatisfiedNegativeConditions + ") q1";
|
||||||
|
|
||||||
|
String selectUnsatisfiedValueIDs = SELECT + playerValueTable + '.' + ExtensionPlayerValueTable.ID +
|
||||||
|
FROM + playerValueTable +
|
||||||
|
INNER_JOIN + providerTable + " on " + providerTable + '.' + ExtensionProviderTable.ID + "=" + ExtensionPlayerValueTable.PROVIDER_ID +
|
||||||
|
LEFT_JOIN + selectSatisfiedConditions + // Left join to preserver values that don't have their condition fulfilled
|
||||||
|
" on (" +
|
||||||
|
playerValueTable + '.' + ExtensionPlayerValueTable.USER_UUID +
|
||||||
|
"=q1." + ExtensionPlayerValueTable.USER_UUID +
|
||||||
|
AND + ExtensionProviderTable.CONDITION +
|
||||||
|
"=q1." + ExtensionProviderTable.PROVIDED_CONDITION +
|
||||||
|
')' +
|
||||||
|
WHERE + "q1." + ExtensionProviderTable.PROVIDED_CONDITION + " IS NULL" + // Conditions that were not in the satisfied condition query
|
||||||
|
AND + ExtensionProviderTable.CONDITION + " IS NOT NULL"; // Ignore values that don't need condition
|
||||||
|
|
||||||
|
String sql = "DELETE FROM " + playerValueTable +
|
||||||
|
WHERE + ExtensionPlayerValueTable.ID + " IN (" + selectUnsatisfiedValueIDs + ')';
|
||||||
|
|
||||||
|
return new ExecStatement(sql) {
|
||||||
|
@Override
|
||||||
|
public void prepare(PreparedStatement statement) throws SQLException {
|
||||||
|
statement.setBoolean(1, true); // Select provided conditions with 'true' value
|
||||||
|
statement.setBoolean(2, false); // Select negated conditions with 'false' value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -52,6 +52,7 @@ import com.djrapitops.plan.extension.implementation.results.player.ExtensionPlay
|
|||||||
import com.djrapitops.plan.extension.implementation.results.player.ExtensionStringData;
|
import com.djrapitops.plan.extension.implementation.results.player.ExtensionStringData;
|
||||||
import com.djrapitops.plan.extension.implementation.results.player.ExtensionTabData;
|
import com.djrapitops.plan.extension.implementation.results.player.ExtensionTabData;
|
||||||
import com.djrapitops.plan.extension.implementation.storage.queries.ExtensionPlayerDataQuery;
|
import com.djrapitops.plan.extension.implementation.storage.queries.ExtensionPlayerDataQuery;
|
||||||
|
import com.djrapitops.plan.extension.implementation.storage.transactions.results.RemoveUnsatisfiedConditionalResultsTransaction;
|
||||||
import com.djrapitops.plan.system.PlanSystem;
|
import com.djrapitops.plan.system.PlanSystem;
|
||||||
import com.djrapitops.plan.system.database.DBSystem;
|
import com.djrapitops.plan.system.database.DBSystem;
|
||||||
import com.djrapitops.plan.system.info.server.Server;
|
import com.djrapitops.plan.system.info.server.Server;
|
||||||
@ -79,6 +80,7 @@ import java.lang.management.ManagementFactory;
|
|||||||
import java.lang.management.OperatingSystemMXBean;
|
import java.lang.management.OperatingSystemMXBean;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -153,6 +155,9 @@ public abstract class CommonDBTest {
|
|||||||
|
|
||||||
db.executeTransaction(new StoreServerInformationTransaction(new Server(-1, serverUUID, "ServerName", "", 20)));
|
db.executeTransaction(new StoreServerInformationTransaction(new Server(-1, serverUUID, "ServerName", "", 20)));
|
||||||
assertEquals(serverUUID, db.getServerUUIDSupplier().get());
|
assertEquals(serverUUID, db.getServerUUIDSupplier().get());
|
||||||
|
|
||||||
|
system.getExtensionService().unregister(new TestExtension());
|
||||||
|
system.getExtensionService().unregister(new ConditionalExtension());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void execute(Executable executable) {
|
private void execute(Executable executable) {
|
||||||
@ -1051,6 +1056,58 @@ public abstract class CommonDBTest {
|
|||||||
OptionalAssert.equals("Something", tabData.getString("stringVal").map(ExtensionStringData::getFormattedValue));
|
OptionalAssert.equals("Something", tabData.getString("stringVal").map(ExtensionStringData::getFormattedValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void unsatisfiedConditionalResultsAreCleaned() throws ExecutionException, InterruptedException {
|
||||||
|
ExtensionServiceImplementation extensionService = (ExtensionServiceImplementation) system.getExtensionService();
|
||||||
|
|
||||||
|
extensionService.register(new ConditionalExtension());
|
||||||
|
|
||||||
|
ConditionalExtension.condition = true;
|
||||||
|
extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME);
|
||||||
|
|
||||||
|
// Check that the wanted data exists
|
||||||
|
checkThatDataExists(ConditionalExtension.condition);
|
||||||
|
|
||||||
|
// Reverse condition
|
||||||
|
ConditionalExtension.condition = false;
|
||||||
|
extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME);
|
||||||
|
|
||||||
|
db.executeTransaction(new RemoveUnsatisfiedConditionalResultsTransaction());
|
||||||
|
|
||||||
|
// Check that the wanted data exists
|
||||||
|
checkThatDataExists(ConditionalExtension.condition);
|
||||||
|
|
||||||
|
// Reverse condition
|
||||||
|
ConditionalExtension.condition = false;
|
||||||
|
extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME);
|
||||||
|
|
||||||
|
db.executeTransaction(new RemoveUnsatisfiedConditionalResultsTransaction());
|
||||||
|
|
||||||
|
// Check that the wanted data exists
|
||||||
|
checkThatDataExists(ConditionalExtension.condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkThatDataExists(boolean condition) {
|
||||||
|
if (condition) { // Condition is true, conditional values exist
|
||||||
|
List<ExtensionPlayerData> ofServer = db.query(new ExtensionPlayerDataQuery(playerUUID)).get(serverUUID);
|
||||||
|
assertTrue("There was no data left", ofServer != null && !ofServer.isEmpty() && !ofServer.get(0).getTabs().isEmpty());
|
||||||
|
|
||||||
|
ExtensionTabData tabData = ofServer.get(0).getTabs().get(0);
|
||||||
|
OptionalAssert.equals("Yes", tabData.getBoolean("isCondition").map(ExtensionBooleanData::getFormattedValue));
|
||||||
|
OptionalAssert.equals("Conditional", tabData.getString("conditionalValue").map(ExtensionStringData::getFormattedValue));
|
||||||
|
OptionalAssert.equals("unconditional", tabData.getString("unconditional").map(ExtensionStringData::getFormattedValue)); // Was not removed
|
||||||
|
assertFalse("Value was not removed: reversedConditionalValue", tabData.getString("reversedConditionalValue").isPresent());
|
||||||
|
} else { // Condition is false, reversed conditional values exist
|
||||||
|
List<ExtensionPlayerData> ofServer = db.query(new ExtensionPlayerDataQuery(playerUUID)).get(serverUUID);
|
||||||
|
assertTrue("There was no data left", ofServer != null && !ofServer.isEmpty() && !ofServer.get(0).getTabs().isEmpty());
|
||||||
|
ExtensionTabData tabData = ofServer.get(0).getTabs().get(0);
|
||||||
|
OptionalAssert.equals("No", tabData.getBoolean("isCondition").map(ExtensionBooleanData::getFormattedValue));
|
||||||
|
OptionalAssert.equals("Reversed", tabData.getString("reversedConditionalValue").map(ExtensionStringData::getFormattedValue));
|
||||||
|
OptionalAssert.equals("unconditional", tabData.getString("unconditional").map(ExtensionStringData::getFormattedValue)); // Was not removed
|
||||||
|
assertFalse("Value was not removed: conditionalValue", tabData.getString("conditionalValue").isPresent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@PluginInfo(name = "TestExtension")
|
@PluginInfo(name = "TestExtension")
|
||||||
public class TestExtension implements DataExtension {
|
public class TestExtension implements DataExtension {
|
||||||
@NumberProvider(text = "a number")
|
@NumberProvider(text = "a number")
|
||||||
@ -1078,4 +1135,32 @@ public abstract class CommonDBTest {
|
|||||||
return "Something";
|
return "Something";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PluginInfo(name = "Conditional TestExtension")
|
||||||
|
public static class ConditionalExtension implements DataExtension {
|
||||||
|
|
||||||
|
static boolean condition = true;
|
||||||
|
|
||||||
|
@BooleanProvider(text = "a boolean", conditionName = "condition")
|
||||||
|
public boolean isCondition(UUID playerUUID) {
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@StringProvider(text = "Conditional Value")
|
||||||
|
@Conditional("condition")
|
||||||
|
public String conditionalValue(UUID playerUUID) {
|
||||||
|
return "Conditional";
|
||||||
|
}
|
||||||
|
|
||||||
|
@StringProvider(text = "Reversed Conditional Value")
|
||||||
|
@Conditional(value = "condition", negated = true)
|
||||||
|
public String reversedConditionalValue(UUID playerUUID) {
|
||||||
|
return "Reversed";
|
||||||
|
}
|
||||||
|
|
||||||
|
@StringProvider(text = "Unconditional")
|
||||||
|
public String unconditional(UUID playerUUID) {
|
||||||
|
return "unconditional";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user