Skip to content

feature(api): Property default override SPI and flattener nesting limit property #1250

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main/4
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
*/
package net.kyori.adventure.internal.properties;

import java.util.Objects;
import java.util.function.Function;
import net.kyori.adventure.text.flattener.ComponentFlattener;
import net.kyori.adventure.util.PlatformAPI;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -52,13 +55,19 @@ public final class AdventureProperties {
*
* @since 4.10.0
*/
public static final Property<Boolean> SERVICE_LOAD_FAILURES_ARE_FATAL = property("serviceLoadFailuresAreFatal", Boolean::parseBoolean, Boolean.TRUE);
public static final Property<Boolean> SERVICE_LOAD_FAILURES_ARE_FATAL = property("serviceLoadFailuresAreFatal", Boolean::parseBoolean, Boolean.TRUE, false);
/**
* Property for specifying whether to warn when legacy formatting is detected.
*
* @since 4.10.0
*/
public static final Property<Boolean> TEXT_WARN_WHEN_LEGACY_FORMATTING_DETECTED = property("text.warnWhenLegacyFormattingDetected", Boolean::parseBoolean, Boolean.FALSE);
/**
* Property for setting a global default for flattener nesting.
*
* @since 4.24.0
*/
public static final Property<Integer> DEFAULT_FLATTENER_NESTING_LIMIT = property("defaultFlattenerNestingLimit", Integer::parseInt, ComponentFlattener.NO_NESTING_LIMIT);

private AdventureProperties() {
}
Expand All @@ -74,7 +83,22 @@ private AdventureProperties() {
* @since 4.10.0
*/
public static <T> @NotNull Property<T> property(final @NotNull String name, final @NotNull Function<String, T> parser, final @Nullable T defaultValue) {
return AdventurePropertiesImpl.property(name, parser, defaultValue);
return property(name, parser, defaultValue, true);
}

/**
* Creates a new property.
*
* @param name the property name
* @param parser the value parser
* @param defaultValue the default value
* @param allowProviderDefaultOverride if the {@link DefaultOverrideProvider} is used to override the default value provided
* @param <T> the value type
* @return a property
* @since 4.24.0
*/
public static <T> @NotNull Property<T> property(final @NotNull String name, final @NotNull Function<String, T> parser, final @Nullable T defaultValue, final boolean allowProviderDefaultOverride) {
return AdventurePropertiesImpl.property(name, parser, defaultValue, allowProviderDefaultOverride);
}

/**
Expand All @@ -93,5 +117,37 @@ public interface Property<T> {
* @since 4.10.0
*/
@Nullable T value();

/**
* Gets the value, returning a default value if the value is {@code null}.
*
* @param defaultValue the default value
* @return the value
* @since 4.24.0
*/
default @NotNull T valueOr(final @NotNull T defaultValue) {
final T value = this.value();
return value == null ? Objects.requireNonNull(defaultValue, "defaultValue") : value;
}
}

/**
* A service provider that allows default property values to be overridden.
*
* @since 4.24.0
*/
@ApiStatus.Internal
@PlatformAPI
public interface DefaultOverrideProvider {
/**
* Overrides the default value for a property.
*
* @param name the name of the property
* @param existingDefault the current default value
* @return the new default value
* @param <T> the value type
* @since 4.24.0
*/
<T> @Nullable T overrideDefault(final @NotNull String name, final @Nullable T existingDefault);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,17 @@
import java.util.Optional;
import java.util.Properties;
import java.util.function.Function;
import net.kyori.adventure.util.Services;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.VisibleForTesting;

final class AdventurePropertiesImpl {

static final class Providers {
static final @NotNull Optional<AdventureProperties.DefaultOverrideProvider> DEFAULT_PROVIDER = Services.service(AdventureProperties.DefaultOverrideProvider.class);
}

private static final String FILESYSTEM_DIRECTORY_NAME = "config";
private static final String FILESYSTEM_FILE_NAME = "adventure.properties";
private static final Properties PROPERTIES = new Properties();
Expand Down Expand Up @@ -67,21 +73,23 @@ private AdventurePropertiesImpl() {
return String.join(".", "net", "kyori", "adventure", name);
}

static <T> AdventureProperties.@NotNull Property<T> property(final @NotNull String name, final @NotNull Function<String, T> parser, final @Nullable T defaultValue) {
return new PropertyImpl<>(name, parser, defaultValue);
static <T> AdventureProperties.@NotNull Property<T> property(final @NotNull String name, final @NotNull Function<String, T> parser, final @Nullable T defaultValue, final boolean allowProviderDefaultOverride) {
return new PropertyImpl<>(name, parser, defaultValue, allowProviderDefaultOverride);
}

private static final class PropertyImpl<T> implements AdventureProperties.Property<T> {
private final String name;
private final Function<String, T> parser;
private final @Nullable T defaultValue;
private final boolean allowProviderDefaultOverride;
private boolean valueCalculated;
private @Nullable T value;

PropertyImpl(final @NotNull String name, final @NotNull Function<String, T> parser, final @Nullable T defaultValue) {
PropertyImpl(final @NotNull String name, final @NotNull Function<String, T> parser, final @Nullable T defaultValue, final boolean allowProviderDefaultOverride) {
this.name = name;
this.parser = parser;
this.defaultValue = defaultValue;
this.allowProviderDefaultOverride = allowProviderDefaultOverride;
}

@Override
Expand All @@ -93,7 +101,13 @@ private static final class PropertyImpl<T> implements AdventureProperties.Proper
this.value = this.parser.apply(value);
}
if (this.value == null) {
this.value = this.defaultValue;
if (this.allowProviderDefaultOverride) {
this.value = Providers.DEFAULT_PROVIDER
.map(provider -> provider.overrideDefault(this.name, this.defaultValue))
.orElse(this.defaultValue);
} else {
this.value = this.defaultValue;
}
}
this.valueCalculated = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ interface Builder extends AbstractBuilder<ComponentFlattener>, Buildable.Builder
/**
* Sets the limit of nested flatten calls.
*
* <p>The default value is {@link #NO_NESTING_LIMIT}, which means there is no limit on nesting.</p>
* <p>Unless the property is changed, the default value is {@link #NO_NESTING_LIMIT},
* which means there is no limit on nesting.</p>
*
* @param limit the new limit (must be a positive integer, or {@link #NO_NESTING_LIMIT})
* @return this builder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import net.kyori.adventure.internal.properties.AdventureProperties;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.KeybindComponent;
import net.kyori.adventure.text.ScoreComponent;
Expand Down Expand Up @@ -170,7 +171,7 @@ interface Handler {
static final class BuilderImpl implements Builder {
private final InheritanceAwareMap.Builder<Component, Handler> flatteners;
private @Nullable Function<Component, String> unknownHandler;
private int maxNestedDepth = ComponentFlattener.NO_NESTING_LIMIT;
private int maxNestedDepth = AdventureProperties.DEFAULT_FLATTENER_NESTING_LIMIT.valueOr(ComponentFlattener.NO_NESTING_LIMIT);

BuilderImpl() {
this.flatteners = InheritanceAwareMap.<Component, Handler>builder().strict(true);
Expand Down