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

Refactoring and documentation

This commit is contained in:
TheBusyBiscuit 2021-12-08 20:25:04 +01:00
parent 4136615c67
commit db5e4ffa2e
5 changed files with 211 additions and 73 deletions

View File

@ -0,0 +1,46 @@
package io.github.thebusybiscuit.slimefun4.utils.biomes;
import javax.annotation.Nonnull;
import com.google.gson.JsonElement;
/**
* A simple functional interface for converting a {@link JsonElement} into the desired data type
* needed for your {@link BiomeMap}.
*
* @author TheBusyBiscuit
*
* @param <T>
* Your target data type
*
* @see BiomeMap
*/
@FunctionalInterface
public interface BiomeDataConverter<T> {
/**
* Override this method and provide a way to convert a {@link JsonElement} into your
* desired data type.
* <p>
* For primitive data values, you you can also just use the following method references:
*
* <ul>
* <li>JsonElement::getAsString</li>
* <li>JsonElement::getAsInt</li>
* <li>JsonElement::getAsDouble</li>
* <li>JsonElement::getAsFloat</li>
* <li>JsonElement::getAsLong</li>
* <li>JsonElement::getAsBoolean</li>
* </ul>
*
* or similar.
*
* @param jsonElement
* The {@link JsonElement} to convert
*
* @return Your desired data type.
*/
@Nonnull
T convert(@Nonnull JsonElement jsonElement);
}

View File

