11 DataExtension API Builders
Aurora Lahtela edited this page 2022-10-30 11:27:50 +02:00

Plan Header

DataExtension API - Builders

DataExtension Builder APIs require DATA_EXTENSION_BUILDER_API capability.


🧰 @DataBuilderProvider annotation

Speciality: Allows you to add data dynamically.

Example use case: Display user configured placeholders

Usage:

@DataBuilderProvider
public ExtensionDataBuilder lotsOfData(UUID playerUUID) {
    ExtensionDataBuilder builder = newExtensionDataBuilder();
    ...
    return builder;
}

Adding values

You can add all the same kinds of values as with the annotation API. In the most simple form:

ExtensionDataBuilder builder = newExtensionDataBuilder();
return builder.addValue(Long.class, 
    builder.valueBuilder("Steps taken") // The text should be different for each value
           .buildNumber(53298L)
);

You can add multiple values to a single builder before returning it.

Here are the types and build methods that are available:

ExtensionDataBuilder builder = newExtensionDataBuilder();

builder.addValue(Boolean.class,  builder.valueBuilder("...").buildBoolean(false));
builder.addValue(Boolean.class,  builder.valueBuilder("...").buildBoolean(() -> false));
// for use with @Conditional on other provider annotations
builder.addValue(Boolean.class,  builder.valueBuilder("...").buildBooleanProvidingCondition(false, "conditionName"));
// for use with @Conditional on other provider annotations
builder.addValue(Boolean.class,     builder.valueBuilder("...").buildBooleanProvidingCondition(() -> false, "conditionName"));
builder.addValue(Long.class,        builder.valueBuilder("...").buildNumber(1234L));
builder.addValue(Long.class,        builder.valueBuilder("...").buildNumber(() -> 1234L));
builder.addValue(Double.class,      builder.valueBuilder("...").buildDouble(500.52));
builder.addValue(Double.class,      builder.valueBuilder("...").buildDouble(() -> 500.52));
builder.addValue(Double.class,      builder.valueBuilder("...").buildPercentage(0.52));
builder.addValue(Double.class,      builder.valueBuilder("...").buildPercentage(() -> 0.52));
builder.addValue(String.class,      builder.valueBuilder("...").buildString("Example"));
builder.addValue(String.class,      builder.valueBuilder("...").buildString(() -> "Example"));
builder.addValue(Component.class,   builder.valueBuilder("...").buildComponent(ComponentService.getInstance().fromAutoDetermine("§eExample")));
builder.addValue(Component.class,   builder.valueBuilder("...").buildComponent(() -> ComponentService.getInstance().fromAutoDetermine("§eExample"))));
builder.addValue(String[].class,    builder.valueBuilder("...").buildGroup(new String[]{"Admin", "Moderator"}));
builder.addValue(String[].class,    builder.valueBuilder("...").buildGroup(() -> new String[]{"Admin", "Moderator"}));
builder.addValue(Table.class,       builder.valueBuilder("...").buildTable(Table.builder()...build(), Color.BLUE));
builder.addValue(Table.class,       builder.valueBuilder("...").buildTable(() -> Table.builder()...build(), Color.BLUE));

return builder;

The lambda methods can be used for method references, conditional values (eg returning null sometimes) and for throwing NotReadyException for a specific value.

Example

@DataBuilderProvider
public ExtensionDataBuilder lotsOfServerData() {
    ExtensionDataBuilder builder = newExtensionDataBuilder();
    return builder.addValue(Long.class, builder.valueBuilder("Houses built")
            .buildNumber(() -> {
                if (database == null) throw new NotReadyException();
                return database.getHouseCount();
            })
        ).addValue(Long.class, builder.valueBuilder("Superheroes")
            .buildNumber(this::getSuperheroCount)
        );

Clean value building example

@DataBuilderProvider
public ExtensionDataBuilder lotsOfServerData() {
    return newExtensionDataBuilder().addValue(Long.class, this::superheroCountValue);
}

private DataValue<Long> superheroCountValue() {
    return valueBuilder("Superheroes")
            .buildNumber(this::getSuperheroCount);
}

private long getSuperheroCount() {
    return 0; // TODO implement later
}

In addition to this value builder has a lot of other methods:

builder.valueBuilder("Example")                                        // 50 char limit
    .description("Describes what Example is about")                    // 150 char limit
    .priority(0)                                                       // ordering priority, highest value is placed top most on the page
    .icon("gavel", Family.SOLID, Color.RED)                            // https://fontawesome.com/icons
    .icon(Icon.called("gavel").of(Family.SOLID).of(Color.RED).build()) // https://fontawesome.com/icons
    .showInPlayerTable()
    .showOnTab("tabName")                                              // remember to add a @TabInfo annotation if using this
    .formatAsDateWithYear()    // for numbers
    .formatAsDateWithSeconds() // for numbers
    .formatAsTimeAmount()      // for numbers
    .format(FormatType.NONE)   // for numbers
    .showAsPlayerPageLink()    // for strings

Adding tables

In addition to the ValueBuilder methods, you can use ExtensionDataBuilder#addTable methods for adding tables dynamically.

ExtensionDataBuilder builder = newExtensionDataBuilder()
    .addTable("table name", Table.builder()...build(), Color.BLUE)
    .addTable("table name", Table.builder()...build(), Color.BLUE, "tabName");

Stuff to avoid

⚠️ Don't define @Conditional with @DataBuilderProvider - it is not supported

@DataBuilderProvider
@Conditional("conditionName") // Throws IllegalArgumentException when registering the extension
public ExtensionDataBuilder lotsOfData(UUID playerUUID) {
}