Increases flexibility and reduces number of methods for the format builder
All checks were successful
KnarCraft/KnarLib/pipeline/head This commit looks good

Adds some tests for the FormatBuilder
Replaces all the different methods with a few methods that accept any object
Adds a method for converting any non-null object to a string
Adds throws to the methods that might throw an IllegalStateException
This commit is contained in:
2025-09-12 02:36:07 +02:00
parent 9526188d27
commit 298b339ac6
2 changed files with 96 additions and 224 deletions

View File

@@ -6,7 +6,9 @@ import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Arrays; import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
/** /**
@@ -17,6 +19,7 @@ public final class FormatBuilder {
private static @Nullable StringFormatter stringFormatter = null; private static @Nullable StringFormatter stringFormatter = null;
private static final IllegalStateException NOT_SETUP_EXCEPTION = new IllegalStateException("String formatter has not been set!"); private static final IllegalStateException NOT_SETUP_EXCEPTION = new IllegalStateException("String formatter has not been set!");
private static final String LIST_DELIMITER = ",";
private @NotNull String toFormat; private @NotNull String toFormat;
/** /**
@@ -41,7 +44,7 @@ public final class FormatBuilder {
* @param translatableMessage <p>The translatable message to format</p> * @param translatableMessage <p>The translatable message to format</p>
* @throws IllegalStateException <p>If the string formatter has not been set</p> * @throws IllegalStateException <p>If the string formatter has not been set</p>
*/ */
public FormatBuilder(@NotNull TranslatableMessage translatableMessage) { public FormatBuilder(@NotNull TranslatableMessage translatableMessage) throws IllegalStateException {
if (FormatBuilder.stringFormatter == null) { if (FormatBuilder.stringFormatter == null) {
throw NOT_SETUP_EXCEPTION; throw NOT_SETUP_EXCEPTION;
} }
@@ -98,10 +101,12 @@ public final class FormatBuilder {
* @param placeholder <p>The placeholder to replace</p> * @param placeholder <p>The placeholder to replace</p>
* @param replacement <p>The replacement</p> * @param replacement <p>The replacement</p>
* @return <p>This format builder</p> * @return <p>This format builder</p>
* @throws IllegalStateException <p>If the string formatter has not been set, and the placeholder or replacement is
* a translatable message</p>
*/ */
@NotNull @NotNull
public FormatBuilder replace(@NotNull String placeholder, @NotNull String replacement) { public <K, L> FormatBuilder replace(@NotNull K placeholder, @NotNull L replacement) throws IllegalStateException {
this.toFormat = StringFormatter.replacePlaceholder(this.toFormat, placeholder, replacement); this.toFormat = StringFormatter.replacePlaceholder(this.toFormat, asString(placeholder), asString(replacement));
return this; return this;
} }
@@ -117,183 +122,6 @@ public final class FormatBuilder {
return this; return this;
} }
/**
* Replaces placeholders for the current string
*
* @param placeholder <p>The translatable message to replace</p>
* @param replacement <p>The replacement translatable message</p>
* @return <p>This format builder</p>
* @throws IllegalStateException <p>If the string formatter has not been set</p>
*/
@NotNull
public FormatBuilder replace(@NotNull TranslatableMessage placeholder,
@NotNull TranslatableMessage replacement) {
if (FormatBuilder.stringFormatter == null) {
throw NOT_SETUP_EXCEPTION;
}
return replace(FormatBuilder.stringFormatter.getUnFormattedMessage(placeholder),
FormatBuilder.stringFormatter.getUnFormattedMessage(replacement));
}
/**
* Replaces placeholders for the current string
*
* @param placeholder <p>The placeholder to replace</p>
* @param replacement <p>The replacement translatable message</p>
* @return <p>This format builder</p>
* @throws IllegalStateException <p>If the string formatter has not been set</p>
*/
@NotNull
public FormatBuilder replace(@NotNull String placeholder, @NotNull TranslatableMessage replacement) {
if (FormatBuilder.stringFormatter == null) {
throw NOT_SETUP_EXCEPTION;
}
return replace(placeholder, FormatBuilder.stringFormatter.getUnFormattedMessage(replacement));
}
/**
* Replaces placeholders for the current string
*
* @param placeholder <p>The translatable message placeholder to replace</p>
* @param replacement <p>The replacement string</p>
* @return <p>This format builder</p>
* @throws IllegalStateException <p>If the string formatter has not been set</p>
*/
@NotNull
public FormatBuilder replace(@NotNull TranslatableMessage placeholder, @NotNull String replacement) {
if (FormatBuilder.stringFormatter == null) {
throw NOT_SETUP_EXCEPTION;
}
return replace(FormatBuilder.stringFormatter.getUnFormattedMessage(placeholder), replacement);
}
/**
* Replaces placeholders for the current string
*
* @param placeholder <p>The placeholder to replace</p>
* @param stringBuilder <p>The replacement string builder</p>
* @return <p>This format builder</p>
*/
@NotNull
public FormatBuilder replace(@NotNull String placeholder, @NotNull StringBuilder stringBuilder) {
return replace(placeholder, stringBuilder.toString());
}
/**
* Replaces placeholders for the current string
*
* @param placeholder <p>The placeholder to replace</p>
* @param replacement <p>The replacement</p>
* @return <p>This format builder</p>
*/
@NotNull
public FormatBuilder replace(@NotNull String placeholder, @NotNull FormatBuilder replacement) {
return replace(placeholder, replacement.toString());
}
/**
* Replaces placeholders for the current string
*
* @param placeholder <p>The placeholder to replace</p>
* @param replacement <p>The replacement</p>
* @return <p>This format builder</p>
*/
@NotNull
public FormatBuilder replace(@NotNull FormatBuilder placeholder, @NotNull String replacement) {
return replace(placeholder.toString(), replacement);
}
/**
* Replaces placeholders for the current string
*
* @param placeholder <p>The placeholder to replace</p>
* @param replacement <p>The replacement</p>
* @return <p>This format builder</p>
*/
@NotNull
public FormatBuilder replace(@NotNull FormatBuilder placeholder, @NotNull FormatBuilder replacement) {
return replace(placeholder.toString(), replacement.toString());
}
/**
* Replaces placeholders for the current string
*
* @param placeholder <p>The placeholder to replace</p>
* @param replacement <p>The replacement</p>
* @return <p>This format builder</p>
* @throws IllegalStateException <p>If the string formatter has not been set</p>
*/
@NotNull
public FormatBuilder replace(@NotNull TranslatableMessage placeholder, @NotNull FormatBuilder replacement) {
return replace(placeholder, replacement.toString());
}
/**
* Replaces placeholders for the current string
*
* @param placeholder <p>The placeholder to replace</p>
* @param replacement <p>The replacement</p>
* @return <p>This format builder</p>
* @throws IllegalStateException <p>If the string formatter has not been set</p>
*/
@NotNull
public FormatBuilder replace(@NotNull FormatBuilder placeholder, @NotNull TranslatableMessage replacement) {
return replace(placeholder.toString(), replacement);
}
/**
* Replaces a placeholder for the current string
*
* @param placeholder <p>The translatable message placeholder to replace</p>
* @param replacement <p>The object to get the string value of</p>
* @return <p>This format builder</p>
* @throws IllegalStateException <p>If the string formatter has not been set</p>
*/
@NotNull
public FormatBuilder replace(@NotNull TranslatableMessage placeholder, @NotNull Object replacement) {
return replace(placeholder, String.valueOf(replacement));
}
/**
* Replaces a placeholder for the current string
*
* @param placeholder <p>The placeholder to replace</p>
* @param replacement <p>The object to get the string value of</p>
* @return <p>This format builder</p>
*/
@NotNull
public FormatBuilder replace(@NotNull String placeholder, @NotNull Object replacement) {
return replace(placeholder, String.valueOf(replacement));
}
/**
* Replaces a placeholder for the current string
*
* <p>This method turns the given array into a string, and replaces the placeholder with that string.</p>
*
* @param placeholder <p>The placeholder to replace</p>
* @param replacement <p>The list of strings to replace with</p>
* @return <p>This format builder</p>
*/
@NotNull
public FormatBuilder replace(@NotNull String placeholder, @NotNull List<String> replacement) {
return replace(placeholder, replacement.toArray());
}
/**
* Replaces a placeholder for the current string
*
* <p>This method turns the given array into a string, and replaces the placeholder with that string.</p>
*
* @param placeholder <p>The placeholder to replace</p>
* @param replacement <p>The list of strings to replace with</p>
* @return <p>This format builder</p>
*/
@NotNull
public FormatBuilder replace(@NotNull String placeholder, @NotNull String[] replacement) {
return replace(placeholder, Arrays.toString(replacement));
}
/** /**
* Converts color codes in the current string * Converts color codes in the current string
* *
@@ -304,7 +132,7 @@ public final class FormatBuilder {
* @throws IllegalStateException <p>If the string formatter has not been set</p> * @throws IllegalStateException <p>If the string formatter has not been set</p>
*/ */
@NotNull @NotNull
public FormatBuilder color() { public FormatBuilder color() throws IllegalStateException {
if (FormatBuilder.stringFormatter == null) { if (FormatBuilder.stringFormatter == null) {
throw NOT_SETUP_EXCEPTION; throw NOT_SETUP_EXCEPTION;
} }
@@ -331,57 +159,21 @@ public final class FormatBuilder {
* *
* @param input <p>The input to append</p> * @param input <p>The input to append</p>
* @return <p>This format builder</p> * @return <p>This format builder</p>
* @throws IllegalStateException <p>If the string formatter has not been set, and the input is a translatable message</p>
*/ */
@NotNull @NotNull
public FormatBuilder append(@NotNull String input) { public <K> FormatBuilder append(@NotNull K input) throws IllegalStateException {
this.toFormat += input; this.toFormat += asString(input);
return this; return this;
} }
/**
* Appends the given translatable message to this format builder
*
* @param translatableMessage <p>The translatable message to append</p>
* @return <p>This format builder</p>
* @throws IllegalStateException <p>If the string formatter has not been set</p>
*/
@NotNull
public FormatBuilder append(@NotNull TranslatableMessage translatableMessage) {
if (FormatBuilder.stringFormatter == null) {
throw NOT_SETUP_EXCEPTION;
}
return append(FormatBuilder.stringFormatter.getUnFormattedMessage(translatableMessage));
}
/**
* Appends the given string builder's output to this format builder
*
* @param stringBuilder <p>The string builder to append</p>
* @return <p>This format builder</p>
*/
@NotNull
public FormatBuilder append(@NotNull StringBuilder stringBuilder) {
return append(stringBuilder.toString());
}
/**
* Appends the given format builder's output to this format builder
*
* @param formatBuilder <p>The format builder to append</p>
* @return <p>This format builder</p>
*/
@NotNull
public FormatBuilder append(@NotNull FormatBuilder formatBuilder) {
return append(formatBuilder.toString());
}
/** /**
* Displays the result to the specified command sender as a success message * Displays the result to the specified command sender as a success message
* *
* @param commandSender <p>The recipient</p> * @param commandSender <p>The recipient</p>
* @throws IllegalStateException <p>If the string formatter has not been set</p> * @throws IllegalStateException <p>If the string formatter has not been set</p>
*/ */
public void success(@NotNull CommandSender commandSender) { public void success(@NotNull CommandSender commandSender) throws IllegalStateException {
if (FormatBuilder.stringFormatter == null) { if (FormatBuilder.stringFormatter == null) {
throw NOT_SETUP_EXCEPTION; throw NOT_SETUP_EXCEPTION;
} }
@@ -394,7 +186,7 @@ public final class FormatBuilder {
* @param commandSender <p>The recipient</p> * @param commandSender <p>The recipient</p>
* @throws IllegalStateException <p>If the string formatter has not been set</p> * @throws IllegalStateException <p>If the string formatter has not been set</p>
*/ */
public void error(@NotNull CommandSender commandSender) { public void error(@NotNull CommandSender commandSender) throws IllegalStateException {
if (FormatBuilder.stringFormatter == null) { if (FormatBuilder.stringFormatter == null) {
throw NOT_SETUP_EXCEPTION; throw NOT_SETUP_EXCEPTION;
} }
@@ -407,7 +199,7 @@ public final class FormatBuilder {
* @param commandSender <p>The recipient</p> * @param commandSender <p>The recipient</p>
* @throws IllegalStateException <p>If the string formatter has not been set</p> * @throws IllegalStateException <p>If the string formatter has not been set</p>
*/ */
public void neutral(@NotNull CommandSender commandSender) { public void neutral(@NotNull CommandSender commandSender) throws IllegalStateException {
if (FormatBuilder.stringFormatter == null) { if (FormatBuilder.stringFormatter == null) {
throw NOT_SETUP_EXCEPTION; throw NOT_SETUP_EXCEPTION;
} }
@@ -420,4 +212,41 @@ public final class FormatBuilder {
return this.toFormat; return this.toFormat;
} }
/**
* Converts the given input to a string
*
* @param input <p>The input to convert</p>
* @return <p>The corresponding string</p>
* @throws IllegalStateException <p>If the string formatter has not been set, and the input is a translatable message.</p>
*/
@NotNull
private <K> String asString(@NotNull K input) {
if (input instanceof String string) {
return string;
} else if (input instanceof TranslatableMessage translatableMessage) {
if (FormatBuilder.stringFormatter == null) {
throw NOT_SETUP_EXCEPTION;
}
return FormatBuilder.stringFormatter.getUnFormattedMessage(translatableMessage);
} else if (input instanceof FormatBuilder builder) {
return builder.toString();
} else if (input instanceof StringBuilder builder) {
return builder.toString();
} else if (input instanceof Collection<?> collection) {
List<String> output = new ArrayList<>(collection.size());
for (Object item : collection) {
output.add(String.valueOf(item));
}
return String.join(LIST_DELIMITER, output);
} else if (input.getClass().isArray()) {
int length = Array.getLength(input);
List<String> output = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
output.add(String.valueOf(Array.get(input, i)));
}
return String.join(LIST_DELIMITER, output);
}
return String.valueOf(input);
}
} }

View File

@@ -0,0 +1,43 @@
package net.knarcraft.knarlib.formatting;
import net.knarcraft.knarlib.particle.ParticleMode;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
@SuppressWarnings("SpellCheckingInspection")
public class FormatBuilderTest {
@Test
public void replaceTest() {
FormatBuilder builder = new FormatBuilder("{1}{2}{3}{4}{5}");
builder.replace("{1}", List.of(1, 2, 3, 4, 5));
assertEquals("1,2,3,4,5{2}{3}{4}{5}", builder.toString());
builder.replace("{2}", "StringTest");
assertEquals("1,2,3,4,5StringTest{3}{4}{5}", builder.toString());
StringBuilder testBuilder = new StringBuilder().append("This").append(" ").append("is").append(" ").append("some").append(" ").append("text");
builder.replace("{3}", testBuilder);
assertEquals("1,2,3,4,5StringTestThis is some text{4}{5}", builder.toString());
builder.replace("{4}", new FormatBuilder("JustTesting").replace("Testing", "Fishing"));
assertEquals("1,2,3,4,5StringTestThis is some textJustFishing{5}", builder.toString());
builder.replace("{5}", new String[]{"a", "b", "c"});
assertEquals("1,2,3,4,5StringTestThis is some textJustFishinga,b,c", builder.toString());
}
@Test
public void appendTest() {
FormatBuilder builder = new FormatBuilder();
assertEquals("", builder.toString());
builder.append("Test");
assertEquals("Test", builder.toString());
builder.append(new int[]{1, 2, 3, 4, 5});
assertEquals("Test1,2,3,4,5", builder.toString());
builder.append(new FormatBuilder("abc")).append(new StringBuilder("k").append(" ").append("z"));
assertEquals("Test1,2,3,4,5abck z", builder.toString());
builder.append(List.of(ParticleMode.SINGLE, ParticleMode.CIRCLE, ParticleMode.CUBE));
assertEquals("Test1,2,3,4,5abck zSINGLE,CIRCLE,CUBE", builder.toString());
}
}