diff --git a/Plan/api/src/main/java/com/djrapitops/plan/capability/Capability.java b/Plan/api/src/main/java/com/djrapitops/plan/capability/Capability.java index e1ae52a1c..3607f6675 100644 --- a/Plan/api/src/main/java/com/djrapitops/plan/capability/Capability.java +++ b/Plan/api/src/main/java/com/djrapitops/plan/capability/Capability.java @@ -56,6 +56,10 @@ enum Capability { * When the parameter is set to {@code true} the value from this Provider is shown on a table alongside players. */ DATA_EXTENSION_SHOW_IN_PLAYER_TABLE, + /** + * DataExtension API addition, {@link com.djrapitops.plan.extension.builder.ExtensionDataBuilder}. + */ + DATA_EXTENSION_BUILDER_API, /** * {@link com.djrapitops.plan.query.QueryService} and {@link com.djrapitops.plan.query.CommonQueries} */ diff --git a/Plan/api/src/main/java/com/djrapitops/plan/extension/DataExtension.java b/Plan/api/src/main/java/com/djrapitops/plan/extension/DataExtension.java index bada70e21..5806d6ea4 100644 --- a/Plan/api/src/main/java/com/djrapitops/plan/extension/DataExtension.java +++ b/Plan/api/src/main/java/com/djrapitops/plan/extension/DataExtension.java @@ -16,6 +16,9 @@ */ package com.djrapitops.plan.extension; +import com.djrapitops.plan.extension.annotation.PluginInfo; +import com.djrapitops.plan.extension.builder.ExtensionDataBuilder; + /** * Interface to implement data extensions with. *

@@ -30,6 +33,9 @@ package com.djrapitops.plan.extension; * {@link com.djrapitops.plan.extension.annotation.DoubleProvider} for {@code double} values. * {@link com.djrapitops.plan.extension.annotation.PercentageProvider} for {@code double} values that represent a percentage. * {@link com.djrapitops.plan.extension.annotation.StringProvider} for {@link String} values. + * {@link com.djrapitops.plan.extension.annotation.TableProvider} for {@link com.djrapitops.plan.extension.table.Table}s. + * {@link com.djrapitops.plan.extension.annotation.GroupProvider} for Player specific group names, such as permission groups. + * {@link com.djrapitops.plan.extension.annotation.DataBuilderProvider} for {@link ExtensionDataBuilder}s. *


*

* Methods can have one of the following as method parameters: @@ -90,4 +96,30 @@ public interface DataExtension { }; } + /** + * Obtain a new {@link ExtensionDataBuilder}. + *

+ * Requires Capability DATA_EXTENSION_BUILDER_API + * + * @return new builder. + */ + default ExtensionDataBuilder newExtensionDataBuilder() { + return ExtensionService.getInstance().newExtensionDataBuilder(this); + } + + /** + * Get the name of the plugin from PluginInfo annotation. + *

+ * Requires Capability DATA_EXTENSION_BUILDER_API + * + * @return new builder. + */ + default String getPluginName() { + PluginInfo annotation = getClass().getAnnotation(PluginInfo.class); + if (annotation == null) { + throw new IllegalArgumentException(getClass().getSimpleName() + " did not have @PluginInfo annotation!"); + } + return annotation.name(); + } + } diff --git a/Plan/api/src/main/java/com/djrapitops/plan/extension/ExtensionService.java b/Plan/api/src/main/java/com/djrapitops/plan/extension/ExtensionService.java index 1d0be17cd..9bcf81c3a 100644 --- a/Plan/api/src/main/java/com/djrapitops/plan/extension/ExtensionService.java +++ b/Plan/api/src/main/java/com/djrapitops/plan/extension/ExtensionService.java @@ -16,6 +16,7 @@ */ package com.djrapitops.plan.extension; +import com.djrapitops.plan.extension.builder.ExtensionDataBuilder; import com.djrapitops.plan.extension.extractor.ExtensionExtractor; import java.util.Optional; @@ -60,6 +61,16 @@ public interface ExtensionService { */ Optional register(DataExtension extension); + /** + * Obtain a new {@link ExtensionDataBuilder}, it is recommended to use {@link DataExtension#newExtensionDataBuilder()}. + *

+ * Requires Capability DATA_EXTENSION_BUILDER_API + * + * @param extension Extension for which this builder is. + * @return a new builder. + */ + ExtensionDataBuilder newExtensionDataBuilder(DataExtension extension); + /** * Unregister your {@link DataExtension} implementation. *

diff --git a/Plan/api/src/main/java/com/djrapitops/plan/extension/annotation/Conditional.java b/Plan/api/src/main/java/com/djrapitops/plan/extension/annotation/Conditional.java index 17fd4ac83..191db0bd7 100644 --- a/Plan/api/src/main/java/com/djrapitops/plan/extension/annotation/Conditional.java +++ b/Plan/api/src/main/java/com/djrapitops/plan/extension/annotation/Conditional.java @@ -53,5 +53,4 @@ public @interface Conditional { * @return {@code false} by default. */ boolean negated() default false; - } \ No newline at end of file diff --git a/Plan/api/src/main/java/com/djrapitops/plan/extension/annotation/DataBuilderProvider.java b/Plan/api/src/main/java/com/djrapitops/plan/extension/annotation/DataBuilderProvider.java new file mode 100644 index 000000000..0c49bb264 --- /dev/null +++ b/Plan/api/src/main/java/com/djrapitops/plan/extension/annotation/DataBuilderProvider.java @@ -0,0 +1,39 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.annotation; + +import com.djrapitops.plan.extension.DataExtension; + +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 {@link com.djrapitops.plan.extension.builder.ExtensionDataBuilder}. + *

+ * Usage: {@code @DataBuilderProvider ExtensionDataBuilder method(UUID playerUUID)} + *

