1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-19 19:25:48 +00:00

Added lenient parsing and more documentation

This commit is contained in:
TheBusyBiscuit 2021-12-09 12:42:02 +01:00
parent db5e4ffa2e
commit 5ba049d29c
4 changed files with 123 additions and 6 deletions

View File

@ -77,12 +77,28 @@ public class BiomeMap<T> implements Keyed {
return dataMap.getOrDefault(biome, defaultValue);
}
public boolean contains(@Nonnull Biome biome) {
public boolean containsKey(@Nonnull Biome biome) {
Validate.notNull(biome, "The biome must not be null.");
return dataMap.containsKey(biome);
}
public boolean containsValue(@Nonnull T value) {
Validate.notNull(value, "The value must not be null.");
return dataMap.containsValue(value);
}
/**
* This returns whether this {@link BiomeMap} is empty.
* An empty {@link BiomeMap} contains no biomes or values.
*
* @return Whether this {@link BiomeMap} is empty.
*/
public boolean isEmpty() {
return dataMap.isEmpty();
}
public boolean put(@Nonnull Biome biome, @Nonnull T value) {
Validate.notNull(biome, "The biome should not be null.");
Validate.notNull(value, "Values cannot be null.");

View File

@ -30,6 +30,8 @@ import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
*
* @param <T>
* The data type of the resulting {@link BiomeMap}
*
* @see BiomeMap
*/
class BiomeMapParser<T> {
@ -40,6 +42,24 @@ class BiomeMapParser<T> {
private final BiomeDataConverter<T> valueConverter;
private final Map<Biome, T> map = new EnumMap<>(Biome.class);
/**
* This flag specifies whether the parsing is "lenient" or not.
* A lenient parser will not throw a {@link BiomeMapException} if the {@link Biome}
* could not be found.
* The default value is false.
*/
private boolean isLenient = false;
/**
* This constructs a new {@link BiomeMapParser}.
* <p>
* To parse data, use the {@link #read(JsonArray)} or {@link #read(String)} method.
*
* @param key
* The {@link NamespacedKey} for the resulting {@link BiomeMap}
* @param valueConverter
* A function to convert {@link JsonElement}s into your desired data type
*/
@ParametersAreNonnullByDefault
BiomeMapParser(NamespacedKey key, BiomeDataConverter<T> valueConverter) {
Validate.notNull(key, "The key shall not be null.");
@ -49,6 +69,33 @@ class BiomeMapParser<T> {
this.valueConverter = valueConverter;
}
/**
* This method sets the "lenient" flag for this parser.
* <p>
* A lenient parser will not throw a {@link BiomeMapException} if the {@link Biome}
* could not be found.
* The default value is false.
*
* @param isLenient
* Whether this parser should be lenient or not.
*/
void setLenient(boolean isLenient) {
this.isLenient = isLenient;
}
/**
* This method returns whether this parser is flagged as "lenient".
* <p>
* A lenient parser will not throw a {@link BiomeMapException} if the {@link Biome}
* could not be found.
* The default value is false.
*
* @return Whether this parser is lenient or not.
*/
boolean isLenient() {
return isLenient;
}
void read(@Nonnull String json) throws BiomeMapException {
Validate.notNull(json, "The JSON string should not be null!");
JsonArray root = null;
@ -82,15 +129,23 @@ class BiomeMapParser<T> {
private void readEntry(@Nonnull JsonObject entry) throws BiomeMapException {
Validate.notNull(entry, "The JSON entry should not be null!");
/*
* Check if the entry has a "value" element.
* The data type is irrelevant here, any JsonElement is supported (in theory).
* If you write a converter for it, you can also serialize complex objects this way.
*/
if (entry.has(VALUE_KEY)) {
T value = valueConverter.convert(entry.get(VALUE_KEY));
// Check if the entry has a "biomes" element of type JsonArray.
if (entry.has(BIOMES_KEY) && entry.get(BIOMES_KEY).isJsonArray()) {
Set<Biome> biomes = readBiomes(entry.get(BIOMES_KEY).getAsJsonArray());
// Loop through all biome strings in this array
for (Biome biome : biomes) {
T prev = map.put(biome, value);
// Check for duplicates
if (prev != null) {
throw new BiomeMapException(key, "Biome '" + biome.getKey() + "' is registered twice");
}
@ -118,6 +173,11 @@ class BiomeMapParser<T> {
Biome biome = Biome.valueOf(formattedValue);
biomes.add(biome);
} catch (IllegalArgumentException x) {
// Lenient Parsers will ignore unknown biomes
if (isLenient) {
continue;
}
throw new BiomeMapException(key, "The Biome '" + value + "' does not exist!");
}
} else {
@ -132,6 +192,14 @@ class BiomeMapParser<T> {
return biomes;
}
/**
* This method builds a {@link BiomeMap} based on the parsed data.
* <p>
* Make sure to parse data via {@link #read(JsonArray)} or {@link #read(String)}
* before calling this method! Otherwise the resulting {@link BiomeMap} will be empty.
*
* @return The resulting {@link BiomeMap}
*/
@Nonnull
BiomeMap<T> buildBiomeMap() {
BiomeMap<T> biomeMap = new BiomeMap<>(key);

View File

@ -74,13 +74,13 @@ class TestBiomeMap {
Biome biome3 = Biome.DESERT;
BiomeMap<Integer> biomes = createBiomeMap(AS_INT, "[{\"value\":1,\"biomes\":[\"" + biome1.getKey() + "\", \"" + biome2.getKey() + "\"]}, {\"value\":2, \"biomes\":[\"" + biome3.getKey() + "\"]}]");
Assertions.assertTrue(biomes.contains(biome1));
Assertions.assertTrue(biomes.containsKey(biome1));
Assertions.assertEquals(1, biomes.get(biome1));
Assertions.assertTrue(biomes.contains(biome2));
Assertions.assertTrue(biomes.containsKey(biome2));
Assertions.assertEquals(1, biomes.get(biome2));
Assertions.assertTrue(biomes.contains(biome3));
Assertions.assertTrue(biomes.containsKey(biome3));
Assertions.assertEquals(2, biomes.get(biome3));
}
@ -92,11 +92,11 @@ class TestBiomeMap {
String value = "Under the sea";
Assertions.assertTrue(biomes.put(biome, value));
Assertions.assertTrue(biomes.contains(biome));
Assertions.assertTrue(biomes.containsKey(biome));
Assertions.assertEquals(value, biomes.get(biome));
Assertions.assertTrue(biomes.remove(biome));
Assertions.assertFalse(biomes.contains(biome));
Assertions.assertFalse(biomes.containsKey(biome));
}
@ParametersAreNonnullByDefault

View File

@ -9,6 +9,8 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import com.google.gson.JsonElement;
@ -93,6 +95,37 @@ class TestBiomeMapParser {
assertMisconfiguration(AS_INT, "[{\"value\": 1, \"biomes\": [\"" + biome.getKey() + "\"]}, {\"value\": 2, \"biomes\": [\"" + biome.getKey() + "\"]}]");
}
@Test
@DisplayName("Test BiomeMapParser being not lenient by default")
void testParserNotLenientByDefault() {
BiomeMapParser<Integer> parser = new BiomeMapParser<>(key, AS_INT);
// Test default value
Assertions.assertFalse(parser.isLenient());
}
@ParameterizedTest
@ValueSource(booleans = { true, false })
@DisplayName("Test lenient parser")
void testLenientParsing(boolean isLenient) {
BiomeMapParser<Integer> parser = new BiomeMapParser<>(key, AS_INT);
parser.setLenient(isLenient);
Assertions.assertEquals(isLenient, parser.isLenient());
/*
* I picked a random String here.
* If this biome will exist in Minecraft one day... then you saw it here first, folks ;D
*/
String json = "[{\"value\": 2048, \"biomes\": [\"minecraft:thebusybiscuits_wonderland\"]}]";
if (isLenient) {
Assertions.assertDoesNotThrow(() -> parser.read(json));
} else {
Assertions.assertThrows(BiomeMapException.class, () -> parser.read(json));
}
}
@ParametersAreNonnullByDefault
private <T> void assertMisconfiguration(BiomeDataConverter<T> function, String json) {
BiomeMapParser<T> parser = new BiomeMapParser<>(key, function);