mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-01-13 11:41:34 +01:00
parent
ded89b9d8c
commit
1dcae30d67
@ -36,9 +36,16 @@ enum Capability {
|
||||
/**
|
||||
* ExtensionService, DataExtension API base package, PluginInfo, Conditional, Tab, TabInfo, TabOrder and BooleanProvider, DoubleProvider, PercentageProvider, NumberProvider, StringProvider annotations.
|
||||
*/
|
||||
DATA_EXTENSION_VALUES;
|
||||
DATA_EXTENSION_VALUES,
|
||||
/**
|
||||
* DataExtension API table package, TableProvider, Table and Table.Factory
|
||||
*/
|
||||
DATA_EXTENSION_TABLES;
|
||||
|
||||
static Optional<Capability> getByName(String name) {
|
||||
if (name == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
try {
|
||||
return Optional.of(valueOf(name));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -32,14 +32,14 @@ public enum ElementOrder {
|
||||
* Represents text - value pair box.
|
||||
*/
|
||||
VALUES,
|
||||
/**
|
||||
* Represents tables.
|
||||
*/
|
||||
TABLE,
|
||||
/**
|
||||
* Represents graphs.
|
||||
*/
|
||||
GRAPH;
|
||||
GRAPH,
|
||||
/**
|
||||
* Represents tables.
|
||||
*/
|
||||
TABLE;
|
||||
|
||||
public static String serialize(ElementOrder[] order) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
@ -43,6 +43,9 @@ public enum FormatType {
|
||||
NONE;
|
||||
|
||||
public static Optional<FormatType> getByName(String name) {
|
||||
if (name == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
try {
|
||||
return Optional.of(valueOf(name));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.annotation;
|
||||
|
||||
import com.djrapitops.plan.extension.icon.Color;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Method annotation to provide a Table.
|
||||
* <p>
|
||||
* Usage: {@code @TableProvider Table method(UUID playerUUID)}
|
||||
* <p>
|
||||
* Tables about players can have up to 4 columns.
|
||||
* Tables about server can have up to 5 columns.
|
||||
* <p>
|
||||
* It is recommended to place each table on their own tab with a {@link Tab} annotation on the same method.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface TableProvider {
|
||||
|
||||
/**
|
||||
* Determine the color of the table header.
|
||||
*
|
||||
* @return Preferred color. If none are specified defaults are used.
|
||||
*/
|
||||
Color tableColor() default Color.NONE;
|
||||
|
||||
}
|
@ -19,6 +19,7 @@ package com.djrapitops.plan.extension.extractor;
|
||||
import com.djrapitops.plan.extension.DataExtension;
|
||||
import com.djrapitops.plan.extension.Group;
|
||||
import com.djrapitops.plan.extension.annotation.*;
|
||||
import com.djrapitops.plan.extension.table.Table;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
@ -103,6 +104,8 @@ public final class ExtensionExtractor {
|
||||
|
||||
MethodAnnotations.get(method, Conditional.class).ifPresent(annotation -> methodAnnotations.put(method, Conditional.class, annotation));
|
||||
MethodAnnotations.get(method, Tab.class).ifPresent(annotation -> methodAnnotations.put(method, Tab.class, annotation));
|
||||
|
||||
MethodAnnotations.get(method, TableProvider.class).ifPresent(annotation -> methodAnnotations.put(method, TableProvider.class, annotation));
|
||||
}
|
||||
|
||||
if (methodAnnotations.isEmpty()) {
|
||||
@ -166,6 +169,7 @@ public final class ExtensionExtractor {
|
||||
validateDoubleProviderAnnotations();
|
||||
validatePercentageProviderAnnotations();
|
||||
validateStringProviderAnnotations();
|
||||
validateTableProviderAnnotations();
|
||||
}
|
||||
|
||||
private void validateBooleanProviderAnnotations() {
|
||||
@ -238,6 +242,13 @@ public final class ExtensionExtractor {
|
||||
}
|
||||
}
|
||||
|
||||
private void validateTableProviderAnnotations() {
|
||||
for (Method method : methodAnnotations.getMethodAnnotations(TableProvider.class).keySet()) {
|
||||
validateReturnType(method, Table.class);
|
||||
validateMethodArguments(method, false, UUID.class, String.class, Group.class);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateConditionals() {
|
||||
Collection<Conditional> conditionals = methodAnnotations.getAnnotations(Conditional.class);
|
||||
Collection<BooleanProvider> conditionProviders = methodAnnotations.getAnnotations(BooleanProvider.class);
|
||||
|
@ -48,6 +48,9 @@ public enum Color {
|
||||
NONE;
|
||||
|
||||
public static Optional<Color> getByName(String name) {
|
||||
if (name == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
try {
|
||||
return Optional.of(valueOf(name));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -29,6 +29,9 @@ public enum Family {
|
||||
BRAND;
|
||||
|
||||
public static Optional<Family> getByName(String name) {
|
||||
if (name == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
try {
|
||||
return Optional.of(valueOf(name));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* 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.table;
|
||||
|
||||
import com.djrapitops.plan.extension.ElementOrder;
|
||||
import com.djrapitops.plan.extension.icon.Color;
|
||||
import com.djrapitops.plan.extension.icon.Icon;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Object for giving Plan table data.
|
||||
* <p>
|
||||
* Usage: {@code Table.builder().columnOne("columnName", new Icon(...)).addRow("Your", "Row", "Data").build()}
|
||||
* <p>
|
||||
* Tables about players can have up to 4 columns.
|
||||
* Tables about server can have up to 5 columns.
|
||||
* <p>
|
||||
* Icon colors are ignored.
|
||||
* <p>
|
||||
* If a row has more values than the column limit, they are ignored.
|
||||
* If a row has less values than table columns, a '-' is displayed to distinguish a missing value.
|
||||
* <p>
|
||||
* If a table has no columns or rows, it is ignored.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @see com.djrapitops.plan.extension.annotation.TableProvider for associated annotation.
|
||||
*/
|
||||
public final class Table {
|
||||
|
||||
private final String[] columns;
|
||||
private final Icon[] icons;
|
||||
|
||||
private final List<Object[]> rows;
|
||||
|
||||
private Table() {
|
||||
/* Tables are constructed with the factory. */
|
||||
|
||||
columns = new String[5];
|
||||
icons = new Icon[5];
|
||||
rows = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Table Factory.
|
||||
*
|
||||
* @return a new Table Factory.
|
||||
*/
|
||||
public static Table.Factory builder() {
|
||||
return new Table.Factory();
|
||||
}
|
||||
|
||||
public String[] getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public int getMaxColumnSize() {
|
||||
int columnCount = 0;
|
||||
for (String column : columns) {
|
||||
if (column == null) {
|
||||
break; // Prevent having one null column between two columns
|
||||
}
|
||||
columnCount++;
|
||||
}
|
||||
return columnCount;
|
||||
}
|
||||
|
||||
public Icon[] getIcons() {
|
||||
return icons;
|
||||
}
|
||||
|
||||
public List<Object[]> getRows() {
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory for creating new {@link Table} objects.
|
||||
*/
|
||||
public static final class Factory {
|
||||
|
||||
private final Table building;
|
||||
|
||||
// These variable are related to implementation, and is used when the table is being fetched from the database.
|
||||
Color color; // Table color is defined with TableProvider annotation.
|
||||
String tableName; // tableName is defined by method name annotated by TableProvider.
|
||||
String tabName; // Tab name is defined with Tab annotation
|
||||
int tabPriority; // Tab priority is defined with TabOrder annotation
|
||||
ElementOrder[] tabOrder; // Tab element order is defined with TabInfo annotation
|
||||
Icon tabIcon; // Tab icon is defined with TabInfo annotation
|
||||
|
||||
private Factory() {
|
||||
building = new Table();
|
||||
}
|
||||
|
||||
private Factory column(int indx, String columnName, Icon icon) {
|
||||
building.columns[indx] = columnName;
|
||||
building.icons[indx] = icon != null ? Icon.called(icon.getName()).of(icon.getFamily()).build() : Icon.called("question").build();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set first column name and icon.
|
||||
*
|
||||
* @param columnName Name of the column.
|
||||
* @param icon Icon of the column, color is ignored.
|
||||
* @return Factory.
|
||||
*/
|
||||
public Factory columnOne(String columnName, Icon icon) {
|
||||
return column(0, columnName, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set second column name and icon.
|
||||
*
|
||||
* @param columnName Name of the column.
|
||||
* @param icon Icon of the column, color is ignored.
|
||||
* @return Factory.
|
||||
*/
|
||||
public Factory columnTwo(String columnName, Icon icon) {
|
||||
return column(1, columnName, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set third column name and icon.
|
||||
*
|
||||
* @param columnName Name of the column.
|
||||
* @param icon Icon of the column, color is ignored.
|
||||
* @return Factory.
|
||||
*/
|
||||
public Factory columnThree(String columnName, Icon icon) {
|
||||
return column(2, columnName, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set fourth column name and icon.
|
||||
*
|
||||
* @param columnName Name of the column.
|
||||
* @param icon Icon of the column, color is ignored.
|
||||
* @return Factory.
|
||||
*/
|
||||
public Factory columnFour(String columnName, Icon icon) {
|
||||
return column(3, columnName, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set fifth column name and icon.
|
||||
*
|
||||
* @param columnName Name of the column.
|
||||
* @param icon Icon of the column, color is ignored.
|
||||
* @return Factory.
|
||||
*/
|
||||
public Factory columnFive(String columnName, Icon icon) {
|
||||
return column(4, columnName, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a row of values to the table.
|
||||
*
|
||||
* @param values One value per column you have defined, {@code Object#toString()} will be called on the objects.
|
||||
* @return Factory.
|
||||
* @throws IllegalArgumentException If given varargs for 'values' is null.
|
||||
*/
|
||||
public Factory addRow(Object... values) {
|
||||
if (values == null) {
|
||||
throw new IllegalArgumentException("'values' for Table#addRow can not be null!");
|
||||
}
|
||||
|
||||
if (values.length == 0 || areAllValuesNull(values)) {
|
||||
return this; // Ignore row when all values are null or no values are present.
|
||||
}
|
||||
|
||||
building.rows.add(Arrays.copyOf(values, 5));
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean areAllValuesNull(Object[] values) {
|
||||
boolean allNull = true;
|
||||
for (Object value : values) {
|
||||
if (value != null) {
|
||||
allNull = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return allNull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish building the table.
|
||||
*
|
||||
* @return Finished Table object.
|
||||
*/
|
||||
public Table build() {
|
||||
return building;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -166,6 +166,20 @@ class ExtensionExtractorTest {
|
||||
assertEquals("Extension.method has invalid return type. was: java.lang.Double, expected: java.lang.String", assertThrows(IllegalArgumentException.class, underTest::validateAnnotations).getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void tableProviderMustReturnTable() {
|
||||
@PluginInfo(name = "Extension")
|
||||
class Extension implements DataExtension {
|
||||
@TableProvider
|
||||
public Double method(UUID playerUUID) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
ExtensionExtractor underTest = new ExtensionExtractor(new Extension());
|
||||
assertEquals("Extension.method has invalid return type. was: java.lang.Double, expected: com.djrapitops.plan.extension.table.Table", assertThrows(IllegalArgumentException.class, underTest::validateAnnotations).getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void booleanProviderCanNotSupplyItsOwnConditional() {
|
||||
@PluginInfo(name = "Extension")
|
||||
|
@ -38,11 +38,10 @@ public class CapabilityServiceImplementation implements CapabilityService {
|
||||
}
|
||||
|
||||
private static CapabilityServiceImplementation get() {
|
||||
CapabilityService instance = CapabilityService.getInstance();
|
||||
if (instance == null) {
|
||||
if (CapabilityServiceHolder.service == null) {
|
||||
return new CapabilityServiceImplementation();
|
||||
}
|
||||
return (CapabilityServiceImplementation) instance;
|
||||
return (CapabilityServiceImplementation) CapabilityServiceHolder.service;
|
||||
}
|
||||
|
||||
public static void notifyAboutEnable(boolean isEnabled) {
|
||||
|
@ -47,6 +47,9 @@ public class RemoveEverythingTransaction extends Transaction {
|
||||
clearTable(ExtensionPlayerValueTable.TABLE_NAME);
|
||||
clearTable(ExtensionServerValueTable.TABLE_NAME);
|
||||
clearTable(ExtensionProviderTable.TABLE_NAME);
|
||||
clearTable(ExtensionPlayerTableValueTable.TABLE_NAME);
|
||||
clearTable(ExtensionServerTableValueTable.TABLE_NAME);
|
||||
clearTable(ExtensionTableProviderTable.TABLE_NAME);
|
||||
clearTable(ExtensionTabTable.TABLE_NAME);
|
||||
clearTable(ExtensionPluginTable.TABLE_NAME);
|
||||
clearTable(ExtensionIconTable.TABLE_NAME);
|
||||
|
@ -53,5 +53,8 @@ public class CreateTablesTransaction extends OperationCriticalTransaction {
|
||||
execute(ExtensionProviderTable.createTableSQL(dbType));
|
||||
execute(ExtensionPlayerValueTable.createTableSQL(dbType));
|
||||
execute(ExtensionServerValueTable.createTableSQL(dbType));
|
||||
execute(ExtensionTableProviderTable.createTableSQL(dbType));
|
||||
execute(ExtensionPlayerTableValueTable.createTableSQL(dbType));
|
||||
execute(ExtensionServerTableValueTable.createTableSQL(dbType));
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import static com.djrapitops.plan.db.sql.parsing.Sql.*;
|
||||
|
||||
@ -54,9 +55,15 @@ public class ExtensionIconTable {
|
||||
}
|
||||
|
||||
public static void set3IconValuesToStatement(PreparedStatement statement, int parameterIndex, Icon icon) throws SQLException {
|
||||
statement.setString(parameterIndex, StringUtils.truncate(icon.getName(), 50));
|
||||
statement.setString(parameterIndex + 1, icon.getFamily().name());
|
||||
statement.setString(parameterIndex + 2, icon.getColor().name());
|
||||
if (icon != null) {
|
||||
statement.setString(parameterIndex, StringUtils.truncate(icon.getName(), 50));
|
||||
statement.setString(parameterIndex + 1, icon.getFamily().name());
|
||||
statement.setString(parameterIndex + 2, icon.getColor().name());
|
||||
} else {
|
||||
statement.setNull(parameterIndex, Types.VARCHAR);
|
||||
statement.setNull(parameterIndex + 1, Types.VARCHAR);
|
||||
statement.setNull(parameterIndex + 2, Types.VARCHAR);
|
||||
}
|
||||
}
|
||||
|
||||
private ExtensionIconTable() {
|
||||
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.db.sql.tables;
|
||||
|
||||
import com.djrapitops.plan.db.DBType;
|
||||
import com.djrapitops.plan.db.sql.parsing.CreateTableParser;
|
||||
import com.djrapitops.plan.db.sql.parsing.Sql;
|
||||
|
||||
import static com.djrapitops.plan.db.sql.parsing.Sql.INT;
|
||||
|
||||
/**
|
||||
* Table information about 'plan_extension_user_table_values'.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ExtensionPlayerTableValueTable {
|
||||
|
||||
public static final String TABLE_NAME = "plan_extension_user_table_values";
|
||||
|
||||
public static final String ID = "id";
|
||||
public static final String TABLE_ID = "table_id";
|
||||
public static final String USER_UUID = "uuid";
|
||||
|
||||
// All values can be null
|
||||
public static final String VALUE_1 = "col_1_value";
|
||||
public static final String VALUE_2 = "col_2_value";
|
||||
public static final String VALUE_3 = "col_3_value";
|
||||
public static final String VALUE_4 = "col_4_value";
|
||||
|
||||
private ExtensionPlayerTableValueTable() {
|
||||
/* Static information class */
|
||||
}
|
||||
|
||||
public static String createTableSQL(DBType dbType) {
|
||||
return CreateTableParser.create(TABLE_NAME, dbType)
|
||||
.column(ID, INT).primaryKey()
|
||||
.column(USER_UUID, Sql.varchar(36)).notNull()
|
||||
.column(VALUE_1, Sql.varchar(50))
|
||||
.column(VALUE_2, Sql.varchar(50))
|
||||
.column(VALUE_3, Sql.varchar(50))
|
||||
.column(VALUE_4, Sql.varchar(50))
|
||||
.column(TABLE_ID, INT).notNull()
|
||||
.foreignKey(TABLE_ID, ExtensionTableProviderTable.TABLE_NAME, ExtensionPluginTable.ID)
|
||||
.build();
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@ public class ExtensionProviderTable {
|
||||
|
||||
public static final String ID = "id";
|
||||
public static final String PROVIDER_NAME = "name";
|
||||
public static final String TEXT = "text"; // Can be null
|
||||
public static final String TEXT = "text";
|
||||
public static final String DESCRIPTION = "description"; // Can be null
|
||||
public static final String PRIORITY = "priority";
|
||||
public static final String GROUPABLE = "groupable"; // default false
|
||||
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.db.sql.tables;
|
||||
|
||||
import com.djrapitops.plan.db.DBType;
|
||||
import com.djrapitops.plan.db.sql.parsing.CreateTableParser;
|
||||
import com.djrapitops.plan.db.sql.parsing.Sql;
|
||||
|
||||
import static com.djrapitops.plan.db.sql.parsing.Sql.INT;
|
||||
|
||||
/**
|
||||
* Table information about 'plan_extension_server_table_values'.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ExtensionServerTableValueTable {
|
||||
|
||||
public static final String TABLE_NAME = "plan_extension_server_table_values";
|
||||
|
||||
public static final String ID = "id";
|
||||
public static final String TABLE_ID = "table_id";
|
||||
public static final String SERVER_UUID = "uuid";
|
||||
|
||||
// All values can be null
|
||||
public static final String VALUE_1 = "col_1_value";
|
||||
public static final String VALUE_2 = "col_2_value";
|
||||
public static final String VALUE_3 = "col_3_value";
|
||||
public static final String VALUE_4 = "col_4_value";
|
||||
public static final String VALUE_5 = "col_5_value";
|
||||
|
||||
private ExtensionServerTableValueTable() {
|
||||
/* Static information class */
|
||||
}
|
||||
|
||||
public static String createTableSQL(DBType dbType) {
|
||||
return CreateTableParser.create(TABLE_NAME, dbType)
|
||||
.column(ID, INT).primaryKey()
|
||||
.column(SERVER_UUID, Sql.varchar(36)).notNull()
|
||||
.column(VALUE_1, Sql.varchar(50))
|
||||
.column(VALUE_2, Sql.varchar(50))
|
||||
.column(VALUE_3, Sql.varchar(50))
|
||||
.column(VALUE_4, Sql.varchar(50))
|
||||
.column(VALUE_5, Sql.varchar(50))
|
||||
.column(TABLE_ID, INT).notNull()
|
||||
.foreignKey(TABLE_ID, ExtensionTableProviderTable.TABLE_NAME, ExtensionPluginTable.ID)
|
||||
.build();
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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.db.sql.tables;
|
||||
|
||||
import com.djrapitops.plan.db.DBType;
|
||||
import com.djrapitops.plan.db.sql.parsing.CreateTableParser;
|
||||
import com.djrapitops.plan.db.sql.parsing.Sql;
|
||||
import com.djrapitops.plan.extension.icon.Color;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.djrapitops.plan.db.sql.parsing.Sql.*;
|
||||
|
||||
/**
|
||||
* Table information about 'plan_extension_tables'.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ExtensionTableProviderTable {
|
||||
|
||||
public static final String TABLE_NAME = "plan_extension_tables";
|
||||
|
||||
public static final String ID = "id";
|
||||
public static final String PROVIDER_NAME = "name";
|
||||
public static final String COLOR = "color";
|
||||
public static final String CONDITION = "condition_name"; // Can be null, related to @Conditional
|
||||
public static final String PLUGIN_ID = "plugin_id";
|
||||
public static final String TAB_ID = "tab_id"; // Can be null, related to @Tab
|
||||
|
||||
// All columns can be null
|
||||
public static final String COL_1 = "col_1_name";
|
||||
public static final String COL_2 = "col_2_name";
|
||||
public static final String COL_3 = "col_3_name";
|
||||
public static final String COL_4 = "col_4_name";
|
||||
public static final String COL_5 = "col_5_name";
|
||||
|
||||
// All icons can be null
|
||||
public static final String ICON_1_ID = "icon_1_id";
|
||||
public static final String ICON_2_ID = "icon_2_id";
|
||||
public static final String ICON_3_ID = "icon_3_id";
|
||||
public static final String ICON_4_ID = "icon_4_id";
|
||||
public static final String ICON_5_ID = "icon_5_id";
|
||||
|
||||
public static final String STATEMENT_SELECT_TABLE_ID = "(" + SELECT + ID + FROM + TABLE_NAME +
|
||||
WHERE + PROVIDER_NAME + "=?" +
|
||||
AND + PLUGIN_ID + "=" + ExtensionPluginTable.STATEMENT_SELECT_PLUGIN_ID + ")";
|
||||
|
||||
private ExtensionTableProviderTable() {
|
||||
/* Static information class */
|
||||
}
|
||||
|
||||
public static void set3PluginValuesToStatement(PreparedStatement statement, int parameterIndex, String providerName, String pluginName, UUID serverUUID) throws SQLException {
|
||||
statement.setString(parameterIndex, providerName);
|
||||
ExtensionPluginTable.set2PluginValuesToStatement(statement, parameterIndex + 1, pluginName, serverUUID);
|
||||
}
|
||||
|
||||
public static String createTableSQL(DBType dbType) {
|
||||
return CreateTableParser.create(TABLE_NAME, dbType)
|
||||
.column(ID, INT).primaryKey()
|
||||
.column(PROVIDER_NAME, Sql.varchar(50)).notNull()
|
||||
.column(COLOR, Sql.varchar(25)).notNull().defaultValue("'" + Color.NONE.name() + "'")
|
||||
.column(CONDITION, Sql.varchar(54)) // 50 + 4 for "not_"
|
||||
.column(COL_1, Sql.varchar(50))
|
||||
.column(COL_2, Sql.varchar(50))
|
||||
.column(COL_3, Sql.varchar(50))
|
||||
.column(COL_4, Sql.varchar(50))
|
||||
.column(COL_5, Sql.varchar(50))
|
||||
.column(PLUGIN_ID, INT).notNull()
|
||||
.column(ICON_1_ID, INT)
|
||||
.column(ICON_2_ID, INT)
|
||||
.column(ICON_3_ID, INT)
|
||||
.column(ICON_4_ID, INT)
|
||||
.column(ICON_5_ID, INT)
|
||||
.column(TAB_ID, INT)
|
||||
.foreignKey(PLUGIN_ID, ExtensionPluginTable.TABLE_NAME, ExtensionPluginTable.ID)
|
||||
.foreignKey(ICON_1_ID, ExtensionIconTable.TABLE_NAME, ExtensionIconTable.ID)
|
||||
.foreignKey(ICON_2_ID, ExtensionIconTable.TABLE_NAME, ExtensionIconTable.ID)
|
||||
.foreignKey(ICON_3_ID, ExtensionIconTable.TABLE_NAME, ExtensionIconTable.ID)
|
||||
.foreignKey(ICON_4_ID, ExtensionIconTable.TABLE_NAME, ExtensionIconTable.ID)
|
||||
.foreignKey(ICON_5_ID, ExtensionIconTable.TABLE_NAME, ExtensionIconTable.ID)
|
||||
.foreignKey(TAB_ID, ExtensionTabTable.TABLE_NAME, ExtensionTabTable.ID)
|
||||
.build();
|
||||
}
|
||||
}
|
@ -124,6 +124,7 @@ public class DataProviderExtractor {
|
||||
extractDataProviders(pluginInfo, tabs, conditions, PercentageProvider.class, PercentageDataProvider::placeToDataProviders);
|
||||
extractDataProviders(pluginInfo, tabs, conditions, NumberProvider.class, NumberDataProvider::placeToDataProviders);
|
||||
extractDataProviders(pluginInfo, tabs, conditions, StringProvider.class, StringDataProvider::placeToDataProviders);
|
||||
extractDataProviders(pluginInfo, tabs, conditions, TableProvider.class, TableDataProvider::placeToDataProviders);
|
||||
}
|
||||
|
||||
private <T extends Annotation> void extractDataProviders(PluginInfo pluginInfo, Map<Method, Tab> tabs, Map<Method, Conditional> conditions, Class<T> ofKind, DataProviderFactory<T> factory) {
|
||||
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.providers;
|
||||
|
||||
import com.djrapitops.plan.extension.annotation.Conditional;
|
||||
import com.djrapitops.plan.extension.annotation.TableProvider;
|
||||
import com.djrapitops.plan.extension.icon.Color;
|
||||
import com.djrapitops.plan.extension.implementation.ProviderInformation;
|
||||
import com.djrapitops.plan.extension.table.Table;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Represents a DataExtension API method annotated with {@link com.djrapitops.plan.extension.annotation.TableProvider} annotation.
|
||||
* <p>
|
||||
* Used to obtain data to place in the database.
|
||||
* <p>
|
||||
* Please note that not all {@link ProviderInformation} is present.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class TableDataProvider extends DataProvider<Table> {
|
||||
|
||||
private final Color tableColor;
|
||||
|
||||
private TableDataProvider(ProviderInformation providerInformation, MethodWrapper<Table> methodWrapper, Color tableColor) {
|
||||
super(providerInformation, methodWrapper);
|
||||
|
||||
this.tableColor = tableColor;
|
||||
}
|
||||
|
||||
public static void placeToDataProviders(
|
||||
DataProviders dataProviders, Method method, TableProvider annotation,
|
||||
Conditional condition, String tab, String pluginName
|
||||
) {
|
||||
MethodWrapper<Table> methodWrapper = new MethodWrapper<>(method, Table.class);
|
||||
|
||||
ProviderInformation providerInformation = new ProviderInformation(
|
||||
pluginName, method.getName(), null, null, null, 0, tab, condition
|
||||
);
|
||||
|
||||
dataProviders.put(new TableDataProvider(providerInformation, methodWrapper, annotation.tableColor()));
|
||||
}
|
||||
|
||||
public static Color getTableColor(DataProvider<Table> provider) {
|
||||
if (provider instanceof TableDataProvider) {
|
||||
return ((TableDataProvider) provider).getTableColor();
|
||||
}
|
||||
return Color.NONE;
|
||||
}
|
||||
|
||||
public Color getTableColor() {
|
||||
return tableColor;
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ import com.djrapitops.plan.extension.DataExtension;
|
||||
import com.djrapitops.plan.extension.icon.Icon;
|
||||
import com.djrapitops.plan.extension.implementation.DataProviderExtractor;
|
||||
import com.djrapitops.plan.extension.implementation.TabInformation;
|
||||
import com.djrapitops.plan.extension.implementation.providers.DataProviders;
|
||||
import com.djrapitops.plan.extension.implementation.storage.transactions.StoreIconTransaction;
|
||||
import com.djrapitops.plan.extension.implementation.storage.transactions.StorePluginTransaction;
|
||||
import com.djrapitops.plan.extension.implementation.storage.transactions.StoreTabInformationTransaction;
|
||||
@ -47,6 +48,7 @@ public class ProviderValueGatherer {
|
||||
private NumberProviderValueGatherer numberGatherer;
|
||||
private DoubleAndPercentageProviderValueGatherer doubleAndPercentageGatherer;
|
||||
private StringProviderValueGatherer stringGatherer;
|
||||
private TableProviderValueGatherer tableGatherer;
|
||||
|
||||
public ProviderValueGatherer(
|
||||
DataExtension extension,
|
||||
@ -60,25 +62,24 @@ public class ProviderValueGatherer {
|
||||
this.dbSystem = dbSystem;
|
||||
this.serverInfo = serverInfo;
|
||||
|
||||
String pluginName = extractor.getPluginName();
|
||||
UUID serverUUID = serverInfo.getServerUUID();
|
||||
Database database = dbSystem.getDatabase();
|
||||
DataProviders dataProviders = extractor.getDataProviders();
|
||||
booleanGatherer = new BooleanProviderValueGatherer(
|
||||
extractor.getPluginName(), extension,
|
||||
serverInfo.getServerUUID(), dbSystem.getDatabase(),
|
||||
extractor.getDataProviders(), logger
|
||||
pluginName, extension, serverUUID, database, dataProviders, logger
|
||||
);
|
||||
numberGatherer = new NumberProviderValueGatherer(
|
||||
extractor.getPluginName(), extension,
|
||||
serverInfo.getServerUUID(), dbSystem.getDatabase(),
|
||||
extractor.getDataProviders(), logger
|
||||
pluginName, extension, serverUUID, database, dataProviders, logger
|
||||
);
|
||||
doubleAndPercentageGatherer = new DoubleAndPercentageProviderValueGatherer(
|
||||
extractor.getPluginName(), extension,
|
||||
serverInfo.getServerUUID(), dbSystem.getDatabase(),
|
||||
extractor.getDataProviders(), logger
|
||||
pluginName, extension, serverUUID, database, dataProviders, logger
|
||||
);
|
||||
stringGatherer = new StringProviderValueGatherer(
|
||||
extractor.getPluginName(), extension,
|
||||
serverInfo.getServerUUID(), dbSystem.getDatabase(),
|
||||
extractor.getDataProviders(), logger
|
||||
pluginName, extension, serverUUID, database, dataProviders, logger
|
||||
);
|
||||
tableGatherer = new TableProviderValueGatherer(
|
||||
pluginName, extension, serverUUID, database, dataProviders, logger
|
||||
);
|
||||
}
|
||||
|
||||
@ -121,6 +122,7 @@ public class ProviderValueGatherer {
|
||||
numberGatherer.gatherNumberDataOfPlayer(playerUUID, playerName, conditions);
|
||||
doubleAndPercentageGatherer.gatherDoubleDataOfPlayer(playerUUID, playerName, conditions);
|
||||
stringGatherer.gatherStringDataOfPlayer(playerUUID, playerName, conditions);
|
||||
tableGatherer.gatherTableDataOfPlayer(playerUUID, playerName, conditions);
|
||||
}
|
||||
|
||||
public void updateValues() {
|
||||
@ -128,5 +130,6 @@ public class ProviderValueGatherer {
|
||||
numberGatherer.gatherNumberDataOfServer(conditions);
|
||||
doubleAndPercentageGatherer.gatherDoubleDataOfServer(conditions);
|
||||
stringGatherer.gatherStringDataOfServer(conditions);
|
||||
tableGatherer.gatherTableDataOfServer(conditions);
|
||||
}
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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.providers.gathering;
|
||||
|
||||
import com.djrapitops.plan.db.Database;
|
||||
import com.djrapitops.plan.db.access.transactions.Transaction;
|
||||
import com.djrapitops.plan.extension.DataExtension;
|
||||
import com.djrapitops.plan.extension.icon.Icon;
|
||||
import com.djrapitops.plan.extension.implementation.ProviderInformation;
|
||||
import com.djrapitops.plan.extension.implementation.providers.DataProvider;
|
||||
import com.djrapitops.plan.extension.implementation.providers.DataProviders;
|
||||
import com.djrapitops.plan.extension.implementation.providers.MethodWrapper;
|
||||
import com.djrapitops.plan.extension.implementation.providers.TableDataProvider;
|
||||
import com.djrapitops.plan.extension.implementation.storage.transactions.StoreIconTransaction;
|
||||
import com.djrapitops.plan.extension.implementation.storage.transactions.providers.StoreTableProviderTransaction;
|
||||
import com.djrapitops.plan.extension.implementation.storage.transactions.results.StorePlayerTableResultTransaction;
|
||||
import com.djrapitops.plan.extension.implementation.storage.transactions.results.StoreServerTableResultTransaction;
|
||||
import com.djrapitops.plan.extension.table.Table;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Gathers TableProvider method data.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
class TableProviderValueGatherer {
|
||||
|
||||
private final String pluginName;
|
||||
private final DataExtension extension;
|
||||
private final UUID serverUUID;
|
||||
|
||||
private final Database database;
|
||||
private final DataProviders dataProviders;
|
||||
private final PluginLogger logger;
|
||||
|
||||
TableProviderValueGatherer(
|
||||
String pluginName, DataExtension extension,
|
||||
UUID serverUUID, Database database,
|
||||
DataProviders dataProviders,
|
||||
PluginLogger logger
|
||||
) {
|
||||
this.pluginName = pluginName;
|
||||
this.extension = extension;
|
||||
this.serverUUID = serverUUID;
|
||||
this.database = database;
|
||||
this.dataProviders = dataProviders;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
void gatherTableDataOfPlayer(UUID playerUUID, String playerName, Conditions conditions) {
|
||||
// Method parameters abstracted away so that same method can be used for all parameter types
|
||||
// Same with Method result store transaction creation
|
||||
Function<MethodWrapper<Table>, Callable<Table>> methodCaller = method -> () -> method.callMethod(extension, playerUUID, playerName);
|
||||
BiFunction<MethodWrapper<Table>, Table, Transaction> storeTransactionCreator = (method, result) -> new StorePlayerTableResultTransaction(pluginName, serverUUID, method.getMethodName(), playerUUID, result);
|
||||
|
||||
for (DataProvider<Table> tableProvider : dataProviders.getPlayerMethodsByType(Table.class)) {
|
||||
gatherTableDataOfProvider(methodCaller, storeTransactionCreator, conditions, tableProvider);
|
||||
}
|
||||
}
|
||||
|
||||
void gatherTableDataOfServer(Conditions conditions) {
|
||||
// Method parameters abstracted away so that same method can be used for all parameter types
|
||||
// Same with Method result store transaction creation
|
||||
Function<MethodWrapper<Table>, Callable<Table>> methodCaller = method -> () -> method.callMethod(extension);
|
||||
BiFunction<MethodWrapper<Table>, Table, Transaction> storeTransactionCreator = (method, result) -> new StoreServerTableResultTransaction(pluginName, serverUUID, method.getMethodName(), result);
|
||||
|
||||
for (DataProvider<Table> tableProvider : dataProviders.getServerMethodsByType(Table.class)) {
|
||||
gatherTableDataOfProvider(methodCaller, storeTransactionCreator, conditions, tableProvider);
|
||||
}
|
||||
}
|
||||
|
||||
private void gatherTableDataOfProvider(
|
||||
Function<MethodWrapper<Table>, Callable<Table>> methodCaller,
|
||||
BiFunction<MethodWrapper<Table>, Table, Transaction> storeTransactionCreator,
|
||||
Conditions conditions,
|
||||
DataProvider<Table> tableProvider
|
||||
) {
|
||||
ProviderInformation providerInformation = tableProvider.getProviderInformation();
|
||||
Optional<String> condition = providerInformation.getCondition();
|
||||
if (condition.isPresent() && conditions.isNotFulfilled(condition.get())) {
|
||||
return;
|
||||
}
|
||||
|
||||
MethodWrapper<Table> method = tableProvider.getMethod();
|
||||
Table result = getMethodResult(
|
||||
methodCaller.apply(method),
|
||||
throwable -> pluginName + " has invalid implementation, method " + method.getMethodName() + " threw exception: " + throwable.toString()
|
||||
);
|
||||
if (result == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Icon icon : result.getIcons()) {
|
||||
if (icon != null) {
|
||||
database.executeTransaction(new StoreIconTransaction(icon));
|
||||
}
|
||||
}
|
||||
database.executeTransaction(new StoreTableProviderTransaction(serverUUID, providerInformation, TableDataProvider.getTableColor(tableProvider), result));
|
||||
database.executeTransaction(storeTransactionCreator.apply(method, result));
|
||||
}
|
||||
|
||||
private <T> T getMethodResult(Callable<T> callable, Function<Throwable, String> errorMsg) {
|
||||
try {
|
||||
return callable.call();
|
||||
} catch (Exception | NoSuchFieldError | NoSuchMethodError e) {
|
||||
logger.warn(errorMsg.apply(e));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -36,6 +36,8 @@ public class ExtensionTabData implements Comparable<ExtensionTabData> {
|
||||
private final Map<String, ExtensionNumberData> numberData;
|
||||
private final Map<String, ExtensionStringData> stringData;
|
||||
|
||||
private final List<ExtensionTableData> tableData;
|
||||
|
||||
private List<String> order;
|
||||
|
||||
// Table and Graph data will be added later.
|
||||
@ -48,6 +50,8 @@ public class ExtensionTabData implements Comparable<ExtensionTabData> {
|
||||
percentageData = new HashMap<>();
|
||||
numberData = new HashMap<>();
|
||||
stringData = new HashMap<>();
|
||||
|
||||
tableData = new ArrayList<>();
|
||||
}
|
||||
|
||||
public TabInformation getTabInformation() {
|
||||
@ -78,6 +82,10 @@ public class ExtensionTabData implements Comparable<ExtensionTabData> {
|
||||
return Optional.ofNullable(stringData.get(providerName));
|
||||
}
|
||||
|
||||
public List<ExtensionTableData> getTableData() {
|
||||
return tableData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ExtensionTabData other) {
|
||||
return Integer.compare(this.tabInformation.getTabPriority(), other.tabInformation.getTabPriority()); // Lower is first
|
||||
@ -103,6 +111,8 @@ public class ExtensionTabData implements Comparable<ExtensionTabData> {
|
||||
this.percentageData.putAll(other.percentageData);
|
||||
this.numberData.putAll(other.numberData);
|
||||
this.stringData.putAll(other.stringData);
|
||||
|
||||
this.tableData.addAll(other.tableData);
|
||||
}
|
||||
|
||||
public static class Factory {
|
||||
@ -138,6 +148,11 @@ public class ExtensionTabData implements Comparable<ExtensionTabData> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Factory putTableData(ExtensionTableData extensionTableData) {
|
||||
data.tableData.add(extensionTableData);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void createOrderingList() {
|
||||
List<ExtensionDescriptive> descriptives = new ArrayList<>();
|
||||
data.booleanData.values().stream().map(ExtensionData::getDescriptive).forEach(descriptives::add);
|
||||
@ -154,6 +169,7 @@ public class ExtensionTabData implements Comparable<ExtensionTabData> {
|
||||
|
||||
public ExtensionTabData build() {
|
||||
createOrderingList();
|
||||
Collections.sort(data.tableData);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.results;
|
||||
|
||||
import com.djrapitops.plan.data.element.TableContainer;
|
||||
import com.djrapitops.plan.extension.icon.Color;
|
||||
import com.djrapitops.plan.extension.icon.Icon;
|
||||
import com.djrapitops.plan.extension.table.Table;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Represents table data from a single TableProvider.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ExtensionTableData implements Comparable<ExtensionTableData> {
|
||||
|
||||
private final String providerName;
|
||||
private final Table table;
|
||||
private final Color tableColor;
|
||||
|
||||
public ExtensionTableData(String providerName, Table table, Color tableColor) {
|
||||
this.providerName = providerName;
|
||||
this.table = table;
|
||||
this.tableColor = tableColor;
|
||||
}
|
||||
|
||||
public TableContainer getHtmlTable() {
|
||||
String[] columns = table.getColumns();
|
||||
Icon[] icons = table.getIcons();
|
||||
List<Object[]> rows = table.getRows();
|
||||
|
||||
String[] header = buildHeader(columns, icons);
|
||||
|
||||
TableContainer htmlTable = new TableContainer(header);
|
||||
if (rows.size() > 50) {
|
||||
htmlTable.useJqueryDataTables(); // Use a jQuery data table since there are a lot of rows.
|
||||
} else {
|
||||
String colorName = com.djrapitops.plan.utilities.html.icon.Color.getByName(tableColor.name()).orElse(com.djrapitops.plan.utilities.html.icon.Color.NONE).getHtmlClass()
|
||||
.replace("col-", ""); // TODO after PluginData deprecation, change this thing
|
||||
htmlTable.setColor(colorName);
|
||||
}
|
||||
|
||||
for (Object[] row : rows) {
|
||||
htmlTable.addRow(Arrays.stream(row).map(value -> value != null ? value.toString() : null).toArray(Serializable[]::new));
|
||||
}
|
||||
|
||||
return htmlTable;
|
||||
}
|
||||
|
||||
private String[] buildHeader(String[] columns, Icon[] icons) {
|
||||
ArrayList<String> header = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
String column = columns[i];
|
||||
if (column == null) {
|
||||
break;
|
||||
}
|
||||
header.add(com.djrapitops.plan.utilities.html.icon.Icon.fromExtensionIcon(icons[i]).toHtml() + ' ' + column);
|
||||
}
|
||||
|
||||
return header.toArray(new String[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof ExtensionTableData)) return false;
|
||||
ExtensionTableData that = (ExtensionTableData) o;
|
||||
return providerName.equals(that.providerName) &&
|
||||
tableColor == that.tableColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(providerName, tableColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ExtensionTableData other) {
|
||||
return String.CASE_INSENSITIVE_ORDER.compare(providerName, other.providerName);
|
||||
}
|
||||
|
||||
public boolean isWideTable() {
|
||||
return table.getMaxColumnSize() > 3;
|
||||
}
|
||||
}
|
@ -19,10 +19,7 @@ package com.djrapitops.plan.extension.implementation.results.player;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionInformation;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionTabData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Represents data of a single extension about a player.
|
||||
@ -104,6 +101,31 @@ public class ExtensionPlayerData implements Comparable<ExtensionPlayerData> {
|
||||
Collections.sort(data.tabs);
|
||||
return data;
|
||||
}
|
||||
|
||||
public Factory combine(Factory with) {
|
||||
if (with != null) {
|
||||
for (ExtensionTabData tab : with.build().getTabs()) {
|
||||
Optional<ExtensionTabData> found = getTab(tab.getTabInformation().getTabName());
|
||||
if (found.isPresent()) {
|
||||
found.get().combine(tab);
|
||||
} else {
|
||||
addTab(tab);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Optional<ExtensionTabData> getTab(String tabName) {
|
||||
for (ExtensionTabData tab : data.tabs) {
|
||||
if (tabName.equals(tab.getTabInformation().getTabName())) {
|
||||
return Optional.of(tab);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -68,9 +68,29 @@ public class ExtensionPlayerDataQuery implements Query<Map<UUID, List<ExtensionP
|
||||
Map<UUID, List<ExtensionInformation>> extensionsByServerUUID = db.query(ExtensionInformationQueries.allExtensions());
|
||||
Map<Integer, ExtensionPlayerData.Factory> extensionDataByPluginID = db.query(fetchIncompletePlayerDataByPluginID());
|
||||
|
||||
Map<Integer, ExtensionPlayerData.Factory> tableDataByPluginID = db.query(new ExtensionPlayerTablesQuery(playerUUID));
|
||||
combine(extensionDataByPluginID, tableDataByPluginID);
|
||||
|
||||
return flatMapByServerUUID(extensionsByServerUUID, extensionDataByPluginID);
|
||||
}
|
||||
|
||||
private void combine(
|
||||
Map<Integer, ExtensionPlayerData.Factory> extensionDataByPluginID,
|
||||
Map<Integer, ExtensionPlayerData.Factory> aggregates
|
||||
) {
|
||||
for (Map.Entry<Integer, ExtensionPlayerData.Factory> entry : aggregates.entrySet()) {
|
||||
Integer pluginID = entry.getKey();
|
||||
ExtensionPlayerData.Factory data = entry.getValue();
|
||||
|
||||
ExtensionPlayerData.Factory found = extensionDataByPluginID.get(pluginID);
|
||||
if (found == null) {
|
||||
extensionDataByPluginID.put(pluginID, data);
|
||||
} else {
|
||||
found.combine(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Map<UUID, List<ExtensionPlayerData>> flatMapByServerUUID(Map<UUID, List<ExtensionInformation>> extensionsByServerUUID, Map<Integer, ExtensionPlayerData.Factory> extensionDataByPluginID) {
|
||||
Map<UUID, List<ExtensionPlayerData>> extensionDataByServerUUID = new HashMap<>();
|
||||
|
||||
|
@ -0,0 +1,287 @@
|
||||
/*
|
||||
* 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.queries;
|
||||
|
||||
import com.djrapitops.plan.db.SQLDB;
|
||||
import com.djrapitops.plan.db.access.Query;
|
||||
import com.djrapitops.plan.db.access.QueryStatement;
|
||||
import com.djrapitops.plan.db.sql.tables.ExtensionIconTable;
|
||||
import com.djrapitops.plan.db.sql.tables.ExtensionPlayerTableValueTable;
|
||||
import com.djrapitops.plan.db.sql.tables.ExtensionTabTable;
|
||||
import com.djrapitops.plan.db.sql.tables.ExtensionTableProviderTable;
|
||||
import com.djrapitops.plan.extension.ElementOrder;
|
||||
import com.djrapitops.plan.extension.icon.Color;
|
||||
import com.djrapitops.plan.extension.icon.Family;
|
||||
import com.djrapitops.plan.extension.icon.Icon;
|
||||
import com.djrapitops.plan.extension.implementation.TabInformation;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionTabData;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionTableData;
|
||||
import com.djrapitops.plan.extension.implementation.results.player.ExtensionPlayerData;
|
||||
import com.djrapitops.plan.extension.table.Table;
|
||||
import com.djrapitops.plan.extension.table.TableAccessor;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
|
||||
import static com.djrapitops.plan.db.sql.parsing.Sql.*;
|
||||
|
||||
/**
|
||||
* Query player tables from tableprovider table.
|
||||
* <p>
|
||||
* Returns Map: PluginID - ExtensionPlayerData.Factory.
|
||||
* <p>
|
||||
* How it is done:
|
||||
* - TableProviders are queried and formed into Table.Factory objects sorted into a multi-map: PluginID - TableID - Table.Factory
|
||||
* - Table values are queried and merged into the above multimap
|
||||
* - Data query is sorted into a multi-map: PluginID - Tab Name - Tab Data
|
||||
* - (Tab Name can be empty.)
|
||||
* - Multi-map is sorted into ExtensionPlayerData objects by PluginID, one per ID
|
||||
* <p>
|
||||
* There are multiple data extraction methods to make extracting the value query easier.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ExtensionPlayerTablesQuery implements Query<Map<Integer, ExtensionPlayerData.Factory>> {
|
||||
|
||||
private final UUID playerUUID;
|
||||
|
||||
public ExtensionPlayerTablesQuery(UUID playerUUID) {
|
||||
this.playerUUID = playerUUID;
|
||||
}
|
||||
|
||||
private static Map<Integer, ExtensionPlayerData.Factory> flatMapByPluginID(Map<Integer, Map<String, ExtensionTabData.Factory>> tabDataByPluginID) {
|
||||
Map<Integer, ExtensionPlayerData.Factory> dataByPluginID = new HashMap<>();
|
||||
for (Map.Entry<Integer, Map<String, ExtensionTabData.Factory>> entry : tabDataByPluginID.entrySet()) {
|
||||
Integer pluginID = entry.getKey();
|
||||
ExtensionPlayerData.Factory data = dataByPluginID.getOrDefault(pluginID, new ExtensionPlayerData.Factory(pluginID));
|
||||
for (ExtensionTabData.Factory tabData : entry.getValue().values()) {
|
||||
data.addTab(tabData.build());
|
||||
}
|
||||
dataByPluginID.put(pluginID, data);
|
||||
}
|
||||
return dataByPluginID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, ExtensionPlayerData.Factory> executeQuery(SQLDB db) {
|
||||
Map<Integer, Map<Integer, Table.Factory>> tablesByPluginIDAndTableID = db.query(queryTableProviders());
|
||||
Map<Integer, Map<Integer, Table.Factory>> tablesWithValues = db.query(queryTableValues(tablesByPluginIDAndTableID));
|
||||
|
||||
Map<Integer, Map<String, ExtensionTabData.Factory>> tabDataByPluginID = mapToTabsByPluginID(tablesWithValues);
|
||||
return flatMapByPluginID(tabDataByPluginID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tablesByPluginIDAndTableID {@code <Plugin ID - <Table ID - Table.Factory>>}
|
||||
* @return {@code <Plugin ID - <Tab name - ExtensionTabData.Factory>}
|
||||
*/
|
||||
private Map<Integer, Map<String, ExtensionTabData.Factory>> mapToTabsByPluginID(Map<Integer, Map<Integer, Table.Factory>> tablesByPluginIDAndTableID) {
|
||||
Map<Integer, Map<String, ExtensionTabData.Factory>> byPluginID = new HashMap<>();
|
||||
|
||||
for (Map.Entry<Integer, Map<Integer, Table.Factory>> entry : tablesByPluginIDAndTableID.entrySet()) {
|
||||
Integer pluginID = entry.getKey();
|
||||
Map<String, ExtensionTabData.Factory> byTabName = byPluginID.getOrDefault(pluginID, new HashMap<>());
|
||||
for (Table.Factory table : entry.getValue().values()) {
|
||||
// Extra Table information
|
||||
String tableName = TableAccessor.getTableName(table);
|
||||
Color tableColor = TableAccessor.getColor(table);
|
||||
|
||||
// Extra tab information
|
||||
String tabName = TableAccessor.getTabName(table);
|
||||
int tabPriority = TableAccessor.getTabPriority(table);
|
||||
ElementOrder[] tabOrder = TableAccessor.getTabOrder(table);
|
||||
Icon tabIcon = TableAccessor.getTabIcon(table);
|
||||
|
||||
ExtensionTabData.Factory tab = byTabName.getOrDefault(tabName, new ExtensionTabData.Factory(new TabInformation(tabName, tabIcon, tabOrder, tabPriority)));
|
||||
tab.putTableData(new ExtensionTableData(
|
||||
tableName, table.build(), tableColor
|
||||
));
|
||||
byTabName.put(tabName, tab);
|
||||
}
|
||||
byPluginID.put(pluginID, byTabName);
|
||||
}
|
||||
|
||||
return byPluginID;
|
||||
}
|
||||
|
||||
// Map: <Plugin ID - <Table ID - Table.Factory>>
|
||||
private Query<Map<Integer, Map<Integer, Table.Factory>>> queryTableValues(Map<Integer, Map<Integer, Table.Factory>> tables) {
|
||||
String selectTableValues = SELECT +
|
||||
ExtensionTableProviderTable.PLUGIN_ID + ',' +
|
||||
ExtensionPlayerTableValueTable.TABLE_ID + ',' +
|
||||
ExtensionPlayerTableValueTable.VALUE_1 + ',' +
|
||||
ExtensionPlayerTableValueTable.VALUE_2 + ',' +
|
||||
ExtensionPlayerTableValueTable.VALUE_3 + ',' +
|
||||
ExtensionPlayerTableValueTable.VALUE_4 +
|
||||
FROM + ExtensionPlayerTableValueTable.TABLE_NAME +
|
||||
INNER_JOIN + ExtensionTableProviderTable.TABLE_NAME + " on " + ExtensionTableProviderTable.TABLE_NAME + '.' + ExtensionTableProviderTable.ID + '=' + ExtensionPlayerTableValueTable.TABLE_NAME + '.' + ExtensionPlayerTableValueTable.TABLE_ID +
|
||||
WHERE + ExtensionPlayerTableValueTable.USER_UUID + "=?";
|
||||
|
||||
return new QueryStatement<Map<Integer, Map<Integer, Table.Factory>>>(selectTableValues, 10000) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setString(1, playerUUID.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, Map<Integer, Table.Factory>> processResults(ResultSet set) throws SQLException {
|
||||
while (set.next()) {
|
||||
Table.Factory table = getTable(set);
|
||||
if (table == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Object[] row = extractTableRow(set);
|
||||
if (row.length > 0) {
|
||||
table.addRow(row);
|
||||
}
|
||||
}
|
||||
return tables;
|
||||
}
|
||||
|
||||
private Table.Factory getTable(ResultSet set) throws SQLException {
|
||||
int pluginID = set.getInt(ExtensionTableProviderTable.PLUGIN_ID);
|
||||
Map<Integer, Table.Factory> byTableID = tables.get(pluginID);
|
||||
if (byTableID == null) {
|
||||
return null;
|
||||
}
|
||||
int tableID = set.getInt(ExtensionPlayerTableValueTable.TABLE_ID);
|
||||
return byTableID.get(tableID);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Object[] extractTableRow(ResultSet set) throws SQLException {
|
||||
List<Object> row = new ArrayList<>();
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
String columnName = "col_" + i + "_value"; // See ExtensionPlayerTableValueTable.VALUE_1
|
||||
String value = set.getString(columnName);
|
||||
if (value == null) {
|
||||
return row.toArray(new Object[0]);
|
||||
}
|
||||
row.add(value);
|
||||
}
|
||||
return row.toArray(new Object[0]);
|
||||
}
|
||||
|
||||
// Map: <Plugin ID - <Table ID - Table.Factory>>
|
||||
private Query<Map<Integer, Map<Integer, Table.Factory>>> queryTableProviders() {
|
||||
String selectTables = SELECT +
|
||||
"p1." + ExtensionTableProviderTable.ID + " as table_id," +
|
||||
"p1." + ExtensionTableProviderTable.PLUGIN_ID + " as plugin_id," +
|
||||
"p1." + ExtensionTableProviderTable.PROVIDER_NAME + " as table_name," +
|
||||
"p1." + ExtensionTableProviderTable.COLOR + " as table_color," +
|
||||
ExtensionTableProviderTable.COL_1 + ',' +
|
||||
ExtensionTableProviderTable.COL_2 + ',' +
|
||||
ExtensionTableProviderTable.COL_3 + ',' +
|
||||
ExtensionTableProviderTable.COL_4 + ',' +
|
||||
"t1." + ExtensionTabTable.TAB_NAME + " as tab_name," +
|
||||
"t1." + ExtensionTabTable.TAB_PRIORITY + " as tab_priority," +
|
||||
"t1." + ExtensionTabTable.ELEMENT_ORDER + " as element_order," +
|
||||
"i1." + ExtensionIconTable.ICON_NAME + " as i1_name," +
|
||||
"i1." + ExtensionIconTable.FAMILY + " as i1_family," +
|
||||
"i1." + ExtensionIconTable.COLOR + " as i1_color," +
|
||||
"i2." + ExtensionIconTable.ICON_NAME + " as i2_name," +
|
||||
"i2." + ExtensionIconTable.FAMILY + " as i2_family," +
|
||||
"i2." + ExtensionIconTable.COLOR + " as i2_color," +
|
||||
"i3." + ExtensionIconTable.ICON_NAME + " as i3_name," +
|
||||
"i3." + ExtensionIconTable.FAMILY + " as i3_family," +
|
||||
"i3." + ExtensionIconTable.COLOR + " as i3_color," +
|
||||
"i4." + ExtensionIconTable.ICON_NAME + " as i4_name," +
|
||||
"i4." + ExtensionIconTable.FAMILY + " as i4_family," +
|
||||
"i4." + ExtensionIconTable.COLOR + " as i4_color," +
|
||||
"i6." + ExtensionIconTable.ICON_NAME + " as tab_icon_name," +
|
||||
"i6." + ExtensionIconTable.FAMILY + " as tab_icon_family," +
|
||||
"i6." + ExtensionIconTable.COLOR + " as tab_icon_color" +
|
||||
FROM + ExtensionTableProviderTable.TABLE_NAME + " p1" +
|
||||
INNER_JOIN + ExtensionPlayerTableValueTable.TABLE_NAME + " v1 on v1." + ExtensionPlayerTableValueTable.TABLE_ID + "=p1." + ExtensionTableProviderTable.ID +
|
||||
LEFT_JOIN + ExtensionTabTable.TABLE_NAME + " t1 on t1." + ExtensionTabTable.ID + "=p1." + ExtensionTableProviderTable.TAB_ID +
|
||||
LEFT_JOIN + ExtensionIconTable.TABLE_NAME + " i1 on i1." + ExtensionIconTable.ID + "=p1." + ExtensionTableProviderTable.ICON_1_ID +
|
||||
LEFT_JOIN + ExtensionIconTable.TABLE_NAME + " i2 on i2." + ExtensionIconTable.ID + "=p1." + ExtensionTableProviderTable.ICON_2_ID +
|
||||
LEFT_JOIN + ExtensionIconTable.TABLE_NAME + " i3 on i3." + ExtensionIconTable.ID + "=p1." + ExtensionTableProviderTable.ICON_3_ID +
|
||||
LEFT_JOIN + ExtensionIconTable.TABLE_NAME + " i4 on i4." + ExtensionIconTable.ID + "=p1." + ExtensionTableProviderTable.ICON_4_ID +
|
||||
LEFT_JOIN + ExtensionIconTable.TABLE_NAME + " i6 on i6." + ExtensionIconTable.ID + "=t1." + ExtensionTabTable.ICON_ID +
|
||||
WHERE + "v1." + ExtensionPlayerTableValueTable.USER_UUID + "=?";
|
||||
|
||||
return new QueryStatement<Map<Integer, Map<Integer, Table.Factory>>>(selectTables, 100) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setString(1, playerUUID.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, Map<Integer, Table.Factory>> processResults(ResultSet set) throws SQLException {
|
||||
Map<Integer, Map<Integer, Table.Factory>> byPluginID = new HashMap<>();
|
||||
|
||||
while (set.next()) {
|
||||
int pluginID = set.getInt("plugin_id");
|
||||
Map<Integer, Table.Factory> byTableID = byPluginID.getOrDefault(pluginID, new HashMap<>());
|
||||
|
||||
int tableID = set.getInt("table_id");
|
||||
Table.Factory table = Table.builder();
|
||||
|
||||
extractColumns(set, table);
|
||||
|
||||
TableAccessor.setColor(table, Color.getByName(set.getString("table_color")).orElse(Color.NONE));
|
||||
TableAccessor.setTableName(table, set.getString("table_name"));
|
||||
TableAccessor.setTabName(table, Optional.ofNullable(set.getString("tab_name")).orElse(""));
|
||||
TableAccessor.setTabPriority(table, Optional.of(set.getInt("tab_priority")).orElse(100));
|
||||
TableAccessor.setTabOrder(table, Optional.ofNullable(set.getString(ExtensionTabTable.ELEMENT_ORDER)).map(ElementOrder::deserialize).orElse(ElementOrder.values()));
|
||||
TableAccessor.setTabIcon(table, extractIcon(set, "tab_icon"));
|
||||
|
||||
byTableID.put(tableID, table);
|
||||
byPluginID.put(pluginID, byTableID);
|
||||
}
|
||||
|
||||
return byPluginID;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void extractColumns(ResultSet set, Table.Factory table) throws SQLException {
|
||||
String col1 = set.getString(ExtensionTableProviderTable.COL_1);
|
||||
if (col1 != null) {
|
||||
table.columnOne(col1, extractIcon(set, "i1"));
|
||||
}
|
||||
String col2 = set.getString(ExtensionTableProviderTable.COL_2);
|
||||
if (col2 != null) {
|
||||
table.columnTwo(col2, extractIcon(set, "i2"));
|
||||
}
|
||||
String col3 = set.getString(ExtensionTableProviderTable.COL_3);
|
||||
if (col3 != null) {
|
||||
table.columnThree(col3, extractIcon(set, "i3"));
|
||||
}
|
||||
String col4 = set.getString(ExtensionTableProviderTable.COL_4);
|
||||
if (col4 != null) {
|
||||
table.columnFour(col4, extractIcon(set, "i4"));
|
||||
}
|
||||
}
|
||||
|
||||
private Icon extractIcon(ResultSet set, String iconColumnName) throws SQLException {
|
||||
String iconName = set.getString(iconColumnName + "_name");
|
||||
if (iconName == null) {
|
||||
return null;
|
||||
}
|
||||
return new Icon(
|
||||
Family.getByName(set.getString(iconColumnName + "_family")).orElse(Family.SOLID),
|
||||
iconName,
|
||||
Color.getByName(set.getString(iconColumnName + "_color")).orElse(Color.NONE)
|
||||
);
|
||||
}
|
||||
}
|
@ -83,6 +83,7 @@ public class ExtensionServerDataQuery implements Query<List<ExtensionServerData>
|
||||
combine(extensionDataByPluginID, db.query(new ExtensionAggregateDoublesQuery(serverUUID)));
|
||||
combine(extensionDataByPluginID, db.query(new ExtensionAggregateNumbersQuery(serverUUID)));
|
||||
combine(extensionDataByPluginID, db.query(new ExtensionAggregatePercentagesQuery(serverUUID)));
|
||||
combine(extensionDataByPluginID, db.query(new ExtensionServerTablesQuery(serverUUID)));
|
||||
|
||||
return combineWithExtensionInfo(extensionsOfServer, extensionDataByPluginID);
|
||||
}
|
||||
|
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* 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.queries;
|
||||
|
||||
import com.djrapitops.plan.db.SQLDB;
|
||||
import com.djrapitops.plan.db.access.Query;
|
||||
import com.djrapitops.plan.db.access.QueryStatement;
|
||||
import com.djrapitops.plan.db.sql.tables.ExtensionIconTable;
|
||||
import com.djrapitops.plan.db.sql.tables.ExtensionServerTableValueTable;
|
||||
import com.djrapitops.plan.db.sql.tables.ExtensionTabTable;
|
||||
import com.djrapitops.plan.db.sql.tables.ExtensionTableProviderTable;
|
||||
import com.djrapitops.plan.extension.ElementOrder;
|
||||
import com.djrapitops.plan.extension.icon.Color;
|
||||
import com.djrapitops.plan.extension.icon.Family;
|
||||
import com.djrapitops.plan.extension.icon.Icon;
|
||||
import com.djrapitops.plan.extension.implementation.TabInformation;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionTabData;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionTableData;
|
||||
import com.djrapitops.plan.extension.implementation.results.server.ExtensionServerData;
|
||||
import com.djrapitops.plan.extension.table.Table;
|
||||
import com.djrapitops.plan.extension.table.TableAccessor;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
|
||||
import static com.djrapitops.plan.db.sql.parsing.Sql.*;
|
||||
|
||||
/**
|
||||
* Query server tables from tableprovider table.
|
||||
* <p>
|
||||
* Returns Map: PluginID - ExtensionServerData.Factory.
|
||||
* <p>
|
||||
* How it is done:
|
||||
* - TableProviders are queried and formed into Table.Factory objects sorted into a multi-map: PluginID - TableID - Table.Factory
|
||||
* - Table values are queried and merged into the above multimap
|
||||
* - Data query is sorted into a multi-map: PluginID - Tab Name - Tab Data
|
||||
* - (Tab Name can be empty.)
|
||||
* - Multi-map is sorted into ExtensionServerData objects by PluginID, one per ID
|
||||
* <p>
|
||||
* There are multiple data extraction methods to make extracting the value query easier.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ExtensionServerTablesQuery implements Query<Map<Integer, ExtensionServerData.Factory>> {
|
||||
|
||||
private final UUID serverUUID;
|
||||
|
||||
public ExtensionServerTablesQuery(UUID serverUUID) {
|
||||
this.serverUUID = serverUUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, ExtensionServerData.Factory> executeQuery(SQLDB db) {
|
||||
Map<Integer, Map<Integer, Table.Factory>> tablesByPluginIDAndTableID = db.query(queryTableProviders());
|
||||
Map<Integer, Map<Integer, Table.Factory>> tablesWithValues = db.query(queryTableValues(tablesByPluginIDAndTableID));
|
||||
|
||||
Map<Integer, Map<String, ExtensionTabData.Factory>> tabDataByPluginID = mapToTabsByPluginID(tablesWithValues);
|
||||
return ExtensionServerDataQuery.flatMapToServerData(tabDataByPluginID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tablesByPluginIDAndTableID {@code <Plugin ID - <Table ID - Table.Factory>>}
|
||||
* @return {@code <Plugin ID - <Tab name - ExtensionTabData.Factory>}
|
||||
*/
|
||||
private Map<Integer, Map<String, ExtensionTabData.Factory>> mapToTabsByPluginID(Map<Integer, Map<Integer, Table.Factory>> tablesByPluginIDAndTableID) {
|
||||
Map<Integer, Map<String, ExtensionTabData.Factory>> byPluginID = new HashMap<>();
|
||||
|
||||
for (Map.Entry<Integer, Map<Integer, Table.Factory>> entry : tablesByPluginIDAndTableID.entrySet()) {
|
||||
Integer pluginID = entry.getKey();
|
||||
Map<String, ExtensionTabData.Factory> byTabName = byPluginID.getOrDefault(pluginID, new HashMap<>());
|
||||
for (Table.Factory table : entry.getValue().values()) {
|
||||
// Extra Table information
|
||||
String tableName = TableAccessor.getTableName(table);
|
||||
Color tableColor = TableAccessor.getColor(table);
|
||||
|
||||
// Extra tab information
|
||||
String tabName = TableAccessor.getTabName(table);
|
||||
int tabPriority = TableAccessor.getTabPriority(table);
|
||||
ElementOrder[] tabOrder = TableAccessor.getTabOrder(table);
|
||||
Icon tabIcon = TableAccessor.getTabIcon(table);
|
||||
|
||||
ExtensionTabData.Factory tab = byTabName.getOrDefault(tabName, new ExtensionTabData.Factory(new TabInformation(tabName, tabIcon, tabOrder, tabPriority)));
|
||||
tab.putTableData(new ExtensionTableData(
|
||||
tableName, table.build(), tableColor
|
||||
));
|
||||
byTabName.put(tabName, tab);
|
||||
}
|
||||
byPluginID.put(pluginID, byTabName);
|
||||
}
|
||||
|
||||
return byPluginID;
|
||||
}
|
||||
|
||||
// Map: <Plugin ID - <Table ID - Table.Factory>>
|
||||
private Query<Map<Integer, Map<Integer, Table.Factory>>> queryTableValues(Map<Integer, Map<Integer, Table.Factory>> tables) {
|
||||
String selectTableValues = SELECT +
|
||||
ExtensionTableProviderTable.PLUGIN_ID + ',' +
|
||||
ExtensionServerTableValueTable.TABLE_ID + ',' +
|
||||
ExtensionServerTableValueTable.VALUE_1 + ',' +
|
||||
ExtensionServerTableValueTable.VALUE_2 + ',' +
|
||||
ExtensionServerTableValueTable.VALUE_3 + ',' +
|
||||
ExtensionServerTableValueTable.VALUE_4 + ',' +
|
||||
ExtensionServerTableValueTable.VALUE_5 +
|
||||
FROM + ExtensionServerTableValueTable.TABLE_NAME +
|
||||
INNER_JOIN + ExtensionTableProviderTable.TABLE_NAME + " on " + ExtensionTableProviderTable.TABLE_NAME + '.' + ExtensionTableProviderTable.ID + '=' + ExtensionServerTableValueTable.TABLE_NAME + '.' + ExtensionServerTableValueTable.TABLE_ID +
|
||||
WHERE + ExtensionServerTableValueTable.SERVER_UUID + "=?";
|
||||
|
||||
return new QueryStatement<Map<Integer, Map<Integer, Table.Factory>>>(selectTableValues, 10000) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setString(1, serverUUID.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, Map<Integer, Table.Factory>> processResults(ResultSet set) throws SQLException {
|
||||
while (set.next()) {
|
||||
Table.Factory table = getTable(set);
|
||||
if (table == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Object[] row = extractTableRow(set);
|
||||
if (row.length > 0) {
|
||||
table.addRow(row);
|
||||
}
|
||||
}
|
||||
return tables;
|
||||
}
|
||||
|
||||
private Table.Factory getTable(ResultSet set) throws SQLException {
|
||||
int pluginID = set.getInt(ExtensionTableProviderTable.PLUGIN_ID);
|
||||
Map<Integer, Table.Factory> byTableID = tables.get(pluginID);
|
||||
if (byTableID == null) {
|
||||
return null;
|
||||
}
|
||||
int tableID = set.getInt(ExtensionServerTableValueTable.TABLE_ID);
|
||||
return byTableID.get(tableID);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Object[] extractTableRow(ResultSet set) throws SQLException {
|
||||
List<Object> row = new ArrayList<>();
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
String columnName = "col_" + i + "_value"; // See ExtensionServerTableValueTable.VALUE_1
|
||||
String value = set.getString(columnName);
|
||||
if (value == null) {
|
||||
return row.toArray(new Object[0]);
|
||||
}
|
||||
row.add(value);
|
||||
}
|
||||
return row.toArray(new Object[0]);
|
||||
}
|
||||
|
||||
// Map: <Plugin ID - <Table ID - Table.Factory>>
|
||||
private Query<Map<Integer, Map<Integer, Table.Factory>>> queryTableProviders() {
|
||||
String selectTables = SELECT +
|
||||
"p1." + ExtensionTableProviderTable.ID + " as table_id," +
|
||||
"p1." + ExtensionTableProviderTable.PLUGIN_ID + " as plugin_id," +
|
||||
"p1." + ExtensionTableProviderTable.PROVIDER_NAME + " as table_name," +
|
||||
"p1." + ExtensionTableProviderTable.COLOR + " as table_color," +
|
||||
ExtensionTableProviderTable.COL_1 + ',' +
|
||||
ExtensionTableProviderTable.COL_2 + ',' +
|
||||
ExtensionTableProviderTable.COL_3 + ',' +
|
||||
ExtensionTableProviderTable.COL_4 + ',' +
|
||||
ExtensionTableProviderTable.COL_5 + ',' +
|
||||
"t1." + ExtensionTabTable.TAB_NAME + " as tab_name," +
|
||||
"t1." + ExtensionTabTable.TAB_PRIORITY + " as tab_priority," +
|
||||
"t1." + ExtensionTabTable.ELEMENT_ORDER + " as element_order," +
|
||||
"i1." + ExtensionIconTable.ICON_NAME + " as i1_name," +
|
||||
"i1." + ExtensionIconTable.FAMILY + " as i1_family," +
|
||||
"i1." + ExtensionIconTable.COLOR + " as i1_color," +
|
||||
"i2." + ExtensionIconTable.ICON_NAME + " as i2_name," +
|
||||
"i2." + ExtensionIconTable.FAMILY + " as i2_family," +
|
||||
"i2." + ExtensionIconTable.COLOR + " as i2_color," +
|
||||
"i3." + ExtensionIconTable.ICON_NAME + " as i3_name," +
|
||||
"i3." + ExtensionIconTable.FAMILY + " as i3_family," +
|
||||
"i3." + ExtensionIconTable.COLOR + " as i3_color," +
|
||||
"i4." + ExtensionIconTable.ICON_NAME + " as i4_name," +
|
||||
"i4." + ExtensionIconTable.FAMILY + " as i4_family," +
|
||||
"i4." + ExtensionIconTable.COLOR + " as i4_color," +
|
||||
"i5." + ExtensionIconTable.ICON_NAME + " as i5_name," +
|
||||
"i5." + ExtensionIconTable.FAMILY + " as i5_family," +
|
||||
"i5." + ExtensionIconTable.COLOR + " as i5_color," +
|
||||
"i6." + ExtensionIconTable.ICON_NAME + " as tab_icon_name," +
|
||||
"i6." + ExtensionIconTable.FAMILY + " as tab_icon_family," +
|
||||
"i6." + ExtensionIconTable.COLOR + " as tab_icon_color" +
|
||||
FROM + ExtensionTableProviderTable.TABLE_NAME + " p1" +
|
||||
INNER_JOIN + ExtensionServerTableValueTable.TABLE_NAME + " v1 on v1." + ExtensionServerTableValueTable.TABLE_ID + "=p1." + ExtensionTableProviderTable.ID +
|
||||
LEFT_JOIN + ExtensionTabTable.TABLE_NAME + " t1 on t1." + ExtensionTabTable.ID + "=p1." + ExtensionTableProviderTable.TAB_ID +
|
||||
LEFT_JOIN + ExtensionIconTable.TABLE_NAME + " i1 on i1." + ExtensionIconTable.ID + "=p1." + ExtensionTableProviderTable.ICON_1_ID +
|
||||
LEFT_JOIN + ExtensionIconTable.TABLE_NAME + " i2 on i2." + ExtensionIconTable.ID + "=p1." + ExtensionTableProviderTable.ICON_2_ID +
|
||||
LEFT_JOIN + ExtensionIconTable.TABLE_NAME + " i3 on i3." + ExtensionIconTable.ID + "=p1." + ExtensionTableProviderTable.ICON_3_ID +
|
||||
LEFT_JOIN + ExtensionIconTable.TABLE_NAME + " i4 on i4." + ExtensionIconTable.ID + "=p1." + ExtensionTableProviderTable.ICON_4_ID +
|
||||
LEFT_JOIN + ExtensionIconTable.TABLE_NAME + " i5 on i5." + ExtensionIconTable.ID + "=p1." + ExtensionTableProviderTable.ICON_5_ID +
|
||||
LEFT_JOIN + ExtensionIconTable.TABLE_NAME + " i6 on i6." + ExtensionIconTable.ID + "=t1." + ExtensionTabTable.ICON_ID +
|
||||
WHERE + "v1." + ExtensionServerTableValueTable.SERVER_UUID + "=?";
|
||||
|
||||
return new QueryStatement<Map<Integer, Map<Integer, Table.Factory>>>(selectTables, 100) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setString(1, serverUUID.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, Map<Integer, Table.Factory>> processResults(ResultSet set) throws SQLException {
|
||||
Map<Integer, Map<Integer, Table.Factory>> byPluginID = new HashMap<>();
|
||||
|
||||
while (set.next()) {
|
||||
int pluginID = set.getInt("plugin_id");
|
||||
Map<Integer, Table.Factory> byTableID = byPluginID.getOrDefault(pluginID, new HashMap<>());
|
||||
|
||||
int tableID = set.getInt("table_id");
|
||||
Table.Factory table = Table.builder();
|
||||
|
||||
extractColumns(set, table);
|
||||
|
||||
TableAccessor.setColor(table, Color.getByName(set.getString("table_color")).orElse(Color.NONE));
|
||||
TableAccessor.setTableName(table, set.getString("table_name"));
|
||||
TableAccessor.setTabName(table, Optional.ofNullable(set.getString("tab_name")).orElse(""));
|
||||
TableAccessor.setTabPriority(table, Optional.of(set.getInt("tab_priority")).orElse(100));
|
||||
TableAccessor.setTabOrder(table, Optional.ofNullable(set.getString(ExtensionTabTable.ELEMENT_ORDER)).map(ElementOrder::deserialize).orElse(ElementOrder.values()));
|
||||
TableAccessor.setTabIcon(table, extractIcon(set, "tab_icon"));
|
||||
|
||||
byTableID.put(tableID, table);
|
||||
byPluginID.put(pluginID, byTableID);
|
||||
}
|
||||
|
||||
return byPluginID;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void extractColumns(ResultSet set, Table.Factory table) throws SQLException {
|
||||
String col1 = set.getString(ExtensionTableProviderTable.COL_1);
|
||||
if (col1 != null) {
|
||||
table.columnOne(col1, extractIcon(set, "i1"));
|
||||
}
|
||||
String col2 = set.getString(ExtensionTableProviderTable.COL_2);
|
||||
if (col2 != null) {
|
||||
table.columnTwo(col2, extractIcon(set, "i2"));
|
||||
}
|
||||
String col3 = set.getString(ExtensionTableProviderTable.COL_3);
|
||||
if (col3 != null) {
|
||||
table.columnThree(col3, extractIcon(set, "i3"));
|
||||
}
|
||||
String col4 = set.getString(ExtensionTableProviderTable.COL_4);
|
||||
if (col4 != null) {
|
||||
table.columnFour(col4, extractIcon(set, "i4"));
|
||||
}
|
||||
String col5 = set.getString(ExtensionTableProviderTable.COL_5);
|
||||
if (col5 != null) {
|
||||
table.columnFive(col5, extractIcon(set, "i5"));
|
||||
}
|
||||
}
|
||||
|
||||
private Icon extractIcon(ResultSet set, String iconColumnName) throws SQLException {
|
||||
String iconName = set.getString(iconColumnName + "_name");
|
||||
if (iconName == null) {
|
||||
return null;
|
||||
}
|
||||
return new Icon(
|
||||
Family.getByName(set.getString(iconColumnName + "_family")).orElse(Family.SOLID),
|
||||
iconName,
|
||||
Color.getByName(set.getString(iconColumnName + "_color")).orElse(Color.NONE)
|
||||
);
|
||||
}
|
||||
}
|
@ -68,14 +68,14 @@ public class StoreTabInformationTransaction extends Transaction {
|
||||
" SET " +
|
||||
ExtensionTabTable.TAB_PRIORITY + "=?," +
|
||||
ExtensionTabTable.ELEMENT_ORDER + "=?," +
|
||||
ExtensionTabTable.ICON_ID + "=" + ExtensionIconTable.STATEMENT_SELECT_ICON_ID + "," +
|
||||
ExtensionTabTable.ICON_ID + "=" + ExtensionIconTable.STATEMENT_SELECT_ICON_ID +
|
||||
WHERE + ExtensionTabTable.PLUGIN_ID + "=" + ExtensionPluginTable.STATEMENT_SELECT_PLUGIN_ID +
|
||||
AND + ExtensionTabTable.TAB_NAME + "=?";
|
||||
return new ExecStatement(sql) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setInt(1, tabInformation.getTabPriority());
|
||||
statement.setString(2, tabInformation.getTabElementOrder().map(ElementOrder::serialize).orElse(null));
|
||||
statement.setString(2, ElementOrder.serialize(tabInformation.getTabElementOrder().orElse(ElementOrder.values())));
|
||||
ExtensionIconTable.set3IconValuesToStatement(statement, 3, tabInformation.getTabIcon());
|
||||
ExtensionPluginTable.set2PluginValuesToStatement(statement, 6, pluginName, serverUUID);
|
||||
statement.setString(8, tabInformation.getTabName());
|
||||
@ -88,14 +88,14 @@ public class StoreTabInformationTransaction extends Transaction {
|
||||
ExtensionTabTable.TAB_NAME + "," +
|
||||
ExtensionTabTable.ELEMENT_ORDER + "," +
|
||||
ExtensionTabTable.TAB_PRIORITY + "," +
|
||||
ExtensionTabTable.ICON_ID +
|
||||
ExtensionTabTable.ICON_ID + "," +
|
||||
ExtensionTabTable.PLUGIN_ID +
|
||||
") VALUES (?,?,?," + ExtensionIconTable.STATEMENT_SELECT_ICON_ID + "," + ExtensionPluginTable.STATEMENT_SELECT_PLUGIN_ID + ")";
|
||||
return new ExecStatement(sql) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setString(1, tabInformation.getTabName());
|
||||
statement.setString(2, tabInformation.getTabElementOrder().map(ElementOrder::serialize).orElse(null));
|
||||
statement.setString(2, ElementOrder.serialize(tabInformation.getTabElementOrder().orElse(ElementOrder.values())));
|
||||
statement.setInt(3, tabInformation.getTabPriority());
|
||||
ExtensionIconTable.set3IconValuesToStatement(statement, 4, tabInformation.getTabIcon());
|
||||
ExtensionPluginTable.set2PluginValuesToStatement(statement, 7, pluginName, serverUUID);
|
||||
|
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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.providers;
|
||||
|
||||
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.ExtensionIconTable;
|
||||
import com.djrapitops.plan.db.sql.tables.ExtensionPluginTable;
|
||||
import com.djrapitops.plan.db.sql.tables.ExtensionTabTable;
|
||||
import com.djrapitops.plan.extension.icon.Color;
|
||||
import com.djrapitops.plan.extension.icon.Icon;
|
||||
import com.djrapitops.plan.extension.implementation.ProviderInformation;
|
||||
import com.djrapitops.plan.extension.table.Table;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.djrapitops.plan.db.sql.parsing.Sql.AND;
|
||||
import static com.djrapitops.plan.db.sql.parsing.Sql.WHERE;
|
||||
import static com.djrapitops.plan.db.sql.tables.ExtensionTableProviderTable.*;
|
||||
|
||||
/**
|
||||
* Transaction to store information about a {@link com.djrapitops.plan.extension.implementation.providers.TableDataProvider}.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class StoreTableProviderTransaction extends Transaction {
|
||||
|
||||
private final UUID serverUUID;
|
||||
private final ProviderInformation providerInformation;
|
||||
private final Color tableColor;
|
||||
private final Table table;
|
||||
|
||||
public StoreTableProviderTransaction(UUID serverUUID, ProviderInformation providerInformation, Color tableColor, Table table) {
|
||||
this.providerInformation = providerInformation;
|
||||
this.tableColor = tableColor;
|
||||
this.table = table;
|
||||
this.serverUUID = serverUUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performOperations() {
|
||||
execute(storeProvider());
|
||||
}
|
||||
|
||||
private Executable storeProvider() {
|
||||
return connection -> {
|
||||
if (!updateProvider().execute(connection)) {
|
||||
return insertProvider().execute(connection);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
private Executable updateProvider() {
|
||||
String[] columns = table.getColumns();
|
||||
Icon[] icons = table.getIcons();
|
||||
|
||||
String sql = "UPDATE " + TABLE_NAME + " SET " +
|
||||
COLOR + "=?," +
|
||||
COL_1 + "=?," +
|
||||
COL_2 + "=?," +
|
||||
COL_3 + "=?," +
|
||||
COL_4 + "=?," +
|
||||
COL_5 + "=?," +
|
||||
CONDITION + "=?," +
|
||||
TAB_ID + '=' + ExtensionTabTable.STATEMENT_SELECT_TAB_ID + ',' +
|
||||
ICON_1_ID + '=' + ExtensionIconTable.STATEMENT_SELECT_ICON_ID + ',' +
|
||||
ICON_2_ID + '=' + ExtensionIconTable.STATEMENT_SELECT_ICON_ID + ',' +
|
||||
ICON_3_ID + '=' + ExtensionIconTable.STATEMENT_SELECT_ICON_ID + ',' +
|
||||
ICON_4_ID + '=' + ExtensionIconTable.STATEMENT_SELECT_ICON_ID + ',' +
|
||||
ICON_5_ID + '=' + ExtensionIconTable.STATEMENT_SELECT_ICON_ID +
|
||||
WHERE + PROVIDER_NAME + "=?" +
|
||||
AND + PLUGIN_ID + '=' + ExtensionPluginTable.STATEMENT_SELECT_PLUGIN_ID;
|
||||
|
||||
return new ExecStatement(sql) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setString(1, tableColor.name());
|
||||
setStringOrNull(statement, 2, columns[0]);
|
||||
setStringOrNull(statement, 3, columns[1]);
|
||||
setStringOrNull(statement, 4, columns[2]);
|
||||
setStringOrNull(statement, 5, columns[3]);
|
||||
setStringOrNull(statement, 6, columns[4]);
|
||||
setStringOrNull(statement, 7, providerInformation.getCondition().orElse(null));
|
||||
ExtensionTabTable.set3TabValuesToStatement(statement, 8, providerInformation.getTab().orElse("No Tab"), providerInformation.getPluginName(), serverUUID);
|
||||
ExtensionIconTable.set3IconValuesToStatement(statement, 11, icons[0]);
|
||||
ExtensionIconTable.set3IconValuesToStatement(statement, 14, icons[1]);
|
||||
ExtensionIconTable.set3IconValuesToStatement(statement, 17, icons[2]);
|
||||
ExtensionIconTable.set3IconValuesToStatement(statement, 20, icons[3]);
|
||||
ExtensionIconTable.set3IconValuesToStatement(statement, 23, icons[4]);
|
||||
statement.setString(26, providerInformation.getName());
|
||||
ExtensionPluginTable.set2PluginValuesToStatement(statement, 27, providerInformation.getPluginName(), serverUUID);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Executable insertProvider() {
|
||||
String[] columns = table.getColumns();
|
||||
Icon[] icons = table.getIcons();
|
||||
|
||||
String sql = "INSERT INTO " + TABLE_NAME + '(' +
|
||||
PROVIDER_NAME + ',' +
|
||||
COLOR + ',' +
|
||||
COL_1 + ',' +
|
||||
COL_2 + ',' +
|
||||
COL_3 + ',' +
|
||||
COL_4 + ',' +
|
||||
COL_5 + ',' +
|
||||
CONDITION + ',' +
|
||||
TAB_ID + ',' +
|
||||
PLUGIN_ID + ',' +
|
||||
ICON_1_ID + ',' +
|
||||
ICON_2_ID + ',' +
|
||||
ICON_3_ID + ',' +
|
||||
ICON_4_ID + ',' +
|
||||
ICON_5_ID +
|
||||
") VALUES (?,?,?,?,?,?,?,?," +
|
||||
ExtensionTabTable.STATEMENT_SELECT_TAB_ID + ',' +
|
||||
ExtensionPluginTable.STATEMENT_SELECT_PLUGIN_ID + ',' +
|
||||
ExtensionIconTable.STATEMENT_SELECT_ICON_ID + ',' +
|
||||
ExtensionIconTable.STATEMENT_SELECT_ICON_ID + ',' +
|
||||
ExtensionIconTable.STATEMENT_SELECT_ICON_ID + ',' +
|
||||
ExtensionIconTable.STATEMENT_SELECT_ICON_ID + ',' +
|
||||
ExtensionIconTable.STATEMENT_SELECT_ICON_ID + ')';
|
||||
|
||||
return new ExecStatement(sql) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setString(1, providerInformation.getName());
|
||||
statement.setString(2, tableColor.name());
|
||||
setStringOrNull(statement, 3, columns[0]);
|
||||
setStringOrNull(statement, 4, columns[1]);
|
||||
setStringOrNull(statement, 5, columns[2]);
|
||||
setStringOrNull(statement, 6, columns[3]);
|
||||
setStringOrNull(statement, 7, columns[4]);
|
||||
setStringOrNull(statement, 8, providerInformation.getCondition().orElse(null));
|
||||
ExtensionTabTable.set3TabValuesToStatement(statement, 9, providerInformation.getTab().orElse("No Tab"), providerInformation.getPluginName(), serverUUID);
|
||||
ExtensionPluginTable.set2PluginValuesToStatement(statement, 12, providerInformation.getPluginName(), serverUUID);
|
||||
ExtensionIconTable.set3IconValuesToStatement(statement, 14, icons[0]);
|
||||
ExtensionIconTable.set3IconValuesToStatement(statement, 17, icons[1]);
|
||||
ExtensionIconTable.set3IconValuesToStatement(statement, 20, icons[2]);
|
||||
ExtensionIconTable.set3IconValuesToStatement(statement, 23, icons[3]);
|
||||
ExtensionIconTable.set3IconValuesToStatement(statement, 26, icons[4]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void setStringOrNull(PreparedStatement statement, int index, String value) throws SQLException {
|
||||
if (value != null) {
|
||||
statement.setString(index, value);
|
||||
} else {
|
||||
statement.setNull(index, Types.VARCHAR);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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.api.exceptions.database.DBOpException;
|
||||
import com.djrapitops.plan.db.access.*;
|
||||
import com.djrapitops.plan.db.access.transactions.Transaction;
|
||||
import com.djrapitops.plan.db.sql.tables.ExtensionPluginTable;
|
||||
import com.djrapitops.plan.db.sql.tables.ExtensionTableProviderTable;
|
||||
import com.djrapitops.plan.extension.table.Table;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.djrapitops.plan.db.sql.parsing.Sql.*;
|
||||
import static com.djrapitops.plan.db.sql.tables.ExtensionPlayerTableValueTable.*;
|
||||
|
||||
/**
|
||||
* Transaction to store method result of a {@link com.djrapitops.plan.extension.implementation.providers.TableDataProvider}.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class StorePlayerTableResultTransaction extends Transaction {
|
||||
|
||||
private final String pluginName;
|
||||
private final UUID serverUUID;
|
||||
private final String providerName;
|
||||
private final UUID playerUUID;
|
||||
|
||||
private final Table table;
|
||||
|
||||
public StorePlayerTableResultTransaction(String pluginName, UUID serverUUID, String providerName, UUID playerUUID, Table table) {
|
||||
this.pluginName = pluginName;
|
||||
this.serverUUID = serverUUID;
|
||||
this.providerName = providerName;
|
||||
this.playerUUID = playerUUID;
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performOperations() {
|
||||
execute(storeValue());
|
||||
}
|
||||
|
||||
private Executable storeValue() {
|
||||
return connection -> {
|
||||
int maxColumnSize = table.getMaxColumnSize();
|
||||
if (maxColumnSize == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Integer tableID = query(tableID());
|
||||
deleteOldValues(tableID).execute(connection);
|
||||
insertNewValues(tableID).execute(connection);
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
private Executable deleteOldValues(int tableID) {
|
||||
String sql = "DELETE FROM " + TABLE_NAME +
|
||||
WHERE + TABLE_ID + "=?" +
|
||||
AND + USER_UUID + "=?";
|
||||
|
||||
return new ExecStatement(sql) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setInt(1, tableID);
|
||||
statement.setString(2, playerUUID.toString());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Executable insertNewValues(int tableID) {
|
||||
String sql = "INSERT INTO " + TABLE_NAME + '(' +
|
||||
TABLE_ID + ',' +
|
||||
USER_UUID + ',' +
|
||||
VALUE_1 + ',' +
|
||||
VALUE_2 + ',' +
|
||||
VALUE_3 + ',' +
|
||||
VALUE_4 +
|
||||
") VALUES (?,?,?,?,?,?)";
|
||||
|
||||
return new ExecBatchStatement(sql) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
int maxColumnSize = Math.min(table.getMaxColumnSize(), 4); // Limit to maximum 4 columns, or how many column names there are.
|
||||
|
||||
for (Object[] row : table.getRows()) {
|
||||
statement.setInt(1, tableID);
|
||||
statement.setString(2, playerUUID.toString());
|
||||
for (int i = 0; i < maxColumnSize; i++) {
|
||||
Object value = row[i];
|
||||
setStringOrNull(statement, 3 + i, value != null ? value.toString() : null);
|
||||
}
|
||||
// Rest are set null if not 4 columns wide.
|
||||
for (int i = maxColumnSize; i < 4; i++) {
|
||||
statement.setNull(3 + i, Types.VARCHAR);
|
||||
}
|
||||
|
||||
statement.addBatch();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void setStringOrNull(PreparedStatement statement, int index, String value) throws SQLException {
|
||||
if (value != null) {
|
||||
statement.setString(index, value);
|
||||
} else {
|
||||
statement.setNull(index, Types.VARCHAR);
|
||||
}
|
||||
}
|
||||
|
||||
private Query<Integer> tableID() {
|
||||
String sql = SELECT + ExtensionTableProviderTable.ID +
|
||||
FROM + ExtensionTableProviderTable.TABLE_NAME +
|
||||
WHERE + ExtensionTableProviderTable.PROVIDER_NAME + "=?" +
|
||||
AND + ExtensionTableProviderTable.PLUGIN_ID + "=" + ExtensionPluginTable.STATEMENT_SELECT_PLUGIN_ID +
|
||||
" LIMIT 1";
|
||||
return new QueryStatement<Integer>(sql) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
ExtensionTableProviderTable.set3PluginValuesToStatement(statement, 1, providerName, pluginName, serverUUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer processResults(ResultSet set) throws SQLException {
|
||||
if (set.next()) {
|
||||
int id = set.getInt(ExtensionTableProviderTable.ID);
|
||||
if (!set.wasNull()) {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
throw new DBOpException("Table Provider was not saved before storing results. Please report this issue. Extension method: " + pluginName + "#" + providerName);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* 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.api.exceptions.database.DBOpException;
|
||||
import com.djrapitops.plan.db.access.*;
|
||||
import com.djrapitops.plan.db.access.transactions.Transaction;
|
||||
import com.djrapitops.plan.db.sql.tables.ExtensionPluginTable;
|
||||
import com.djrapitops.plan.db.sql.tables.ExtensionTableProviderTable;
|
||||
import com.djrapitops.plan.extension.table.Table;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.djrapitops.plan.db.sql.parsing.Sql.*;
|
||||
import static com.djrapitops.plan.db.sql.tables.ExtensionServerTableValueTable.*;
|
||||
|
||||
/**
|
||||
* Transaction to store method result of a {@link com.djrapitops.plan.extension.implementation.providers.TableDataProvider}.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class StoreServerTableResultTransaction extends Transaction {
|
||||
|
||||
private final String pluginName;
|
||||
private final UUID serverUUID;
|
||||
private final String providerName;
|
||||
|
||||
private final Table table;
|
||||
|
||||
public StoreServerTableResultTransaction(String pluginName, UUID serverUUID, String providerName, Table table) {
|
||||
this.pluginName = pluginName;
|
||||
this.serverUUID = serverUUID;
|
||||
this.providerName = providerName;
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performOperations() {
|
||||
execute(storeValue());
|
||||
}
|
||||
|
||||
private Executable storeValue() {
|
||||
return connection -> {
|
||||
int maxColumnSize = table.getMaxColumnSize();
|
||||
if (maxColumnSize == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Integer tableID = query(tableID());
|
||||
deleteOldValues(tableID).execute(connection);
|
||||
insertNewValues(tableID).execute(connection);
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
private Executable deleteOldValues(int tableID) {
|
||||
String sql = "DELETE FROM " + TABLE_NAME +
|
||||
WHERE + TABLE_ID + "=?" +
|
||||
AND + SERVER_UUID + "=?";
|
||||
|
||||
return new ExecStatement(sql) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setInt(1, tableID);
|
||||
statement.setString(2, serverUUID.toString());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Executable insertNewValues(int tableID) {
|
||||
String sql = "INSERT INTO " + TABLE_NAME + '(' +
|
||||
TABLE_ID + ',' +
|
||||
SERVER_UUID + ',' +
|
||||
VALUE_1 + ',' +
|
||||
VALUE_2 + ',' +
|
||||
VALUE_3 + ',' +
|
||||
VALUE_4 + ',' +
|
||||
VALUE_5 +
|
||||
") VALUES (?,?,?,?,?,?, ?)";
|
||||
|
||||
return new ExecBatchStatement(sql) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
int maxColumnSize = Math.min(table.getMaxColumnSize(), 5); // Limit to maximum 5 columns, or how many column names there are.
|
||||
|
||||
for (Object[] row : table.getRows()) {
|
||||
statement.setInt(1, tableID);
|
||||
statement.setString(2, serverUUID.toString());
|
||||
for (int i = 0; i < maxColumnSize; i++) {
|
||||
Object value = row[i];
|
||||
setStringOrNull(statement, 3 + i, value != null ? value.toString() : null);
|
||||
}
|
||||
// Rest are set null if not 5 columns wide.
|
||||
for (int i = maxColumnSize; i < 5; i++) {
|
||||
statement.setNull(3 + i, Types.VARCHAR);
|
||||
}
|
||||
|
||||
statement.addBatch();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void setStringOrNull(PreparedStatement statement, int index, String value) throws SQLException {
|
||||
if (value != null) {
|
||||
statement.setString(index, value);
|
||||
} else {
|
||||
statement.setNull(index, Types.VARCHAR);
|
||||
}
|
||||
}
|
||||
|
||||
private Query<Integer> tableID() {
|
||||
String sql = SELECT + ExtensionTableProviderTable.ID +
|
||||
FROM + ExtensionTableProviderTable.TABLE_NAME +
|
||||
WHERE + ExtensionTableProviderTable.PROVIDER_NAME + "=?" +
|
||||
AND + ExtensionTableProviderTable.PLUGIN_ID + "=" + ExtensionPluginTable.STATEMENT_SELECT_PLUGIN_ID +
|
||||
" LIMIT 1";
|
||||
return new QueryStatement<Integer>(sql) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
ExtensionTableProviderTable.set3PluginValuesToStatement(statement, 1, providerName, pluginName, serverUUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer processResults(ResultSet set) throws SQLException {
|
||||
if (set.next()) {
|
||||
int id = set.getInt(ExtensionTableProviderTable.ID);
|
||||
if (!set.wasNull()) {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
throw new DBOpException("Table Provider was not saved before storing results. Please report this issue. Extension method: " + pluginName + "#" + providerName);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.table;
|
||||
|
||||
import com.djrapitops.plan.extension.ElementOrder;
|
||||
import com.djrapitops.plan.extension.icon.Color;
|
||||
import com.djrapitops.plan.extension.icon.Icon;
|
||||
|
||||
/**
|
||||
* Utility for accessing implementation variables inside Table.Factory object.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class TableAccessor {
|
||||
|
||||
private TableAccessor() {
|
||||
/* Static method class */
|
||||
}
|
||||
|
||||
public static Color getColor(Table.Factory factory) {
|
||||
return factory.color;
|
||||
}
|
||||
|
||||
public static void setColor(Table.Factory factory, Color color) {
|
||||
factory.color = color;
|
||||
}
|
||||
|
||||
public static String getTableName(Table.Factory factory) {
|
||||
return factory.tableName;
|
||||
}
|
||||
|
||||
public static void setTableName(Table.Factory factory, String tableName) {
|
||||
factory.tableName = tableName;
|
||||
}
|
||||
|
||||
public static String getTabName(Table.Factory factory) {
|
||||
return factory.tabName;
|
||||
}
|
||||
|
||||
public static void setTabName(Table.Factory factory, String tabName) {
|
||||
factory.tabName = tabName;
|
||||
}
|
||||
|
||||
public static int getTabPriority(Table.Factory factory) {
|
||||
return factory.tabPriority;
|
||||
}
|
||||
|
||||
public static void setTabPriority(Table.Factory factory, int tabPriority) {
|
||||
factory.tabPriority = tabPriority;
|
||||
}
|
||||
|
||||
public static ElementOrder[] getTabOrder(Table.Factory factory) {
|
||||
return factory.tabOrder;
|
||||
}
|
||||
|
||||
public static void setTabOrder(Table.Factory factory, ElementOrder[] tabOrder) {
|
||||
factory.tabOrder = tabOrder;
|
||||
}
|
||||
|
||||
public static Icon getTabIcon(Table.Factory factory) {
|
||||
return factory.tabIcon;
|
||||
}
|
||||
|
||||
public static void setTabIcon(Table.Factory factory, Icon tabIcon) {
|
||||
factory.tabIcon = tabIcon;
|
||||
}
|
||||
}
|
@ -58,6 +58,9 @@ public enum Color {
|
||||
}
|
||||
|
||||
public static Optional<Color> getByName(String name) {
|
||||
if (name == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
try {
|
||||
return Optional.of(valueOf(name));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -37,6 +37,9 @@ public enum Family {
|
||||
}
|
||||
|
||||
public static Optional<Family> getByName(String name) {
|
||||
if (name == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
try {
|
||||
return Optional.of(valueOf(name));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -30,6 +30,9 @@ public class Icon {
|
||||
}
|
||||
|
||||
public static Icon fromExtensionIcon(com.djrapitops.plan.extension.icon.Icon icon) {
|
||||
if (icon == null) {
|
||||
return Icon.called("question").build();
|
||||
}
|
||||
return new Icon(
|
||||
Family.getByName(icon.getFamily().name()).orElse(Family.SOLID),
|
||||
icon.getName(),
|
||||
|
@ -16,11 +16,13 @@
|
||||
*/
|
||||
package com.djrapitops.plan.utilities.html.pages;
|
||||
|
||||
import com.djrapitops.plan.extension.ElementOrder;
|
||||
import com.djrapitops.plan.extension.FormatType;
|
||||
import com.djrapitops.plan.extension.implementation.TabInformation;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionDescriptive;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionInformation;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionTabData;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionTableData;
|
||||
import com.djrapitops.plan.extension.implementation.results.server.ExtensionServerData;
|
||||
import com.djrapitops.plan.utilities.formatting.Formatter;
|
||||
import com.djrapitops.plan.utilities.formatting.Formatters;
|
||||
@ -50,6 +52,8 @@ public class AnalysisPluginTabs {
|
||||
private String nav;
|
||||
private String tab;
|
||||
|
||||
private boolean hasWideTable;
|
||||
|
||||
public AnalysisPluginTabs(String nav, String tab) {
|
||||
this.nav = nav;
|
||||
this.tab = tab;
|
||||
@ -70,6 +74,8 @@ public class AnalysisPluginTabs {
|
||||
this.decimalFormatter = formatters.decimals();
|
||||
this.percentageFormatter = formatters.percentage();
|
||||
|
||||
hasWideTable = false;
|
||||
|
||||
generate();
|
||||
}
|
||||
|
||||
@ -106,7 +112,7 @@ public class AnalysisPluginTabs {
|
||||
String tabsElement;
|
||||
if (onlyGeneric) {
|
||||
ExtensionTabData genericTabData = datum.getTabs().get(0);
|
||||
tabsElement = Html.BODY.parse(parseDataHtml(genericTabData));
|
||||
tabsElement = parseContentHtml(genericTabData);
|
||||
} else {
|
||||
tabsElement = new TabsElement(
|
||||
datum.getTabs().stream().map(this::wrapToTabElementTab).toArray(TabsElement.Tab[]::new)
|
||||
@ -125,11 +131,53 @@ public class AnalysisPluginTabs {
|
||||
|
||||
private TabsElement.Tab wrapToTabElementTab(ExtensionTabData tabData) {
|
||||
TabInformation tabInformation = tabData.getTabInformation();
|
||||
String tabContentHtml = parseContentHtml(tabData);
|
||||
|
||||
return new TabsElement.Tab(tabInformation.getTabName(), parseDataHtml(tabData));
|
||||
String tabName = tabInformation.getTabName();
|
||||
return new TabsElement.Tab(tabName.isEmpty()
|
||||
? Icon.called("info-circle").build().toHtml() + " General"
|
||||
: Icon.fromExtensionIcon(tabInformation.getTabIcon()).toHtml() + ' ' + tabName,
|
||||
tabContentHtml);
|
||||
}
|
||||
|
||||
private String parseDataHtml(ExtensionTabData tabData) {
|
||||
private String parseContentHtml(ExtensionTabData tabData) {
|
||||
TabInformation tabInformation = tabData.getTabInformation();
|
||||
|
||||
ElementOrder[] order = tabInformation.getTabElementOrder().orElse(ElementOrder.values());
|
||||
String values = parseValuesHtml(tabData);
|
||||
String valuesHtml = values.isEmpty() ? "" : Html.BODY.parse(values);
|
||||
String tablesHtml = parseTablesHtml(tabData);
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
for (ElementOrder ordering : order) {
|
||||
switch (ordering) {
|
||||
case VALUES:
|
||||
builder.append(valuesHtml);
|
||||
break;
|
||||
case TABLE:
|
||||
builder.append(tablesHtml);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String parseTablesHtml(ExtensionTabData tabData) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (ExtensionTableData tableData : tabData.getTableData()) {
|
||||
if (tableData.isWideTable()) {
|
||||
hasWideTable = true;
|
||||
}
|
||||
builder.append(tableData.getHtmlTable().parseHtml());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String parseValuesHtml(ExtensionTabData tabData) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (String key : tabData.getValueOrder()) {
|
||||
tabData.getBoolean(key).ifPresent(data -> append(builder, data.getDescriptive(), data.getFormattedValue()));
|
||||
@ -153,7 +201,8 @@ public class AnalysisPluginTabs {
|
||||
}
|
||||
|
||||
private String wrapInContainer(ExtensionInformation information, String tabsElement) {
|
||||
return "<div class=\"col-xs-12 col-sm-12 col-md-4 col-lg-4\"><div class=\"card\">" +
|
||||
String colWidth = hasWideTable ? "col-md-8 col-lg-8" : "col-md-4 col-lg-4";
|
||||
return "<div class=\"col-xs-12 col-sm-12 " + colWidth + "\"><div class=\"card\">" +
|
||||
"<div class=\"header\">" +
|
||||
"<h2>" + Icon.fromExtensionIcon(information.getIcon()) + ' ' + information.getPluginName() + "</h2>" +
|
||||
"</div>" +
|
||||
|
@ -16,11 +16,13 @@
|
||||
*/
|
||||
package com.djrapitops.plan.utilities.html.pages;
|
||||
|
||||
import com.djrapitops.plan.extension.ElementOrder;
|
||||
import com.djrapitops.plan.extension.FormatType;
|
||||
import com.djrapitops.plan.extension.implementation.TabInformation;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionDescriptive;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionInformation;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionTabData;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionTableData;
|
||||
import com.djrapitops.plan.extension.implementation.results.player.ExtensionPlayerData;
|
||||
import com.djrapitops.plan.utilities.formatting.Formatter;
|
||||
import com.djrapitops.plan.utilities.formatting.Formatters;
|
||||
@ -48,6 +50,8 @@ public class InspectPluginTab implements Comparable<InspectPluginTab> {
|
||||
private String nav;
|
||||
private String tab;
|
||||
|
||||
private boolean hasWideTable;
|
||||
|
||||
public InspectPluginTab(String nav, String tab) {
|
||||
this.nav = nav;
|
||||
this.tab = tab;
|
||||
@ -70,6 +74,8 @@ public class InspectPluginTab implements Comparable<InspectPluginTab> {
|
||||
this.decimalFormatter = formatters.decimals();
|
||||
this.percentageFormatter = formatters.percentage();
|
||||
|
||||
hasWideTable = false;
|
||||
|
||||
generate();
|
||||
}
|
||||
|
||||
@ -106,7 +112,7 @@ public class InspectPluginTab implements Comparable<InspectPluginTab> {
|
||||
String tabsElement;
|
||||
if (onlyGeneric) {
|
||||
ExtensionTabData genericTabData = datum.getTabs().get(0);
|
||||
tabsElement = Html.BODY.parse(parseDataHtml(genericTabData));
|
||||
tabsElement = parseContentHtml(genericTabData);
|
||||
} else {
|
||||
tabsElement = new TabsElement(
|
||||
datum.getTabs().stream().map(this::wrapToTabElementTab).toArray(TabsElement.Tab[]::new)
|
||||
@ -125,11 +131,53 @@ public class InspectPluginTab implements Comparable<InspectPluginTab> {
|
||||
|
||||
private TabsElement.Tab wrapToTabElementTab(ExtensionTabData tabData) {
|
||||
TabInformation tabInformation = tabData.getTabInformation();
|
||||
String tabContentHtml = parseContentHtml(tabData);
|
||||
|
||||
return new TabsElement.Tab(tabInformation.getTabName(), parseDataHtml(tabData));
|
||||
String tabName = tabInformation.getTabName();
|
||||
return new TabsElement.Tab(tabName.isEmpty()
|
||||
? Icon.called("info-circle").build().toHtml() + " General"
|
||||
: Icon.fromExtensionIcon(tabInformation.getTabIcon()).toHtml() + ' ' + tabName,
|
||||
tabContentHtml);
|
||||
}
|
||||
|
||||
private String parseDataHtml(ExtensionTabData tabData) {
|
||||
private String parseContentHtml(ExtensionTabData tabData) {
|
||||
TabInformation tabInformation = tabData.getTabInformation();
|
||||
|
||||
ElementOrder[] order = tabInformation.getTabElementOrder().orElse(ElementOrder.values());
|
||||
String values = parseValuesHtml(tabData);
|
||||
String valuesHtml = values.isEmpty() ? "" : Html.BODY.parse(values);
|
||||
String tablesHtml = parseTablesHtml(tabData);
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
for (ElementOrder ordering : order) {
|
||||
switch (ordering) {
|
||||
case VALUES:
|
||||
builder.append(valuesHtml);
|
||||
break;
|
||||
case TABLE:
|
||||
builder.append(tablesHtml);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String parseTablesHtml(ExtensionTabData tabData) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (ExtensionTableData tableData : tabData.getTableData()) {
|
||||
if (tableData.isWideTable()) {
|
||||
hasWideTable = true;
|
||||
}
|
||||
builder.append(tableData.getHtmlTable().parseHtml());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String parseValuesHtml(ExtensionTabData tabData) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (String key : tabData.getValueOrder()) {
|
||||
tabData.getBoolean(key).ifPresent(data -> append(builder, data.getDescriptive(), data.getFormattedValue()));
|
||||
@ -153,7 +201,8 @@ public class InspectPluginTab implements Comparable<InspectPluginTab> {
|
||||
}
|
||||
|
||||
private String wrapInContainer(ExtensionInformation information, String tabsElement) {
|
||||
return "<div class=\"col-xs-12 col-sm-12 col-md-4 col-lg-4\"><div class=\"card\">" +
|
||||
String colWidth = hasWideTable ? "col-md-8 col-lg-8" : "col-md-4 col-lg-4";
|
||||
return "<div class=\"col-xs-12 col-sm-12 " + colWidth + "\"><div class=\"card\">" +
|
||||
"<div class=\"header\">" +
|
||||
"<h2>" + Icon.fromExtensionIcon(information.getIcon()) + ' ' + information.getPluginName() + "</h2>" +
|
||||
"</div>" +
|
||||
|
@ -18,6 +18,7 @@ package com.djrapitops.plan.db;
|
||||
|
||||
import com.djrapitops.plan.data.WebUser;
|
||||
import com.djrapitops.plan.data.container.*;
|
||||
import com.djrapitops.plan.data.element.TableContainer;
|
||||
import com.djrapitops.plan.data.store.Key;
|
||||
import com.djrapitops.plan.data.store.containers.AnalysisContainer;
|
||||
import com.djrapitops.plan.data.store.containers.NetworkContainer;
|
||||
@ -49,16 +50,21 @@ import com.djrapitops.plan.db.patches.Patch;
|
||||
import com.djrapitops.plan.db.tasks.DBCleanTask;
|
||||
import com.djrapitops.plan.extension.CallEvents;
|
||||
import com.djrapitops.plan.extension.DataExtension;
|
||||
import com.djrapitops.plan.extension.ExtensionService;
|
||||
import com.djrapitops.plan.extension.ExtensionServiceImplementation;
|
||||
import com.djrapitops.plan.extension.annotation.*;
|
||||
import com.djrapitops.plan.extension.icon.Color;
|
||||
import com.djrapitops.plan.extension.icon.Icon;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionBooleanData;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionStringData;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionTabData;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionTableData;
|
||||
import com.djrapitops.plan.extension.implementation.results.player.ExtensionPlayerData;
|
||||
import com.djrapitops.plan.extension.implementation.results.server.ExtensionServerData;
|
||||
import com.djrapitops.plan.extension.implementation.storage.queries.ExtensionPlayerDataQuery;
|
||||
import com.djrapitops.plan.extension.implementation.storage.queries.ExtensionServerDataQuery;
|
||||
import com.djrapitops.plan.extension.implementation.storage.transactions.results.RemoveUnsatisfiedConditionalResultsTransaction;
|
||||
import com.djrapitops.plan.extension.table.Table;
|
||||
import com.djrapitops.plan.system.PlanSystem;
|
||||
import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.info.server.Server;
|
||||
@ -160,9 +166,11 @@ public abstract class CommonDBTest {
|
||||
db.executeTransaction(new StoreServerInformationTransaction(new Server(-1, serverUUID, "ServerName", "", 20)));
|
||||
assertEquals(serverUUID, db.getServerUUIDSupplier().get());
|
||||
|
||||
system.getExtensionService().unregister(new PlayerExtension());
|
||||
system.getExtensionService().unregister(new ServerExtension());
|
||||
system.getExtensionService().unregister(new ConditionalExtension());
|
||||
ExtensionService extensionService = system.getExtensionService();
|
||||
extensionService.unregister(new PlayerExtension());
|
||||
extensionService.unregister(new ServerExtension());
|
||||
extensionService.unregister(new ConditionalExtension());
|
||||
extensionService.unregister(new TableExtension());
|
||||
}
|
||||
|
||||
private void execute(Executable executable) {
|
||||
@ -1155,7 +1163,7 @@ public abstract class CommonDBTest {
|
||||
ExtensionServiceImplementation extensionService = (ExtensionServiceImplementation) system.getExtensionService();
|
||||
|
||||
extensionService.register(new PlayerExtension());
|
||||
extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME, CallEvents.PLAYER_JOIN);
|
||||
extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME, CallEvents.MANUAL);
|
||||
|
||||
Map<UUID, List<ExtensionPlayerData>> playerDataByServerUUID = db.query(new ExtensionPlayerDataQuery(playerUUID));
|
||||
List<ExtensionPlayerData> ofServer = playerDataByServerUUID.get(serverUUID);
|
||||
@ -1201,7 +1209,7 @@ public abstract class CommonDBTest {
|
||||
ExtensionServiceImplementation extensionService = (ExtensionServiceImplementation) system.getExtensionService();
|
||||
|
||||
extensionService.register(new PlayerExtension());
|
||||
extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME, CallEvents.PLAYER_JOIN);
|
||||
extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME, CallEvents.MANUAL);
|
||||
|
||||
List<ExtensionServerData> ofServer = db.query(new ExtensionServerDataQuery(serverUUID));
|
||||
assertFalse(ofServer.isEmpty());
|
||||
@ -1228,14 +1236,14 @@ public abstract class CommonDBTest {
|
||||
extensionService.register(new ConditionalExtension());
|
||||
|
||||
ConditionalExtension.condition = true;
|
||||
extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME, CallEvents.PLAYER_JOIN);
|
||||
extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME, CallEvents.MANUAL);
|
||||
|
||||
// Check that the wanted data exists
|
||||
checkThatDataExists(ConditionalExtension.condition);
|
||||
|
||||
// Reverse condition
|
||||
ConditionalExtension.condition = false;
|
||||
extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME, CallEvents.PLAYER_JOIN);
|
||||
extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME, CallEvents.MANUAL);
|
||||
|
||||
db.executeTransaction(new RemoveUnsatisfiedConditionalResultsTransaction());
|
||||
|
||||
@ -1244,7 +1252,7 @@ public abstract class CommonDBTest {
|
||||
|
||||
// Reverse condition
|
||||
ConditionalExtension.condition = false;
|
||||
extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME, CallEvents.PLAYER_JOIN);
|
||||
extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME, CallEvents.MANUAL);
|
||||
|
||||
db.executeTransaction(new RemoveUnsatisfiedConditionalResultsTransaction());
|
||||
|
||||
@ -1273,6 +1281,70 @@ public abstract class CommonDBTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extensionServerTableValuesAreInserted() {
|
||||
ExtensionServiceImplementation extensionService = (ExtensionServiceImplementation) system.getExtensionService();
|
||||
|
||||
extensionService.register(new TableExtension());
|
||||
extensionService.updateServerValues(CallEvents.MANUAL);
|
||||
extensionService.updateServerValues(CallEvents.MANUAL);
|
||||
|
||||
List<ExtensionServerData> ofServer = db.query(new ExtensionServerDataQuery(serverUUID));
|
||||
assertFalse(ofServer.isEmpty());
|
||||
|
||||
ExtensionServerData extensionServerData = ofServer.get(0);
|
||||
List<ExtensionTabData> tabs = extensionServerData.getTabs();
|
||||
assertEquals(1, tabs.size()); // No tab defined, should contain 1 tab
|
||||
ExtensionTabData tabData = tabs.get(0);
|
||||
|
||||
List<ExtensionTableData> tableData = tabData.getTableData();
|
||||
assertEquals(1, tableData.size());
|
||||
ExtensionTableData table = tableData.get(0);
|
||||
|
||||
TableContainer expected = new TableContainer(
|
||||
"<i class=\" fa fa-gavel\"></i> first",
|
||||
"<i class=\" fa fa-what\"></i> second",
|
||||
"<i class=\" fa fa-question\"></i> third"
|
||||
);
|
||||
expected.setColor("amber");
|
||||
expected.addRow("value", 3, 0.5, 400L);
|
||||
|
||||
assertEquals(expected.parseHtml(), table.getHtmlTable().parseHtml());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extensionPlayerTableValuesAreInserted() {
|
||||
ExtensionServiceImplementation extensionService = (ExtensionServiceImplementation) system.getExtensionService();
|
||||
|
||||
extensionService.register(new TableExtension());
|
||||
extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME, CallEvents.MANUAL);
|
||||
extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME, CallEvents.MANUAL);
|
||||
|
||||
Map<UUID, List<ExtensionPlayerData>> ofPlayer = db.query(new ExtensionPlayerDataQuery(playerUUID));
|
||||
assertFalse(ofPlayer.isEmpty());
|
||||
|
||||
List<ExtensionPlayerData> ofServer = ofPlayer.get(serverUUID);
|
||||
assertEquals(1, ofServer.size());
|
||||
ExtensionPlayerData extensionServerData = ofServer.get(0);
|
||||
List<ExtensionTabData> tabs = extensionServerData.getTabs();
|
||||
assertEquals(1, tabs.size()); // No tab defined, should contain 1 tab
|
||||
ExtensionTabData tabData = tabs.get(0);
|
||||
|
||||
List<ExtensionTableData> tableData = tabData.getTableData();
|
||||
assertEquals(1, tableData.size());
|
||||
ExtensionTableData table = tableData.get(0);
|
||||
|
||||
TableContainer expected = new TableContainer(
|
||||
"<i class=\" fa fa-gavel\"></i> first",
|
||||
"<i class=\" fa fa-what\"></i> second",
|
||||
"<i class=\" fa fa-question\"></i> third"
|
||||
);
|
||||
expected.setColor("amber");
|
||||
expected.addRow("value", 3, 0.5, 400L);
|
||||
|
||||
assertEquals(expected.parseHtml(), table.getHtmlTable().parseHtml());
|
||||
}
|
||||
|
||||
@PluginInfo(name = "ConditionalExtension")
|
||||
public static class ConditionalExtension implements DataExtension {
|
||||
|
||||
@ -1356,4 +1428,27 @@ public abstract class CommonDBTest {
|
||||
return "Something";
|
||||
}
|
||||
}
|
||||
|
||||
@PluginInfo(name = "TableExtension")
|
||||
public class TableExtension implements DataExtension {
|
||||
@TableProvider(tableColor = Color.AMBER)
|
||||
public Table table() {
|
||||
return createTestTable();
|
||||
}
|
||||
|
||||
@TableProvider(tableColor = Color.AMBER)
|
||||
public Table playerTable(UUID playerUUID) {
|
||||
return createTestTable();
|
||||
}
|
||||
|
||||
private Table createTestTable() {
|
||||
return Table.builder()
|
||||
.columnOne("first", Icon.called("gavel").of(Color.AMBER).build())
|
||||
.columnTwo("second", Icon.called("what").of(Color.BROWN).build()) // Colors are ignored
|
||||
.columnThree("third", null) // Can handle improper icons
|
||||
.columnFive("five", Icon.called("").build()) // Can handle null column in between and ignore the next column
|
||||
.addRow("value", 3, 0.5, 400L) // Can handle too many row values
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user