Component DataExtension API (#2686)

* Component DataExtension API

* Finish up component extension data, add react-mcjsonchat library to the react dashboard in preparation for the rewrite

* Update Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/results/ExtensionComponentData.java

* Update Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ExtensionsDatabaseTest.java

* Update Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/DataValueGatherer.java

Co-authored-by: Aurora Lahtela <24460436+AuroraLS3@users.noreply.github.com>
This commit is contained in:
Henri Schubin 2022-10-29 08:23:16 +03:00 committed by GitHub
parent 4ecf0c2b64
commit 96a14a24f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 562 additions and 39 deletions

View File

@ -0,0 +1,109 @@
/*
* 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.FormatType;
import com.djrapitops.plan.extension.icon.Color;
import com.djrapitops.plan.extension.icon.Family;
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 Minecraft text {@link com.djrapitops.plan.component.Component} value.
* <p>
* Usage: {@code @ComponentProvider Component method(UUID playerUUID)}
*
* @author Vankka
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ComponentProvider {
/**
* Text displayed before the value, limited to 50 characters.
* <p>
* Should inform the user what the value represents, for example
* "Owned Chickens", "Claimed Blocks"
*
* @return String of max 50 characters, remainder will be clipped.
*/
String text();
/**
* Display-priority of the value, highest value is placed top most.
* <p>
* Two values with same priority may appear in a random order.
*
* @return Priority between 0 and {@code Integer.MAX_VALUE}.
*/
int priority() default 0;
/**
* Text displayed when hovering over the value, limited to 150 characters.
* <p>
* Should be used to clarify what the value is if not self evident, for example
* text: "Fished", description: "How long the player has fished for"
*
* @return String of max 150 characters, remainder will be clipped.
*/
String description() default "";
/**
* Apply special formatting to the value before presentation.
*
* @return {@link FormatType} that best represents the long value.
* @see FormatType for available formatters.
*/
FormatType format() default FormatType.NONE;
/**
* Name of Font Awesome icon.
* <p>
* See https://fontawesome.com/icons (select 'free')) for icons and their {@link Family}.
*
* @return Name of the icon, if name is not valid no icon is shown.
*/
String iconName() default "question";
/**
* Family of Font Awesome icon.
* <p>
* See https://fontawesome.com/icons (select 'free')) for icons and their {@link Family}.
*
* @return Family that matches an icon, if there is no icon for this family no icon is shown.
*/
Family iconFamily() default Family.SOLID;
/**
* Color preference of the plugin.
* <p>
* This color will be set as the default color to use for plugin's elements.
*
* @return Preferred color. If none are specified defaults are used.
*/
Color iconColor() default Color.NONE;
/**
* When the parameter is set to {@code true} the value from this Provider is shown on a table alongside players.
*
* @return false by default.
*/
boolean showInPlayerTable() default false;
}

View File