+ * ExtensionDataBuilder can be obtained with {@link DataExtension#newExtensionDataBuilder()}. + * + * @author AuroraLS3 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface DataBuilderProvider { + +} diff --git a/Plan/api/src/main/java/com/djrapitops/plan/extension/builder/DataValue.java b/Plan/api/src/main/java/com/djrapitops/plan/extension/builder/DataValue.java new file mode 100644 index 000000000..66c94ef6c --- /dev/null +++ b/Plan/api/src/main/java/com/djrapitops/plan/extension/builder/DataValue.java @@ -0,0 +1,40 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.builder; + +import java.util.Optional; + +/** + * Represents a value given to {@link ExtensionDataBuilder}. + *

+ * Please do not implement this class, it is an implementation detail. + * Obtain instances with {@link ValueBuilder}. + * + * @param Type of the value. + */ +public interface DataValue { + + T getValue(); + + M getInformation(Class ofType); + + default > Optional getMetadata(Class metadataType) { + if (getClass().equals(metadataType)) return Optional.of(metadataType.cast(this)); + return Optional.empty(); + } + +} diff --git a/Plan/api/src/main/java/com/djrapitops/plan/extension/builder/ExtensionDataBuilder.java b/Plan/api/src/main/java/com/djrapitops/plan/extension/builder/ExtensionDataBuilder.java new file mode 100644 index 000000000..ffdcabe05 --- /dev/null +++ b/Plan/api/src/main/java/com/djrapitops/plan/extension/builder/ExtensionDataBuilder.java @@ -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 . + */ +package com.djrapitops.plan.extension.builder; + +import com.djrapitops.plan.extension.DataExtension; +import com.djrapitops.plan.extension.icon.Color; +import com.djrapitops.plan.extension.table.Table; + +import java.util.function.Supplier; + +/** + * Builder API for Extension data. + *

+ * Requires Capability DATA_EXTENSION_BUILDER_API + *

+ * Obtain an instance with {@link DataExtension#newExtensionDataBuilder()} + *

+ * Used with {@link com.djrapitops.plan.extension.annotation.DataBuilderProvider}. + * See documentation on how to use the API. + * + * @author AuroraLS3 + */ +public interface ExtensionDataBuilder { + + /** + * Creates a new {@link ValueBuilder} in order to use addValue methods. + *

+ * Using same text for two values can be problematic as the text is used for id in the database. + *

+ * If you need to use {@link com.djrapitops.plan.extension.annotation.InvalidateMethod} with built values, + * lowercase 'text' and remove all whitespace. Example {@code valueBuilder("Times Jumped"); @InvalidateMethod("timesjumped")} + * + * @param text Text that should be displayed next to the value. + * @return a new value builder. + * @throws IllegalArgumentException If text is null or empty String. + */ + ValueBuilder valueBuilder(String text); + + /** + * Add a value. + * + * @param ofType Class for type of the data, matches what Provider annotations want. + * @param dataValue Use {@link ValueBuilder} to create one. + * @param Type of the data. + * @return This builder. + * @throws IllegalArgumentException If either parameter is null + */ + ExtensionDataBuilder addValue(Class ofType, DataValue dataValue); + + /** + * Compared to the other addValue method, this method allows you to use {@link com.djrapitops.plan.extension.NotReadyException} when building your data. + * + * @param ofType Class for type of the data, matches what Provider annotations want. + * @param dataValue Use {@link ValueBuilder} to create one. + * @param Type of the data. + * @return This builder. + * @throws IllegalArgumentException If either parameter is null + */ + ExtensionDataBuilder addValue(Class ofType, Supplier> dataValue); + + /** + * Add a table. + * + * @param name Name of the table, used in the database. + * @param table Table built using {@link Table#builder()} + * @param color Color of the table + * @return This builder. + */ + default ExtensionDataBuilder addTable(String name, Table table, Color color) { + if (name == null) throw new IllegalArgumentException("'name' can not be null!"); + return addTable(name, table, color, null); + } + + /** + * Add a table to a specific tab. + * + * @param name Name of the table, used in the database. + * @param table Table built using {@link Table#builder()} + * @param color Color of the table + * @param tab Name of the tab, remember to define {@link com.djrapitops.plan.extension.annotation.TabInfo}. + * @return This builder. + */ + default ExtensionDataBuilder addTable(String name, Table table, Color color, String tab) { + return addValue(Table.class, valueBuilder(name) + .showOnTab(tab) + .buildTable(table, color)); + } + + /** + * Adds all values and tables in another builder to this builder. + * + * @param builder Builder to combine with this one. + */ + void addAll(ExtensionDataBuilder builder); +} diff --git a/Plan/api/src/main/java/com/djrapitops/plan/extension/builder/ValueBuilder.java b/Plan/api/src/main/java/com/djrapitops/plan/extension/builder/ValueBuilder.java new file mode 100644 index 000000000..1efea98f6 --- /dev/null +++ b/Plan/api/src/main/java/com/djrapitops/plan/extension/builder/ValueBuilder.java @@ -0,0 +1,318 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.builder; + +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.extractor.ExtensionMethod; +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.table.Table; + +import java.util.function.Supplier; + +/** + * Used for building {@link DataValue}s for {@link ExtensionDataBuilder#addValue(Class, DataValue)}. + *

+ * Requires Capability DATA_EXTENSION_BUILDER_API + *

+ * Obtain an instance with {@link ExtensionDataBuilder#valueBuilder(String)}. + */ +public interface ValueBuilder { + + /** + * Description about the value that is shown on hover. + * + * @param description Describe what the value is about, maximum 150 characters. + * @return This builder. + */ + ValueBuilder description(String description); + + /** + * Display-priority of the value, highest value is placed top most. + *

+ * Two values with same priority may appear in a random order. + * + * @param priority Priority between 0 and {@code Integer.MAX_VALUE}. + * @return This builder. + */ + ValueBuilder priority(int priority); + + /** + * Show this value in the players table. + * + * @return This builder. + */ + ValueBuilder showInPlayerTable(); + + /** + * Icon displayed next to the value. + *

+ * See https://fontawesome.com/icons (select 'free')) for icons + * + * @param iconName Name of the icon + * @param iconFamily Family of the icon + * @param iconColor Color of the icon + * @return This builder. + */ + default ValueBuilder icon(String iconName, Family iconFamily, Color iconColor) { + return icon(Icon.called(iconName).of(iconFamily).of(iconColor).build()); + } + + /** + * Icon displayed next to the value. + *

+ * See https://fontawesome.com/icons (select 'free')) for icons + * + * @param icon Icon built using the methods in {@link Icon}. + * @return This builder. + */ + ValueBuilder icon(Icon icon); + + /** + * Show the value on a specific tab. + *

+ * Remember to define {@link com.djrapitops.plan.extension.annotation.TabInfo} annotation. + * + * @param tabName Name of the tab. + * @return This builder. + */ + ValueBuilder showOnTab(String tabName); + + /** + * {@link ValueBuilder#buildNumber(long)} specific method, format the value as a epoch ms timestamp. + * + * @return This builder. + */ + default ValueBuilder formatAsDateWithYear() { + return format(FormatType.DATE_YEAR); + } + + /** + * {@link ValueBuilder#buildNumber(long)} specific method, format the value as a epoch ms timestamp. + * + * @return This builder. + */ + default ValueBuilder formatAsDateWithSeconds() { + return format(FormatType.DATE_SECOND); + } + + /** + * {@link ValueBuilder#buildNumber(long)} specific method, format the value as milliseconds of time. + * + * @return This builder. + */ + default ValueBuilder formatAsTimeAmount() { + return format(FormatType.TIME_MILLISECONDS); + } + + /** + * {@link ValueBuilder#buildNumber(long)} specific method, format the value with {@link FormatType} + * + * @return This builder. + */ + ValueBuilder format(FormatType formatType); + + /** + * {@link ValueBuilder#buildString(String)} specific method, link the value to a player page. + * + * @return This builder. + */ + ValueBuilder showAsPlayerPageLink(); + + /** + * Build a Boolean. Displayed as "Yes/No" on the page. + * + * @param value true/false + * @return a data value to give to {@link ExtensionDataBuilder}. + */ + DataValue buildBoolean(boolean value); + + /** + * Build a Boolean that provides a value for {@link Conditional}. Displayed as "Yes/No" on the page. + * + * @param value true/false + * @return a data value to give to {@link ExtensionDataBuilder}. + */ + DataValue buildBooleanProvidingCondition(boolean value, String providedCondition); + + /** + * Build a String. + * + * @param value any string. Limited to 50 characters. + * @return a data value to give to {@link ExtensionDataBuilder}. + */ + DataValue buildString(String value); + + /** + * Build a Number. + * + * @param value a non-floating point number. + * @return a data value to give to {@link ExtensionDataBuilder}. + */ + DataValue buildNumber(long value); + + /** + * Build a Floating point number. + * + * @param value a floating point number. + * @return a data value to give to {@link ExtensionDataBuilder}. + */ + DataValue buildDouble(double value); + + /** + * Build a Percentage. + * + * @param percentage value between 0.0 and 1.0 + * @return a data value to give to {@link ExtensionDataBuilder}. + */ + DataValue buildPercentage(double percentage); + + /** + * Build a list of groups. + * + * @param groups names of groups a player is in. + * @return a data value to give to {@link ExtensionDataBuilder}. + */ + DataValue buildGroup(String[] groups); + + /** + * Build a table. + * + * @param table Table built using {@link Table#builder()} + * @param tableColor Color of the table + * @return a data value to give to {@link ExtensionDataBuilder}. + */ + DataValue buildTable(Table table, Color tableColor); + + /** + * Lambda version for conditional return or throwing {@link com.djrapitops.plan.extension.NotReadyException}. + * + * @see ValueBuilder#buildBoolean(boolean). + */ + DataValue buildBoolean(Supplier value); + + /** + * Lambda version for conditional return or throwing {@link com.djrapitops.plan.extension.NotReadyException}. + * + * @see ValueBuilder#buildBooleanProvidingCondition(boolean, String). + */ + DataValue buildBooleanProvidingCondition(Supplier value, String providedCondition); + + /** + * Lambda version for conditional return or throwing {@link com.djrapitops.plan.extension.NotReadyException}. + * + * @see ValueBuilder#buildString(String) + */ + DataValue buildString(Supplier value); + + /** + * Lambda version for conditional return or throwing {@link com.djrapitops.plan.extension.NotReadyException}. + * + * @see ValueBuilder#buildNumber(long) + */ + DataValue buildNumber(Supplier value); + + /** + * Lambda version for conditional return or throwing {@link com.djrapitops.plan.extension.NotReadyException}. + * + * @see ValueBuilder#buildDouble(double) + */ + DataValue buildDouble(Supplier value); + + /** + * Lambda version for conditional return or throwing {@link com.djrapitops.plan.extension.NotReadyException}. + * + * @see ValueBuilder#buildPercentage(double) + */ + DataValue buildPercentage(Supplier percentage); + + /** + * Lambda version for conditional return or throwing {@link com.djrapitops.plan.extension.NotReadyException}. + * + * @see ValueBuilder#buildGroup(String[]) + */ + DataValue buildGroup(Supplier groups); + + /** + * Lambda version for conditional return or throwing {@link com.djrapitops.plan.extension.NotReadyException}. + * + * @see ValueBuilder#buildTable(Table, Color) + */ + DataValue
buildTable(Supplier
table, Color tableColor); + + /** + * Implementation detail - for abstracting annotations with the builder API. + * + * @param annotation BooleanProvider annotation. + * @return This builder. + */ + ValueBuilder hideFromUsers(BooleanProvider annotation); + + /** + * Implementation detail - for abstracting annotations with the builder API. + * + * @param conditional Conditional annotation. + * @return This builder. + */ + ValueBuilder conditional(Conditional conditional); + + /** + * Implementation detail - for abstracting annotations with the builder API. + * + * @param annotation StringProvider annotation. + * @return This builder. + */ + default ValueBuilder showAsPlayerPageLink(StringProvider annotation) { + if (annotation.playerName()) return showAsPlayerPageLink(); + return this; + } + + /** + * Implementation detail - for abstracting annotations with the builder API. + * + * @param method Method this value is from. + * @return This builder. + */ + ValueBuilder methodName(ExtensionMethod method); + + /** + * Implementation detail - for abstracting annotations with the builder API. + * + * @param show true/false + * @return This builder. + */ + default ValueBuilder showInPlayerTable(boolean show) { + if (show) return showInPlayerTable(); + return this; + } + + /** + * Implementation detail - for abstracting annotations with the builder API. + * + * @param annotation Tab annotation. + * @return This builder. + */ + default ValueBuilder showOnTab(Tab annotation) { + if (annotation != null) return showOnTab(annotation.value()); + return this; + } +} diff --git a/Plan/api/src/main/java/com/djrapitops/plan/extension/builder/package-info.java b/Plan/api/src/main/java/com/djrapitops/plan/extension/builder/package-info.java new file mode 100644 index 000000000..0ce6474ca --- /dev/null +++ b/Plan/api/src/main/java/com/djrapitops/plan/extension/builder/package-info.java @@ -0,0 +1,6 @@ +/** + * DataExtension Builder API. + *

+ * Requires Capability DATA_EXTENSION_BUILDER_API + */ +package com.djrapitops.plan.extension.builder; \ No newline at end of file diff --git a/Plan/api/src/main/java/com/djrapitops/plan/extension/extractor/ExtensionExtractor.java b/Plan/api/src/main/java/com/djrapitops/plan/extension/extractor/ExtensionExtractor.java index c7a062d17..71c2a4165 100644 --- a/Plan/api/src/main/java/com/djrapitops/plan/extension/extractor/ExtensionExtractor.java +++ b/Plan/api/src/main/java/com/djrapitops/plan/extension/extractor/ExtensionExtractor.java @@ -19,11 +19,11 @@ 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.builder.ExtensionDataBuilder; import com.djrapitops.plan.extension.table.Table; import java.lang.annotation.Annotation; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import java.util.*; import java.util.stream.Collectors; @@ -43,10 +43,12 @@ public final class ExtensionExtractor { private final List warnings = new ArrayList<>(); private PluginInfo pluginInfo; - private TabOrder tabOrder; private List tabInformation; private List invalidMethods; private MethodAnnotations methodAnnotations; + private Map methods; + private Collection conditionalMethods; + private Collection tabAnnotations; private static final String WAS_OVER_50_CHARACTERS = "' was over 50 characters."; @@ -56,78 +58,126 @@ public final class ExtensionExtractor { } /** - * Use this method in an unit test to validate your DataExtension. - * - * @throws IllegalArgumentException If an implementation error is found. + * @deprecated Use {@link DataExtension#getPluginName()} instead. */ - public void validateAnnotations() { - extractAnnotationInformation(); - - if (!warnings.isEmpty()) { - throw new IllegalArgumentException("Warnings: " + warnings.toString()); - } + @Deprecated + public static String getPluginName(Class extensionClass) { + return getClassAnnotation(extensionClass, PluginInfo.class).map(PluginInfo::name) + .orElseThrow(() -> new IllegalArgumentException("Given class had no PluginInfo annotation")); } private static Optional getClassAnnotation(Class from, Class ofClass) { return Optional.ofNullable(from.getAnnotation(ofClass)); } - public static String getPluginName(Class extensionClass) { - return getClassAnnotation(extensionClass, PluginInfo.class).map(PluginInfo::name) - .orElseThrow(() -> new IllegalArgumentException("Given class had no PluginInfo annotation")); - } - - private Method[] getMethods() { - return extension.getClass().getMethods(); - } - - public void extractAnnotationInformation() { + /** + * Use this method in an unit test to validate your DataExtension. + * + * @throws IllegalArgumentException If an implementation error is found. + */ + public void validateAnnotations() { extractPluginInfo(); extractInvalidMethods(); - - extractMethodAnnotations(); - validateMethodAnnotations(); - - validateConditionals(); - + extractMethods(); extractTabInfo(); + + if (!warnings.isEmpty()) { + throw new IllegalArgumentException("Warnings: " + warnings.toString()); + } } - private void extractMethodAnnotations() { - methodAnnotations = new MethodAnnotations(); + private Collection getExtensionMethods() { + List extensionMethods = new ArrayList<>(); + for (Method method : extension.getClass().getMethods()) { + try { + extensionMethods.add(new ExtensionMethod(extension, method)); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException(extensionName + '.' + e.getMessage()); + } + } + return extensionMethods; + } - for (Method method : getMethods()) { - int modifiers = method.getModifiers(); - if (Modifier.isPrivate(modifiers) - || Modifier.isProtected(modifiers) - || Modifier.isStatic(modifiers) - || Modifier.isNative(modifiers)) { + /** + * @deprecated No longer used anywhere, no-op. + */ + @Deprecated + public void extractAnnotationInformation() { + // no-op + } + + private void extractMethods() { + methodAnnotations = new MethodAnnotations(); + methods = new EnumMap<>(ExtensionMethod.ParameterType.class); + methods.put(ExtensionMethod.ParameterType.SERVER_NONE, new ExtensionMethods()); + methods.put(ExtensionMethod.ParameterType.PLAYER_STRING, new ExtensionMethods()); + methods.put(ExtensionMethod.ParameterType.PLAYER_UUID, new ExtensionMethods()); + methods.put(ExtensionMethod.ParameterType.GROUP, new ExtensionMethods()); + + conditionalMethods = new ArrayList<>(); + tabAnnotations = new ArrayList<>(); + + for (ExtensionMethod method : getExtensionMethods()) { + if (method.isInaccessible()) { continue; } - MethodAnnotations.get(method, BooleanProvider.class).ifPresent(annotation -> methodAnnotations.put(method, BooleanProvider.class, annotation)); - MethodAnnotations.get(method, NumberProvider.class).ifPresent(annotation -> methodAnnotations.put(method, NumberProvider.class, annotation)); - MethodAnnotations.get(method, DoubleProvider.class).ifPresent(annotation -> methodAnnotations.put(method, DoubleProvider.class, annotation)); - MethodAnnotations.get(method, PercentageProvider.class).ifPresent(annotation -> methodAnnotations.put(method, PercentageProvider.class, annotation)); - MethodAnnotations.get(method, StringProvider.class).ifPresent(annotation -> methodAnnotations.put(method, StringProvider.class, annotation)); + method.getAnnotation(BooleanProvider.class).ifPresent(annotation -> { + validateMethod(method, annotation); + methods.get(method.getParameterType()).addBooleanMethod(method); + methodAnnotations.put(method.getMethod(), BooleanProvider.class, annotation); + }); + method.getAnnotation(NumberProvider.class).ifPresent(annotation -> { + validateMethod(method, annotation); + methods.get(method.getParameterType()).addNumberMethod(method); + methodAnnotations.put(method.getMethod(), NumberProvider.class, annotation); + }); + method.getAnnotation(DoubleProvider.class).ifPresent(annotation -> { + validateMethod(method, annotation); + methods.get(method.getParameterType()).addDoubleMethod(method); + methodAnnotations.put(method.getMethod(), DoubleProvider.class, annotation); + }); + method.getAnnotation(PercentageProvider.class).ifPresent(annotation -> { + validateMethod(method, annotation); + methods.get(method.getParameterType()).addPercentageMethod(method); + methodAnnotations.put(method.getMethod(), PercentageProvider.class, annotation); + }); + method.getAnnotation(StringProvider.class).ifPresent(annotation -> { + validateMethod(method, annotation); + methods.get(method.getParameterType()).addStringMethod(method); + methodAnnotations.put(method.getMethod(), StringProvider.class, annotation); + }); + method.getAnnotation(TableProvider.class).ifPresent(annotation -> { + validateMethod(method, annotation); + methods.get(method.getParameterType()).addTableMethod(method); + methodAnnotations.put(method.getMethod(), TableProvider.class, annotation); + }); + method.getAnnotation(GroupProvider.class).ifPresent(annotation -> { + validateMethod(method, annotation); + methods.get(method.getParameterType()).addGroupMethod(method); + methodAnnotations.put(method.getMethod(), GroupProvider.class, annotation); + }); + method.getAnnotation(DataBuilderProvider.class).ifPresent(annotation -> { + validateMethod(method, annotation); + methods.get(method.getParameterType()).addDataBuilderMethod(method); + methodAnnotations.put(method.getMethod(), DataBuilderProvider.class, annotation); + }); - 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)); - MethodAnnotations.get(method, GroupProvider.class).ifPresent(annotation -> methodAnnotations.put(method, GroupProvider.class, annotation)); + method.getAnnotation(Conditional.class).ifPresent(annotation -> { + conditionalMethods.add(method.getMethod()); + methodAnnotations.put(method.getMethod(), Conditional.class, annotation); + }); + method.getAnnotation(Tab.class).ifPresent(annotation -> { + tabAnnotations.add(annotation); + methodAnnotations.put(method.getMethod(), Tab.class, annotation); + }); } if (methodAnnotations.isEmpty()) { throw new IllegalArgumentException(extensionName + " class had no methods annotated with a Provider annotation"); } - try { - methodAnnotations.makeMethodsAccessible(); - } catch (SecurityException failedToMakeAccessible) { - throw new IllegalArgumentException(extensionName + " has non accessible Provider method that could not be made accessible: " + - failedToMakeAccessible.getMessage(), failedToMakeAccessible); - } + validateConditionals(); } private void validateReturnType(Method method, Class expectedType) { @@ -144,7 +194,7 @@ public final class ExtensionExtractor { private void validateMethodAnnotationPropertyLength(String property, String name, int maxLength, Method method) { if (property.length() > maxLength) { - warnings.add(extensionName + "." + method.getName() + " '" + name + WAS_OVER_50_CHARACTERS); + warnings.add(extensionName + "." + method.getName() + " '" + name + "' was over " + maxLength + " characters."); } } @@ -186,135 +236,109 @@ public final class ExtensionExtractor { // Has valid parameter & it is acceptable. } - private void validateMethodAnnotations() { - validateBooleanProviderAnnotations(); - validateNumberProviderAnnotations(); - validateDoubleProviderAnnotations(); - validatePercentageProviderAnnotations(); - validateStringProviderAnnotations(); - validateTableProviderAnnotations(); - validateGroupProviderAnnotations(); - } + private void validateMethod(ExtensionMethod extensionMethod, BooleanProvider annotation) { + Method method = extensionMethod.getMethod(); + validateReturnType(method, boolean.class); + validateMethodAnnotationPropertyLength(annotation.text(), "text", 50, method); + validateMethodAnnotationPropertyLength(annotation.description(), "description", 150, method); + validateMethodAnnotationPropertyLength(annotation.conditionName(), "conditionName", 50, method); + validateMethodArguments(method, false, UUID.class, String.class, Group.class); - private void validateBooleanProviderAnnotations() { - for (Map.Entry booleanProvider : methodAnnotations.getMethodAnnotations(BooleanProvider.class).entrySet()) { - Method method = booleanProvider.getKey(); - BooleanProvider annotation = booleanProvider.getValue(); + String condition = extensionMethod.getAnnotation(Conditional.class).map(Conditional::value).orElse(null); + if (annotation.conditionName().equals(condition)) { + warnings.add(extensionName + "." + method.getName() + " can not be conditional of itself. required condition: " + condition + ", provided condition: " + annotation.conditionName()); + } - validateReturnType(method, boolean.class); - validateMethodAnnotationPropertyLength(annotation.text(), "text", 50, method); - validateMethodAnnotationPropertyLength(annotation.description(), "description", 150, method); - validateMethodAnnotationPropertyLength(annotation.conditionName(), "conditionName", 50, method); - validateMethodArguments(method, false, UUID.class, String.class, Group.class); - - String condition = MethodAnnotations.get(method, Conditional.class).map(Conditional::value).orElse(null); - if (annotation.conditionName().equals(condition)) { - warnings.add(extensionName + "." + method.getName() + " can not be conditional of itself. required condition: " + condition + ", provided condition: " + annotation.conditionName()); - } - - if (annotation.conditionName().isEmpty() && annotation.hidden()) { - throw new IllegalArgumentException(extensionName + "." + method.getName() + " can not be 'hidden' without a 'conditionName'"); - } + if (annotation.conditionName().isEmpty() && annotation.hidden()) { + throw new IllegalArgumentException(extensionName + "." + method.getName() + " can not be 'hidden' without a 'conditionName'"); } } - private void validateNumberProviderAnnotations() { - for (Map.Entry numberProvider : methodAnnotations.getMethodAnnotations(NumberProvider.class).entrySet()) { - Method method = numberProvider.getKey(); - NumberProvider annotation = numberProvider.getValue(); + private void validateMethod(ExtensionMethod extensionMethod, NumberProvider annotation) { + Method method = extensionMethod.getMethod(); - validateReturnType(method, long.class); - validateMethodAnnotationPropertyLength(annotation.text(), "text", 50, method); - validateMethodAnnotationPropertyLength(annotation.description(), "description", 150, method); - validateMethodArguments(method, false, UUID.class, String.class, Group.class); - } + validateReturnType(method, long.class); + validateMethodAnnotationPropertyLength(annotation.text(), "text", 50, method); + validateMethodAnnotationPropertyLength(annotation.description(), "description", 150, method); + validateMethodArguments(method, false, UUID.class, String.class, Group.class); } - private void validateDoubleProviderAnnotations() { - for (Map.Entry doubleProvider : methodAnnotations.getMethodAnnotations(DoubleProvider.class).entrySet()) { - Method method = doubleProvider.getKey(); - DoubleProvider annotation = doubleProvider.getValue(); + private void validateMethod(ExtensionMethod extensionMethod, DoubleProvider annotation) { + Method method = extensionMethod.getMethod(); - validateReturnType(method, double.class); - validateMethodAnnotationPropertyLength(annotation.text(), "text", 50, method); - validateMethodAnnotationPropertyLength(annotation.description(), "description", 150, method); - validateMethodArguments(method, false, UUID.class, String.class, Group.class); - } + validateReturnType(method, double.class); + validateMethodAnnotationPropertyLength(annotation.text(), "text", 50, method); + validateMethodAnnotationPropertyLength(annotation.description(), "description", 150, method); + validateMethodArguments(method, false, UUID.class, String.class, Group.class); } - private void validatePercentageProviderAnnotations() { - for (Map.Entry percentageProvider : methodAnnotations.getMethodAnnotations(PercentageProvider.class).entrySet()) { - Method method = percentageProvider.getKey(); - PercentageProvider annotation = percentageProvider.getValue(); + private void validateMethod(ExtensionMethod extensionMethod, PercentageProvider annotation) { + Method method = extensionMethod.getMethod(); - validateReturnType(method, double.class); - validateMethodAnnotationPropertyLength(annotation.text(), "text", 50, method); - validateMethodAnnotationPropertyLength(annotation.description(), "description", 150, method); - validateMethodArguments(method, false, UUID.class, String.class, Group.class); - } + validateReturnType(method, double.class); + validateMethodAnnotationPropertyLength(annotation.text(), "text", 50, method); + validateMethodAnnotationPropertyLength(annotation.description(), "description", 150, method); + validateMethodArguments(method, false, UUID.class, String.class, Group.class); } - private void validateStringProviderAnnotations() { - for (Map.Entry stringProvider : methodAnnotations.getMethodAnnotations(StringProvider.class).entrySet()) { - Method method = stringProvider.getKey(); - StringProvider annotation = stringProvider.getValue(); + private void validateMethod(ExtensionMethod extensionMethod, StringProvider annotation) { + Method method = extensionMethod.getMethod(); - validateReturnType(method, String.class); - validateMethodAnnotationPropertyLength(annotation.text(), "text", 50, method); - validateMethodAnnotationPropertyLength(annotation.description(), "description", 150, method); - validateMethodArguments(method, false, UUID.class, String.class, Group.class); - } + validateReturnType(method, String.class); + validateMethodAnnotationPropertyLength(annotation.text(), "text", 50, method); + validateMethodAnnotationPropertyLength(annotation.description(), "description", 150, method); + validateMethodArguments(method, false, UUID.class, String.class, Group.class); } - 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 validateMethod(ExtensionMethod extensionMethod, TableProvider annotation) { + Method method = extensionMethod.getMethod(); + + validateReturnType(method, Table.class); + validateMethodArguments(method, false, UUID.class, String.class, Group.class); } - private void validateGroupProviderAnnotations() { - for (Map.Entry groupProvider : methodAnnotations.getMethodAnnotations(GroupProvider.class).entrySet()) { - Method method = groupProvider.getKey(); - GroupProvider annotation = groupProvider.getValue(); + private void validateMethod(ExtensionMethod extensionMethod, GroupProvider annotation) { + Method method = extensionMethod.getMethod(); - validateReturnType(method, String[].class); - validateMethodAnnotationPropertyLength(annotation.text(), "text", 50, method); - validateMethodArguments(method, true, UUID.class, String.class); - } + validateReturnType(method, String[].class); + validateMethodAnnotationPropertyLength(annotation.text(), "text", 50, method); + validateMethodArguments(method, true, UUID.class, String.class); + } + + private void validateMethod(ExtensionMethod extensionMethod, DataBuilderProvider annotation) { + Method method = extensionMethod.getMethod(); + + validateReturnType(method, ExtensionDataBuilder.class); + validateMethodArguments(method, false, UUID.class, String.class); } private void validateConditionals() { - Collection conditionals = methodAnnotations.getAnnotations(Conditional.class); - Collection conditionProviders = methodAnnotations.getAnnotations(BooleanProvider.class); - - Set providedConditions = conditionProviders.stream().map(BooleanProvider::conditionName).collect(Collectors.toSet()); - - for (Conditional condition : conditionals) { - String conditionName = condition.value(); - - if (conditionName.length() > 50) { - warnings.add(extensionName + ": '" + conditionName + "' conditionName was over 50 characters."); - } - - if (!providedConditions.contains(conditionName)) { - warnings.add(extensionName + ": '" + conditionName + "' Condition was not provided by any BooleanProvider."); - } - } - // Make sure that all methods annotated with Conditional have a Provider annotation - Collection conditionalMethods = methodAnnotations.getMethodAnnotations(Conditional.class).keySet(); for (Method conditionalMethod : conditionalMethods) { - if (!MethodAnnotations.hasAnyOf(conditionalMethod, + if (!hasAnyOf(conditionalMethod, BooleanProvider.class, DoubleProvider.class, NumberProvider.class, PercentageProvider.class, StringProvider.class, TableProvider.class, - GroupProvider.class + GroupProvider.class, DataBuilderProvider.class )) { throw new IllegalArgumentException(extensionName + "." + conditionalMethod.getName() + " did not have any associated Provider for Conditional."); } + if (hasAnyOf(conditionalMethod, DataBuilderProvider.class)) { + throw new IllegalArgumentException(extensionName + "." + conditionalMethod.getName() + " had Conditional, but DataBuilderProvider does not support it!"); + } } } + private boolean hasAnyOf(Method method, Class... annotationClasses) { + for (Annotation annotation : method.getAnnotations()) { + for (Class annotationClass : annotationClasses) { + if (annotationClass.isAssignableFrom(annotation.getClass())) { + return true; + } + } + } + return false; + } + private Optional getClassAnnotation(Class ofClass) { return getClassAnnotation(extension.getClass(), ofClass); } @@ -324,7 +348,7 @@ public final class ExtensionExtractor { .orElseThrow(() -> new IllegalArgumentException("Given class had no PluginInfo annotation")); if (pluginInfo.name().length() > 50) { - warnings.add(extensionName + " PluginInfo 'name' was over 50 characters."); + warnings.add(extensionName + " PluginInfo 'name" + WAS_OVER_50_CHARACTERS); } } @@ -343,17 +367,22 @@ public final class ExtensionExtractor { } }); - tabOrder = getClassAnnotation(TabOrder.class).orElse(null); + getClassAnnotation(TabOrder.class).map(TabOrder::value) + .ifPresent(order -> { + List orderAsList = Arrays.asList(order); + // Order by the 2nd list. https://stackoverflow.com/a/18130019 + // O(n^2 log n), not very bad here because there aren't going to be more than 10 tabs maybe ever. + tabInformation.sort(Comparator.comparingInt(item -> orderAsList.indexOf(item.tab()))); + }); - Map tabs = this.methodAnnotations.getMethodAnnotations(Tab.class); - Set tabNames = tabs.values().stream().map(Tab::value).collect(Collectors.toSet()); + Set tabNames = getTabAnnotations().stream().map(Tab::value).collect(Collectors.toSet()); // Check for unused TabInfo annotations for (TabInfo tabInfo : tabInformation) { String tabName = tabInfo.tab(); if (tabName.length() > 50) { - warnings.add(extensionName + " TabInfo " + tabName + " name was over 50 characters."); + warnings.add(extensionName + " TabInfo " + tabName + " 'name" + WAS_OVER_50_CHARACTERS); } if (!tabNames.contains(tabName)) { @@ -362,10 +391,9 @@ public final class ExtensionExtractor { } // Check Tab name lengths - for (Map.Entry tab : tabs.entrySet()) { - String tabName = tab.getValue().value(); + for (String tabName : tabNames) { if (tabName.length() > 50) { - warnings.add(extensionName + "." + tab.getKey().getName() + " Tab '" + tabName + "' name was over 50 characters."); + warnings.add(extensionName + " Tab '" + tabName + "' 'name" + WAS_OVER_50_CHARACTERS); } } } @@ -391,22 +419,37 @@ public final class ExtensionExtractor { } public PluginInfo getPluginInfo() { + if (pluginInfo == null) extractPluginInfo(); return pluginInfo; } public Optional getTabOrder() { - return Optional.ofNullable(tabOrder); + return getClassAnnotation(TabOrder.class); + } + + public Collection getTabAnnotations() { + if (tabAnnotations == null) extractMethods(); + return tabAnnotations; } public List getTabInformation() { - return tabInformation != null ? tabInformation : Collections.emptyList(); + if (tabInformation == null) extractTabInfo(); + return tabInformation; } + @Deprecated public MethodAnnotations getMethodAnnotations() { + if (methodAnnotations == null) extractMethods(); return methodAnnotations; } + public Map getMethods() { + if (methods == null) extractMethods(); + return methods; + } + public List getInvalidateMethodAnnotations() { - return invalidMethods != null ? invalidMethods : Collections.emptyList(); + if (invalidMethods == null) extractInvalidMethods(); + return invalidMethods; } } diff --git a/Plan/api/src/main/java/com/djrapitops/plan/extension/extractor/ExtensionMethod.java b/Plan/api/src/main/java/com/djrapitops/plan/extension/extractor/ExtensionMethod.java new file mode 100644 index 000000000..af51d794a --- /dev/null +++ b/Plan/api/src/main/java/com/djrapitops/plan/extension/extractor/ExtensionMethod.java @@ -0,0 +1,135 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.extractor; + +import com.djrapitops.plan.extension.DataExtension; +import com.djrapitops.plan.extension.Group; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; + +/** + * Implementation detail, abstracts away some method reflection to a more usable API. + */ +public class ExtensionMethod { + private final DataExtension extension; + private final Method method; + + private final Class returnType; + + public ExtensionMethod(DataExtension extension, Method method) { + this.extension = extension; + this.method = method; + returnType = method.getReturnType(); + } + + public boolean isInaccessible() { + int modifiers = method.getModifiers(); + return Modifier.isPrivate(modifiers) + || Modifier.isProtected(modifiers) + || Modifier.isStatic(modifiers) + || Modifier.isNative(modifiers); + } + + public Optional getAnnotation(Class ofType) { + return Optional.ofNullable(method.getAnnotation(ofType)); + } + + public T getExistingAnnotation(Class ofType) { + return getAnnotation(ofType).orElseThrow(() -> new IllegalArgumentException(method.getName() + " did not have " + ofType.getName() + " annotation")); + } + + public T getAnnotationOrNull(Class ofType) { + return getAnnotation(ofType).orElse(null); + } + + public ParameterType getParameterType() { + return ParameterType.getByMethodSignature(method); + } + + public Class getReturnType() { + return returnType; + } + + public Method getMethod() { + return method; + } + + public String getMethodName() { + return getMethod().getName(); + } + + public enum ParameterType { + SERVER_NONE(null), + PLAYER_STRING(String.class), + PLAYER_UUID(UUID.class), + GROUP(Group.class); + + private final Class type; + + ParameterType(Class type) { + this.type = type; + } + + public static ParameterType getByMethodSignature(Method method) { + Class[] parameters = method.getParameterTypes(); + if (parameters.length == 0) return SERVER_NONE; + + if (parameters.length > 1) { + // Has too many parameters + throw new IllegalArgumentException(method.getName() + " has too many parameters, only one parameter is required."); + } + + Class parameter = parameters[0]; + if (String.class.equals(parameter)) return PLAYER_STRING; + if (UUID.class.equals(parameter)) return PLAYER_UUID; + if (Group.class.equals(parameter)) return GROUP; + + throw new IllegalArgumentException(method.getName() + " does not have a valid parameter. Needs none, String, UUID or Group, had " + parameter.getSimpleName()); + } + + public Class getType() { + return type; + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ExtensionMethod that = (ExtensionMethod) o; + return Objects.equals(extension.getPluginName(), that.extension.getPluginName()) && Objects.equals(method, that.method) && Objects.equals(returnType, that.returnType); + } + + @Override + public int hashCode() { + return Objects.hash(extension.getPluginName(), method, returnType); + } + + @Override + public String toString() { + return "ExtensionMethod{" + + "extension=" + extension + + ", method=" + method + + ", returnType=" + returnType + + '}'; + } +} diff --git a/Plan/api/src/main/java/com/djrapitops/plan/extension/extractor/ExtensionMethods.java b/Plan/api/src/main/java/com/djrapitops/plan/extension/extractor/ExtensionMethods.java new file mode 100644 index 000000000..cfba74ba9 --- /dev/null +++ b/Plan/api/src/main/java/com/djrapitops/plan/extension/extractor/ExtensionMethods.java @@ -0,0 +1,145 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.extractor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * Implementation detail, abstracts away method type reflection to a more usable API. + */ +public class ExtensionMethods { + + private final List booleanProviders; + private final List numberProviders; + private final List doubleProviders; + private final List percentageProviders; + private final List stringProviders; + private final List tableProviders; + private final List groupProviders; + private final List dataBuilderProviders; + + public ExtensionMethods() { + booleanProviders = new ArrayList<>(); + numberProviders = new ArrayList<>(); + doubleProviders = new ArrayList<>(); + percentageProviders = new ArrayList<>(); + stringProviders = new ArrayList<>(); + tableProviders = new ArrayList<>(); + groupProviders = new ArrayList<>(); + dataBuilderProviders = new ArrayList<>(); + } + + public List getBooleanProviders() { + return booleanProviders; + } + + public List getNumberProviders() { + return numberProviders; + } + + public List getDoubleProviders() { + return doubleProviders; + } + + public List getPercentageProviders() { + return percentageProviders; + } + + public List getStringProviders() { + return stringProviders; + } + + public List getTableProviders() { + return tableProviders; + } + + public List getGroupProviders() { + return groupProviders; + } + + public List getDataBuilderProviders() { + return dataBuilderProviders; + } + + public void addBooleanMethod(ExtensionMethod method) { + booleanProviders.add(method); + } + + public void addNumberMethod(ExtensionMethod method) { + numberProviders.add(method); + } + + public void addDoubleMethod(ExtensionMethod method) { + doubleProviders.add(method); + } + + public void addPercentageMethod(ExtensionMethod method) { + percentageProviders.add(method); + } + + public void addStringMethod(ExtensionMethod method) { + stringProviders.add(method); + } + + public void addTableMethod(ExtensionMethod method) { + tableProviders.add(method); + } + + public void addGroupMethod(ExtensionMethod method) { + groupProviders.add(method); + } + + public void addDataBuilderMethod(ExtensionMethod method) { + dataBuilderProviders.add(method); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ExtensionMethods that = (ExtensionMethods) o; + return Objects.equals(booleanProviders, that.booleanProviders) + && Objects.equals(numberProviders, that.numberProviders) + && Objects.equals(doubleProviders, that.doubleProviders) + && Objects.equals(percentageProviders, that.percentageProviders) + && Objects.equals(stringProviders, that.stringProviders) + && Objects.equals(tableProviders, that.tableProviders) + && Objects.equals(groupProviders, that.groupProviders) + && Objects.equals(dataBuilderProviders, that.dataBuilderProviders); + } + + @Override + public int hashCode() { + return Objects.hash(booleanProviders, numberProviders, doubleProviders, percentageProviders, stringProviders, tableProviders, groupProviders, dataBuilderProviders); + } + + @Override + public String toString() { + return "ExtensionMethods{" + + "booleanProviders=" + booleanProviders + + ", numberProviders=" + numberProviders + + ", doubleProviders=" + doubleProviders + + ", percentageProviders=" + percentageProviders + + ", stringProviders=" + stringProviders + + ", tableProviders=" + tableProviders + + ", groupProviders=" + groupProviders + + ", dataBuilderProviders=" + dataBuilderProviders + + '}'; + } +} diff --git a/Plan/api/src/main/java/com/djrapitops/plan/extension/extractor/MethodAnnotations.java b/Plan/api/src/main/java/com/djrapitops/plan/extension/extractor/MethodAnnotations.java index 574c26281..1032c2556 100644 --- a/Plan/api/src/main/java/com/djrapitops/plan/extension/extractor/MethodAnnotations.java +++ b/Plan/api/src/main/java/com/djrapitops/plan/extension/extractor/MethodAnnotations.java @@ -27,7 +27,9 @@ import java.util.Optional; * Implementation detail, utility class for handling method annotations. * * @author AuroraLS3 + * @deprecated Old implementation used this. */ +@Deprecated public class MethodAnnotations { private final Map, Map> byAnnotationType; diff --git a/Plan/api/src/test/java/com/djrapitops/plan/extension/extractor/ExtensionExtractorTest.java b/Plan/api/src/test/java/com/djrapitops/plan/extension/extractor/ExtensionExtractorTest.java index 228d43c8e..860004788 100644 --- a/Plan/api/src/test/java/com/djrapitops/plan/extension/extractor/ExtensionExtractorTest.java +++ b/Plan/api/src/test/java/com/djrapitops/plan/extension/extractor/ExtensionExtractorTest.java @@ -19,9 +19,13 @@ 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.builder.ExtensionDataBuilder; +import com.djrapitops.plan.extension.table.Table; import org.junit.jupiter.api.Test; -import java.util.UUID; +import java.util.*; +import java.util.function.BiConsumer; +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -43,6 +47,13 @@ class ExtensionExtractorTest { assertEquals("Given class had no PluginInfo annotation", assertThrows(IllegalArgumentException.class, underTest::validateAnnotations).getMessage()); } + @Test + void pluginInfoIsRequired2() { + class Extension implements DataExtension {} + + assertEquals("Extension did not have @PluginInfo annotation!", assertThrows(IllegalArgumentException.class, new Extension()::getPluginName).getMessage()); + } + @Test void providerMethodsAreRequired() { @PluginInfo(name = "Extension") @@ -52,6 +63,14 @@ class ExtensionExtractorTest { assertEquals("Extension class had no methods annotated with a Provider annotation", assertThrows(IllegalArgumentException.class, underTest::validateAnnotations).getMessage()); } + @Test + void extensionNameIsAvailable() { + @PluginInfo(name = "Extension") + class Extension implements DataExtension {} + + assertEquals("Extension", new Extension().getPluginName()); + } + @Test void publicProviderMethodsAreRequired() { @PluginInfo(name = "Extension") @@ -206,6 +225,20 @@ class ExtensionExtractorTest { assertEquals("Extension.method has invalid return type. was: com.djrapitops.plan.extension.Group, expected: [Ljava.lang.String; (an array)", assertThrows(IllegalArgumentException.class, underTest::validateAnnotations).getMessage()); } + @Test + void dataBuilderProviderMustProvideDataBuilder() { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @DataBuilderProvider + public Group method(UUID playerUUID) { + return null; + } + } + + ExtensionExtractor underTest = new ExtensionExtractor(new Extension()); + assertEquals("Extension.method has invalid return type. was: com.djrapitops.plan.extension.Group, expected: com.djrapitops.plan.extension.builder.ExtensionDataBuilder", assertThrows(IllegalArgumentException.class, underTest::validateAnnotations).getMessage()); + } + @Test void booleanProviderCanNotSupplyItsOwnConditional() { @PluginInfo(name = "Extension") @@ -235,21 +268,6 @@ class ExtensionExtractorTest { assertEquals("Extension.method did not have any associated Provider for Conditional.", assertThrows(IllegalArgumentException.class, underTest::validateAnnotations).getMessage()); } - @Test - void conditionalNeedsToBeProvided() { - @PluginInfo(name = "Extension") - class Extension implements DataExtension { - @Conditional("hasJoined") - @BooleanProvider(text = "Banned", conditionName = "isBanned") - public boolean method(UUID playerUUID) { - return false; - } - } - - ExtensionExtractor underTest = new ExtensionExtractor(new Extension()); - assertEquals("Warnings: [Extension: 'hasJoined' Condition was not provided by any BooleanProvider.]", assertThrows(IllegalArgumentException.class, underTest::validateAnnotations).getMessage()); - } - @Test void methodNeedsValidParameters() { @PluginInfo(name = "Extension") @@ -280,4 +298,254 @@ class ExtensionExtractorTest { assertEquals("Extension.method has too many parameters, only one of [class java.util.UUID, class java.lang.String, interface com.djrapitops.plan.extension.Group] is required as a parameter.", assertThrows(IllegalArgumentException.class, underTest::validateAnnotations).getMessage()); } + @Test + void methodsAreExtracted1() throws NoSuchMethodException { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @Conditional("hasJoined") + @BooleanProvider(text = "Test", conditionName = "isBanned") + public boolean method() { + return false; + } + } + Extension extension = new Extension(); + ExtensionExtractor underTest = new ExtensionExtractor(extension); + Map result = underTest.getMethods(); + Map expected = buildExpectedExtensionMethodMap(extension, ExtensionMethods::addBooleanMethod); + + assertEquals(expected, result); + } + + @Test + void methodsAreExtracted2() throws NoSuchMethodException { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @Conditional("hasJoined") + @NumberProvider(text = "Test") + public long method() { + return 0; + } + } + Extension extension = new Extension(); + ExtensionExtractor underTest = new ExtensionExtractor(extension); + Map result = underTest.getMethods(); + Map expected = buildExpectedExtensionMethodMap(extension, ExtensionMethods::addNumberMethod); + + assertEquals(expected, result); + } + + @Test + void methodsAreExtracted3() throws NoSuchMethodException { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @Conditional("hasJoined") + @DoubleProvider(text = "Test") + public double method() { + return 0; + } + } + Extension extension = new Extension(); + ExtensionExtractor underTest = new ExtensionExtractor(extension); + Map result = underTest.getMethods(); + Map expected = buildExpectedExtensionMethodMap(extension, ExtensionMethods::addDoubleMethod); + + assertEquals(expected, result); + } + + @Test + void methodsAreExtracted4() throws NoSuchMethodException { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @Conditional("hasJoined") + @PercentageProvider(text = "Test") + public double method() { + return 0; + } + } + Extension extension = new Extension(); + ExtensionExtractor underTest = new ExtensionExtractor(extension); + Map result = underTest.getMethods(); + Map expected = buildExpectedExtensionMethodMap(extension, ExtensionMethods::addPercentageMethod); + + assertEquals(expected, result); + } + + @Test + void methodsAreExtracted5() throws NoSuchMethodException { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @Conditional("hasJoined") + @StringProvider(text = "Test") + public String method() { + return "example"; + } + } + Extension extension = new Extension(); + ExtensionExtractor underTest = new ExtensionExtractor(extension); + Map result = underTest.getMethods(); + Map expected = buildExpectedExtensionMethodMap(extension, ExtensionMethods::addStringMethod); + + assertEquals(expected, result); + } + + @Test + void methodsAreExtracted6() throws NoSuchMethodException { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @TableProvider + public Table method() { + return Table.builder().build(); + } + } + Extension extension = new Extension(); + ExtensionExtractor underTest = new ExtensionExtractor(extension); + Map result = underTest.getMethods(); + Map expected = buildExpectedExtensionMethodMap(extension, ExtensionMethods::addTableMethod); + + assertEquals(expected, result); + } + + @Test + void methodsAreExtracted7() throws NoSuchMethodException { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @GroupProvider + public String[] method(UUID playerUUID) { + return new String[]{"example"}; + } + } + Extension extension = new Extension(); + ExtensionExtractor underTest = new ExtensionExtractor(extension); + Map result = underTest.getMethods(); + + Map expected = new EnumMap<>(ExtensionMethod.ParameterType.class); + for (ExtensionMethod.ParameterType value : ExtensionMethod.ParameterType.values()) { + expected.put(value, new ExtensionMethods()); + } + expected.get(ExtensionMethod.ParameterType.PLAYER_UUID).addGroupMethod(new ExtensionMethod(extension, extension.getClass().getMethod("method", UUID.class))); + + assertEquals(expected, result); + } + + private Map buildExpectedExtensionMethodMap(DataExtension extension, BiConsumer addTo) throws NoSuchMethodException { + Map map = new EnumMap<>(ExtensionMethod.ParameterType.class); + for (ExtensionMethod.ParameterType value : ExtensionMethod.ParameterType.values()) { + map.put(value, new ExtensionMethods()); + } + addTo.accept( + map.get(ExtensionMethod.ParameterType.SERVER_NONE), + new ExtensionMethod(extension, extension.getClass().getMethod("method")) + ); + return map; + } + + @Test + void methodsAreExtracted8() throws NoSuchMethodException { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @DataBuilderProvider + public ExtensionDataBuilder method() { + return null; + } + } + Extension extension = new Extension(); + ExtensionExtractor underTest = new ExtensionExtractor(extension); + Map result = underTest.getMethods(); + Map expected = buildExpectedExtensionMethodMap(extension, ExtensionMethods::addDataBuilderMethod); + + assertEquals(expected, result); + } + + @Test + void tabsAreExtracted() throws NoSuchMethodException { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @Tab("Tab name") + @DataBuilderProvider + public ExtensionDataBuilder method() { + return null; + } + } + Extension extension = new Extension(); + ExtensionExtractor underTest = new ExtensionExtractor(extension); + + Collection expected = Collections.singletonList(extension.getClass().getMethod("method").getAnnotation(Tab.class)); + Collection result = underTest.getTabAnnotations(); + assertEquals(expected, result); + } + + @Test + void conditionalsAreExtracted() throws NoSuchMethodException { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @Conditional("example") + @StringProvider(text = "Test") + public String method() { + return "example"; + } + } + Extension extension = new Extension(); + ExtensionExtractor underTest = new ExtensionExtractor(extension); + + String expected = Stream.of(extension.getClass().getMethod("method").getAnnotation(Conditional.class)) + .map(Conditional::value).findFirst().orElseThrow(AssertionError::new); + String result = underTest.getMethodAnnotations().getAnnotations(Conditional.class).stream() + .map(Conditional::value).findFirst().orElseThrow(AssertionError::new); + assertEquals(expected, result); + } + + @Test + void textOver50CharsIsWarnedAbout() { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @StringProvider(text = "aaaaaAAAAAbbbbbBBBBBcccccCCCCCdddddDDDDDeeeeeEEEEEfffffFFFF") + public String method() { + return "example"; + } + } + Extension extension = new Extension(); + ExtensionExtractor underTest = new ExtensionExtractor(extension); + assertEquals( + "Warnings: [Extension.method 'text' was over 50 characters.]", + assertThrows(IllegalArgumentException.class, underTest::validateAnnotations).getMessage() + ); + } + + @Test + void descriptionOver50CharsIsWarnedAbout() { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @StringProvider( + text = "a", + description = "aaaaaAAAAAbbbbbBBBBBcccccCCCCCdddddDDDDDeeeeeEEEEEaaaaaAAAAAbbbbbBBBBBcccccCCCCCdddddDDDDDeeeeeEEEEEaaaaaAAAAAbbbbbBBBBBcccccCCCCCdddddDDDDDeeeeeEEEEEfffffFFFFF" + ) + public String method() { + return "example"; + } + } + Extension extension = new Extension(); + ExtensionExtractor underTest = new ExtensionExtractor(extension); + assertEquals( + "Warnings: [Extension.method 'description' was over 150 characters.]", + assertThrows(IllegalArgumentException.class, underTest::validateAnnotations).getMessage() + ); + } + + @Test + void dataBuilderProviderCanNotHaveConditional() { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @Conditional("bad") + @DataBuilderProvider + public ExtensionDataBuilder method() { + return null; + } + } + Extension extension = new Extension(); + ExtensionExtractor underTest = new ExtensionExtractor(extension); + assertEquals( + "Extension.method had Conditional, but DataBuilderProvider does not support it!", + assertThrows(IllegalArgumentException.class, underTest::validateAnnotations).getMessage() + ); + } } \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/PlanSystem.java b/Plan/common/src/main/java/com/djrapitops/plan/PlanSystem.java index 886a1c6d4..868ffedf1 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/PlanSystem.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/PlanSystem.java @@ -23,7 +23,6 @@ import com.djrapitops.plan.delivery.web.ResolverSvc; import com.djrapitops.plan.delivery.web.ResourceSvc; import com.djrapitops.plan.delivery.webserver.NonProxyWebserverDisableChecker; import com.djrapitops.plan.delivery.webserver.WebServerSystem; -import com.djrapitops.plan.extension.ExtensionService; import com.djrapitops.plan.extension.ExtensionSvc; import com.djrapitops.plan.gathering.cache.CacheSystem; import com.djrapitops.plan.gathering.importing.ImportSystem; @@ -275,7 +274,7 @@ public class PlanSystem implements SubSystem { return enabled; } - public ExtensionService getExtensionService() { + public ExtensionSvc getExtensionService() { return extensionService; } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/exceptions/DataExtensionMethodCallException.java b/Plan/common/src/main/java/com/djrapitops/plan/exceptions/DataExtensionMethodCallException.java index 393659151..9c29b5495 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/exceptions/DataExtensionMethodCallException.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/exceptions/DataExtensionMethodCallException.java @@ -16,8 +16,6 @@ */ package com.djrapitops.plan.exceptions; -import com.djrapitops.plan.extension.implementation.providers.MethodWrapper; - import java.util.Optional; /** @@ -28,21 +26,19 @@ import java.util.Optional; public class DataExtensionMethodCallException extends IllegalStateException { private final String pluginName; - // Non serializable field due to Method not being serializable. - private final transient MethodWrapper method; + private final String methodName; - public DataExtensionMethodCallException(Throwable cause, String pluginName, MethodWrapper method) { - super(cause); + public DataExtensionMethodCallException(String message, Throwable cause, String pluginName, String methodName) { + super(message, cause); this.pluginName = pluginName; - this.method = method; + this.methodName = methodName; } public String getPluginName() { return pluginName; } - public Optional> getMethod() { - // method is transient and might be lost if flushed to disk. - return Optional.ofNullable(method); + public Optional getMethodName() { + return Optional.ofNullable(methodName); } } \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/ExtensionSvc.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/ExtensionSvc.java index 72e71d987..876050ebf 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/ExtensionSvc.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/ExtensionSvc.java @@ -16,12 +16,12 @@ */ package com.djrapitops.plan.extension; -import com.djrapitops.plan.exceptions.DataExtensionMethodCallException; +import com.djrapitops.plan.extension.builder.ExtensionDataBuilder; import com.djrapitops.plan.extension.implementation.CallerImplementation; import com.djrapitops.plan.extension.implementation.ExtensionRegister; import com.djrapitops.plan.extension.implementation.ExtensionWrapper; -import com.djrapitops.plan.extension.implementation.providers.MethodWrapper; -import com.djrapitops.plan.extension.implementation.providers.gathering.ProviderValueGatherer; +import com.djrapitops.plan.extension.implementation.builder.ExtDataBuilder; +import com.djrapitops.plan.extension.implementation.providers.gathering.DataValueGatherer; import com.djrapitops.plan.identification.ServerInfo; import com.djrapitops.plan.processing.Processing; import com.djrapitops.plan.settings.config.ExtensionSettings; @@ -55,7 +55,7 @@ public class ExtensionSvc implements ExtensionService { private final PluginLogger logger; private final ErrorLogger errorLogger; - private final Map extensionGatherers; + private final Map extensionGatherers; @Inject public ExtensionSvc( @@ -98,17 +98,17 @@ public class ExtensionSvc implements ExtensionService { } @Override - public Optional register(DataExtension extension) { - ExtensionWrapper extractor = new ExtensionWrapper(extension); - String pluginName = extractor.getPluginName(); + public Optional register(DataExtension dataExtension) { + ExtensionWrapper extension = new ExtensionWrapper(dataExtension); + String pluginName = extension.getPluginName(); if (shouldNotAllowRegistration(pluginName)) return Optional.empty(); - for (String warning : extractor.getWarnings()) { + for (String warning : extension.getWarnings()) { logger.warn("DataExtension API implementation mistake for " + pluginName + ": " + warning); } - ProviderValueGatherer gatherer = new ProviderValueGatherer(extractor, dbSystem, serverInfo); + DataValueGatherer gatherer = new DataValueGatherer(extension, dbSystem, serverInfo, errorLogger); gatherer.storeExtensionInformation(); extensionGatherers.put(pluginName, gatherer); @@ -120,9 +120,12 @@ public class ExtensionSvc implements ExtensionService { @Override public void unregister(DataExtension extension) { - ExtensionWrapper extractor = new ExtensionWrapper(extension); - String pluginName = extractor.getPluginName(); - extensionGatherers.remove(pluginName); + extensionGatherers.remove(extension.getPluginName()); + } + + @Override + public ExtensionDataBuilder newExtensionDataBuilder(DataExtension extension) { + return new ExtDataBuilder(extension); } private boolean shouldNotAllowRegistration(String pluginName) { @@ -145,61 +148,27 @@ public class ExtensionSvc implements ExtensionService { } public void updatePlayerValues(UUID playerUUID, String playerName, CallEvents event) { - for (ProviderValueGatherer gatherer : extensionGatherers.values()) { + for (DataValueGatherer gatherer : extensionGatherers.values()) { updatePlayerValues(gatherer, playerUUID, playerName, event); } } - public void updatePlayerValues(ProviderValueGatherer gatherer, UUID playerUUID, String playerName, CallEvents event) { + public void updatePlayerValues(DataValueGatherer gatherer, UUID playerUUID, String playerName, CallEvents event) { if (gatherer.shouldSkipEvent(event)) return; if (playerUUID == null && playerName == null) return; - try { - gatherer.updateValues(playerUUID, playerName); - } catch (DataExtensionMethodCallException methodCallFailed) { - logFailure(playerName, methodCallFailed); - methodCallFailed.getMethod().ifPresent(gatherer::disableMethodFromUse); - } catch (Exception | NoClassDefFoundError | NoSuchFieldError | NoSuchMethodError unexpectedError) { - ErrorContext.Builder context = ErrorContext.builder() - .whatToDo("Report and/or disable " + gatherer.getPluginName() + " extension in the Plan config.") - .related(gatherer.getPluginName()) - .related(event) - .related("Player: " + playerName + " " + playerUUID); - errorLogger.warn(unexpectedError, context.build()); - } - } - - private void logFailure(String playerName, DataExtensionMethodCallException methodCallFailed) { - Throwable cause = methodCallFailed.getCause(); - ErrorContext.Builder context = ErrorContext.builder() - .whatToDo("Report and/or disable " + methodCallFailed.getPluginName() + " extension in the Plan config.") - .related(methodCallFailed.getPluginName()) - .related("Method:" + methodCallFailed.getMethod().map(MethodWrapper::getMethodName).orElse("-")) - .related("Player: " + playerName); - errorLogger.warn(cause, context.build()); + gatherer.updateValues(playerUUID, playerName); } public void updateServerValues(CallEvents event) { - for (ProviderValueGatherer gatherer : extensionGatherers.values()) { + for (DataValueGatherer gatherer : extensionGatherers.values()) { updateServerValues(gatherer, event); } } - public void updateServerValues(ProviderValueGatherer gatherer, CallEvents event) { + public void updateServerValues(DataValueGatherer gatherer, CallEvents event) { if (gatherer.shouldSkipEvent(event)) return; - try { - gatherer.updateValues(); - } catch (DataExtensionMethodCallException methodCallFailed) { - logFailure("server", methodCallFailed); - methodCallFailed.getMethod().ifPresent(gatherer::disableMethodFromUse); - } catch (Exception | NoClassDefFoundError | NoSuchFieldError | NoSuchMethodError unexpectedError) { - ErrorContext.Builder context = ErrorContext.builder() - .whatToDo("Report and/or disable " + gatherer.getPluginName() + " extension in the Plan config.") - .related(gatherer.getPluginName()) - .related(event) - .related("Gathering for server"); - errorLogger.warn(unexpectedError, context.build()); - } + gatherer.updateValues(); } } \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/CallerImplementation.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/CallerImplementation.java index 1908ee570..c3bf670a5 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/CallerImplementation.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/CallerImplementation.java @@ -19,7 +19,7 @@ package com.djrapitops.plan.extension.implementation; import com.djrapitops.plan.extension.CallEvents; import com.djrapitops.plan.extension.Caller; import com.djrapitops.plan.extension.ExtensionSvc; -import com.djrapitops.plan.extension.implementation.providers.gathering.ProviderValueGatherer; +import com.djrapitops.plan.extension.implementation.providers.gathering.DataValueGatherer; import com.djrapitops.plan.processing.Processing; import java.util.UUID; @@ -31,12 +31,12 @@ import java.util.UUID; */ public class CallerImplementation implements Caller { - private final ProviderValueGatherer gatherer; + private final DataValueGatherer gatherer; private final ExtensionSvc extensionService; private final Processing processing; public CallerImplementation( - ProviderValueGatherer gatherer, + DataValueGatherer gatherer, ExtensionSvc extensionService, Processing processing ) { diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/ExtensionWrapper.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/ExtensionWrapper.java index 247065fd5..0a7f36d9c 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/ExtensionWrapper.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/ExtensionWrapper.java @@ -20,19 +20,13 @@ import com.djrapitops.plan.extension.CallEvents; import com.djrapitops.plan.extension.DataExtension; import com.djrapitops.plan.extension.annotation.*; import com.djrapitops.plan.extension.extractor.ExtensionExtractor; -import com.djrapitops.plan.extension.extractor.MethodAnnotations; +import com.djrapitops.plan.extension.extractor.ExtensionMethod; +import com.djrapitops.plan.extension.extractor.ExtensionMethods; import com.djrapitops.plan.extension.icon.Color; import com.djrapitops.plan.extension.icon.Icon; -import com.djrapitops.plan.extension.implementation.providers.*; import com.djrapitops.plan.utilities.java.Lists; -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.function.Function; +import java.util.*; import java.util.stream.Collectors; /** @@ -47,9 +41,12 @@ import java.util.stream.Collectors; public class ExtensionWrapper { private final ExtensionExtractor extractor; - private final DataProviders providers; private final DataExtension extension; + private final PluginInfo pluginInfo; + private final List tabInformation; + private final Map methods; + /** * Create an ExtensionWrapper. * @@ -60,10 +57,9 @@ public class ExtensionWrapper { this.extension = extension; extractor = new ExtensionExtractor(this.extension); - extractor.extractAnnotationInformation(); - - providers = new DataProviders(); - extractProviders(); + pluginInfo = extractor.getPluginInfo(); + tabInformation = extractor.getTabInformation(); + methods = extractor.getMethods(); } public CallEvents[] getCallEvents() { @@ -75,30 +71,28 @@ public class ExtensionWrapper { } public String getPluginName() { - return extractor.getPluginInfo().name(); + return pluginInfo.name(); } public Icon getPluginIcon() { - PluginInfo pluginInfo = extractor.getPluginInfo(); return new Icon(pluginInfo.iconFamily(), pluginInfo.iconName(), pluginInfo.color()); } public Collection getPluginTabs() { - Map tabInformation = extractor.getTabInformation() - .stream().collect(Collectors.toMap(TabInfo::tab, Function.identity(), (one, two) -> one)); - Map order = getTabOrder().map(this::orderToMap).orElse(new HashMap<>()); - // Extracts PluginTabs - return extractor.getMethodAnnotations().getAnnotations(Tab.class).stream() + Set usedTabs = extractor.getTabAnnotations().stream() .map(Tab::value) - .distinct() - .map(tabName -> { - Optional tabInfo = Optional.ofNullable(tabInformation.get(tabName)); + .collect(Collectors.toSet()); + return extractor.getTabInformation() + .stream() + .filter(info -> usedTabs.contains(info.tab())) + .map(tabInfo -> { + String tabName = tabInfo.tab(); return new TabInformation( tabName, - tabInfo.map(info -> new Icon(info.iconFamily(), info.iconName(), Color.NONE)).orElse(null), - tabInfo.map(TabInfo::elementOrder).orElse(null), + new Icon(tabInfo.iconFamily(), tabInfo.iconName(), Color.NONE), + tabInfo.elementOrder(), order.getOrDefault(tabName, 100) ); }).collect(Collectors.toList()); @@ -120,57 +114,23 @@ public class ExtensionWrapper { return Lists.mapUnique(extractor.getInvalidateMethodAnnotations(), InvalidateMethod::value); } - public DataProviders getProviders() { - return providers; - } - - private void extractProviders() { - PluginInfo pluginInfo = extractor.getPluginInfo(); - - MethodAnnotations methodAnnotations = extractor.getMethodAnnotations(); - Map tabs = methodAnnotations.getMethodAnnotations(Tab.class); - Map conditions = methodAnnotations.getMethodAnnotations(Conditional.class); - - extractProviders(pluginInfo, tabs, conditions, BooleanProvider.class, BooleanDataProvider::placeToDataProviders); - extractProviders(pluginInfo, tabs, conditions, DoubleProvider.class, DoubleDataProvider::placeToDataProviders); - extractProviders(pluginInfo, tabs, conditions, PercentageProvider.class, PercentageDataProvider::placeToDataProviders); - extractProviders(pluginInfo, tabs, conditions, NumberProvider.class, NumberDataProvider::placeToDataProviders); - extractProviders(pluginInfo, tabs, conditions, StringProvider.class, StringDataProvider::placeToDataProviders); - extractProviders(pluginInfo, tabs, conditions, TableProvider.class, TableDataProvider::placeToDataProviders); - extractProviders(pluginInfo, tabs, conditions, GroupProvider.class, GroupDataProvider::placeToDataProviders); - } - - private void extractProviders(PluginInfo pluginInfo, Map tabs, Map conditions, Class ofKind, DataProviderFactory factory) { - String pluginName = pluginInfo.name(); - - for (Map.Entry entry : extractor.getMethodAnnotations().getMethodAnnotations(ofKind).entrySet()) { - Method method = entry.getKey(); - T annotation = entry.getValue(); - Conditional conditional = conditions.get(method); - Optional tab = Optional.ofNullable(tabs.get(method)); - - factory.placeToDataProviders( - providers, method, annotation, - conditional, - tab.map(Tab::value).orElse(null), - pluginName - ); - } - } - public Collection getWarnings() { return extractor.getWarnings(); } - /** - * Functional interface for defining a method that places required DataProvider to DataProviders. - * - * @param Type of the annotation on the method that is going to be extracted. - */ - interface DataProviderFactory { - void placeToDataProviders( - DataProviders dataProviders, - Method method, T annotation, Conditional condition, String tab, String pluginName - ); + public ExtensionExtractor getExtractor() { + return extractor; + } + + public PluginInfo getPluginInfo() { + return pluginInfo; + } + + public List getTabInformation() { + return tabInformation; + } + + public Map getMethods() { + return methods; } } \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/ProviderInformation.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/ProviderInformation.java index 60f36a6b1..eee2219bc 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/ProviderInformation.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/ProviderInformation.java @@ -45,7 +45,13 @@ public class ProviderInformation extends ExtensionDescription { private final boolean percentage; // affects where doubles are stored private ProviderInformation(ProviderInformation.Builder builder) { - super(builder.name, builder.text, builder.description, builder.icon, builder.priority); + super( + builder.name, + builder.text, + builder.description, + builder.icon != null ? builder.icon : Icon.called("cube").build(), + builder.priority + ); pluginName = builder.pluginName; showInPlayersTable = builder.showInPlayersTable; tab = builder.tab; @@ -136,7 +142,7 @@ public class ProviderInformation extends ExtensionDescription { private String text; private String description; private Icon icon; - private int priority; + private int priority = 0; private boolean showInPlayersTable = false; private String tab; // can be null private Conditional condition; // can be null diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/BooleanDataValue.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/BooleanDataValue.java new file mode 100644 index 000000000..1fb7c2fec --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/BooleanDataValue.java @@ -0,0 +1,31 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.implementation.builder; + +import com.djrapitops.plan.extension.implementation.ProviderInformation; + +import java.util.function.Supplier; + +public class BooleanDataValue extends BuiltDataValue { + public BooleanDataValue(Boolean value, ProviderInformation information) { + super(value, information); + } + + public BooleanDataValue(Supplier supplier, ProviderInformation information) { + super(supplier, information); + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/BuiltDataValue.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/BuiltDataValue.java new file mode 100644 index 000000000..cb37a2b04 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/BuiltDataValue.java @@ -0,0 +1,83 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.implementation.builder; + +import com.djrapitops.plan.extension.builder.DataValue; +import com.djrapitops.plan.extension.implementation.ProviderInformation; + +import java.util.Objects; +import java.util.function.Supplier; + +public abstract class BuiltDataValue implements DataValue { + + private final T value; + private final Supplier supplier; + private final ProviderInformation information; + + protected BuiltDataValue(T value, ProviderInformation information) { + this(value, null, information); + } + + protected BuiltDataValue(Supplier supplier, ProviderInformation information) { + this(null, supplier, information); + } + + private BuiltDataValue(T value, Supplier supplier, ProviderInformation information) { + this.value = value; + this.supplier = supplier; + this.information = information; + } + + @Override + public T getValue() { + if (value != null) return value; + if (supplier != null) return supplier.get(); + return null; + } + + public ProviderInformation getInformation() { + return information; + } + + @Override + public M getInformation(Class ofType) { + if (ProviderInformation.class.equals(ofType)) return ofType.cast(getInformation()); + return null; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + BuiltDataValue that = (BuiltDataValue) o; + return Objects.equals(value, that.value) && Objects.equals(supplier, that.supplier) && Objects.equals(information, that.information); + } + + @Override + public int hashCode() { + return Objects.hash(value, supplier, information); + } + + @Override + public String toString() { + return getClass().getSimpleName() + "{" + + "value=" + value + + ", supplier=" + supplier + + ", information=" + information + + '}'; + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/DoubleDataValue.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/DoubleDataValue.java new file mode 100644 index 000000000..c22f14cc9 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/DoubleDataValue.java @@ -0,0 +1,31 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.implementation.builder; + +import com.djrapitops.plan.extension.implementation.ProviderInformation; + +import java.util.function.Supplier; + +public class DoubleDataValue extends BuiltDataValue { + public DoubleDataValue(Double value, ProviderInformation information) { + super(value, information); + } + + public DoubleDataValue(Supplier supplier, ProviderInformation information) { + super(supplier, information); + } +} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/ExtDataBuilder.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/ExtDataBuilder.java new file mode 100644 index 000000000..2fa5075ee --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/ExtDataBuilder.java @@ -0,0 +1,149 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.implementation.builder; + +import com.djrapitops.plan.extension.DataExtension; +import com.djrapitops.plan.extension.NotReadyException; +import com.djrapitops.plan.extension.builder.DataValue; +import com.djrapitops.plan.extension.builder.ExtensionDataBuilder; +import com.djrapitops.plan.extension.builder.ValueBuilder; +import com.djrapitops.plan.extension.implementation.providers.gathering.Conditions; + +import java.util.*; +import java.util.function.Supplier; + +public class ExtDataBuilder implements ExtensionDataBuilder { + + private final List values; + private final DataExtension extension; + + public ExtDataBuilder(DataExtension extension) { + this.extension = extension; + values = new ArrayList<>(); + } + + @Override + public ValueBuilder valueBuilder(String text) { + if (text == null || text.isEmpty()) throw new IllegalArgumentException("'text' can't be null or empty"); + return new ExtValueBuilder(text, extension); + } + + @Override + public ExtensionDataBuilder addValue(Class ofType, DataValue dataValue) { + if (ofType != null && dataValue != null) values.add(new ClassValuePair(ofType, dataValue)); + return this; + } + + @Override + public ExtensionDataBuilder addValue(Class ofType, Supplier> dataValue) { + try { + if (ofType != null && dataValue != null) values.add(new ClassValuePair(ofType, dataValue.get())); + } catch (NotReadyException | UnsupportedOperationException ignored) { + // This exception is ignored by default to allow throwing errors inside the lambda to keep code clean. + } + // Other exceptions handled by ProviderValueGatherer during method call. + return this; + } + + public List getValues() { + Collections.sort(values); + return values; + } + + public String getExtensionName() { + return extension.getPluginName(); + } + + @Override + public void addAll(ExtensionDataBuilder builder) { + if (!(builder instanceof ExtDataBuilder)) return; + // From same DataExtension + if (!extension.getClass().equals(((ExtDataBuilder) builder).extension.getClass())) { + throw new IllegalArgumentException("Can not combine data from two different extensions! (" + + extension.getClass().getName() + ',' + ((ExtDataBuilder) builder).extension.getClass().getName() + ")"); + } + + this.values.addAll(((ExtDataBuilder) builder).values); + } + + public static final class ClassValuePair implements Comparable { + private final Class type; + private final DataValue value; + + public ClassValuePair(Class type, DataValue value) { + this.type = type; + this.value = value; + } + + public Optional> getValue(Class ofType) { + if (type.equals(ofType)) { + return Optional.ofNullable((DataValue) value); + } + return Optional.empty(); + } + + @Override + public int compareTo(ClassValuePair that) { + boolean thisIsBoolean = Boolean.class.isAssignableFrom(type) && value instanceof BooleanDataValue; + boolean otherIsBoolean = Boolean.class.isAssignableFrom(that.type) && that.value instanceof BooleanDataValue; + if (thisIsBoolean && !otherIsBoolean) { + return -1; // This is boolean, have it go first + } else if (!thisIsBoolean && otherIsBoolean) { + return 1; // Other is boolean, have it go first + } else if (thisIsBoolean) { + // Both are Booleans, so they might provide a condition + + Optional otherCondition = ((BooleanDataValue) that.value).getInformation().getCondition(); + String providedCondition = ((BooleanDataValue) value).getInformation().getProvidedCondition(); + // Another provider's required condition is satisfied by this, have this first + if (otherCondition.filter(c -> Conditions.matchesCondition(c, providedCondition)).isPresent()) { + return -1; + } + + // Required condition is satisfied by another provider, have that first + Optional condition = ((BooleanDataValue) value).getInformation().getCondition(); + String otherProvidedCondition = ((BooleanDataValue) that.value).getInformation().getProvidedCondition(); + if (condition.filter(c -> Conditions.matchesCondition(c, otherProvidedCondition)).isPresent()) { + return 1; + } + } + // Irrelevant, keep where is + return 0; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ClassValuePair that = (ClassValuePair) o; + return Objects.equals(type, that.type) && Objects.equals(value, that.value); + } + + @Override + public int hashCode() { + return Objects.hash(type, value); + } + + @Override + public String toString() { + return "ClassValuePair{" + + "type=" + type + + ", value=" + value + + '}'; + } + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/ExtValueBuilder.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/ExtValueBuilder.java new file mode 100644 index 000000000..7af5b4060 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/ExtValueBuilder.java @@ -0,0 +1,243 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.implementation.builder; + +import com.djrapitops.plan.extension.DataExtension; +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.PluginInfo; +import com.djrapitops.plan.extension.builder.DataValue; +import com.djrapitops.plan.extension.builder.ValueBuilder; +import com.djrapitops.plan.extension.extractor.ExtensionMethod; +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.util.function.Supplier; + +public class ExtValueBuilder implements ValueBuilder { + + private final String pluginName; + private final String text; + private String providerName; + private String description; + private int priority = 0; + private boolean showInPlayerTable = false; + private Icon icon; + private String tabName; + + private boolean hidden = false; + private boolean formatAsPlayerName = false; + private FormatType formatType = FormatType.NONE; + private Conditional conditional; + + public ExtValueBuilder(String text, DataExtension extension) { + this.text = text; + pluginName = extension.getClass().getAnnotation(PluginInfo.class).name(); + } + + @Override + public ValueBuilder methodName(ExtensionMethod method) { + this.providerName = method.getMethod().getName(); + return this; + } + + @Override + public ValueBuilder description(String description) { + this.description = description; + return this; + } + + @Override + public ValueBuilder priority(int priority) { + this.priority = priority; + return this; + } + + @Override + public ValueBuilder showInPlayerTable() { + this.showInPlayerTable = true; + return this; + } + + @Override + public ValueBuilder icon(Icon icon) { + this.icon = icon; + return this; + } + + @Override + public ValueBuilder showOnTab(String tabName) { + this.tabName = tabName; + return this; + } + + @Override + public ValueBuilder format(FormatType formatType) { + this.formatType = formatType; + return this; + } + + @Override + public ValueBuilder showAsPlayerPageLink() { + formatAsPlayerName = true; + return this; + } + + @Override + public ValueBuilder hideFromUsers(BooleanProvider annotation) { + this.hidden = annotation.hidden(); + return this; + } + + @Override + public ValueBuilder conditional(Conditional conditional) { + this.conditional = conditional; + return this; + } + + private ProviderInformation getProviderInformation() { + return getProviderInformation(false, null); + } + + private ProviderInformation getBooleanProviderInformation(String providedCondition) { + return getProviderInformation(false, providedCondition); + } + + private ProviderInformation getPercentageProviderInformation() { + return getProviderInformation(true, null); + } + + private ProviderInformation getProviderInformation(boolean percentage, String providedCondition) { + ProviderInformation.Builder builder = ProviderInformation.builder(pluginName) + .setName(providerName != null ? providerName + : text.toLowerCase().replaceAll("\\s", "")) + .setText(text) + .setDescription(description) + .setPriority(priority) + .setIcon(icon) + .setShowInPlayersTable(showInPlayerTable) + .setTab(tabName) + .setPlayerName(formatAsPlayerName) + .setFormatType(formatType) + .setHidden(hidden) + .setCondition(conditional); + + if (percentage) { + builder = builder.setAsPercentage(); + } + + if (providedCondition != null && !providedCondition.isEmpty()) { + builder = builder.setProvidedCondition(providedCondition); + } + + return builder.build(); + } + + private ProviderInformation getTableProviderInformation(Color tableColor) { + return ProviderInformation.builder(pluginName) + .setName(providerName != null ? providerName + : text.toLowerCase().replaceAll("\\s", "")) + .setPriority(0) + .setCondition(conditional) + .setTab(tabName) + .setTableColor(tableColor) + .build(); + } + + @Override + public DataValue buildBoolean(boolean value) { + return new BooleanDataValue(value, getProviderInformation()); + } + + @Override + public DataValue buildBooleanProvidingCondition(boolean value, String providedCondition) { + return new BooleanDataValue(value, getBooleanProviderInformation(providedCondition)); + } + + @Override + public DataValue buildString(String value) { + return new StringDataValue(value, getProviderInformation()); + } + + @Override + public DataValue buildNumber(long value) { + return new NumberDataValue(value, getProviderInformation()); + } + + @Override + public DataValue buildDouble(double value) { + return new DoubleDataValue(value, getProviderInformation()); + } + + @Override + public DataValue buildPercentage(double value) { + return new DoubleDataValue(value, getPercentageProviderInformation()); + } + + @Override + public DataValue buildGroup(String[] groups) { + return new GroupsDataValue(groups, getProviderInformation()); + } + + @Override + public DataValue buildBoolean(Supplier value) { + return new BooleanDataValue(value, getProviderInformation()); + } + + @Override + public DataValue buildBooleanProvidingCondition(Supplier value, String providedCondition) { + return new BooleanDataValue(value, getBooleanProviderInformation(providedCondition)); + } + + @Override + public DataValue buildString(Supplier value) { + return new StringDataValue(value, getProviderInformation()); + } + + @Override + public DataValue buildNumber(Supplier value) { + return new NumberDataValue(value, getProviderInformation()); + } + + @Override + public DataValue buildDouble(Supplier value) { + return new DoubleDataValue(value, getProviderInformation()); + } + + @Override + public DataValue buildPercentage(Supplier percentage) { + return new DoubleDataValue(percentage, getPercentageProviderInformation()); + } + + @Override + public DataValue buildGroup(Supplier groups) { + return new GroupsDataValue(groups, getProviderInformation()); + } + + @Override + public DataValue

buildTable(Table table, Color tableColor) { + return new TableDataValue(table, getTableProviderInformation(tableColor)); + } + + @Override + public DataValue
buildTable(Supplier
table, Color tableColor) { + return new TableDataValue(table, getTableProviderInformation(tableColor)); + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/GroupsDataValue.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/GroupsDataValue.java new file mode 100644 index 000000000..013e49291 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/GroupsDataValue.java @@ -0,0 +1,31 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.implementation.builder; + +import com.djrapitops.plan.extension.implementation.ProviderInformation; + +import java.util.function.Supplier; + +public class GroupsDataValue extends BuiltDataValue { + public GroupsDataValue(String[] value, ProviderInformation information) { + super(value, information); + } + + public GroupsDataValue(Supplier supplier, ProviderInformation information) { + super(supplier, information); + } +} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/NumberDataValue.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/NumberDataValue.java new file mode 100644 index 000000000..46055e5f8 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/NumberDataValue.java @@ -0,0 +1,31 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.implementation.builder; + +import com.djrapitops.plan.extension.implementation.ProviderInformation; + +import java.util.function.Supplier; + +public class NumberDataValue extends BuiltDataValue { + public NumberDataValue(Long value, ProviderInformation information) { + super(value, information); + } + + public NumberDataValue(Supplier supplier, ProviderInformation information) { + super(supplier, information); + } +} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/StringDataValue.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/StringDataValue.java new file mode 100644 index 000000000..1ace9ab50 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/StringDataValue.java @@ -0,0 +1,31 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.implementation.builder; + +import com.djrapitops.plan.extension.implementation.ProviderInformation; + +import java.util.function.Supplier; + +public class StringDataValue extends BuiltDataValue { + public StringDataValue(String value, ProviderInformation information) { + super(value, information); + } + + public StringDataValue(Supplier supplier, ProviderInformation information) { + super(supplier, information); + } +} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/TableDataValue.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/TableDataValue.java new file mode 100644 index 000000000..ca27db653 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/builder/TableDataValue.java @@ -0,0 +1,32 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.implementation.builder; + +import com.djrapitops.plan.extension.implementation.ProviderInformation; +import com.djrapitops.plan.extension.table.Table; + +import java.util.function.Supplier; + +public class TableDataValue extends BuiltDataValue
{ + public TableDataValue(Table value, ProviderInformation information) { + super(value, information); + } + + public TableDataValue(Supplier
supplier, ProviderInformation information) { + super(supplier, information); + } +} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/BooleanDataProvider.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/BooleanDataProvider.java deleted file mode 100644 index 7fbffe4e0..000000000 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/BooleanDataProvider.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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 . - */ -package com.djrapitops.plan.extension.implementation.providers; - -import com.djrapitops.plan.extension.annotation.BooleanProvider; -import com.djrapitops.plan.extension.annotation.Conditional; -import com.djrapitops.plan.extension.icon.Icon; -import com.djrapitops.plan.extension.implementation.ProviderInformation; - -import java.lang.reflect.Method; - -/** - * Contains code that acts on {@link BooleanProvider} annotations. - * - * @author AuroraLS3 - */ -public class BooleanDataProvider { - - private BooleanDataProvider() { - // Static method class - } - - public static void placeToDataProviders( - DataProviders dataProviders, Method method, BooleanProvider annotation, - Conditional condition, String tab, String pluginName - ) { - ProviderInformation information = ProviderInformation.builder(pluginName) - .setName(method.getName()) - .setText(annotation.text()) - .setDescription(annotation.description()) - .setPriority(annotation.priority()) - .setIcon(new Icon( - annotation.iconFamily(), - annotation.iconName(), - annotation.iconColor()) - ).setShowInPlayersTable(annotation.showInPlayerTable()) - .setCondition(condition) - .setTab(tab) - .setHidden(annotation.hidden()) - .setProvidedCondition(annotation.conditionName()) - .build(); - - MethodWrapper methodWrapper = new MethodWrapper<>(method, Boolean.class); - dataProviders.put(new DataProvider<>(information, methodWrapper)); - } -} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/DataProviders.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/DataProviders.java deleted file mode 100644 index dea2dd162..000000000 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/DataProviders.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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 . - */ -package com.djrapitops.plan.extension.implementation.providers; - -import com.djrapitops.plan.extension.implementation.MethodType; -import com.djrapitops.plan.utilities.java.Lists; -import com.djrapitops.plan.utilities.java.Maps; - -import java.util.*; - -/** - * Group class for handling multiple different types of {@link DataProvider}s. - * - * @author AuroraLS3 - */ -public class DataProviders { - - private final Map, List>>> byMethodType; - - public DataProviders() { - byMethodType = new EnumMap<>(MethodType.class); - } - - public void put(DataProvider provider) { - MethodWrapper method = provider.getMethod(); - MethodType methodType = method.getMethodType(); - Class returnType = method.getReturnType(); - - computeIfAbsent(methodType, returnType).add(provider); - } - - private List> computeIfAbsent(MethodType methodType, Class returnType) { - return byMethodType.computeIfAbsent(methodType, Maps::create).computeIfAbsent(returnType, Lists::create); - } - - public List> getProvidersByTypes(MethodType methodType, Class returnType) { - Map, List>> byReturnType = byMethodType.getOrDefault(methodType, Collections.emptyMap()); - List> wildcardProvidersWithSpecificType = byReturnType.get(returnType); - if (wildcardProvidersWithSpecificType == null) { - return Collections.emptyList(); - } - // Cast to T - List> providers = new ArrayList<>(); - for (DataProvider dataProvider : wildcardProvidersWithSpecificType) { - providers.add((DataProvider) dataProvider); - } - return providers; - } - - public List> getPlayerMethodsByType(Class returnType) { - return getProvidersByTypes(MethodType.PLAYER, returnType); - } - - public List> getServerMethodsByType(Class returnType) { - return getProvidersByTypes(MethodType.SERVER, returnType); - } - - public List> getGroupMethodsByType(Class returnType) { - return getProvidersByTypes(MethodType.GROUP, returnType); - } - - public void removeProviderWithMethod(MethodWrapper toRemove) { - MethodType methodType = toRemove.getMethodType(); - Map, List>> byResultType = byMethodType.getOrDefault(methodType, Collections.emptyMap()); - if (byResultType.isEmpty()) { - return; - } - - Class returnType = toRemove.getReturnType(); - List> providers = getProvidersByTypes(methodType, returnType); - - DataProvider providerToRemove = null; - for (DataProvider provider : providers) { - if (provider.getMethod().equals(toRemove)) { - providerToRemove = provider; - break; - } - } - providers.remove(providerToRemove); - } -} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/DoubleDataProvider.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/DoubleDataProvider.java deleted file mode 100644 index 57dd81058..000000000 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/DoubleDataProvider.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 . - */ -package com.djrapitops.plan.extension.implementation.providers; - -import com.djrapitops.plan.extension.annotation.Conditional; -import com.djrapitops.plan.extension.annotation.DoubleProvider; -import com.djrapitops.plan.extension.icon.Icon; -import com.djrapitops.plan.extension.implementation.ProviderInformation; - -import java.lang.reflect.Method; - -/** - * Contains code that acts on {@link DoubleProvider} annotations. - * - * @author AuroraLS3 - */ -public class DoubleDataProvider { - - private DoubleDataProvider() { - // Static method class - } - - public static void placeToDataProviders( - DataProviders dataProviders, Method method, DoubleProvider annotation, - Conditional condition, String tab, String pluginName - ) { - ProviderInformation information = ProviderInformation.builder(pluginName) - .setName(method.getName()) - .setText(annotation.text()) - .setDescription(annotation.description()) - .setPriority(annotation.priority()) - .setIcon(new Icon( - annotation.iconFamily(), - annotation.iconName(), - annotation.iconColor()) - ).setShowInPlayersTable(annotation.showInPlayerTable()) - .setCondition(condition) - .setTab(tab) - .build(); - - MethodWrapper methodWrapper = new MethodWrapper<>(method, Double.class); - - dataProviders.put(new DataProvider<>(information, methodWrapper)); - } -} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/GroupDataProvider.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/GroupDataProvider.java deleted file mode 100644 index 198599434..000000000 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/GroupDataProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 . - */ -package com.djrapitops.plan.extension.implementation.providers; - -import com.djrapitops.plan.extension.annotation.Conditional; -import com.djrapitops.plan.extension.annotation.GroupProvider; -import com.djrapitops.plan.extension.icon.Icon; -import com.djrapitops.plan.extension.implementation.ProviderInformation; - -import java.lang.reflect.Method; - -/** - * Contains code that acts on {@link GroupProvider} annotations. - * - * @author AuroraLS3 - */ -public class GroupDataProvider { - - private GroupDataProvider() { - // Static method class - } - - public static void placeToDataProviders( - DataProviders dataProviders, Method method, GroupProvider annotation, - Conditional condition, String tab, String pluginName - ) { - ProviderInformation information = ProviderInformation.builder(pluginName) - .setName(method.getName()) - .setText(annotation.text()) - .setPriority(0) - .setIcon(new Icon( - annotation.iconFamily(), - annotation.iconName(), - annotation.groupColor()) - ).setShowInPlayersTable(true) - .setCondition(condition) - .setTab(tab) - .build(); - - MethodWrapper methodWrapper = new MethodWrapper<>(method, String[].class); - dataProviders.put(new DataProvider<>(information, methodWrapper)); - } -} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/MethodWrapper.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/MethodWrapper.java index d46d196e1..104ca8930 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/MethodWrapper.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/MethodWrapper.java @@ -16,6 +16,7 @@ */ package com.djrapitops.plan.extension.implementation.providers; +import com.djrapitops.plan.exceptions.DataExtensionMethodCallException; import com.djrapitops.plan.extension.DataExtension; import com.djrapitops.plan.extension.NotReadyException; import com.djrapitops.plan.extension.implementation.MethodType; @@ -23,6 +24,7 @@ import com.djrapitops.plan.extension.implementation.MethodType; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Objects; +import java.util.Optional; /** * Wrap a Method so that it is easier to call. @@ -47,17 +49,22 @@ public class MethodWrapper { try { return returnType.cast(with.usingOn(extension, method)); } catch (InvocationTargetException notReadyToBeCalled) { - if (notReadyToBeCalled.getCause() instanceof NotReadyException - || notReadyToBeCalled.getCause() instanceof UnsupportedOperationException) { + Throwable cause = notReadyToBeCalled.getCause(); + if (cause instanceof NotReadyException || cause instanceof UnsupportedOperationException) { return null; // Data or API not available to make the call. } else { - throw new IllegalArgumentException(method.getDeclaringClass() + " method " + method.getName() + " could not be called: " + notReadyToBeCalled.getMessage(), notReadyToBeCalled); + throw new DataExtensionMethodCallException(getErrorMessage(extension, notReadyToBeCalled), notReadyToBeCalled, extension.getPluginName(), getMethodName()); } } catch (IllegalAccessException e) { - throw new IllegalArgumentException(method.getDeclaringClass() + " method " + method.getName() + " could not be called: " + e.getMessage(), e); + throw new DataExtensionMethodCallException(extension.getPluginName() + '.' + getMethodName() + " could not be accessed: " + e.getMessage(), e, extension.getPluginName(), getMethodName()); } } + private String getErrorMessage(DataExtension extension, InvocationTargetException e) { + Optional actualCause = Optional.ofNullable(e.getCause()); // InvocationTargetException + return extension.getPluginName() + '.' + getMethodName() + " errored: " + actualCause.orElse(e).toString(); + } + public String getMethodName() { return method.getName(); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/NumberDataProvider.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/NumberDataProvider.java deleted file mode 100644 index 1a95573e0..000000000 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/NumberDataProvider.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 . - */ -package com.djrapitops.plan.extension.implementation.providers; - -import com.djrapitops.plan.extension.annotation.Conditional; -import com.djrapitops.plan.extension.annotation.NumberProvider; -import com.djrapitops.plan.extension.icon.Icon; -import com.djrapitops.plan.extension.implementation.ProviderInformation; - -import java.lang.reflect.Method; - -/** - * Contains code that acts on {@link NumberProvider} annotations. - * - * @author AuroraLS3 - */ -public class NumberDataProvider { - - private NumberDataProvider() { - // Static method class - } - - public static void placeToDataProviders( - DataProviders dataProviders, Method method, NumberProvider annotation, - Conditional condition, String tab, String pluginName - ) { - ProviderInformation information = ProviderInformation.builder(pluginName) - .setName(method.getName()) - .setText(annotation.text()) - .setDescription(annotation.description()) - .setPriority(annotation.priority()) - .setIcon(new Icon( - annotation.iconFamily(), - annotation.iconName(), - annotation.iconColor()) - ).setShowInPlayersTable(annotation.showInPlayerTable()) - .setCondition(condition) - .setTab(tab) - .setFormatType(annotation.format()) - .build(); - - MethodWrapper methodWrapper = new MethodWrapper<>(method, Long.class); - dataProviders.put(new DataProvider<>(information, methodWrapper)); - } -} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/PercentageDataProvider.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/PercentageDataProvider.java deleted file mode 100644 index 4f4b400ab..000000000 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/PercentageDataProvider.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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 . - */ -package com.djrapitops.plan.extension.implementation.providers; - -import com.djrapitops.plan.extension.annotation.Conditional; -import com.djrapitops.plan.extension.annotation.PercentageProvider; -import com.djrapitops.plan.extension.icon.Icon; -import com.djrapitops.plan.extension.implementation.ProviderInformation; - -import java.lang.reflect.Method; - -/** - * Contains code that acts on {@link PercentageProvider} annotations. - * - * @author AuroraLS3 - */ -public class PercentageDataProvider { - - private PercentageDataProvider() { - // Static method class - } - - public static void placeToDataProviders( - DataProviders dataProviders, Method method, PercentageProvider annotation, - Conditional condition, String tab, String pluginName - ) { - ProviderInformation information = ProviderInformation.builder(pluginName) - .setName(method.getName()) - .setText(annotation.text()) - .setDescription(annotation.description()) - .setPriority(annotation.priority()) - .setIcon(new Icon( - annotation.iconFamily(), - annotation.iconName(), - annotation.iconColor()) - ).setShowInPlayersTable(annotation.showInPlayerTable()) - .setCondition(condition) - .setTab(tab) - .setAsPercentage() - .build(); - - MethodWrapper methodWrapper = new MethodWrapper<>(method, Double.class); - - dataProviders.put(new DataProvider<>(information, methodWrapper)); - } -} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/StringDataProvider.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/StringDataProvider.java deleted file mode 100644 index 8a588f423..000000000 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/StringDataProvider.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 . - */ -package com.djrapitops.plan.extension.implementation.providers; - -import com.djrapitops.plan.extension.annotation.Conditional; -import com.djrapitops.plan.extension.annotation.StringProvider; -import com.djrapitops.plan.extension.icon.Icon; -import com.djrapitops.plan.extension.implementation.ProviderInformation; - -import java.lang.reflect.Method; - -/** - * Contains code that acts on {@link StringProvider} annotations. - * - * @author AuroraLS3 - */ -public class StringDataProvider { - - private StringDataProvider() { - // Static method class - } - - public static void placeToDataProviders( - DataProviders dataProviders, Method method, StringProvider annotation, - Conditional condition, String tab, String pluginName - ) { - ProviderInformation information = ProviderInformation.builder(pluginName) - .setName(method.getName()) - .setText(annotation.text()) - .setDescription(annotation.description()) - .setPriority(annotation.priority()) - .setIcon(new Icon( - annotation.iconFamily(), - annotation.iconName(), - annotation.iconColor()) - ).setShowInPlayersTable(annotation.showInPlayerTable()) - .setCondition(condition) - .setTab(tab) - .setPlayerName(annotation.playerName()) - .build(); - - MethodWrapper methodWrapper = new MethodWrapper<>(method, String.class); - dataProviders.put(new DataProvider<>(information, methodWrapper)); - } -} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/TableDataProvider.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/TableDataProvider.java deleted file mode 100644 index 8c0ed66c2..000000000 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/TableDataProvider.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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 . - */ -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.implementation.ProviderInformation; -import com.djrapitops.plan.extension.table.Table; - -import java.lang.reflect.Method; - -/** - * Contains code that acts on {@link TableProvider} annotations. - *

- * Please note that not all {@link ProviderInformation} is present in this annotation. - * - * @author AuroraLS3 - */ -public class TableDataProvider { - - private TableDataProvider() { - // Static method class - } - - public static void placeToDataProviders( - DataProviders dataProviders, Method method, TableProvider annotation, - Conditional condition, String tab, String pluginName - ) { - ProviderInformation information = ProviderInformation.builder(pluginName) - .setName(method.getName()) - .setPriority(0) - .setCondition(condition) - .setTab(tab) - .setTableColor(annotation.tableColor()) - .build(); - - MethodWrapper

methodWrapper = new MethodWrapper<>(method, Table.class); - dataProviders.put(new DataProvider<>(information, methodWrapper)); - } - -} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/BooleanProviderValueGatherer.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/BooleanProviderValueGatherer.java deleted file mode 100644 index 5f66cc98d..000000000 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/BooleanProviderValueGatherer.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * 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 . - */ -package com.djrapitops.plan.extension.implementation.providers.gathering; - -import com.djrapitops.plan.exceptions.DataExtensionMethodCallException; -import com.djrapitops.plan.extension.DataExtension; -import com.djrapitops.plan.extension.implementation.ExtensionWrapper; -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.Parameters; -import com.djrapitops.plan.extension.implementation.storage.transactions.StoreIconTransaction; -import com.djrapitops.plan.extension.implementation.storage.transactions.providers.StoreProviderTransaction; -import com.djrapitops.plan.extension.implementation.storage.transactions.results.StorePlayerBooleanResultTransaction; -import com.djrapitops.plan.extension.implementation.storage.transactions.results.StoreServerBooleanResultTransaction; -import com.djrapitops.plan.identification.ServerUUID; -import com.djrapitops.plan.storage.database.Database; -import com.djrapitops.plan.storage.database.transactions.Transaction; - -import java.util.*; -import java.util.concurrent.Callable; -import java.util.function.BiFunction; -import java.util.function.Function; - -/** - * Gathers BooleanProvider method data. - * - * @author AuroraLS3 - */ -class BooleanProviderValueGatherer { - - private final String pluginName; - private final DataExtension extension; - private final ServerUUID serverUUID; - - private final Database database; - private final DataProviders dataProviders; - - BooleanProviderValueGatherer( - String pluginName, - ServerUUID serverUUID, Database database, - ExtensionWrapper extensionWrapper - ) { - this.pluginName = pluginName; - this.extension = extensionWrapper.getExtension(); - this.serverUUID = serverUUID; - this.database = database; - this.dataProviders = extensionWrapper.getProviders(); - } - - Conditions gatherBooleanDataOfPlayer(UUID playerUUID, String playerName) { - Conditions conditions = new Conditions(); - - List> unsatisfiedProviders = new ArrayList<>(dataProviders.getPlayerMethodsByType(Boolean.class)); - Set> satisfied; - - // Method parameters abstracted away so that same method can be used for all parameter types - // Same with Method result store transaction creation - Function, Callable> methodCaller = method -> () -> method.callMethod(extension, Parameters.player(serverUUID, playerUUID, playerName)); - BiFunction, Boolean, Transaction> storeTransactionCreator = (method, result) -> new StorePlayerBooleanResultTransaction(pluginName, serverUUID, method.getMethodName(), playerUUID, result); - - do { - // Loop through all unsatisfied providers to see if more conditions are satisfied - satisfied = attemptToSatisfyMoreConditionsAndStoreResults(methodCaller, storeTransactionCreator, conditions, unsatisfiedProviders); - // Remove now satisfied Providers so that they are not called again - unsatisfiedProviders.removeAll(satisfied); - // If no new conditions could be satisfied, stop looping. - } while (!satisfied.isEmpty()); - - return conditions; - } - - Conditions gatherBooleanDataOfServer() { - Conditions conditions = new Conditions(); - - List> unsatisfiedProviders = new ArrayList<>(dataProviders.getServerMethodsByType(Boolean.class)); - Set> satisfied; - - // Method parameters abstracted away so that same method can be used for all parameter types - // Same with Method result store transaction creation - Function, Callable> methodCaller = method -> () -> method.callMethod(extension, Parameters.server(serverUUID)); - BiFunction, Boolean, Transaction> storeTransactionCreator = (method, result) -> new StoreServerBooleanResultTransaction(pluginName, serverUUID, method.getMethodName(), result); - - do { - // Loop through all unsatisfied providers to see if more conditions are satisfied - satisfied = attemptToSatisfyMoreConditionsAndStoreResults(methodCaller, storeTransactionCreator, conditions, unsatisfiedProviders); - // Remove now satisfied Providers so that they are not called again - unsatisfiedProviders.removeAll(satisfied); - // If no new conditions could be satisfied, stop looping. - } while (!satisfied.isEmpty()); - - return conditions; - } - - private Set> attemptToSatisfyMoreConditionsAndStoreResults( - Function, Callable> methodCaller, - BiFunction, Boolean, Transaction> storeTransactionCreator, - Conditions conditions, List> unsatisfiedProviders - ) { - Set> satisfied = new HashSet<>(); - for (DataProvider booleanProvider : unsatisfiedProviders) { - ProviderInformation information = booleanProvider.getProviderInformation(); - - Optional condition = information.getCondition(); - if (condition.isPresent() && conditions.isNotFulfilled(condition.get())) { - // Condition required by the BooleanProvider is not satisfied - continue; - } - - - String providedCondition = information.getProvidedCondition(); - MethodWrapper method = booleanProvider.getMethod(); - Boolean result = getMethodResult(methodCaller.apply(method), method); - if (result == null) { - // Error during method call - satisfied.add(booleanProvider); // Prevents further attempts to call this provider for this player. - continue; - } - - if (providedCondition != null) { - if (Boolean.TRUE.equals(result)) { - // The condition was fulfilled (true) for this player. - conditions.conditionFulfilled(providedCondition); - } else { - // The negated condition was fulfilled (false) for this player. - conditions.conditionFulfilled("not_" + providedCondition); - } - } - - satisfied.add(booleanProvider); // Prevents further attempts to call this provider for this player. - database.executeTransaction(new StoreIconTransaction(information.getIcon())); - database.executeTransaction(new StoreProviderTransaction(booleanProvider, serverUUID)); - database.executeTransaction(storeTransactionCreator.apply(method, result)); - } - return satisfied; - } - - private T getMethodResult(Callable callable, MethodWrapper method) { - try { - return callable.call(); - } catch (Exception | NoClassDefFoundError | NoSuchFieldError | NoSuchMethodError e) { - throw new DataExtensionMethodCallException(e, pluginName, method); - } - } -} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/Conditions.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/Conditions.java index 48048da41..57d24a087 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/Conditions.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/Conditions.java @@ -17,6 +17,7 @@ package com.djrapitops.plan.extension.implementation.providers.gathering; import java.util.HashSet; +import java.util.Objects; import java.util.Set; /** @@ -36,7 +37,14 @@ public class Conditions { return !fulfilledConditions.contains(condition); } + public static boolean matchesCondition(String condition1, String condition2) { + return Objects.equals(condition1, condition2) || // condition == condition, not_condition == not_condition + Objects.equals("not_" + condition1, condition2) || // condition == not_condition + Objects.equals(condition1, "not_" + condition2); // not_condition == condition + } + public void conditionFulfilled(String condition) { + if (condition == null || condition.isEmpty()) return; fulfilledConditions.add(condition); } } \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/DataValueGatherer.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/DataValueGatherer.java new file mode 100644 index 000000000..4fbcccc84 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/DataValueGatherer.java @@ -0,0 +1,455 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.implementation.providers.gathering; + +import com.djrapitops.plan.exceptions.DataExtensionMethodCallException; +import com.djrapitops.plan.extension.CallEvents; +import com.djrapitops.plan.extension.annotation.*; +import com.djrapitops.plan.extension.builder.DataValue; +import com.djrapitops.plan.extension.builder.ExtensionDataBuilder; +import com.djrapitops.plan.extension.extractor.ExtensionMethod; +import com.djrapitops.plan.extension.extractor.ExtensionMethods; +import com.djrapitops.plan.extension.icon.Color; +import com.djrapitops.plan.extension.icon.Icon; +import com.djrapitops.plan.extension.implementation.ExtensionWrapper; +import com.djrapitops.plan.extension.implementation.ProviderInformation; +import com.djrapitops.plan.extension.implementation.TabInformation; +import com.djrapitops.plan.extension.implementation.builder.*; +import com.djrapitops.plan.extension.implementation.providers.MethodWrapper; +import com.djrapitops.plan.extension.implementation.providers.Parameters; +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; +import com.djrapitops.plan.extension.implementation.storage.transactions.providers.StoreProviderTransaction; +import com.djrapitops.plan.extension.implementation.storage.transactions.providers.StoreTableProviderTransaction; +import com.djrapitops.plan.extension.implementation.storage.transactions.results.*; +import com.djrapitops.plan.extension.table.Table; +import com.djrapitops.plan.identification.ServerInfo; +import com.djrapitops.plan.identification.ServerUUID; +import com.djrapitops.plan.storage.database.DBSystem; +import com.djrapitops.plan.storage.database.Database; +import com.djrapitops.plan.utilities.logging.ErrorContext; +import com.djrapitops.plan.utilities.logging.ErrorLogger; + +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; + +/** + * Object that can be called to place data about players to the database. + * + * @author AuroraLS3 + */ +public class DataValueGatherer { + + private final CallEvents[] callEvents; + private final ExtensionWrapper extension; + private final DBSystem dbSystem; + private final ServerInfo serverInfo; + private final ErrorLogger errorLogger; + + private final Set brokenMethods; + + public DataValueGatherer( + ExtensionWrapper extension, + DBSystem dbSystem, + ServerInfo serverInfo, + ErrorLogger errorLogger + ) { + this.callEvents = extension.getCallEvents(); + this.extension = extension; + this.dbSystem = dbSystem; + this.serverInfo = serverInfo; + this.errorLogger = errorLogger; + + this.brokenMethods = new HashSet<>(); + } + + public boolean shouldSkipEvent(CallEvents event) { + if (event == CallEvents.MANUAL) { + return false; + } + for (CallEvents accepted : callEvents) { + if (event == accepted) { + return false; + } + } + return true; + } + + public String getPluginName() { + return extension.getPluginName(); + } + + public void storeExtensionInformation() { + String pluginName = extension.getPluginName(); + Icon pluginIcon = extension.getPluginIcon(); + + long time = System.currentTimeMillis(); + ServerUUID serverUUID = serverInfo.getServerUUID(); + + Database database = dbSystem.getDatabase(); + database.executeTransaction(new StoreIconTransaction(pluginIcon)); + database.executeTransaction(new StorePluginTransaction(pluginName, time, serverUUID, pluginIcon)); + for (TabInformation tab : extension.getPluginTabs()) { + database.executeTransaction(new StoreIconTransaction(tab.getTabIcon())); + database.executeTransaction(new StoreTabInformationTransaction(pluginName, serverUUID, tab)); + } + + database.executeTransaction(new RemoveInvalidResultsTransaction(pluginName, serverUUID, extension.getInvalidatedMethods())); + } + + private void addValuesToBuilder(ExtensionDataBuilder dataBuilder, ExtensionMethods methods, Parameters parameters) { + for (ExtensionMethod provider : methods.getBooleanProviders()) { + if (brokenMethods.contains(provider)) continue; + BooleanProvider annotation = provider.getExistingAnnotation(BooleanProvider.class); + dataBuilder.addValue(Boolean.class, dataBuilder.valueBuilder(annotation.text()) + .methodName(provider) + .icon(annotation.iconName(), annotation.iconFamily(), annotation.iconColor()) + .description(annotation.description()) + .priority(annotation.priority()) + .showInPlayerTable(annotation.showInPlayerTable()) + .hideFromUsers(annotation) + .conditional(provider.getAnnotationOrNull(Conditional.class)) + .showOnTab(provider.getAnnotationOrNull(Tab.class)) + .buildBooleanProvidingCondition(() -> callMethod(provider, parameters, Boolean.class), annotation.conditionName())); + } + for (ExtensionMethod provider : methods.getDoubleProviders()) { + if (brokenMethods.contains(provider)) continue; + DoubleProvider annotation = provider.getExistingAnnotation(DoubleProvider.class); + dataBuilder.addValue(Double.class, 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)) + .buildDouble(() -> callMethod(provider, parameters, Double.class))); + } + for (ExtensionMethod provider : methods.getPercentageProviders()) { + if (brokenMethods.contains(provider)) continue; + PercentageProvider annotation = provider.getExistingAnnotation(PercentageProvider.class); + dataBuilder.addValue(Double.class, 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)) + .buildPercentage(() -> callMethod(provider, parameters, Double.class))); + } + for (ExtensionMethod provider : methods.getNumberProviders()) { + if (brokenMethods.contains(provider)) continue; + NumberProvider annotation = provider.getExistingAnnotation(NumberProvider.class); + dataBuilder.addValue(Long.class, dataBuilder.valueBuilder(annotation.text()) + .methodName(provider) + .icon(annotation.iconName(), annotation.iconFamily(), annotation.iconColor()) + .description(annotation.description()) + .priority(annotation.priority()) + .showInPlayerTable(annotation.showInPlayerTable()) + .format(annotation.format()) + .conditional(provider.getAnnotationOrNull(Conditional.class)) + .showOnTab(provider.getAnnotationOrNull(Tab.class)) + .buildNumber(() -> callMethod(provider, parameters, Long.class))); + } + for (ExtensionMethod provider : methods.getStringProviders()) { + if (brokenMethods.contains(provider)) continue; + StringProvider annotation = provider.getExistingAnnotation(StringProvider.class); + dataBuilder.addValue(String.class, dataBuilder.valueBuilder(annotation.text()) + .methodName(provider) + .icon(annotation.iconName(), annotation.iconFamily(), annotation.iconColor()) + .description(annotation.description()) + .priority(annotation.priority()) + .showInPlayerTable(annotation.showInPlayerTable()) + .showAsPlayerPageLink(annotation) + .conditional(provider.getAnnotationOrNull(Conditional.class)) + .showOnTab(provider.getAnnotationOrNull(Tab.class)) + .buildString(() -> callMethod(provider, parameters, String.class))); + } + for (ExtensionMethod provider : methods.getGroupProviders()) { + if (brokenMethods.contains(provider)) continue; + GroupProvider annotation = provider.getExistingAnnotation(GroupProvider.class); + dataBuilder.addValue(String[].class, dataBuilder.valueBuilder(annotation.text()) + .methodName(provider) + .icon(annotation.iconName(), annotation.iconFamily(), Color.NONE) + .conditional(provider.getAnnotationOrNull(Conditional.class)) + .showOnTab(provider.getAnnotationOrNull(Tab.class)) + .buildGroup(() -> callMethod(provider, parameters, String[].class))); + } + for (ExtensionMethod provider : methods.getTableProviders()) { + if (brokenMethods.contains(provider)) continue; + TableProvider annotation = provider.getExistingAnnotation(TableProvider.class); + dataBuilder.addValue(Table.class, dataBuilder.valueBuilder(provider.getMethodName()) + .conditional(provider.getAnnotationOrNull(Conditional.class)) + .showOnTab(provider.getAnnotationOrNull(Tab.class)) + .buildTable(() -> callMethod(provider, parameters, Table.class), annotation.tableColor())); + } + for (ExtensionMethod provider : methods.getDataBuilderProviders()) { + if (brokenMethods.contains(provider)) continue; + addDataFromAnotherBuilder(dataBuilder, parameters, provider); + } + } + + private void addDataFromAnotherBuilder(ExtensionDataBuilder dataBuilder, Parameters parameters, ExtensionMethod provider) { + try { + ExtensionDataBuilder providedBuilder = callMethod(provider, parameters, ExtensionDataBuilder.class); + dataBuilder.addAll(providedBuilder); + } catch (DataExtensionMethodCallException methodError) { + logFailure(methodError); + } catch (Exception | NoClassDefFoundError | NoSuchFieldError | NoSuchMethodError unexpectedError) { + logFailure(unexpectedError); + } + } + + private T callMethod(ExtensionMethod provider, Parameters params, Class returnType) { + try { + return new MethodWrapper<>(provider.getMethod(), returnType) + .callMethod(extension.getExtension(), params); + } catch (DataExtensionMethodCallException e) { + brokenMethods.add(provider); + throw e; + } + } + + public void updateValues(UUID playerUUID, String playerName) { + Parameters parameters = Parameters.player(serverInfo.getServerUUID(), playerUUID, playerName); + ExtensionDataBuilder dataBuilder = extension.getExtension().newExtensionDataBuilder(); + + addValuesToBuilder(dataBuilder, extension.getMethods().get(ExtensionMethod.ParameterType.PLAYER_STRING), parameters); + addValuesToBuilder(dataBuilder, extension.getMethods().get(ExtensionMethod.ParameterType.PLAYER_UUID), parameters); + + gatherPlayer(parameters, (ExtDataBuilder) dataBuilder); + } + + public void updateValues() { + Parameters parameters = Parameters.server(serverInfo.getServerUUID()); + ExtensionDataBuilder dataBuilder = extension.getExtension().newExtensionDataBuilder(); + + addValuesToBuilder(dataBuilder, extension.getMethods().get(ExtensionMethod.ParameterType.SERVER_NONE), parameters); + + gather(parameters, (ExtDataBuilder) dataBuilder); + } + + + private void gatherPlayer(Parameters parameters, ExtDataBuilder dataBuilder) { + Conditions conditions = new Conditions(); + for (ExtDataBuilder.ClassValuePair pair : dataBuilder.getValues()) { + try { + pair.getValue(Boolean.class).flatMap(data -> data.getMetadata(BooleanDataValue.class)) + .ifPresent(data -> storePlayerBoolean(parameters, conditions, data)); + pair.getValue(Long.class).flatMap(data -> data.getMetadata(NumberDataValue.class)) + .ifPresent(data -> storePlayerNumber(parameters, conditions, data)); + pair.getValue(Double.class).flatMap(data -> data.getMetadata(DoubleDataValue.class)) + .ifPresent(data -> storePlayerDouble(parameters, conditions, data)); + pair.getValue(String.class).flatMap(data -> data.getMetadata(StringDataValue.class)) + .ifPresent(data -> storePlayerString(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)) + .ifPresent(data -> storePlayerTable(parameters, conditions, data)); + } catch (DataExtensionMethodCallException methodError) { + logFailure(methodError); + } catch (Exception | NoClassDefFoundError | NoSuchFieldError | NoSuchMethodError unexpectedError) { + logFailure(unexpectedError); + } + } + } + + private void gather(Parameters parameters, ExtDataBuilder dataBuilder) { + Conditions conditions = new Conditions(); + for (ExtDataBuilder.ClassValuePair pair : dataBuilder.getValues()) { + try { + pair.getValue(Boolean.class).flatMap(data -> data.getMetadata(BooleanDataValue.class)) + .ifPresent(data -> storeBoolean(parameters, conditions, data)); + pair.getValue(Long.class).flatMap(data -> data.getMetadata(NumberDataValue.class)) + .ifPresent(data -> storeNumber(parameters, conditions, data)); + pair.getValue(Double.class).flatMap(data -> data.getMetadata(DoubleDataValue.class)) + .ifPresent(data -> storeDouble(parameters, conditions, data)); + pair.getValue(String.class).flatMap(data -> data.getMetadata(StringDataValue.class)) + .ifPresent(data -> storeString(parameters, conditions, data)); + pair.getValue(Table.class).flatMap(data -> data.getMetadata(TableDataValue.class)) + .ifPresent(data -> storeTable(parameters, conditions, data)); + } catch (DataExtensionMethodCallException methodError) { + logFailure(methodError); + } catch (Exception | NoClassDefFoundError | NoSuchFieldError | NoSuchMethodError unexpectedError) { + logFailure(unexpectedError); + } + } + } + + private void logFailure(DataExtensionMethodCallException methodCallFailed) { + ErrorContext.Builder context = ErrorContext.builder() + .whatToDo("Report and/or disable " + methodCallFailed.getPluginName() + " extension in the Plan config.") + .related(methodCallFailed.getPluginName()) + .related("Method:" + methodCallFailed.getMethodName().orElse("-")); + errorLogger.warn(methodCallFailed, context.build()); + } + + private void logFailure(Throwable unexpectedError) { + ErrorContext.Builder context = ErrorContext.builder() + .whatToDo("Report and/or disable " + extension.getPluginName() + " extension in the Plan config.") + .related(extension.getPluginName()); + errorLogger.warn(unexpectedError, context.build()); + } + + private T getValue(Conditions conditions, DataValue data, ProviderInformation information) { + Optional condition = information.getCondition(); + if (condition.isPresent() && conditions.isNotFulfilled(condition.get())) { + return null; + } + return data.getValue(); // can be null, can throw + } + + private void storeBoolean(Parameters parameters, Conditions conditions, BooleanDataValue data) { + ProviderInformation information = data.getInformation(); + Boolean value = getValue(conditions, data, information); + if (value == null) return; + if (value) { + conditions.conditionFulfilled(information.getProvidedCondition()); + } else { + conditions.conditionFulfilled("not_" + information.getProvidedCondition()); + } + + Database db = dbSystem.getDatabase(); + db.executeTransaction(new StoreIconTransaction(information.getIcon())); + db.executeTransaction(new StoreProviderTransaction(information, parameters)); + db.executeTransaction(new StoreServerBooleanResultTransaction(information, parameters, value)); + } + + private void storeNumber(Parameters parameters, Conditions conditions, NumberDataValue data) { + ProviderInformation information = data.getInformation(); + Long value = 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 StoreServerNumberResultTransaction(information, parameters, value)); + } + + + private void storeDouble(Parameters parameters, Conditions conditions, DoubleDataValue data) { + ProviderInformation information = data.getInformation(); + Double value = 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 StoreServerDoubleResultTransaction(information, parameters, value)); + } + + private void storeString(Parameters parameters, Conditions conditions, StringDataValue data) { + ProviderInformation information = data.getInformation(); + String value = 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); + if (value == null) return; + + Database db = dbSystem.getDatabase(); + for (Icon icon : value.getIcons()) { + if (icon != null) db.executeTransaction(new StoreIconTransaction(icon)); + } + db.executeTransaction(new StoreTableProviderTransaction(information, parameters, value)); + db.executeTransaction(new StoreServerTableResultTransaction(information, parameters, value)); + } + + private void storePlayerBoolean(Parameters parameters, Conditions conditions, BooleanDataValue data) { + ProviderInformation information = data.getInformation(); + Boolean value = getValue(conditions, data, information); + if (value == null) return; + if (value) { + conditions.conditionFulfilled(information.getProvidedCondition()); + } else { + conditions.conditionFulfilled("not_" + information.getProvidedCondition()); + } + + Database db = dbSystem.getDatabase(); + db.executeTransaction(new StoreIconTransaction(information.getIcon())); + db.executeTransaction(new StoreProviderTransaction(information, parameters)); + db.executeTransaction(new StorePlayerBooleanResultTransaction(information, parameters, value)); + } + + private void storePlayerNumber(Parameters parameters, Conditions conditions, NumberDataValue data) { + ProviderInformation information = data.getInformation(); + Long value = 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 StorePlayerNumberResultTransaction(information, parameters, value)); + } + + private void storePlayerDouble(Parameters parameters, Conditions conditions, DoubleDataValue data) { + ProviderInformation information = data.getInformation(); + Double value = 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 StorePlayerDoubleResultTransaction(information, parameters, value)); + } + + private void storePlayerString(Parameters parameters, Conditions conditions, StringDataValue data) { + ProviderInformation information = data.getInformation(); + String value = 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); + if (value == null) return; + + Database db = dbSystem.getDatabase(); + db.executeTransaction(new StoreIconTransaction(information.getIcon())); + db.executeTransaction(new StoreProviderTransaction(information, parameters)); + db.executeTransaction(new StorePlayerGroupsResultTransaction(information, parameters, value)); + } + + private void storePlayerTable(Parameters parameters, Conditions conditions, TableDataValue data) { + ProviderInformation information = data.getInformation(); + Table value = getValue(conditions, data, information); + if (value == null) return; + + Database db = dbSystem.getDatabase(); + for (Icon icon : value.getIcons()) { + if (icon != null) db.executeTransaction(new StoreIconTransaction(icon)); + } + db.executeTransaction(new StoreTableProviderTransaction(information, parameters, value)); + db.executeTransaction(new StorePlayerTableResultTransaction(information, parameters, value)); + } +} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/ProviderValueGatherer.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/ProviderValueGatherer.java deleted file mode 100644 index c46c9b6d4..000000000 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/ProviderValueGatherer.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * 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 . - */ -package com.djrapitops.plan.extension.implementation.providers.gathering; - -import com.djrapitops.plan.extension.CallEvents; -import com.djrapitops.plan.extension.icon.Icon; -import com.djrapitops.plan.extension.implementation.ExtensionWrapper; -import com.djrapitops.plan.extension.implementation.ProviderInformation; -import com.djrapitops.plan.extension.implementation.TabInformation; -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.Parameters; -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; -import com.djrapitops.plan.extension.implementation.storage.transactions.providers.StoreProviderTransaction; -import com.djrapitops.plan.extension.implementation.storage.transactions.results.*; -import com.djrapitops.plan.identification.ServerInfo; -import com.djrapitops.plan.identification.ServerUUID; -import com.djrapitops.plan.storage.database.DBSystem; -import com.djrapitops.plan.storage.database.Database; -import com.djrapitops.plan.storage.database.transactions.Transaction; - -import java.util.UUID; - -/** - * Object that can be called to place data about players to the database. - * - * @author AuroraLS3 - */ -public class ProviderValueGatherer { - - private final CallEvents[] callEvents; - private final ExtensionWrapper extensionWrapper; - private final DBSystem dbSystem; - private final ServerInfo serverInfo; - - private final DataProviders dataProviders; - private final BooleanProviderValueGatherer booleanGatherer; - private final TableProviderValueGatherer tableGatherer; - private final Gatherer serverNumberGatherer; - private final Gatherer playerNumberGatherer; - private final Gatherer serverDoubleGatherer; - private final Gatherer playerDoubleGatherer; - private final Gatherer serverStringGatherer; - private final Gatherer playerStringGatherer; - private final Gatherer playerGroupGatherer; - - public ProviderValueGatherer( - ExtensionWrapper extension, - DBSystem dbSystem, - ServerInfo serverInfo - ) { - this.callEvents = extension.getCallEvents(); - this.extensionWrapper = extension; - this.dbSystem = dbSystem; - this.serverInfo = serverInfo; - - String pluginName = extension.getPluginName(); - ServerUUID serverUUID = serverInfo.getServerUUID(); - Database database = dbSystem.getDatabase(); - dataProviders = extension.getProviders(); - booleanGatherer = new BooleanProviderValueGatherer( - pluginName, serverUUID, database, extension - ); - tableGatherer = new TableProviderValueGatherer( - pluginName, serverUUID, database, extension - ); - - serverNumberGatherer = new Gatherer<>( - Long.class, StoreServerNumberResultTransaction::new - ); - serverDoubleGatherer = new Gatherer<>( - Double.class, StoreServerDoubleResultTransaction::new - ); - serverStringGatherer = new Gatherer<>( - String.class, StoreServerStringResultTransaction::new - ); - playerNumberGatherer = new Gatherer<>( - Long.class, StorePlayerNumberResultTransaction::new - ); - playerDoubleGatherer = new Gatherer<>( - Double.class, StorePlayerDoubleResultTransaction::new - ); - playerStringGatherer = new Gatherer<>( - String.class, StorePlayerStringResultTransaction::new - ); - playerGroupGatherer = new Gatherer<>( - String[].class, StorePlayerGroupsResultTransaction::new - ); - } - - public void disableMethodFromUse(MethodWrapper method) { - method.disable(); - dataProviders.removeProviderWithMethod(method); - } - - public boolean shouldSkipEvent(CallEvents event) { - if (event == CallEvents.MANUAL) { - return false; - } - for (CallEvents accepted : callEvents) { - if (event == accepted) { - return false; - } - } - return true; - } - - public String getPluginName() { - return extensionWrapper.getPluginName(); - } - - public void storeExtensionInformation() { - String pluginName = extensionWrapper.getPluginName(); - Icon pluginIcon = extensionWrapper.getPluginIcon(); - - long time = System.currentTimeMillis(); - ServerUUID serverUUID = serverInfo.getServerUUID(); - - Database database = dbSystem.getDatabase(); - database.executeTransaction(new StoreIconTransaction(pluginIcon)); - database.executeTransaction(new StorePluginTransaction(pluginName, time, serverUUID, pluginIcon)); - for (TabInformation tab : extensionWrapper.getPluginTabs()) { - database.executeTransaction(new StoreIconTransaction(tab.getTabIcon())); - database.executeTransaction(new StoreTabInformationTransaction(pluginName, serverUUID, tab)); - } - - database.executeTransaction(new RemoveInvalidResultsTransaction(pluginName, serverUUID, extensionWrapper.getInvalidatedMethods())); - } - - public void updateValues(UUID playerUUID, String playerName) { - Conditions conditions = booleanGatherer.gatherBooleanDataOfPlayer(playerUUID, playerName); - Parameters params = Parameters.player(serverInfo.getServerUUID(), playerUUID, playerName); - playerNumberGatherer.gather(conditions, params); - playerDoubleGatherer.gather(conditions, params); - playerStringGatherer.gather(conditions, params); - tableGatherer.gatherTableDataOfPlayer(playerUUID, playerName, conditions); - playerGroupGatherer.gather(conditions, params); - } - - public void updateValues() { - Conditions conditions = booleanGatherer.gatherBooleanDataOfServer(); - Parameters params = Parameters.server(serverInfo.getServerUUID()); - - serverNumberGatherer.gather(conditions, params); - serverDoubleGatherer.gather(conditions, params); - serverStringGatherer.gather(conditions, params); - tableGatherer.gatherTableDataOfServer(conditions); - } - - interface ResultTransactionConstructor { - Transaction create(DataProvider provider, Parameters parameters, T result); - } - - class Gatherer { - private final Class type; - private final ResultTransactionConstructor resultTransactionConstructor; - - public Gatherer( - Class type, - ResultTransactionConstructor resultTransactionConstructor - ) { - this.type = type; - this.resultTransactionConstructor = resultTransactionConstructor; - } - - public void gather(Conditions conditions, Parameters parameters) { - for (DataProvider provider : dataProviders.getProvidersByTypes(parameters.getMethodType(), type)) { - gather(conditions, provider, parameters); - } - } - - private void gather(Conditions conditions, DataProvider provider, Parameters parameters) { - ProviderInformation information = provider.getProviderInformation(); - if (information.getCondition().map(conditions::isNotFulfilled).orElse(false)) { - return; // Condition not fulfilled - } - - T result = provider.getMethod().callMethod(extensionWrapper.getExtension(), parameters); - if (result == null) { - return; // Error during method call - } - - Database db = dbSystem.getDatabase(); - db.executeTransaction(new StoreIconTransaction(information.getIcon())); - db.executeTransaction(new StoreProviderTransaction(provider, parameters.getServerUUID())); - db.executeTransaction(resultTransactionConstructor.create(provider, parameters, result)); - } - } -} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/TableProviderValueGatherer.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/TableProviderValueGatherer.java deleted file mode 100644 index 02abbcc86..000000000 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/gathering/TableProviderValueGatherer.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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 . - */ -package com.djrapitops.plan.extension.implementation.providers.gathering; - -import com.djrapitops.plan.exceptions.DataExtensionMethodCallException; -import com.djrapitops.plan.extension.DataExtension; -import com.djrapitops.plan.extension.icon.Icon; -import com.djrapitops.plan.extension.implementation.ExtensionWrapper; -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.Parameters; -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.plan.identification.ServerUUID; -import com.djrapitops.plan.storage.database.Database; -import com.djrapitops.plan.storage.database.transactions.Transaction; - -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 AuroraLS3 - */ -class TableProviderValueGatherer { - - private final String pluginName; - private final DataExtension extension; - private final ServerUUID serverUUID; - - private final Database database; - private final DataProviders dataProviders; - - TableProviderValueGatherer( - String pluginName, - ServerUUID serverUUID, Database database, - ExtensionWrapper extensionWrapper - ) { - this.pluginName = pluginName; - this.extension = extensionWrapper.getExtension(); - this.serverUUID = serverUUID; - this.database = database; - this.dataProviders = extensionWrapper.getProviders(); - } - - 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, Callable
> methodCaller = method -> () -> method.callMethod(extension, Parameters.player(serverUUID, playerUUID, playerName)); - BiFunction, Table, Transaction> storeTransactionCreator = (method, result) -> new StorePlayerTableResultTransaction(pluginName, serverUUID, method.getMethodName(), playerUUID, result); - - for (DataProvider
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, Callable
> methodCaller = method -> () -> method.callMethod(extension, Parameters.server(serverUUID)); - BiFunction, Table, Transaction> storeTransactionCreator = (method, result) -> new StoreServerTableResultTransaction(pluginName, serverUUID, method.getMethodName(), result); - - for (DataProvider
tableProvider : dataProviders.getServerMethodsByType(Table.class)) { - gatherTableDataOfProvider(methodCaller, storeTransactionCreator, conditions, tableProvider); - } - } - - private void gatherTableDataOfProvider( - Function, Callable
> methodCaller, - BiFunction, Table, Transaction> storeTransactionCreator, - Conditions conditions, - DataProvider
tableProvider - ) { - ProviderInformation providerInformation = tableProvider.getProviderInformation(); - Optional condition = providerInformation.getCondition(); - if (condition.isPresent() && conditions.isNotFulfilled(condition.get())) { - return; - } - - MethodWrapper
method = tableProvider.getMethod(); - Table result = getMethodResult(methodCaller.apply(method), method); - if (result == null) { - return; // Error during call - } - - for (Icon icon : result.getIcons()) { - if (icon != null) { - database.executeTransaction(new StoreIconTransaction(icon)); - } - } - database.executeTransaction(new StoreTableProviderTransaction(serverUUID, providerInformation, result)); - database.executeTransaction(storeTransactionCreator.apply(method, result)); - } - - private T getMethodResult(Callable callable, MethodWrapper method) { - try { - return callable.call(); - } catch (Exception | NoClassDefFoundError | NoSuchFieldError | NoSuchMethodError e) { - throw new DataExtensionMethodCallException(e, pluginName, method); - } - } - -} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/providers/StoreProviderTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/providers/StoreProviderTransaction.java index 04bda1229..54a8aed05 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/providers/StoreProviderTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/providers/StoreProviderTransaction.java @@ -19,6 +19,7 @@ package com.djrapitops.plan.extension.implementation.storage.transactions.provid import com.djrapitops.plan.extension.FormatType; import com.djrapitops.plan.extension.implementation.ProviderInformation; import com.djrapitops.plan.extension.implementation.providers.DataProvider; +import com.djrapitops.plan.extension.implementation.providers.Parameters; import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.storage.database.sql.building.Sql; import com.djrapitops.plan.storage.database.sql.tables.ExtensionIconTable; @@ -42,12 +43,20 @@ import static com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderT */ public class StoreProviderTransaction extends ThrowawayTransaction { - private final DataProvider provider; private final ServerUUID serverUUID; + private final ProviderInformation info; public StoreProviderTransaction(DataProvider provider, ServerUUID serverUUID) { - this.provider = provider; + this(provider.getProviderInformation(), serverUUID); + } + + public StoreProviderTransaction(ProviderInformation info, Parameters parameters) { + this(info, parameters.getServerUUID()); + } + + public StoreProviderTransaction(ProviderInformation info, ServerUUID serverUUID) { this.serverUUID = serverUUID; + this.info = info; } @Override @@ -84,8 +93,6 @@ public class StoreProviderTransaction extends ThrowawayTransaction { return new ExecStatement(sql) { @Override public void prepare(PreparedStatement statement) throws SQLException { - ProviderInformation info = provider.getProviderInformation(); - // Found for all providers statement.setString(1, info.getText()); Sql.setStringOrNull(statement, 2, info.getDescription().orElse(null)); @@ -130,8 +137,6 @@ public class StoreProviderTransaction extends ThrowawayTransaction { return new ExecStatement(sql) { @Override public void prepare(PreparedStatement statement) throws SQLException { - ProviderInformation info = provider.getProviderInformation(); - // Found for all providers statement.setString(1, info.getName()); statement.setString(2, info.getText()); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/providers/StoreTableProviderTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/providers/StoreTableProviderTransaction.java index 85f2f67fa..9337c0278 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/providers/StoreTableProviderTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/providers/StoreTableProviderTransaction.java @@ -18,6 +18,7 @@ package com.djrapitops.plan.extension.implementation.storage.transactions.provid import com.djrapitops.plan.extension.icon.Icon; import com.djrapitops.plan.extension.implementation.ProviderInformation; +import com.djrapitops.plan.extension.implementation.providers.Parameters; import com.djrapitops.plan.extension.table.Table; import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.storage.database.sql.tables.ExtensionIconTable; @@ -36,7 +37,7 @@ import static com.djrapitops.plan.storage.database.sql.building.Sql.WHERE; import static com.djrapitops.plan.storage.database.sql.tables.ExtensionTableProviderTable.*; /** - * Transaction to store information about a {@link com.djrapitops.plan.extension.implementation.providers.TableDataProvider}. + * Transaction to store information about a Table. * * @author AuroraLS3 */ @@ -46,6 +47,10 @@ public class StoreTableProviderTransaction extends ThrowawayTransaction { private final ProviderInformation information; private final Table table; + public StoreTableProviderTransaction(ProviderInformation information, Parameters parameters, Table table) { + this(parameters.getServerUUID(), information, table); + } + public StoreTableProviderTransaction(ServerUUID serverUUID, ProviderInformation information, Table table) { this.information = information; this.table = table; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerBooleanResultTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerBooleanResultTransaction.java index ccf085fcd..462be295f 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerBooleanResultTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerBooleanResultTransaction.java @@ -16,6 +16,8 @@ */ package com.djrapitops.plan.extension.implementation.storage.transactions.results; +import com.djrapitops.plan.extension.implementation.ProviderInformation; +import com.djrapitops.plan.extension.implementation.providers.Parameters; import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderTable; import com.djrapitops.plan.storage.database.transactions.ExecStatement; @@ -31,7 +33,7 @@ import static com.djrapitops.plan.storage.database.sql.building.Sql.WHERE; import static com.djrapitops.plan.storage.database.sql.tables.ExtensionPlayerValueTable.*; /** - * Transaction to store method result of a {@link com.djrapitops.plan.extension.implementation.providers.BooleanDataProvider}. + * Transaction to store method result of a boolean. * * @author AuroraLS3 */ @@ -52,6 +54,10 @@ public class StorePlayerBooleanResultTransaction extends ThrowawayTransaction { this.value = value; } + public StorePlayerBooleanResultTransaction(ProviderInformation information, Parameters parameters, boolean value) { + this(information.getPluginName(), parameters.getServerUUID(), information.getName(), parameters.getPlayerUUID(), value); + } + @Override protected void performOperations() { execute(storeValue()); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerDoubleResultTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerDoubleResultTransaction.java index 2cdae6635..b6d5a00ff 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerDoubleResultTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerDoubleResultTransaction.java @@ -16,7 +16,7 @@ */ package com.djrapitops.plan.extension.implementation.storage.transactions.results; -import com.djrapitops.plan.extension.implementation.providers.DataProvider; +import com.djrapitops.plan.extension.implementation.ProviderInformation; import com.djrapitops.plan.extension.implementation.providers.Parameters; import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderTable; @@ -51,13 +51,13 @@ public class StorePlayerDoubleResultTransaction extends ThrowawayTransaction { private final double value; private final boolean percentage; - public StorePlayerDoubleResultTransaction(DataProvider provider, Parameters parameters, double value) { - this.pluginName = provider.getProviderInformation().getPluginName(); - this.providerName = provider.getProviderInformation().getName(); + public StorePlayerDoubleResultTransaction(ProviderInformation information, Parameters parameters, double value) { + this.pluginName = information.getPluginName(); + this.providerName = information.getName(); this.serverUUID = parameters.getServerUUID(); this.playerUUID = parameters.getPlayerUUID(); this.value = value; - this.percentage = provider.getProviderInformation().isPercentage(); + this.percentage = information.isPercentage(); } @Override diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerGroupsResultTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerGroupsResultTransaction.java index 89609d427..2c17232ba 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerGroupsResultTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerGroupsResultTransaction.java @@ -16,7 +16,7 @@ */ package com.djrapitops.plan.extension.implementation.storage.transactions.results; -import com.djrapitops.plan.extension.implementation.providers.DataProvider; +import com.djrapitops.plan.extension.implementation.ProviderInformation; import com.djrapitops.plan.extension.implementation.providers.Parameters; import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.storage.database.sql.tables.ExtensionGroupsTable; @@ -33,7 +33,7 @@ import java.util.UUID; import static com.djrapitops.plan.storage.database.sql.building.Sql.*; /** - * Transaction to store method result of a {@link com.djrapitops.plan.extension.implementation.providers.GroupDataProvider}. + * Transaction to store method result of player's groups. * * @author AuroraLS3 */ @@ -46,9 +46,9 @@ public class StorePlayerGroupsResultTransaction extends ThrowawayTransaction { private final String[] value; - public StorePlayerGroupsResultTransaction(DataProvider provider, Parameters parameters, String[] value) { - this.pluginName = provider.getProviderInformation().getPluginName(); - this.providerName = provider.getProviderInformation().getName(); + public StorePlayerGroupsResultTransaction(ProviderInformation information, Parameters parameters, String[] value) { + this.pluginName = information.getPluginName(); + this.providerName = information.getName(); this.serverUUID = parameters.getServerUUID(); this.playerUUID = parameters.getPlayerUUID(); this.value = value; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerNumberResultTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerNumberResultTransaction.java index 078e414b7..7e7d9f1c9 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerNumberResultTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerNumberResultTransaction.java @@ -16,7 +16,7 @@ */ package com.djrapitops.plan.extension.implementation.storage.transactions.results; -import com.djrapitops.plan.extension.implementation.providers.DataProvider; +import com.djrapitops.plan.extension.implementation.ProviderInformation; import com.djrapitops.plan.extension.implementation.providers.Parameters; import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderTable; @@ -33,7 +33,7 @@ import static com.djrapitops.plan.storage.database.sql.building.Sql.WHERE; import static com.djrapitops.plan.storage.database.sql.tables.ExtensionPlayerValueTable.*; /** - * Transaction to store method result of a {@link com.djrapitops.plan.extension.implementation.providers.NumberDataProvider}. + * Transaction to store method result of a long. * * @author AuroraLS3 */ @@ -46,9 +46,9 @@ public class StorePlayerNumberResultTransaction extends ThrowawayTransaction { private final long value; - public StorePlayerNumberResultTransaction(DataProvider provider, Parameters parameters, long value) { - this.pluginName = provider.getProviderInformation().getPluginName(); - this.providerName = provider.getProviderInformation().getName(); + public StorePlayerNumberResultTransaction(ProviderInformation information, Parameters parameters, long value) { + this.pluginName = information.getPluginName(); + this.providerName = information.getName(); this.serverUUID = parameters.getServerUUID(); this.playerUUID = parameters.getPlayerUUID(); this.value = value; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerStringResultTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerStringResultTransaction.java index 35e16b0c2..626feac62 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerStringResultTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerStringResultTransaction.java @@ -16,7 +16,7 @@ */ package com.djrapitops.plan.extension.implementation.storage.transactions.results; -import com.djrapitops.plan.extension.implementation.providers.DataProvider; +import com.djrapitops.plan.extension.implementation.ProviderInformation; import com.djrapitops.plan.extension.implementation.providers.Parameters; import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderTable; @@ -34,7 +34,7 @@ import static com.djrapitops.plan.storage.database.sql.building.Sql.WHERE; import static com.djrapitops.plan.storage.database.sql.tables.ExtensionPlayerValueTable.*; /** - * Transaction to store method result of a {@link com.djrapitops.plan.extension.implementation.providers.StringDataProvider}. + * Transaction to store method result of a String. * * @author AuroraLS3 */ @@ -47,9 +47,9 @@ public class StorePlayerStringResultTransaction extends ThrowawayTransaction { private final String value; - public StorePlayerStringResultTransaction(DataProvider provider, Parameters parameters, String value) { - this.pluginName = provider.getProviderInformation().getPluginName(); - this.providerName = provider.getProviderInformation().getName(); + public StorePlayerStringResultTransaction(ProviderInformation information, Parameters parameters, String value) { + this.pluginName = information.getPluginName(); + this.providerName = information.getName(); this.serverUUID = parameters.getServerUUID(); this.playerUUID = parameters.getPlayerUUID(); this.value = StringUtils.truncate(value, 50); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerTableResultTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerTableResultTransaction.java index aade948fd..69db2a8f0 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerTableResultTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StorePlayerTableResultTransaction.java @@ -17,6 +17,8 @@ package com.djrapitops.plan.extension.implementation.storage.transactions.results; import com.djrapitops.plan.exceptions.database.DBOpException; +import com.djrapitops.plan.extension.implementation.ProviderInformation; +import com.djrapitops.plan.extension.implementation.providers.Parameters; import com.djrapitops.plan.extension.table.Table; import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.storage.database.queries.Query; @@ -39,7 +41,7 @@ import static com.djrapitops.plan.storage.database.sql.building.Sql.*; import static com.djrapitops.plan.storage.database.sql.tables.ExtensionPlayerTableValueTable.*; /** - * Transaction to store method result of a {@link com.djrapitops.plan.extension.implementation.providers.TableDataProvider}. + * Transaction to store method result of a Table. * * @author AuroraLS3 */ @@ -60,6 +62,10 @@ public class StorePlayerTableResultTransaction extends ThrowawayTransaction { this.table = table; } + public StorePlayerTableResultTransaction(ProviderInformation information, Parameters parameters, Table value) { + this(information.getPluginName(), parameters.getServerUUID(), information.getName(), parameters.getPlayerUUID(), value); + } + @Override protected void performOperations() { execute(storeValue()); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerBooleanResultTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerBooleanResultTransaction.java index c1c12883a..99edd2fd3 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerBooleanResultTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerBooleanResultTransaction.java @@ -16,6 +16,8 @@ */ package com.djrapitops.plan.extension.implementation.storage.transactions.results; +import com.djrapitops.plan.extension.implementation.ProviderInformation; +import com.djrapitops.plan.extension.implementation.providers.Parameters; import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderTable; import com.djrapitops.plan.storage.database.transactions.ExecStatement; @@ -29,7 +31,7 @@ import static com.djrapitops.plan.storage.database.sql.building.Sql.WHERE; import static com.djrapitops.plan.storage.database.sql.tables.ExtensionServerValueTable.*; /** - * Transaction to store method result of a {@link com.djrapitops.plan.extension.implementation.providers.BooleanDataProvider}. + * Transaction to store method result of a boolean. * * @author AuroraLS3 */ @@ -48,6 +50,14 @@ public class StoreServerBooleanResultTransaction extends ThrowawayTransaction { this.value = value; } + public StoreServerBooleanResultTransaction(ProviderInformation information, Parameters parameters, boolean value) { + this(information.getPluginName(), + parameters.getServerUUID(), + information.getName(), + value + ); + } + @Override protected void performOperations() { execute(storeValue()); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerDoubleResultTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerDoubleResultTransaction.java index 6d61c3b1c..27dd7a6d2 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerDoubleResultTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerDoubleResultTransaction.java @@ -16,7 +16,7 @@ */ package com.djrapitops.plan.extension.implementation.storage.transactions.results; -import com.djrapitops.plan.extension.implementation.providers.DataProvider; +import com.djrapitops.plan.extension.implementation.ProviderInformation; import com.djrapitops.plan.extension.implementation.providers.Parameters; import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderTable; @@ -31,7 +31,7 @@ import static com.djrapitops.plan.storage.database.sql.building.Sql.WHERE; import static com.djrapitops.plan.storage.database.sql.tables.ExtensionServerValueTable.*; /** - * Transaction to store method result of a {@link com.djrapitops.plan.extension.implementation.providers.DoubleDataProvider}. + * Transaction to store method result of a double. * * @author AuroraLS3 */ @@ -44,12 +44,12 @@ public class StoreServerDoubleResultTransaction extends ThrowawayTransaction { private final double value; private final boolean percentage; - public StoreServerDoubleResultTransaction(DataProvider provider, Parameters parameters, double value) { - this.pluginName = provider.getProviderInformation().getPluginName(); - this.providerName = provider.getProviderInformation().getName(); + public StoreServerDoubleResultTransaction(ProviderInformation info, Parameters parameters, double value) { + this.pluginName = info.getPluginName(); + this.providerName = info.getName(); + this.percentage = info.isPercentage(); this.serverUUID = parameters.getServerUUID(); this.value = value; - this.percentage = provider.getProviderInformation().isPercentage(); } @Override diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerNumberResultTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerNumberResultTransaction.java index 66b3b6cf0..b77c4dd88 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerNumberResultTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerNumberResultTransaction.java @@ -16,7 +16,7 @@ */ package com.djrapitops.plan.extension.implementation.storage.transactions.results; -import com.djrapitops.plan.extension.implementation.providers.DataProvider; +import com.djrapitops.plan.extension.implementation.ProviderInformation; import com.djrapitops.plan.extension.implementation.providers.Parameters; import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderTable; @@ -31,7 +31,7 @@ import static com.djrapitops.plan.storage.database.sql.building.Sql.WHERE; import static com.djrapitops.plan.storage.database.sql.tables.ExtensionServerValueTable.*; /** - * Transaction to store method result of a {@link com.djrapitops.plan.extension.implementation.providers.NumberDataProvider}. + * Transaction to store method result of a long. * * @author AuroraLS3 */ @@ -43,9 +43,9 @@ public class StoreServerNumberResultTransaction extends ThrowawayTransaction { private final long value; - public StoreServerNumberResultTransaction(DataProvider provider, Parameters parameters, long value) { - this.pluginName = provider.getProviderInformation().getPluginName(); - this.providerName = provider.getProviderInformation().getName(); + public StoreServerNumberResultTransaction(ProviderInformation information, Parameters parameters, long value) { + this.pluginName = information.getPluginName(); + this.providerName = information.getName(); this.serverUUID = parameters.getServerUUID(); this.value = value; } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerStringResultTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerStringResultTransaction.java index c6f3377f5..fe5374c01 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerStringResultTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerStringResultTransaction.java @@ -16,7 +16,7 @@ */ package com.djrapitops.plan.extension.implementation.storage.transactions.results; -import com.djrapitops.plan.extension.implementation.providers.DataProvider; +import com.djrapitops.plan.extension.implementation.ProviderInformation; import com.djrapitops.plan.extension.implementation.providers.Parameters; import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderTable; @@ -44,9 +44,9 @@ public class StoreServerStringResultTransaction extends ThrowawayTransaction { private final String value; - public StoreServerStringResultTransaction(DataProvider provider, Parameters parameters, String value) { - this.pluginName = provider.getProviderInformation().getPluginName(); - this.providerName = provider.getProviderInformation().getName(); + 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); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerTableResultTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerTableResultTransaction.java index 20542a062..008d42073 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerTableResultTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/storage/transactions/results/StoreServerTableResultTransaction.java @@ -17,6 +17,8 @@ package com.djrapitops.plan.extension.implementation.storage.transactions.results; import com.djrapitops.plan.exceptions.database.DBOpException; +import com.djrapitops.plan.extension.implementation.ProviderInformation; +import com.djrapitops.plan.extension.implementation.providers.Parameters; import com.djrapitops.plan.extension.table.Table; import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.storage.database.queries.Query; @@ -38,7 +40,7 @@ import static com.djrapitops.plan.storage.database.sql.building.Sql.*; import static com.djrapitops.plan.storage.database.sql.tables.ExtensionServerTableValueTable.*; /** - * Transaction to store method result of a {@link com.djrapitops.plan.extension.implementation.providers.TableDataProvider}. + * Transaction to store method result of a Table. * * @author AuroraLS3 */ @@ -57,6 +59,10 @@ public class StoreServerTableResultTransaction extends ThrowawayTransaction { this.table = table; } + public StoreServerTableResultTransaction(ProviderInformation information, Parameters parameters, Table value) { + this(information.getPluginName(), parameters.getServerUUID(), information.getName(), value); + } + @Override protected void performOperations() { execute(storeValue()); diff --git a/Plan/common/src/test/java/com/djrapitops/plan/extension/implementation/builder/ClassValuePairOrderTest.java b/Plan/common/src/test/java/com/djrapitops/plan/extension/implementation/builder/ClassValuePairOrderTest.java new file mode 100644 index 000000000..d85e23810 --- /dev/null +++ b/Plan/common/src/test/java/com/djrapitops/plan/extension/implementation/builder/ClassValuePairOrderTest.java @@ -0,0 +1,191 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.implementation.builder; + +import com.djrapitops.plan.extension.DataExtension; +import com.djrapitops.plan.extension.annotation.Conditional; +import com.djrapitops.plan.extension.annotation.PluginInfo; +import com.djrapitops.plan.extension.annotation.StringProvider; +import com.djrapitops.plan.extension.builder.DataValue; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ClassValuePairOrderTest { + + @Test + void providedConditionsComeBeforeConditions() throws NoSuchMethodException { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @Conditional("condition") + @StringProvider(text = "a") + public String value() { + return ""; + } + } + + ExtDataBuilder builder = new ExtDataBuilder(new Extension()); + + DataValue first = builder.valueBuilder("test") + .buildBooleanProvidingCondition(false, "condition"); + DataValue second = builder.valueBuilder("test") + .conditional(Extension.class.getMethod("value").getAnnotation(Conditional.class)) + .buildBoolean(false); + + builder.addValue(Boolean.class, second); + builder.addValue(Boolean.class, first); + + List expected = Arrays.asList( + new ExtDataBuilder.ClassValuePair(Boolean.class, first), + new ExtDataBuilder.ClassValuePair(Boolean.class, second) + ); + List result = builder.getValues(); + + assertEquals(expected, result); + } + + @Test + void booleansComeFirst() throws NoSuchMethodException { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @Conditional("condition") + @StringProvider(text = "a") + public String value() { + return ""; + } + } + + ExtDataBuilder builder = new ExtDataBuilder(new Extension()); + + DataValue first = builder.valueBuilder("test") + .buildBooleanProvidingCondition(false, "condition"); + DataValue second = builder.valueBuilder("test") + .conditional(Extension.class.getMethod("value").getAnnotation(Conditional.class)) + .buildString("e"); + + builder.addValue(String.class, second); + builder.addValue(String.class, second); + builder.addValue(String.class, second); + builder.addValue(Boolean.class, first); + + List expected = Arrays.asList( + new ExtDataBuilder.ClassValuePair(Boolean.class, first), + new ExtDataBuilder.ClassValuePair(String.class, second), + new ExtDataBuilder.ClassValuePair(String.class, second), + new ExtDataBuilder.ClassValuePair(String.class, second) + ); + List result = builder.getValues(); + + assertEquals(expected, result); + } + + @Test + void booleansWithConditionsComeFirst() throws NoSuchMethodException { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @Conditional("condition") + @StringProvider(text = "a") + public String value() { + return ""; + } + + @Conditional("condition2") + @StringProvider(text = "a") + public String value2() { + return ""; + } + } + + ExtDataBuilder builder = new ExtDataBuilder(new Extension()); + + DataValue first = builder.valueBuilder("test") + .buildBooleanProvidingCondition(false, "condition"); + DataValue second = builder.valueBuilder("test") + .conditional(Extension.class.getMethod("value").getAnnotation(Conditional.class)) + .buildBooleanProvidingCondition(false, "condition2"); + DataValue third = builder.valueBuilder("test") + .conditional(Extension.class.getMethod("value2").getAnnotation(Conditional.class)) + .buildString("e"); + + builder.addValue(String.class, third); + builder.addValue(String.class, third); + builder.addValue(String.class, third); + builder.addValue(Boolean.class, second); + builder.addValue(Boolean.class, first); + + List expected = Arrays.asList( + new ExtDataBuilder.ClassValuePair(Boolean.class, first), + new ExtDataBuilder.ClassValuePair(Boolean.class, second), + new ExtDataBuilder.ClassValuePair(String.class, third), + new ExtDataBuilder.ClassValuePair(String.class, third), + new ExtDataBuilder.ClassValuePair(String.class, third) + ); + List result = builder.getValues(); + + assertEquals(expected, result); + } + + @Test + void booleansWithConditionsComeFirst2() throws NoSuchMethodException { + @PluginInfo(name = "Extension") + class Extension implements DataExtension { + @Conditional("condition") + @StringProvider(text = "a") + public String value() { + return ""; + } + + @Conditional("condition2") + @StringProvider(text = "a") + public String value2() { + return ""; + } + } + + ExtDataBuilder builder = new ExtDataBuilder(new Extension()); + + DataValue first = builder.valueBuilder("test") + .buildBooleanProvidingCondition(false, "condition"); + DataValue second = builder.valueBuilder("test") + .conditional(Extension.class.getMethod("value").getAnnotation(Conditional.class)) + .buildBooleanProvidingCondition(false, "condition2"); + DataValue third = builder.valueBuilder("test") + .conditional(Extension.class.getMethod("value2").getAnnotation(Conditional.class)) + .buildString("e"); + + builder.addValue(String.class, third); + builder.addValue(String.class, third); + builder.addValue(Boolean.class, first); + builder.addValue(Boolean.class, second); + builder.addValue(String.class, third); + + List expected = Arrays.asList( + new ExtDataBuilder.ClassValuePair(Boolean.class, first), + new ExtDataBuilder.ClassValuePair(Boolean.class, second), + new ExtDataBuilder.ClassValuePair(String.class, third), + new ExtDataBuilder.ClassValuePair(String.class, third), + new ExtDataBuilder.ClassValuePair(String.class, third) + ); + List result = builder.getValues(); + + assertEquals(expected, result); + } + +} diff --git a/Plan/common/src/test/java/com/djrapitops/plan/extension/implementation/builder/ExtendionDataBuilderTest.java b/Plan/common/src/test/java/com/djrapitops/plan/extension/implementation/builder/ExtendionDataBuilderTest.java new file mode 100644 index 000000000..2cfffe78c --- /dev/null +++ b/Plan/common/src/test/java/com/djrapitops/plan/extension/implementation/builder/ExtendionDataBuilderTest.java @@ -0,0 +1,56 @@ +/* + * 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 . + */ +package com.djrapitops.plan.extension.implementation.builder; + +import com.djrapitops.plan.extension.DataExtension; +import com.djrapitops.plan.extension.annotation.PluginInfo; +import org.junit.jupiter.api.Test; + +import java.util.Collections; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class ExtendionDataBuilderTest { + @Test + void nullTextWhenCreatingValueBuilderThrowsException() { + ExtDataBuilder builder = new ExtDataBuilder(new Extension()); + assertEquals( + "'text' can't be null or empty", + assertThrows(IllegalArgumentException.class, () -> builder.valueBuilder(null)).getMessage() + ); + } + + @Test + void emptyTextWhenCreatingValueBuilderThrowsException() { + ExtDataBuilder builder = new ExtDataBuilder(new Extension()); + assertEquals( + "'text' can't be null or empty", + assertThrows(IllegalArgumentException.class, () -> builder.valueBuilder("")).getMessage() + ); + } + + @Test + void nullClassSupplierNotAdded() { + ExtDataBuilder builder = new ExtDataBuilder(new Extension()); + builder.addValue(null, () -> null); + assertEquals(Collections.emptyList(), builder.getValues()); + } + + @PluginInfo(name = "Extension") + static class Extension implements DataExtension {} +} diff --git a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/DatabaseTestPreparer.java b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/DatabaseTestPreparer.java index 96d80d233..c95b1f436 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/DatabaseTestPreparer.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/DatabaseTestPreparer.java @@ -18,7 +18,7 @@ package com.djrapitops.plan.storage.database; import com.djrapitops.plan.PlanSystem; import com.djrapitops.plan.delivery.DeliveryUtilities; -import com.djrapitops.plan.extension.ExtensionService; +import com.djrapitops.plan.extension.ExtensionSvc; import com.djrapitops.plan.identification.ServerInfo; import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.settings.config.PlanConfig; @@ -59,7 +59,7 @@ public interface DatabaseTestPreparer { return system().getDeliveryUtilities(); } - default ExtensionService extensionService() {return system().getExtensionService();} + default ExtensionSvc extensionService() {return system().getExtensionService();} default void execute(Executable executable) { try { diff --git a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/H2Test.java b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/H2Test.java index d905fe670..ac0845295 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/H2Test.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/H2Test.java @@ -18,7 +18,7 @@ package com.djrapitops.plan.storage.database; import com.djrapitops.plan.PlanSystem; import com.djrapitops.plan.delivery.DeliveryUtilities; -import com.djrapitops.plan.extension.ExtensionService; +import com.djrapitops.plan.extension.ExtensionSvc; import com.djrapitops.plan.identification.Server; import com.djrapitops.plan.identification.ServerInfo; import com.djrapitops.plan.identification.ServerUUID; @@ -37,6 +37,7 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import utilities.DBPreparer; import utilities.RandomData; +import utilities.TestErrorLogger; import java.nio.file.Path; @@ -82,6 +83,7 @@ public class H2Test implements DatabaseTest, @BeforeEach void setUp() { + TestErrorLogger.throwErrors(true); db().executeTransaction(new Patch() { @Override public boolean hasBeenApplied() { @@ -144,7 +146,7 @@ public class H2Test implements DatabaseTest, } @Override - public ExtensionService extensionService() { + public ExtensionSvc extensionService() { return component.extensionService(); } diff --git a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/MySQLTest.java b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/MySQLTest.java index 5a3c5f060..0780ab476 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/MySQLTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/MySQLTest.java @@ -18,7 +18,7 @@ package com.djrapitops.plan.storage.database; import com.djrapitops.plan.PlanSystem; import com.djrapitops.plan.delivery.DeliveryUtilities; -import com.djrapitops.plan.extension.ExtensionService; +import com.djrapitops.plan.extension.ExtensionSvc; import com.djrapitops.plan.identification.Server; import com.djrapitops.plan.identification.ServerInfo; import com.djrapitops.plan.identification.ServerUUID; @@ -39,6 +39,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import utilities.DBPreparer; import utilities.RandomData; import utilities.TestConstants; +import utilities.TestErrorLogger; import java.nio.file.Path; import java.util.Optional; @@ -90,6 +91,7 @@ class MySQLTest implements DatabaseTest, @BeforeEach void setUp() { + TestErrorLogger.throwErrors(true); db().executeTransaction(new Patch() { @Override public boolean hasBeenApplied() { @@ -148,7 +150,7 @@ class MySQLTest implements DatabaseTest, } @Override - public ExtensionService extensionService() { + public ExtensionSvc extensionService() { return component.extensionService(); } diff --git a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/SQLiteTest.java b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/SQLiteTest.java index eba59a228..f335e0329 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/SQLiteTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/SQLiteTest.java @@ -18,7 +18,7 @@ package com.djrapitops.plan.storage.database; import com.djrapitops.plan.PlanSystem; import com.djrapitops.plan.delivery.DeliveryUtilities; -import com.djrapitops.plan.extension.ExtensionService; +import com.djrapitops.plan.extension.ExtensionSvc; import com.djrapitops.plan.identification.Server; import com.djrapitops.plan.identification.ServerInfo; import com.djrapitops.plan.identification.ServerUUID; @@ -37,6 +37,7 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import utilities.DBPreparer; import utilities.RandomData; +import utilities.TestErrorLogger; import java.nio.file.Path; @@ -82,6 +83,7 @@ public class SQLiteTest implements DatabaseTest, @BeforeEach void setUp() { + TestErrorLogger.throwErrors(true); db().executeTransaction(new Patch() { @Override public boolean hasBeenApplied() { @@ -141,7 +143,7 @@ public class SQLiteTest implements DatabaseTest, } @Override - public ExtensionService extensionService() { + public ExtensionSvc extensionService() { return component.extensionService(); } diff --git a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ExtensionsDatabaseTest.java b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ExtensionsDatabaseTest.java index b12fc868f..2094f874a 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ExtensionsDatabaseTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ExtensionsDatabaseTest.java @@ -19,9 +19,10 @@ package com.djrapitops.plan.storage.database.queries; import com.djrapitops.plan.delivery.rendering.html.structure.HtmlTable; import com.djrapitops.plan.extension.CallEvents; import com.djrapitops.plan.extension.DataExtension; -import com.djrapitops.plan.extension.ExtensionService; import com.djrapitops.plan.extension.ExtensionSvc; +import com.djrapitops.plan.extension.NotReadyException; import com.djrapitops.plan.extension.annotation.*; +import com.djrapitops.plan.extension.builder.ExtensionDataBuilder; import com.djrapitops.plan.extension.icon.Color; import com.djrapitops.plan.extension.icon.Icon; import com.djrapitops.plan.extension.implementation.results.*; @@ -42,6 +43,7 @@ import org.junit.jupiter.api.Test; import utilities.OptionalAssert; import utilities.RandomData; import utilities.TestConstants; +import utilities.TestErrorLogger; import java.util.List; import java.util.Map; @@ -59,11 +61,13 @@ public interface ExtensionsDatabaseTest extends DatabaseTestPreparer { @BeforeEach default void unregisterExtensions() { - ExtensionService extensionService = extensionService(); + ExtensionSvc extensionService = extensionService(); + extensionService.register(); extensionService.unregister(new PlayerExtension()); extensionService.unregister(new ServerExtension()); extensionService.unregister(new ConditionalExtension()); extensionService.unregister(new TableExtension()); + extensionService.unregister(new ThrowingExtension()); } @Test @@ -82,7 +86,7 @@ public interface ExtensionsDatabaseTest extends DatabaseTestPreparer { @Test default void extensionPlayerValuesAreStored() { - ExtensionSvc extensionService = (ExtensionSvc) extensionService(); + ExtensionSvc extensionService = extensionService(); extensionService.register(new PlayerExtension()); extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME, CallEvents.MANUAL); @@ -130,7 +134,7 @@ public interface ExtensionsDatabaseTest extends DatabaseTestPreparer { @Test default void extensionServerValuesAreStored() { - ExtensionSvc extensionService = (ExtensionSvc) extensionService(); + ExtensionSvc extensionService = extensionService(); extensionService.register(new ServerExtension()); extensionService.updateServerValues(CallEvents.SERVER_EXTENSION_REGISTER); @@ -152,7 +156,7 @@ public interface ExtensionsDatabaseTest extends DatabaseTestPreparer { @Test default void extensionServerAggregateQueriesWork() { - ExtensionSvc extensionService = (ExtensionSvc) extensionService(); + ExtensionSvc extensionService = extensionService(); extensionService.register(new PlayerExtension()); extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME, CallEvents.MANUAL); @@ -183,7 +187,7 @@ public interface ExtensionsDatabaseTest extends DatabaseTestPreparer { @Test default void unsatisfiedPlayerConditionalResultsAreCleaned() { - ExtensionSvc extensionService = (ExtensionSvc) extensionService(); + ExtensionSvc extensionService = extensionService(); extensionService.register(new ConditionalExtension()); @@ -237,7 +241,7 @@ public interface ExtensionsDatabaseTest extends DatabaseTestPreparer { @Test default void unsatisfiedServerConditionalResultsAreCleaned() { - ExtensionSvc extensionService = (ExtensionSvc) extensionService(); + ExtensionSvc extensionService = extensionService(); ConditionalExtension.condition = true; extensionService.register(new ConditionalExtension()); @@ -288,7 +292,7 @@ public interface ExtensionsDatabaseTest extends DatabaseTestPreparer { @Test default void extensionServerTableValuesAreInserted() { - ExtensionSvc extensionService = (ExtensionSvc) extensionService(); + ExtensionSvc extensionService = extensionService(); extensionService.register(new TableExtension()); extensionService.updateServerValues(CallEvents.MANUAL); @@ -320,7 +324,7 @@ public interface ExtensionsDatabaseTest extends DatabaseTestPreparer { @Test default void extensionPlayerTableValuesAreInserted() { - ExtensionSvc extensionService = (ExtensionSvc) extensionService(); + ExtensionSvc extensionService = extensionService(); extensionService.register(new TableExtension()); extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME, CallEvents.MANUAL); @@ -352,6 +356,19 @@ public interface ExtensionsDatabaseTest extends DatabaseTestPreparer { assertEquals(expected.toHtml(), table.getHtmlTable().toHtml()); } + @Test + default void extensionExceptionsAreCaught() { + TestErrorLogger.throwErrors(false); + ExtensionSvc extensionService = extensionService(); + extensionService.register(new ThrowingExtension()); + + extensionService.updateServerValues(CallEvents.MANUAL); + extensionService.updatePlayerValues(playerUUID, TestConstants.PLAYER_ONE_NAME, CallEvents.MANUAL); + // 5 of the exceptions need to be logged, there are 8 exceptions total 3 of which are ignored. + assertEquals(5, TestErrorLogger.getCaught().size(), () -> "Not all exceptions got logged, logged exceptions: " + TestErrorLogger.getCaught().toString()); + } + + @PluginInfo(name = "ConditionalExtension") class ConditionalExtension implements DataExtension { @@ -491,4 +508,53 @@ public interface ExtensionsDatabaseTest extends DatabaseTestPreparer { .build(); } } + + @PluginInfo(name = "ThrowingExtension") + class ThrowingExtension implements DataExtension { + @BooleanProvider(text = "a boolean") + public boolean booleanMethod() { + throw new IllegalArgumentException("Failed to catch"); + } + + @BooleanProvider(text = "a boolean") + public boolean booleanPlayerMethod(UUID playerUUID) { + throw new NotReadyException(); + } + + @StringProvider(text = "a string") + public String stringMethod() { + throw new NoSuchMethodError(); + } + + @NumberProvider(text = "a string") + public long numberMethod() { + throw new UnsupportedOperationException(); + } + + @GroupProvider(text = "group") + public String[] groupMethod(UUID playerUUID) { + throw new NoClassDefFoundError(); + } + + @DataBuilderProvider + public ExtensionDataBuilder builder() { + return newExtensionDataBuilder() + .addValue(String.class, () -> { + throw new NotReadyException(); + }); + } + + @DataBuilderProvider + public ExtensionDataBuilder builder2() { + return newExtensionDataBuilder() + .addValue(String.class, () -> { + throw new NoClassDefFoundError(); + }); + } + + @DataBuilderProvider + public ExtensionDataBuilder builder3() { + throw new NoSuchMethodError(); + } + } } diff --git a/Plan/common/src/test/java/utilities/TestErrorLogger.java b/Plan/common/src/test/java/utilities/TestErrorLogger.java index 4d687a218..7f9ac5f0c 100644 --- a/Plan/common/src/test/java/utilities/TestErrorLogger.java +++ b/Plan/common/src/test/java/utilities/TestErrorLogger.java @@ -19,29 +19,51 @@ package utilities; import com.djrapitops.plan.utilities.logging.ErrorContext; import com.djrapitops.plan.utilities.logging.ErrorLogger; +import java.util.ArrayList; +import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; public class TestErrorLogger implements ErrorLogger { + private static final List caught = new ArrayList<>(); + private static boolean throwErrors = true; + + public static void throwErrors(boolean throwErrors) { + caught.clear(); + TestErrorLogger.throwErrors = throwErrors; + } + + public static List getCaught() { + return caught; + } + @Override public void critical(Throwable throwable, ErrorContext context) { System.out.println("[CRITICAL] Exception occurred during test, context: " + context); Logger.getGlobal().log(Level.SEVERE, "The exception: " + throwable.getMessage(), throwable); - throw new AssertionError(throwable); + throwOrStore(throwable); } @Override public void error(Throwable throwable, ErrorContext context) { System.out.println("[ERROR] Exception occurred during test, context: " + context); Logger.getGlobal().log(Level.SEVERE, "The exception: " + throwable.getMessage(), throwable); - throw new AssertionError(throwable); + throwOrStore(throwable); } @Override public void warn(Throwable throwable, ErrorContext context) { System.out.println("[WARN] Exception occurred during test, context: " + context); Logger.getGlobal().log(Level.SEVERE, "The exception: " + throwable.getMessage(), throwable); - throw new AssertionError(throwable); + throwOrStore(throwable); + } + + public void throwOrStore(Throwable throwable) { + if (throwErrors) { + throw new AssertionError(throwable); + } else { + caught.add(throwable); + } } } diff --git a/Plan/extensions/src/main/java/com/djrapitops/plan/extension/implementation/ExtensionRegister.java b/Plan/extensions/src/main/java/com/djrapitops/plan/extension/implementation/ExtensionRegister.java index 4f3bbc57f..c8700328c 100644 --- a/Plan/extensions/src/main/java/com/djrapitops/plan/extension/implementation/ExtensionRegister.java +++ b/Plan/extensions/src/main/java/com/djrapitops/plan/extension/implementation/ExtensionRegister.java @@ -21,7 +21,6 @@ import com.djrapitops.plan.extension.Caller; import com.djrapitops.plan.extension.DataExtension; import com.djrapitops.plan.extension.ExtensionService; import com.djrapitops.plan.extension.NotReadyException; -import com.djrapitops.plan.extension.extractor.ExtensionExtractor; import javax.inject.Inject; import javax.inject.Named; @@ -181,7 +180,7 @@ public class ExtensionRegister { } private Optional register(DataExtension dataExtension) { - String extensionName = ExtensionExtractor.getPluginName(dataExtension.getClass()); + String extensionName = dataExtension.getPluginName(); if (disabledExtensions.contains(extensionName)) return Optional.empty(); return extensionService.register(dataExtension);