@ -6,7 +6,6 @@ import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.EnumMap;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
@ -21,13 +20,44 @@ import org.bukkit.block.Biome;
import com.google.gson.JsonElement;
import io.github.thebusybiscuit.slimefun4.api.exceptions.BiomeMapException;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.implementation.Slimefun;
/**
* {@link BiomeMap}s are used to map data values to {@link Biome} constants.
* <p>
* We heavily utilise this method of data mapping for {@link GEOResource}s, especially
* when supporting multiple versions of Minecraft. This way, we can have different {@link BiomeMap}s
* for different versions of Minecraft, incase {@link Biome} names change inbetween versions.
* <p>
* The data type can be any type of {@link Object}.
* The most common type is {@link Integer}, if you are using complex objects and try to read
* your {@link BiomeMap} from a {@link JsonElement}, make sure to provide an adequate
* {@link BiomeDataConverter} to convert the raw json data.
*
* @author TheBusyBiscuit
*
* @param <T>
* The stored data type
*/
public class BiomeMap<T> implements Keyed {
/**
* Our internal {@link EnumMap} holding all the data.
*/
private final Map<Biome, T> dataMap = new EnumMap<>(Biome.class);
/**
* The {@link NamespacedKey} to identify this {@link BiomeMap}.
*/
private final NamespacedKey namespacedKey;
/**
* This constructs a new {@link BiomeMap} with the given {@link NamespacedKey}.
*
* @param namespacedKey
* The {@link NamespacedKey} for this {@link BiomeMap}
*/
@ParametersAreNonnullByDefault
public BiomeMap(NamespacedKey namespacedKey) {
Validate.notNull(namespacedKey, "The key must not be null.");
@ -86,13 +116,16 @@ public class BiomeMap<T> implements Keyed {
return namespacedKey;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "BiomeMap " + dataMap.toString();
}
@ParametersAreNonnullByDefault
public static <T> @Nonnull BiomeMap<T> fromJson(NamespacedKey key, String json, Function<JsonElement, T> valueConverter) throws BiomeMapException {
public static <T> @Nonnull BiomeMap<T> fromJson(NamespacedKey key, String json, BiomeDataConverter<T> valueConverter) throws BiomeMapException {
// All parameters are validated by the Parser.
BiomeMapParser<T> parser = new BiomeMapParser<>(key, valueConverter);
parser.read(json);
@ -100,7 +133,7 @@ public class BiomeMap<T> implements Keyed {
}
@ParametersAreNonnullByDefault
public static <T> @Nonnull BiomeMap<T> fromResource(NamespacedKey key, String path, Function<JsonElement, T> valueConverter) throws BiomeMapException {
public static <T> @Nonnull BiomeMap<T> fromResource(NamespacedKey key, String path, BiomeDataConverter<T> valueConverter) throws BiomeMapException {
Validate.notNull(key, "The key shall not be null.");
Validate.notNull(path, "The path should not be null!");

View File

@ -5,7 +5,6 @@ import java.util.EnumSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
@ -24,17 +23,25 @@ import io.github.bakedlibs.dough.common.CommonPatterns;
import io.github.thebusybiscuit.slimefun4.api.exceptions.BiomeMapException;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
/**
* The {@link BiomeMapParser} allows you to parse json data into a {@link BiomeMap}.
*
* @author TheBusyBiscuit
*
* @param <T>
* The data type of the resulting {@link BiomeMap}
*/
class BiomeMapParser<T> {
private static final String VALUE_KEY = "value";
private static final String BIOMES_KEY = "biomes";
private final NamespacedKey key;
private final Function<JsonElement, T> valueConverter;
private final BiomeDataConverter<T> valueConverter;
private final Map<Biome, T> map = new EnumMap<>(Biome.class);
@ParametersAreNonnullByDefault
BiomeMapParser(NamespacedKey key, Function<JsonElement, T> valueConverter) {
BiomeMapParser(NamespacedKey key, BiomeDataConverter<T> valueConverter) {
Validate.notNull(key, "The key shall not be null.");
Validate.notNull(valueConverter, "You must provide a Function to convert raw json values to your desired data type.");
@ -76,7 +83,7 @@ class BiomeMapParser<T> {
Validate.notNull(entry, "The JSON entry should not be null!");
if (entry.has(VALUE_KEY)) {
T value = valueConverter.apply(entry.get(VALUE_KEY));
T value = valueConverter.convert(entry.get(VALUE_KEY));
if (entry.has(BIOMES_KEY) && entry.get(BIOMES_KEY).isJsonArray()) {
Set<Biome> biomes = readBiomes(entry.get(BIOMES_KEY).getAsJsonArray());

View File

@ -0,0 +1,115 @@
package io.github.thebusybiscuit.slimefun4.utils.biomes;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Biome;
import org.junit.jupiter.api.AfterAll;
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 com.google.gson.JsonElement;
import io.github.thebusybiscuit.slimefun4.api.exceptions.BiomeMapException;
import io.github.thebusybiscuit.slimefun4.implementation.Slimefun;
import be.seeseemelk.mockbukkit.MockBukkit;
class TestBiomeMap {
private static final BiomeDataConverter<String> AS_STRING = JsonElement::getAsString;
private static final BiomeDataConverter<Integer> AS_INT = JsonElement::getAsInt;
private static Slimefun plugin;
private static NamespacedKey key;
@BeforeAll
public static void load() {
MockBukkit.mock();
plugin = MockBukkit.load(Slimefun.class);
key = new NamespacedKey(plugin, "test");
}
@AfterAll
public static void unload() {
MockBukkit.unmock();
}
@Test
@DisplayName("Test BiomeMap#getKey")
void testKeyed() {
BiomeMap<String> biomes = new BiomeMap<>(key);
Assertions.assertEquals(key, biomes.getKey());
}
@Test
@DisplayName("Test BiomeMap#toString")
void testToString() {
BiomeMap<String> biomes = new BiomeMap<>(key);
Assertions.assertTrue(biomes.toString().startsWith("BiomeMap"));
}
@Test
@DisplayName("Test different value converters")
void testValueConversion() {
Biome biome = Biome.OCEAN;
String stringValue = "hello world";
BiomeMap<String> stringMap = createBiomeMap(AS_STRING, "[{\"value\": \"" + stringValue + "\", \"biomes\": [\"" + biome.getKey() + "\"]}]");
Assertions.assertEquals(stringValue, stringMap.get(biome));
int intValue = 1024;
BiomeMap<Integer> intMap = createBiomeMap(AS_INT, "[{\"value\": \"" + intValue + "\", \"biomes\": [\"" + biome.getKey() + "\"]}]");
Assertions.assertEquals(intValue, intMap.get(biome));
}
@Test
@DisplayName("Test working BiomeMap from JSON")
void testBiomeMapFromJson() {
Biome biome1 = Biome.JUNGLE;
Biome biome2 = Biome.OCEAN;
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.assertEquals(1, biomes.get(biome1));
Assertions.assertTrue(biomes.contains(biome2));
Assertions.assertEquals(1, biomes.get(biome2));
Assertions.assertTrue(biomes.contains(biome3));
Assertions.assertEquals(2, biomes.get(biome3));
}
@Test
@DisplayName("Test working BiomeMap manually")
void testManualBiomeMap() {
BiomeMap<String> biomes = new BiomeMap<>(key);
Biome biome = Biome.OCEAN;
String value = "Under the sea";
Assertions.assertTrue(biomes.put(biome, value));
Assertions.assertTrue(biomes.contains(biome));
Assertions.assertEquals(value, biomes.get(biome));
Assertions.assertTrue(biomes.remove(biome));
Assertions.assertFalse(biomes.contains(biome));
}
@ParametersAreNonnullByDefault
private @Nonnull <T> BiomeMap<T> createBiomeMap(BiomeDataConverter<T> function, String json) {
BiomeMapParser<T> parser = new BiomeMapParser<>(key, function);
try {
parser.read(json);
} catch (BiomeMapException e) {
Assertions.fail(e);
}
return parser.buildBiomeMap();
}
}

View File

@ -1,8 +1,5 @@
package io.github.thebusybiscuit.slimefun4.utils.biomes;
import java.util.function.Function;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.NamespacedKey;
@ -22,8 +19,8 @@ import be.seeseemelk.mockbukkit.MockBukkit;
class TestBiomeMapParser {
private static final Function<JsonElement, String> AS_STRING = JsonElement::getAsString;
private static final Function<JsonElement, Integer> AS_INT = JsonElement::getAsInt;
private static final BiomeDataConverter<String> AS_STRING = JsonElement::getAsString;
private static final BiomeDataConverter<Integer> AS_INT = JsonElement::getAsInt;
private static Slimefun plugin;
private static NamespacedKey key;
@ -96,68 +93,8 @@ class TestBiomeMapParser {
assertMisconfiguration(AS_INT, "[{\"value\": 1, \"biomes\": [\"" + biome.getKey() + "\"]}, {\"value\": 2, \"biomes\": [\"" + biome.getKey() + "\"]}]");
}
@Test
@DisplayName("Test different value converters")
void testValueConversion() {
Biome biome = Biome.OCEAN;
String stringValue = "hello world";
BiomeMap<String> stringMap = createBiomeMap(AS_STRING, "[{\"value\": \"" + stringValue + "\", \"biomes\": [\"" + biome.getKey() + "\"]}]");
Assertions.assertEquals(stringValue, stringMap.get(biome));
int intValue = 1024;
BiomeMap<Integer> intMap = createBiomeMap(AS_INT, "[{\"value\": \"" + intValue + "\", \"biomes\": [\"" + biome.getKey() + "\"]}]");
Assertions.assertEquals(intValue, intMap.get(biome));
}
@Test
@DisplayName("Test working BiomeMap from JSON")
void testBiomeMapFromJson() {
Biome biome1 = Biome.JUNGLE;
Biome biome2 = Biome.OCEAN;
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.assertEquals(1, biomes.get(biome1));
Assertions.assertTrue(biomes.contains(biome2));
Assertions.assertEquals(1, biomes.get(biome2));
Assertions.assertTrue(biomes.contains(biome3));
Assertions.assertEquals(2, biomes.get(biome3));
}
@Test
@DisplayName("Test working BiomeMap manually")
void testManualBiomeMap() {
BiomeMap<String> biomes = new BiomeMap<>(key);
Biome biome = Biome.OCEAN;
String value = "Under the sea";
Assertions.assertTrue(biomes.put(biome, value));
Assertions.assertTrue(biomes.contains(biome));
Assertions.assertEquals(value, biomes.get(biome));
Assertions.assertTrue(biomes.remove(biome));
Assertions.assertFalse(biomes.contains(biome));
}
@ParametersAreNonnullByDefault
private @Nonnull <T> BiomeMap<T> createBiomeMap(Function<JsonElement, T> function, String json) {
BiomeMapParser<T> parser = new BiomeMapParser<>(key, function);
try {
parser.read(json);
} catch (BiomeMapException e) {
Assertions.fail(e);
}
return parser.buildBiomeMap();
}
@ParametersAreNonnullByDefault
private <T> void assertMisconfiguration(Function<JsonElement, T> function, String json) {
private <T> void assertMisconfiguration(BiomeDataConverter<T> function, String json) {
BiomeMapParser<T> parser = new BiomeMapParser<>(key, function);
Assertions.assertThrows(BiomeMapException.class, () -> parser.read(json));
}