@ -16,11 +16,9 @@
*/
package com.djrapitops.plan.extension.builder;
import com.djrapitops.plan.component.Component;
import com.djrapitops.plan.extension.FormatType;
import com.djrapitops.plan.extension.annotation.BooleanProvider;
import com.djrapitops.plan.extension.annotation.Conditional;
import com.djrapitops.plan.extension.annotation.StringProvider;
import com.djrapitops.plan.extension.annotation.Tab;
import com.djrapitops.plan.extension.annotation.*;
import com.djrapitops.plan.extension.extractor.ExtensionMethod;
import com.djrapitops.plan.extension.icon.Color;
import com.djrapitops.plan.extension.icon.Family;
@ -162,6 +160,14 @@ public interface ValueBuilder {
*/
DataValue<String> buildString(String value);
/**
* Build a {@link Component}.
*
* @param value a {@link Component} made by {@link com.djrapitops.plan.component.ComponentService}
* @return a data value to give to {@link ExtensionDataBuilder}.
*/
DataValue<Component> buildComponent(Component value);
/**
* Build a Number.
*
@ -244,6 +250,13 @@ public interface ValueBuilder {
*/
DataValue<String> buildString(Supplier<String> value);
/**
* Lambda version for conditional return or throwing {@link com.djrapitops.plan.extension.NotReadyException}.
* <p>
* {@link ValueBuilder#buildComponent(Component)}
*/
DataValue<Component> buildComponent(Supplier<Component> value);
/**
* Lambda version for conditional return or throwing {@link com.djrapitops.plan.extension.NotReadyException}.
* <p>

View File

@ -16,6 +16,7 @@
*/
package com.djrapitops.plan.extension.extractor;
import com.djrapitops.plan.component.Component;
import com.djrapitops.plan.extension.DataExtension;
import com.djrapitops.plan.extension.Group;
import com.djrapitops.plan.extension.annotation.*;
@ -145,6 +146,10 @@ public final class ExtensionExtractor {
validateMethod(method, annotation);
methods.get(method.getParameterType()).addStringMethod(method);
});
method.getAnnotation(ComponentProvider.class).ifPresent(annotation -> {
validateMethod(method, annotation);
methods.get(method.getParameterType()).addComponentMethod(method);
});
method.getAnnotation(TableProvider.class).ifPresent(annotation -> {
validateMethod(method, annotation);
methods.get(method.getParameterType()).addTableMethod(method);
@ -279,6 +284,15 @@ public final class ExtensionExtractor {
validateMethodArguments(method, false, UUID.class, String.class, Group.class);
}
private void validateMethod(ExtensionMethod extensionMethod, ComponentProvider annotation) {
Method method = extensionMethod.getMethod();
validateReturnType(method, Component.class);
validateMethodAnnotationPropertyLength(annotation.text(), "text", 50, method);
validateMethodAnnotationPropertyLength(annotation.description(), "description", 150, method);
validateMethodArguments(method, false, UUID.class, String.class, Group.class);
}
private void validateMethod(ExtensionMethod extensionMethod, TableProvider annotation) {
Method method = extensionMethod.getMethod();
@ -306,8 +320,8 @@ public final class ExtensionExtractor {
for (Method conditionalMethod : conditionalMethods) {
if (!hasAnyOf(conditionalMethod,
BooleanProvider.class, DoubleProvider.class, NumberProvider.class,
PercentageProvider.class, StringProvider.class, TableProvider.class,
GroupProvider.class, DataBuilderProvider.class
PercentageProvider.class, StringProvider.class, ComponentProvider.class,
TableProvider.class, GroupProvider.class, DataBuilderProvider.class
)) {
throw new IllegalArgumentException(extensionName + "." + conditionalMethod.getName() + " did not have any associated Provider for Conditional.");
}

View File

@ -30,6 +30,7 @@ public class ExtensionMethods {
private final List<ExtensionMethod> doubleProviders;
private final List<ExtensionMethod> percentageProviders;
private final List<ExtensionMethod> stringProviders;
private final List<ExtensionMethod> componentProviders;
private final List<ExtensionMethod> tableProviders;
private final List<ExtensionMethod> groupProviders;
private final List<ExtensionMethod> dataBuilderProviders;
@ -40,6 +41,7 @@ public class ExtensionMethods {
doubleProviders = new ArrayList<>();
percentageProviders = new ArrayList<>();
stringProviders = new ArrayList<>();
componentProviders = new ArrayList<>();
tableProviders = new ArrayList<>();
groupProviders = new ArrayList<>();
dataBuilderProviders = new ArrayList<>();
@ -65,6 +67,10 @@ public class ExtensionMethods {
return stringProviders;
}
public List<ExtensionMethod> getComponentProviders() {
return componentProviders;
}
public List<ExtensionMethod> getTableProviders() {
return tableProviders;
}
@ -97,6 +103,10 @@ public class ExtensionMethods {
stringProviders.add(method);
}
public void addComponentMethod(ExtensionMethod method) {
componentProviders.add(method);
}
public void addTableMethod(ExtensionMethod method) {
tableProviders.add(method);
}
@ -119,6 +129,7 @@ public class ExtensionMethods {
&& Objects.equals(doubleProviders, that.doubleProviders)
&& Objects.equals(percentageProviders, that.percentageProviders)
&& Objects.equals(stringProviders, that.stringProviders)
&& Objects.equals(componentProviders, that.componentProviders)
&& Objects.equals(tableProviders, that.tableProviders)
&& Objects.equals(groupProviders, that.groupProviders)
&& Objects.equals(dataBuilderProviders, that.dataBuilderProviders);
@ -126,7 +137,7 @@ public class ExtensionMethods {
@Override
public int hashCode() {
return Objects.hash(booleanProviders, numberProviders, doubleProviders, percentageProviders, stringProviders, tableProviders, groupProviders, dataBuilderProviders);
return Objects.hash(booleanProviders, numberProviders, doubleProviders, percentageProviders, stringProviders, componentProviders, tableProviders, groupProviders, dataBuilderProviders);
}
@Override
@ -137,6 +148,7 @@ public class ExtensionMethods {
", doubleProviders=" + doubleProviders +
", percentageProviders=" + percentageProviders +
", stringProviders=" + stringProviders +
", componentProviders=" + componentProviders +
", tableProviders=" + tableProviders +
", groupProviders=" + groupProviders +
", dataBuilderProviders=" + dataBuilderProviders +
@ -149,6 +161,7 @@ public class ExtensionMethods {
&& doubleProviders.isEmpty()
&& percentageProviders.isEmpty()
&& stringProviders.isEmpty()
&& componentProviders.isEmpty()
&& tableProviders.isEmpty()
&& groupProviders.isEmpty()
&& dataBuilderProviders.isEmpty();

View File

@ -16,6 +16,7 @@
*/
package com.djrapitops.plan.extension.extractor;
import com.djrapitops.plan.component.Component;
import com.djrapitops.plan.extension.DataExtension;
import com.djrapitops.plan.extension.Group;
import com.djrapitops.plan.extension.annotation.*;
@ -456,6 +457,24 @@ class ExtensionExtractorTest {
assertEquals(expected, result);
}
@Test
void methodsAreExtracted9() throws NoSuchMethodException {
@PluginInfo(name = "Extension")
class Extension implements DataExtension {
@Conditional("hasJoined")
@ComponentProvider(text = "Test")
public Component method() {
return null;
}
}
Extension extension = new Extension();
ExtensionExtractor underTest = new ExtensionExtractor(extension);
Map<ExtensionMethod.ParameterType, ExtensionMethods> result = underTest.getMethods();
Map<ExtensionMethod.ParameterType, ExtensionMethods> expected = buildExpectedExtensionMethodMap(extension, ExtensionMethods::addComponentMethod);
assertEquals(expected, result);
}
@Test
void tabsAreExtracted() throws NoSuchMethodException {
@PluginInfo(name = "Extension")

View File

@ -328,6 +328,10 @@ public class PlanSystem implements SubSystem {
return extensionService;
}
public ComponentSvc getComponentService() {
return componentService;
}
public static long getServerEnableTime() {
return SERVER_ENABLE_TIME;
}

View File

@ -54,6 +54,7 @@ public class ExtensionTabDataDto {
tabData.getPercentage(key).ifPresent(data -> extensionValues.add(new ExtensionValueDataDto(data.getDescription(), "PERCENTAGE", data.getFormattedValue(percentageFormatter))));
tabData.getNumber(key).ifPresent(data -> extensionValues.add(new ExtensionValueDataDto(data.getDescription(), data.getFormatType() == FormatType.NONE ? "NUMBER" : data.getFormatType().name(), data.getFormattedValue(numberFormatters.get(data.getFormatType())))));
tabData.getString(key).ifPresent(data -> extensionValues.add(new ExtensionValueDataDto(data.getDescription(), data.isPlayerName() ? "HTML" : "STRING", data.getFormattedValue())));
tabData.getComponent(key).ifPresent(data -> extensionValues.add(new ExtensionValueDataDto(data.getDescription(), "COMPONENT", data.getFormattedValue())));
}
return extensionValues;
}

View File

@ -16,6 +16,7 @@
*/
package com.djrapitops.plan.delivery.rendering.pages;
import com.djrapitops.plan.component.ComponentSvc;
import com.djrapitops.plan.delivery.domain.container.CachingSupplier;
import com.djrapitops.plan.delivery.formatting.Formatters;
import com.djrapitops.plan.delivery.formatting.PlaceholderReplacer;
@ -56,6 +57,7 @@ public class NetworkPage implements Page {
private final JSONStorage jsonStorage;
private final Formatters formatters;
private final Locale locale;
private final ComponentSvc componentSvc;
NetworkPage(
String templateHtml,
@ -66,7 +68,8 @@ public class NetworkPage implements Page {
ServerInfo serverInfo,
JSONStorage jsonStorage,
Formatters formatters,
Locale locale
Locale locale,
ComponentSvc componentSvc
) {
this.templateHtml = templateHtml;
this.dbSystem = dbSystem;
@ -77,6 +80,7 @@ public class NetworkPage implements Page {
this.jsonStorage = jsonStorage;
this.formatters = formatters;
this.locale = locale;
this.componentSvc = componentSvc;
}
@Override
@ -105,7 +109,7 @@ public class NetworkPage implements Page {
CachingSupplier<ServerPluginTabs> pluginTabs = new CachingSupplier<>(() -> {
List<ExtensionData> extensionData = dbSystem.getDatabase().query(new ExtensionServerDataQuery(serverUUID));
return new ServerPluginTabs(extensionData, formatters);
return new ServerPluginTabs(extensionData, formatters, componentSvc);
});
long after = System.currentTimeMillis() - config.get(WebserverSettings.REDUCED_REFRESH_BARRIER);

View File

@ -16,6 +16,7 @@
*/
package com.djrapitops.plan.delivery.rendering.pages;
import com.djrapitops.plan.component.ComponentSvc;
import com.djrapitops.plan.delivery.domain.container.PlayerContainer;
import com.djrapitops.plan.delivery.formatting.Formatters;
import com.djrapitops.plan.delivery.rendering.html.icon.Icon;
@ -62,6 +63,7 @@ public class PageFactory {
private final Lazy<JSONStorage> jsonStorage;
private final Lazy<Formatters> formatters;
private final Lazy<Locale> locale;
private final Lazy<ComponentSvc> componentService;
@Inject
public PageFactory(
@ -73,7 +75,8 @@ public class PageFactory {
Lazy<ServerInfo> serverInfo,
Lazy<JSONStorage> jsonStorage,
Lazy<Formatters> formatters,
Lazy<Locale> locale
Lazy<Locale> locale,
Lazy<ComponentSvc> componentService
) {
this.versionChecker = versionChecker;
this.files = files;
@ -84,6 +87,7 @@ public class PageFactory {
this.jsonStorage = jsonStorage;
this.formatters = formatters;
this.locale = locale;
this.componentService = componentService;
}
public Page playersPage() throws IOException {
@ -123,7 +127,8 @@ public class PageFactory {
serverInfo.get(),
jsonStorage.get(),
formatters.get(),
locale.get()
locale.get(),
componentService.get()
);
}
@ -154,7 +159,7 @@ public class PageFactory {
Map<ServerUUID, List<ExtensionData>> extensionPlayerData = database.query(new ExtensionPlayerDataQuery(playerUUID));
if (extensionPlayerData.isEmpty()) {
return new PlayerPluginTab("", Collections.emptyList(), formatters.get());
return new PlayerPluginTab("", Collections.emptyList(), formatters.get(), componentService.get());
}
List<PlayerPluginTab> playerPluginTabs = new ArrayList<>();
@ -167,7 +172,7 @@ public class PageFactory {
continue;
}
playerPluginTabs.add(new PlayerPluginTab(serverName, ofServer, formatters.get()));
playerPluginTabs.add(new PlayerPluginTab(serverName, ofServer, formatters.get(), componentService.get()));
}
StringBuilder navs = new StringBuilder();
@ -178,7 +183,7 @@ public class PageFactory {
tabs.append(tab.getTab());
});
return new PlayerPluginTab(navs.toString(), tabs.toString());
return new PlayerPluginTab(navs.toString(), tabs.toString(), componentService.get());
}
public Page networkPage() throws IOException {
@ -195,7 +200,8 @@ public class PageFactory {
serverInfo.get(),
jsonStorage.get(),
formatters.get(),
locale.get()
locale.get(),
componentService.get()
);
}

View File

@ -16,6 +16,7 @@
*/
package com.djrapitops.plan.delivery.rendering.pages;
import com.djrapitops.plan.component.ComponentSvc;
import com.djrapitops.plan.delivery.formatting.Formatter;
import com.djrapitops.plan.delivery.formatting.Formatters;
import com.djrapitops.plan.delivery.rendering.html.icon.Icon;
@ -47,19 +48,23 @@ public class PlayerPluginTab implements Comparable<PlayerPluginTab> {
private String tab;
private boolean hasWideTable;
private final ComponentSvc componentSvc;
public PlayerPluginTab(String nav, String tab) {
public PlayerPluginTab(String nav, String tab, ComponentSvc componentSvc) {
this.nav = nav;
this.tab = tab;
this.componentSvc = componentSvc;
}
public PlayerPluginTab(
String serverName,
List<ExtensionData> playerData,
Formatters formatters
Formatters formatters,
ComponentSvc componentSvc
) {
this.serverName = serverName;
this.playerData = playerData;
this.componentSvc = componentSvc;
numberFormatters = new EnumMap<>(FormatType.class);
numberFormatters.put(FormatType.DATE_SECOND, formatters.secondLong());
@ -197,6 +202,7 @@ public class PlayerPluginTab implements Comparable<PlayerPluginTab> {
tabData.getPercentage(key).ifPresent(data -> append(builder, data.getDescription(), data.getFormattedValue(percentageFormatter)));
tabData.getNumber(key).ifPresent(data -> append(builder, data.getDescription(), data.getFormattedValue(numberFormatters.get(data.getFormatType()))));
tabData.getString(key).ifPresent(data -> append(builder, data.getDescription(), data.getFormattedValue()));
tabData.getComponent(key).ifPresent(data -> append(builder, data.getDescription(), data.getHtmlValue(componentSvc)));
}
return builder.toString();
}

View File

@ -16,6 +16,7 @@
*/
package com.djrapitops.plan.delivery.rendering.pages;
import com.djrapitops.plan.component.ComponentSvc;
import com.djrapitops.plan.delivery.domain.container.CachingSupplier;
import com.djrapitops.plan.delivery.formatting.Formatters;
import com.djrapitops.plan.delivery.formatting.PlaceholderReplacer;
@ -56,6 +57,7 @@ public class ServerPage implements Page {
private final JSONStorage jsonStorage;
private final Formatters formatters;
private final Locale locale;
private final ComponentSvc componentSvc;
ServerPage(
String templateHtml, Server server,
@ -66,7 +68,8 @@ public class ServerPage implements Page {
ServerInfo serverInfo,
JSONStorage jsonStorage,
Formatters formatters,
Locale locale
Locale locale,
ComponentSvc componentSvc
) {
this.templateHtml = templateHtml;
this.server = server;
@ -78,6 +81,7 @@ public class ServerPage implements Page {
this.jsonStorage = jsonStorage;
this.formatters = formatters;
this.locale = locale;
this.componentSvc = componentSvc;
}
@Override
@ -100,7 +104,7 @@ public class ServerPage implements Page {
CachingSupplier<ServerPluginTabs> pluginTabs = new CachingSupplier<>(() -> {
List<ExtensionData> extensionData = dbSystem.getDatabase().query(new ExtensionServerDataQuery(serverUUID));
return new ServerPluginTabs(extensionData, formatters);
return new ServerPluginTabs(extensionData, formatters, componentSvc);
});
long after = System.currentTimeMillis() - config.get(WebserverSettings.REDUCED_REFRESH_BARRIER);

View File

@ -16,6 +16,7 @@
*/
package com.djrapitops.plan.delivery.rendering.pages;
import com.djrapitops.plan.component.ComponentSvc;
import com.djrapitops.plan.delivery.formatting.Formatter;
import com.djrapitops.plan.delivery.formatting.Formatters;
import com.djrapitops.plan.delivery.rendering.html.icon.Icon;
@ -49,20 +50,24 @@ public class ServerPluginTabs {
private StringBuilder nav;
private String tab;
private final ComponentSvc componentSvc;
public ServerPluginTabs(String nav, String tab) {
public ServerPluginTabs(String nav, String tab, ComponentSvc componentSvc) {
this.nav = new StringBuilder(nav);
this.tab = tab;
this.componentSvc = componentSvc;
}
public ServerPluginTabs(
List<ExtensionData> serverData,
Formatters formatters
Formatters formatters,
ComponentSvc componentSvc
) {
this.serverData = serverData;
Collections.sort(serverData);
this.extraTabServerData = Lists.filter(serverData, ExtensionData::doesNeedWiderSpace);
this.serverData.removeAll(extraTabServerData);
this.componentSvc = componentSvc;
numberFormatters = new EnumMap<>(FormatType.class);
numberFormatters.put(FormatType.DATE_SECOND, formatters.secondLong());
@ -220,6 +225,7 @@ public class ServerPluginTabs {
tabData.getPercentage(key).ifPresent(data -> append(builder, data.getDescription(), data.getFormattedValue(percentageFormatter)));
tabData.getNumber(key).ifPresent(data -> append(builder, data.getDescription(), data.getFormattedValue(numberFormatters.get(data.getFormatType()))));
tabData.getString(key).ifPresent(data -> append(builder, data.getDescription(), data.getFormattedValue()));
tabData.getComponent(key).ifPresent(data -> append(builder, data.getDescription(), data.getHtmlValue(componentSvc)));
}
return builder.toString();
}

View File

@ -16,6 +16,7 @@
*/
package com.djrapitops.plan.extension;
import com.djrapitops.plan.component.ComponentSvc;
import com.djrapitops.plan.extension.builder.ExtensionDataBuilder;
import com.djrapitops.plan.extension.implementation.CallerImplementation;
import com.djrapitops.plan.extension.implementation.ExtensionRegister;
@ -51,6 +52,7 @@ public class ExtensionSvc implements ExtensionService {
private final PlanConfig config;
private final DBSystem dbSystem;
private final ComponentSvc componentService;
private final ServerInfo serverInfo;
private final Processing processing;
private final ExtensionRegister extensionRegister;
@ -65,6 +67,7 @@ public class ExtensionSvc implements ExtensionService {
public ExtensionSvc(
PlanConfig config,
DBSystem dbSystem,
ComponentSvc componentService,
ServerInfo serverInfo,
Processing processing,
ExtensionRegister extensionRegister,
@ -74,6 +77,7 @@ public class ExtensionSvc implements ExtensionService {
) {
this.config = config;
this.dbSystem = dbSystem;
this.componentService = componentService;
this.serverInfo = serverInfo;
this.processing = processing;
this.extensionRegister = extensionRegister;
@ -116,7 +120,7 @@ public class ExtensionSvc implements ExtensionService {
logger.warn("DataExtension API implementation mistake for " + pluginName + ": " + warning);
}
DataValueGatherer gatherer = new DataValueGatherer(extension, dbSystem, serverInfo, errorLogger);
DataValueGatherer gatherer = new DataValueGatherer(extension, dbSystem, componentService, serverInfo, errorLogger);
gatherer.storeExtensionInformation();
extensionGatherers.put(pluginName, gatherer);

View File

@ -43,6 +43,7 @@ public class ProviderInformation extends ExtensionDescription {
private final boolean isPlayerName; // default false, StringProvider
private final Color tableColor; // can be null, TableProvider
private final boolean percentage; // affects where doubles are stored
private final boolean component; // affects where strings are stored
private ProviderInformation(ProviderInformation.Builder builder) {
super(
@ -62,6 +63,7 @@ public class ProviderInformation extends ExtensionDescription {
isPlayerName = builder.isPlayerName;
tableColor = builder.tableColor;
percentage = builder.percentage;
component = builder.component;
}
public static ProviderInformation.Builder builder(String pluginName) {
@ -136,6 +138,10 @@ public class ProviderInformation extends ExtensionDescription {
return percentage;
}
public boolean isComponent() {
return component;
}
public static class Builder {
private final String pluginName;
private String name;
@ -152,6 +158,7 @@ public class ProviderInformation extends ExtensionDescription {
private boolean isPlayerName = false; // default false, StringProvider
private Color tableColor; // can be null, TableProvider
private boolean percentage; // affects where doubles are stored
private boolean component; // affects where strings are stored
public Builder(String pluginName) {
this.pluginName = pluginName;
@ -227,6 +234,11 @@ public class ProviderInformation extends ExtensionDescription {
return this;
}
public Builder setAsComponent() {
component = true;
return this;
}
public ProviderInformation build() {
return new ProviderInformation(this);
}

View File

@ -0,0 +1,34 @@
/*
* 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.builder;
import com.djrapitops.plan.component.Component;
import com.djrapitops.plan.extension.implementation.ProviderInformation;
import java.util.function.Supplier;
public class ComponentDataValue extends BuiltDataValue<Component> {
public static final int MAX_LENGTH = 500;
public ComponentDataValue(Component value, ProviderInformation information) {
super(value, information);
}
public ComponentDataValue(Supplier<Component> supplier, ProviderInformation information) {
super(supplier, information);
}
}

View File

@ -16,6 +16,7 @@
*/
package com.djrapitops.plan.extension.implementation.builder;
import com.djrapitops.plan.component.Component;
import com.djrapitops.plan.extension.DataExtension;
import com.djrapitops.plan.extension.FormatType;
import com.djrapitops.plan.extension.annotation.BooleanProvider;
@ -117,18 +118,22 @@ public class ExtValueBuilder implements ValueBuilder {
}
private ProviderInformation getProviderInformation() {
return getProviderInformation(false, null);
return getProviderInformation(false, false, null);
}
private ProviderInformation getBooleanProviderInformation(String providedCondition) {
return getProviderInformation(false, providedCondition);
return getProviderInformation(false, false, providedCondition);
}
private ProviderInformation getComponentProviderInformation() {
return getProviderInformation(false, true, null);
}
private ProviderInformation getPercentageProviderInformation() {
return getProviderInformation(true, null);
return getProviderInformation(true, false, null);
}
private ProviderInformation getProviderInformation(boolean percentage, String providedCondition) {
private ProviderInformation getProviderInformation(boolean percentage, boolean component, String providedCondition) {
ProviderInformation.Builder builder = ProviderInformation.builder(pluginName)
.setName(providerName != null ? providerName
: formatTextAsIdentifier(text))
@ -147,6 +152,10 @@ public class ExtValueBuilder implements ValueBuilder {
builder = builder.setAsPercentage();
}
if (component) {
builder = builder.setAsComponent();
}
if (providedCondition != null && !providedCondition.isEmpty()) {
builder = builder.setProvidedCondition(providedCondition);
}
@ -180,6 +189,11 @@ public class ExtValueBuilder implements ValueBuilder {
return new StringDataValue(value, getProviderInformation());
}
@Override
public DataValue<Component> buildComponent(Component value) {
return new ComponentDataValue(value, getComponentProviderInformation());
}
@Override
public DataValue<Long> buildNumber(Long value) {
return new NumberDataValue(value, getProviderInformation());
@ -215,6 +229,11 @@ public class ExtValueBuilder implements ValueBuilder {
return new StringDataValue(value, getProviderInformation());
}
@Override
public DataValue<Component> buildComponent(Supplier<Component> value) {
return new ComponentDataValue(value, getComponentProviderInformation());
}
@Override
public DataValue<Long> buildNumber(Supplier<Long> value) {
return new NumberDataValue(value, getProviderInformation());

View File

@ -21,6 +21,8 @@ import com.djrapitops.plan.extension.implementation.ProviderInformation;
import java.util.function.Supplier;
public class StringDataValue extends BuiltDataValue<String> {
public static final int MAX_LENGTH = 50;
public StringDataValue(String value, ProviderInformation information) {
super(value, information);
}

View File

@ -16,6 +16,9 @@
*/
package com.djrapitops.plan.extension.implementation.providers.gathering;
import com.djrapitops.plan.component.Component;
import com.djrapitops.plan.component.ComponentOperation;
import com.djrapitops.plan.component.ComponentSvc;
import com.djrapitops.plan.exceptions.DataExtensionMethodCallException;
import com.djrapitops.plan.extension.CallEvents;
import com.djrapitops.plan.extension.annotation.*;
@ -61,6 +64,7 @@ public class DataValueGatherer {
private final CallEvents[] callEvents;
private final ExtensionWrapper extension;
private final DBSystem dbSystem;
private final ComponentSvc componentService;
private final ServerInfo serverInfo;
private final ErrorLogger errorLogger;
@ -69,12 +73,14 @@ public class DataValueGatherer {
public DataValueGatherer(
ExtensionWrapper extension,
DBSystem dbSystem,
ComponentSvc componentService,
ServerInfo serverInfo,
ErrorLogger errorLogger
) {
this.callEvents = extension.getCallEvents();
this.extension = extension;
this.dbSystem = dbSystem;
this.componentService = componentService;
this.serverInfo = serverInfo;
this.errorLogger = errorLogger;
@ -136,6 +142,10 @@ public class DataValueGatherer {
if (brokenMethods.contains(provider)) continue;
dataBuilder.addValue(String.class, tryToBuildString(dataBuilder, parameters, provider));
}
for (ExtensionMethod provider : methods.getComponentProviders()) {
if (brokenMethods.contains(provider)) continue;
dataBuilder.addValue(Component.class, tryToBuildComponent(dataBuilder, parameters, provider));
}
for (ExtensionMethod provider : methods.getGroupProviders()) {
if (brokenMethods.contains(provider)) continue;
dataBuilder.addValue(String[].class, tryToBuildGroups(dataBuilder, parameters, provider));
@ -144,6 +154,11 @@ public class DataValueGatherer {
if (brokenMethods.contains(provider)) continue;
dataBuilder.addValue(Table.class, tryToBuildTable(dataBuilder, parameters, provider));
}
addValuesToBuilder2(dataBuilder, methods, parameters);
}
// TODO refactor to reduce cyclomatic complexity of the calling method
private void addValuesToBuilder2(ExtensionDataBuilder dataBuilder, ExtensionMethods methods, Parameters parameters) {
for (ExtensionMethod provider : methods.getDataBuilderProviders()) {
if (brokenMethods.contains(provider)) continue;
addDataFromAnotherBuilder(dataBuilder, parameters, provider);
@ -198,6 +213,24 @@ public class DataValueGatherer {
}
}
private DataValue<Component> tryToBuildComponent(ExtensionDataBuilder dataBuilder, Parameters parameters, ExtensionMethod provider) {
ComponentProvider annotation = provider.getExistingAnnotation(ComponentProvider.class);
try {
return dataBuilder.valueBuilder(annotation.text())
.methodName(provider)
.icon(annotation.iconName(), annotation.iconFamily(), annotation.iconColor())
.description(annotation.description())
.priority(annotation.priority())
.showInPlayerTable(annotation.showInPlayerTable())
.conditional(provider.getAnnotationOrNull(Conditional.class))
.showOnTab(provider.getAnnotationOrNull(Tab.class))
.buildComponent(() -> callMethod(provider, parameters, Component.class));
} catch (IllegalArgumentException e) {
logFailure(e, getPluginName(), provider.getMethodName());
return null;
}
}
private DataValue<Long> tryToBuildNumber(ExtensionDataBuilder dataBuilder, Parameters parameters, ExtensionMethod provider) {
NumberProvider annotation = provider.getExistingAnnotation(NumberProvider.class);
try {
@ -343,6 +376,8 @@ public class DataValueGatherer {
.ifPresent(data -> storePlayerDouble(parameters, conditions, data));
pair.getValue(String.class).flatMap(data -> data.getMetadata(StringDataValue.class))
.ifPresent(data -> storePlayerString(parameters, conditions, data));
pair.getValue(Component.class).flatMap(data -> data.getMetadata(ComponentDataValue.class))
.ifPresent(data -> storePlayerComponent(parameters, conditions, data));
pair.getValue(String[].class).flatMap(data -> data.getMetadata(GroupsDataValue.class))
.ifPresent(data -> storePlayerGroups(parameters, conditions, data));
pair.getValue(Table.class).flatMap(data -> data.getMetadata(TableDataValue.class))
@ -367,6 +402,8 @@ public class DataValueGatherer {
.ifPresent(data -> storeDouble(parameters, conditions, data));
pair.getValue(String.class).flatMap(data -> data.getMetadata(StringDataValue.class))
.ifPresent(data -> storeString(parameters, conditions, data));
pair.getValue(Component.class).flatMap(data -> data.getMetadata(ComponentDataValue.class))
.ifPresent(data -> storeComponent(parameters, conditions, data));
pair.getValue(Table.class).flatMap(data -> data.getMetadata(TableDataValue.class))
.ifPresent(data -> storeTable(parameters, conditions, data));
} catch (DataExtensionMethodCallException methodError) {
@ -412,6 +449,16 @@ public class DataValueGatherer {
return data.getValue(); // can be null, can throw
}
private String getComponentAsJson(Component component) {
if (component == null) return null;
String json = componentService.convert(component, ComponentOperation.JSON);
if (json.length() > ComponentDataValue.MAX_LENGTH) {
json = "{\"text\":\"<Component too long>\"}";
}
return json;
}
private void storeBoolean(Parameters parameters, Conditions conditions, BooleanDataValue data) {
ProviderInformation information = data.getInformation();
Boolean value = getValue(conditions, data, information);
@ -462,6 +509,17 @@ public class DataValueGatherer {
db.executeTransaction(new StoreServerStringResultTransaction(information, parameters, value));
}
private void storeComponent(Parameters parameters, Conditions conditions, ComponentDataValue data) {
ProviderInformation information = data.getInformation();
String value = getComponentAsJson(getValue(conditions, data, information));
if (value == null) return;
Database db = dbSystem.getDatabase();
db.executeTransaction(new StoreIconTransaction(information.getIcon()));
db.executeTransaction(new StoreProviderTransaction(information, parameters));
db.executeTransaction(new StoreServerStringResultTransaction(information, parameters, value));
}
private void storeTable(Parameters parameters, Conditions conditions, TableDataValue data) {
ProviderInformation information = data.getInformation();
Table value = getValue(conditions, data, information);
@ -524,6 +582,17 @@ public class DataValueGatherer {
db.executeTransaction(new StorePlayerStringResultTransaction(information, parameters, value));
}
private void storePlayerComponent(Parameters parameters, Conditions conditions, ComponentDataValue data) {
ProviderInformation information = data.getInformation();
String value = getComponentAsJson(getValue(conditions, data, information)) ;
if (value == null) return;
Database db = dbSystem.getDatabase();
db.executeTransaction(new StoreIconTransaction(information.getIcon()));
db.executeTransaction(new StoreProviderTransaction(information, parameters));
db.executeTransaction(new StorePlayerStringResultTransaction(information, parameters, value));
}
private void storePlayerGroups(Parameters parameters, Conditions conditions, GroupsDataValue data) {
ProviderInformation information = data.getInformation();
String[] value = getValue(conditions, data, information);

View File

@ -0,0 +1,51 @@
/*
* 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.component.Component;
import com.djrapitops.plan.component.ComponentOperation;
import com.djrapitops.plan.component.ComponentSvc;
import com.djrapitops.plan.delivery.rendering.html.Html;
/**
* Represents component data returned by a ComponentProvider method.
*
* @author AuroraLS3
*/
public class ExtensionComponentData implements DescribedExtensionData {
private final ExtensionDescription description;
private final String value;
public ExtensionComponentData(ExtensionDescription description, String value) {
this.description = description;
this.value = value;
}
public ExtensionDescription getDescription() {
return description;
}
public String getFormattedValue() {
return value;
}
public String getHtmlValue(ComponentSvc service) {
String legacy = service.convert(service.fromJson(value), ComponentOperation.LEGACY, Component.SECTION);
return Html.swapColorCodesToSpan(legacy);
}
}

View File

@ -36,6 +36,7 @@ public class ExtensionTabData implements Comparable<ExtensionTabData> {
private final Map<String, ExtensionDoubleData> percentageData;
private final Map<String, ExtensionNumberData> numberData;
private final Map<String, ExtensionStringData> stringData;
private final Map<String, ExtensionComponentData> componentData;
private final List<ExtensionTableData> tableData;
private final List<ExtensionDescription> descriptions;
@ -52,6 +53,7 @@ public class ExtensionTabData implements Comparable<ExtensionTabData> {
percentageData = new HashMap<>();
numberData = new HashMap<>();
stringData = new HashMap<>();
componentData = new HashMap<>();
tableData = new ArrayList<>();
descriptions = new ArrayList<>();
@ -85,6 +87,10 @@ public class ExtensionTabData implements Comparable<ExtensionTabData> {
return Optional.ofNullable(stringData.get(providerName));
}
public Optional<ExtensionComponentData> getComponent(String providerName) {
return Optional.ofNullable(componentData.get(providerName));
}
public List<ExtensionTableData> getTableData() {
return tableData;
}
@ -125,6 +131,7 @@ public class ExtensionTabData implements Comparable<ExtensionTabData> {
this.percentageData.putAll(other.percentageData);
this.numberData.putAll(other.numberData);
this.stringData.putAll(other.stringData);
this.componentData.putAll(other.componentData);
this.tableData.addAll(other.tableData);
@ -137,6 +144,7 @@ public class ExtensionTabData implements Comparable<ExtensionTabData> {
descriptions.addAll(Lists.map(percentageData.values(), DescribedExtensionData::getDescription));
descriptions.addAll(Lists.map(numberData.values(), DescribedExtensionData::getDescription));
descriptions.addAll(Lists.map(stringData.values(), DescribedExtensionData::getDescription));
descriptions.addAll(Lists.map(componentData.values(), DescribedExtensionData::getDescription));
order = descriptions.stream().sorted()
.map(ExtensionDescription::getName)
@ -186,6 +194,11 @@ public class ExtensionTabData implements Comparable<ExtensionTabData> {
return this;
}
public Builder putComponentData(ExtensionComponentData extensionComponentData) {
data.componentData.put(extensionComponentData.getDescription().getName(), extensionComponentData);
return this;
}
public Builder putGroupData(ExtensionStringData extensionStringData) {
String name = extensionStringData.getDescription().getName();
ExtensionStringData previous = data.stringData.get(name);

View File

@ -27,10 +27,7 @@ import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.storage.database.SQLDB;
import com.djrapitops.plan.storage.database.queries.Query;
import com.djrapitops.plan.storage.database.queries.QueryStatement;
import com.djrapitops.plan.storage.database.sql.tables.ExtensionIconTable;
import com.djrapitops.plan.storage.database.sql.tables.ExtensionPlayerValueTable;
import com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderTable;
import com.djrapitops.plan.storage.database.sql.tables.ExtensionTabTable;
import com.djrapitops.plan.storage.database.sql.tables.*;
import com.djrapitops.plan.utilities.java.Lists;
import java.sql.PreparedStatement;
@ -113,6 +110,7 @@ public class ExtensionPlayerDataQuery implements Query<Map<ServerUUID, List<Exte
"v1." + ExtensionPlayerValueTable.PERCENTAGE_VALUE + " as percentage_value," +
"v1." + ExtensionPlayerValueTable.LONG_VALUE + " as long_value," +
"v1." + ExtensionPlayerValueTable.STRING_VALUE + " as string_value," +
"v1." + ExtensionPlayerValueTable.COMPONENT_VALUE + " as component_value," +
"p1." + ExtensionProviderTable.PLUGIN_ID + " as plugin_id," +
"p1." + ExtensionProviderTable.PROVIDER_NAME + " as provider_name," +
"p1." + ExtensionProviderTable.TEXT + " as text," +
@ -213,6 +211,11 @@ public class ExtensionPlayerDataQuery implements Query<Map<ServerUUID, List<Exte
boolean isPlayerName = set.getBoolean("is_player_name");
extensionTab.putStringData(new ExtensionStringData(description, isPlayerName, stringValue));
}
String componentValue = set.getString(ExtensionPlayerValueTable.COMPONENT_VALUE);
if (componentValue != null) {
extensionTab.putComponentData(new ExtensionComponentData(description, componentValue));
}
}
private ExtensionDescription extractDescription(ResultSet set) throws SQLException {

View File

@ -115,6 +115,7 @@ public class ExtensionServerDataQuery implements Query<List<ExtensionData>> {
"v1." + ExtensionServerValueTable.PERCENTAGE_VALUE + " as percentage_value," +
"v1." + ExtensionServerValueTable.LONG_VALUE + " as long_value," +
"v1." + ExtensionServerValueTable.STRING_VALUE + " as string_value," +
"v1." + ExtensionServerValueTable.COMPONENT_VALUE + " as component_value," +
"p1." + ExtensionProviderTable.PLUGIN_ID + " as plugin_id," +
"p1." + ExtensionProviderTable.PROVIDER_NAME + " as provider_name," +
"p1." + ExtensionProviderTable.TEXT + " as text," +
@ -216,6 +217,11 @@ public class ExtensionServerDataQuery implements Query<List<ExtensionData>> {
boolean isPlayerName = set.getBoolean("is_player_name");
extensionTab.putStringData(new ExtensionStringData(description, isPlayerName, stringValue));
}
String componentValue = set.getString(ExtensionServerValueTable.COMPONENT_VALUE);
if (componentValue != null) {
extensionTab.putComponentData(new ExtensionComponentData(description, componentValue));
}
}
private ExtensionDescription extractDescription(ResultSet set) throws SQLException {

View File

@ -89,6 +89,7 @@ public class ExtensionServerTableDataQuery implements Query<Map<UUID, ExtensionT
"v1." + ExtensionPlayerValueTable.PERCENTAGE_VALUE + " as percentage_value," +
"v1." + ExtensionPlayerValueTable.LONG_VALUE + " as long_value," +
"v1." + ExtensionPlayerValueTable.STRING_VALUE + " as string_value," +
"v1." + ExtensionPlayerValueTable.COMPONENT_VALUE + " as component_value," +
"null as group_value," +
"p1." + ExtensionProviderTable.PROVIDER_NAME + " as provider_name," +
"p1." + ExtensionProviderTable.TEXT + " as text," +
@ -209,6 +210,11 @@ public class ExtensionServerTableDataQuery implements Query<Map<UUID, ExtensionT
if (stringValue != null) {
extensionTab.putStringData(ExtensionStringData.regularString(description, stringValue));
}
String componentValue = set.getString(ExtensionPlayerValueTable.COMPONENT_VALUE);
if (componentValue != null) {
extensionTab.putComponentData(new ExtensionComponentData(description, componentValue));
}
}
private ExtensionDescription extractDescription(ResultSet set) throws SQLException {

View File

@ -17,6 +17,8 @@
package com.djrapitops.plan.extension.implementation.storage.transactions.results;
import com.djrapitops.plan.extension.implementation.ProviderInformation;
import com.djrapitops.plan.extension.implementation.builder.ComponentDataValue;
import com.djrapitops.plan.extension.implementation.builder.StringDataValue;
import com.djrapitops.plan.extension.implementation.providers.Parameters;
import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderTable;
@ -45,6 +47,7 @@ public class StorePlayerStringResultTransaction extends ThrowawayTransaction {
private final String providerName;
private final UUID playerUUID;
private final boolean component;
private final String value;
public StorePlayerStringResultTransaction(ProviderInformation information, Parameters parameters, String value) {
@ -52,7 +55,8 @@ public class StorePlayerStringResultTransaction extends ThrowawayTransaction {
this.providerName = information.getName();
this.serverUUID = parameters.getServerUUID();
this.playerUUID = parameters.getPlayerUUID();
this.value = StringUtils.truncate(value, 50);
this.component = information.isComponent();
this.value = StringUtils.truncate(value, component ? ComponentDataValue.MAX_LENGTH : StringDataValue.MAX_LENGTH);
}
@Override
@ -72,7 +76,7 @@ public class StorePlayerStringResultTransaction extends ThrowawayTransaction {
private Executable updateValue() {
String sql = "UPDATE " + TABLE_NAME +
" SET " +
STRING_VALUE + "=?" +
(component ? COMPONENT_VALUE : STRING_VALUE) + "=?" +
WHERE + USER_UUID + "=?" +
AND + PROVIDER_ID + "=" + ExtensionProviderTable.STATEMENT_SELECT_PROVIDER_ID;
@ -88,7 +92,7 @@ public class StorePlayerStringResultTransaction extends ThrowawayTransaction {
private Executable insertValue() {
String sql = "INSERT INTO " + TABLE_NAME + "(" +
STRING_VALUE + "," +
(component ? COMPONENT_VALUE : STRING_VALUE) + "," +
USER_UUID + "," +
PROVIDER_ID +
") VALUES (?,?," + ExtensionProviderTable.STATEMENT_SELECT_PROVIDER_ID + ")";

View File

@ -17,6 +17,8 @@
package com.djrapitops.plan.extension.implementation.storage.transactions.results;
import com.djrapitops.plan.extension.implementation.ProviderInformation;
import com.djrapitops.plan.extension.implementation.builder.ComponentDataValue;
import com.djrapitops.plan.extension.implementation.builder.StringDataValue;
import com.djrapitops.plan.extension.implementation.providers.Parameters;
import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderTable;
@ -42,13 +44,15 @@ public class StoreServerStringResultTransaction extends ThrowawayTransaction {
private final ServerUUID serverUUID;
private final String providerName;
private final boolean component;
private final String value;
public StoreServerStringResultTransaction(ProviderInformation information, Parameters parameters, String value) {
this.pluginName = information.getPluginName();
this.providerName = information.getName();
this.serverUUID = parameters.getServerUUID();
this.value = StringUtils.truncate(value, 50);
this.component = information.isComponent();
this.value = StringUtils.truncate(value, component ? ComponentDataValue.MAX_LENGTH : StringDataValue.MAX_LENGTH);
}
@Override
@ -68,7 +72,7 @@ public class StoreServerStringResultTransaction extends ThrowawayTransaction {
private Executable updateValue() {
String sql = "UPDATE " + TABLE_NAME +
" SET " +
STRING_VALUE + "=?" +
(component ? COMPONENT_VALUE : STRING_VALUE) + "=?" +
WHERE + PROVIDER_ID + "=" + ExtensionProviderTable.STATEMENT_SELECT_PROVIDER_ID;
return new ExecStatement(sql) {
@ -82,7 +86,7 @@ public class StoreServerStringResultTransaction extends ThrowawayTransaction {
private Executable insertValue() {
String sql = "INSERT INTO " + TABLE_NAME + "(" +
STRING_VALUE + "," +
(component ? COMPONENT_VALUE : STRING_VALUE) + "," +
PROVIDER_ID +
") VALUES (?," + ExtensionProviderTable.STATEMENT_SELECT_PROVIDER_ID + ")";
return new ExecStatement(sql) {

View File

@ -242,7 +242,8 @@ public abstract class SQLDB extends AbstractDatabase {
new RegisterDateMinimizationPatch(),
new UsersTableNameLengthPatch(),
new SessionJoinAddressPatch(),
new RemoveUsernameFromAccessLogPatch()
new RemoveUsernameFromAccessLogPatch(),
new ComponentColumnToExtensionDataPatch()
};
}

View File

@ -16,6 +16,8 @@
*/
package com.djrapitops.plan.storage.database.sql.tables;
import com.djrapitops.plan.extension.implementation.builder.ComponentDataValue;
import com.djrapitops.plan.extension.implementation.builder.StringDataValue;
import com.djrapitops.plan.storage.database.DBType;
import com.djrapitops.plan.storage.database.sql.building.CreateTableBuilder;
import com.djrapitops.plan.storage.database.sql.building.Sql;
@ -38,6 +40,7 @@ public class ExtensionPlayerValueTable {
public static final String PERCENTAGE_VALUE = "percentage_value";
public static final String LONG_VALUE = "long_value";
public static final String STRING_VALUE = "string_value";
public static final String COMPONENT_VALUE = "component_value";
public static final String GROUP_VALUE = "group_value";
private ExtensionPlayerValueTable() {
@ -51,7 +54,8 @@ public class ExtensionPlayerValueTable {
.column(DOUBLE_VALUE, Sql.DOUBLE)
.column(PERCENTAGE_VALUE, Sql.DOUBLE)
.column(LONG_VALUE, Sql.LONG)
.column(STRING_VALUE, Sql.varchar(50))
.column(STRING_VALUE, Sql.varchar(StringDataValue.MAX_LENGTH))
.column(COMPONENT_VALUE, Sql.varchar(ComponentDataValue.MAX_LENGTH))
.column(GROUP_VALUE, Sql.varchar(50))
.column(USER_UUID, Sql.varchar(36)).notNull()
.column(PROVIDER_ID, Sql.INT).notNull()

View File

@ -16,6 +16,8 @@
*/
package com.djrapitops.plan.storage.database.sql.tables;
import com.djrapitops.plan.extension.implementation.builder.ComponentDataValue;
import com.djrapitops.plan.extension.implementation.builder.StringDataValue;
import com.djrapitops.plan.storage.database.DBType;
import com.djrapitops.plan.storage.database.sql.building.CreateTableBuilder;
import com.djrapitops.plan.storage.database.sql.building.Sql;
@ -38,6 +40,7 @@ public class ExtensionServerValueTable {
public static final String PERCENTAGE_VALUE = "percentage_value";
public static final String LONG_VALUE = "long_value";
public static final String STRING_VALUE = "string_value";
public static final String COMPONENT_VALUE = "component_value";
public static final String GROUP_VALUE = "group_value";
private ExtensionServerValueTable() {
@ -51,7 +54,8 @@ public class ExtensionServerValueTable {
.column(DOUBLE_VALUE, Sql.DOUBLE)
.column(PERCENTAGE_VALUE, Sql.DOUBLE)
.column(LONG_VALUE, Sql.LONG)
.column(STRING_VALUE, Sql.varchar(50))
.column(STRING_VALUE, Sql.varchar(StringDataValue.MAX_LENGTH))
.column(COMPONENT_VALUE, Sql.varchar(ComponentDataValue.MAX_LENGTH))
.column(GROUP_VALUE, Sql.varchar(50))
.column(PROVIDER_ID, Sql.INT).notNull()
.foreignKey(PROVIDER_ID, ExtensionProviderTable.TABLE_NAME, ExtensionProviderTable.ID)

View File

@ -0,0 +1,42 @@
/*
* 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.storage.database.transactions.patches;
import com.djrapitops.plan.storage.database.sql.building.Sql;
import com.djrapitops.plan.storage.database.sql.tables.ExtensionPlayerValueTable;
import com.djrapitops.plan.storage.database.sql.tables.ExtensionServerValueTable;
public class ComponentColumnToExtensionDataPatch extends Patch {
private static final String serverTable = ExtensionServerValueTable.TABLE_NAME;
private static final String serverColumn = ExtensionServerValueTable.COMPONENT_VALUE;
private static final String playerTable = ExtensionPlayerValueTable.TABLE_NAME;
private static final String playerColumn = ExtensionPlayerValueTable.COMPONENT_VALUE;
private static final int length = 500;
@Override
public boolean hasBeenApplied() {
return hasColumn(serverTable, serverColumn)
&& hasColumn(playerTable, playerColumn);
}
@Override
protected void applyPatch() {
addColumn(serverTable, serverColumn + " " + Sql.varchar(length));
addColumn(playerTable, playerColumn + " " + Sql.varchar(length));
}
}

View File

@ -16,6 +16,7 @@
*/
package com.djrapitops.plan.storage.database;
import com.djrapitops.plan.component.ComponentSvc;
import com.djrapitops.plan.delivery.DeliveryUtilities;
import com.djrapitops.plan.extension.ExtensionSvc;
import com.djrapitops.plan.identification.ServerInfo;
@ -83,6 +84,8 @@ public interface DatabaseTestComponent extends DBPreparer.Dependencies {
ExtensionSvc extensionService();
ComponentSvc componentService();
QueryFilters queryFilters();
@Component.Builder

View File

@ -17,6 +17,7 @@
package com.djrapitops.plan.storage.database;
import com.djrapitops.plan.PlanSystem;
import com.djrapitops.plan.component.ComponentSvc;
import com.djrapitops.plan.delivery.DeliveryUtilities;
import com.djrapitops.plan.extension.ExtensionSvc;
import com.djrapitops.plan.identification.ServerInfo;
@ -65,6 +66,8 @@ public interface DatabaseTestPreparer {
default ExtensionSvc extensionService() {return system().getExtensionService();}
default ComponentSvc componentService() {return system().getComponentService();}
QueryFilters queryFilters();
default void execute(Executable executable) {

View File

@ -17,6 +17,7 @@
package com.djrapitops.plan.storage.database;
import com.djrapitops.plan.PlanSystem;
import com.djrapitops.plan.component.ComponentSvc;
import com.djrapitops.plan.delivery.DeliveryUtilities;
import com.djrapitops.plan.extension.ExtensionSvc;
import com.djrapitops.plan.identification.Server;
@ -149,6 +150,11 @@ class MySQLTest implements DatabaseTest, DatabaseTestAggregate {
return component.extensionService();
}
@Override
public ComponentSvc componentService() {
return component.componentService();
}
@Override
public QueryFilters queryFilters() {
return component.queryFilters();

View File

@ -17,6 +17,7 @@
package com.djrapitops.plan.storage.database;
import com.djrapitops.plan.PlanSystem;
import com.djrapitops.plan.component.ComponentSvc;
import com.djrapitops.plan.delivery.DeliveryUtilities;
import com.djrapitops.plan.extension.ExtensionSvc;
import com.djrapitops.plan.identification.Server;
@ -138,6 +139,11 @@ public class SQLiteTest implements DatabaseTest, DatabaseTestAggregate {
return component.extensionService();
}
@Override
public ComponentSvc componentService() {
return component.componentService();
}
@Override
public QueryFilters queryFilters() {
return component.queryFilters();

View File

@ -16,6 +16,8 @@
*/
package com.djrapitops.plan.storage.database.queries;
import com.djrapitops.plan.component.Component;
import com.djrapitops.plan.component.ComponentService;
import com.djrapitops.plan.delivery.rendering.html.structure.HtmlTable;
import com.djrapitops.plan.extension.CallEvents;
import com.djrapitops.plan.extension.DataExtension;
@ -43,6 +45,8 @@ import com.djrapitops.plan.storage.database.transactions.events.StoreWorldNameTr
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import utilities.OptionalAssert;
import utilities.RandomData;
import utilities.TestConstants;
@ -64,6 +68,7 @@ public interface ExtensionsDatabaseTest extends DatabaseTestPreparer {
@BeforeEach
default void unregisterExtensions() {
componentService().register();
ExtensionSvc extensionService = extensionService();
extensionService.register();
extensionService.unregister(new PlayerExtension());
@ -112,6 +117,18 @@ public interface ExtensionsDatabaseTest extends DatabaseTestPreparer {
OptionalAssert.equals("0.5", tabData.getPercentage("percentageVal").map(data -> data.getFormattedValue(Object::toString)));
OptionalAssert.equals("Something", tabData.getString("stringVal").map(ExtensionStringData::getFormattedValue));
OptionalAssert.equals("Group", tabData.getString("groupVal").map(ExtensionStringData::getFormattedValue));
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode objectNode = objectMapper.createObjectNode();
objectNode.put("color", "green");
objectNode.put("text", "Test");
OptionalAssert.equals(objectNode, tabData.getComponent("componentVal").map(ExtensionComponentData::getFormattedValue).map(str -> {
try {
return objectMapper.readTree(str);
} catch (Throwable t) {
return fail(t);
}
}));
}
@Test
@ -490,6 +507,11 @@ public interface ExtensionsDatabaseTest extends DatabaseTestPreparer {
public String[] groupVal(UUID playerUUID) {
return new String[]{"Group"};
}
@ComponentProvider(text = "colored text")
public Component componentVal(UUID playerUUID) {
return ComponentService.getInstance().fromLegacy("&aTest", '&');
}
}
@PluginInfo(name = "TableExtension")

View File

@ -33,6 +33,7 @@
"react-bootstrap-v5": "^1.4.0",
"react-dom": "^17.0.2",
"react-i18next": "^12.0.0",
"react-mcjsonchat": "^1.0.0",
"react-router-dom": "6",
"react-scripts": "5.0.1",
"sass": "^1.55.0",

View File

@ -7675,6 +7675,11 @@ react-lifecycles-compat@^3.0.4:
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
react-mcjsonchat@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/react-mcjsonchat/-/react-mcjsonchat-1.0.0.tgz#6a0c748b074c06a2d64a66db76e5fb2036c48a9a"
integrity sha512-H/OYi1iRYFG2Bntj1EYWfTxOaWtIopHy6ILoaXtD3OFONK7kQnp0lXFf6sw1G3BU0DL7s8NL4+AmMCer/A5eIQ==
react-overlays@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-4.1.1.tgz#0060107cbe1c5171a744ccda3fbf0556d064bc5f"