Refactor: Improved handling of unknown materials and issues during ItemData deserialization.
parent
cb843307da
commit
55ed27979e
|
@ -21,6 +21,7 @@ import com.nisovin.shopkeepers.config.annotation.WithValueType;
|
|||
import com.nisovin.shopkeepers.config.annotation.WithValueTypeProvider;
|
||||
import com.nisovin.shopkeepers.config.value.DefaultValueTypes;
|
||||
import com.nisovin.shopkeepers.config.value.SettingLoadException;
|
||||
import com.nisovin.shopkeepers.config.value.UnknownMaterialException;
|
||||
import com.nisovin.shopkeepers.config.value.ValueType;
|
||||
import com.nisovin.shopkeepers.config.value.ValueTypeProvider;
|
||||
import com.nisovin.shopkeepers.config.value.ValueTypeRegistry;
|
||||
|
@ -348,6 +349,9 @@ public abstract class Config {
|
|||
protected <T> void onSettingLoadException(Field field, ConfigurationSection config, SettingLoadException e) throws ConfigLoadException {
|
||||
String configKey = this.getConfigKey(field);
|
||||
Log.warning(this.msgSettingLoadException(configKey, e));
|
||||
if (e instanceof UnknownMaterialException) {
|
||||
Log.warning(this.getLogPrefix() + "All valid material names can be found here: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Material.html");
|
||||
}
|
||||
}
|
||||
|
||||
protected String msgSettingLoadException(String configKey, SettingLoadException e) {
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package com.nisovin.shopkeepers.config.value;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
/**
|
||||
* This exception is issued by {@link ValueType#load(Object)} when an unknown {@link Material} is encountered.
|
||||
*/
|
||||
public class UnknownMaterialException extends SettingLoadException {
|
||||
|
||||
private static final long serialVersionUID = 1653518607452366268L;
|
||||
|
||||
public UnknownMaterialException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UnknownMaterialException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
package com.nisovin.shopkeepers.config.value.types;
|
||||
|
||||
import com.nisovin.shopkeepers.config.value.SettingLoadException;
|
||||
import com.nisovin.shopkeepers.config.value.UnknownMaterialException;
|
||||
import com.nisovin.shopkeepers.config.value.ValueType;
|
||||
import com.nisovin.shopkeepers.util.ItemData;
|
||||
import com.nisovin.shopkeepers.util.ItemData.ItemDataDeserializeException;
|
||||
import com.nisovin.shopkeepers.util.ItemData.UnknownItemTypeException;
|
||||
|
||||
public class ItemDataValue extends ValueType<ItemData> {
|
||||
|
||||
|
@ -13,27 +16,14 @@ public class ItemDataValue extends ValueType<ItemData> {
|
|||
|
||||
@Override
|
||||
public ItemData load(Object configValue) throws SettingLoadException {
|
||||
ItemData itemData = null;
|
||||
try {
|
||||
// Returns null if the config value is null. Otherwise triggers a warning, which we translate into an
|
||||
// exception.
|
||||
itemData = ItemData.deserialize(configValue, (warning) -> {
|
||||
String errorMsg = warning;
|
||||
if (warning.contains("Unknown item type")) { // TODO this is ugly
|
||||
errorMsg = warning + " (All valid material names can be found here: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Material.html)";
|
||||
}
|
||||
// We can only throw unchecked exceptions here, so we wrap the exception here and unwrap it again
|
||||
// outside:
|
||||
throw new RuntimeException(new SettingLoadException(errorMsg));
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
if (e.getCause() instanceof SettingLoadException) {
|
||||
throw (SettingLoadException) e.getCause();
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
// Returns null if the config value is null.
|
||||
return ItemData.deserialize(configValue);
|
||||
} catch (UnknownItemTypeException e) {
|
||||
throw new UnknownMaterialException(e.getMessage(), e);
|
||||
} catch (ItemDataDeserializeException e) {
|
||||
throw new SettingLoadException(e.getMessage(), e);
|
||||
}
|
||||
return itemData;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.nisovin.shopkeepers.config.value.types;
|
|||
import org.bukkit.Material;
|
||||
|
||||
import com.nisovin.shopkeepers.config.value.SettingLoadException;
|
||||
import com.nisovin.shopkeepers.config.value.UnknownMaterialException;
|
||||
import com.nisovin.shopkeepers.config.value.ValueType;
|
||||
|
||||
public class MaterialValue extends ValueType<Material> {
|
||||
|
@ -21,8 +22,7 @@ public class MaterialValue extends ValueType<Material> {
|
|||
// This assumes that legacy item conversion has already been performed:
|
||||
Material material = Material.matchMaterial(materialName); // Can be null
|
||||
if (material == null) {
|
||||
throw new SettingLoadException("Unknown material: " + materialName
|
||||
+ " (All valid material names can be found here: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Material.html)");
|
||||
throw new UnknownMaterialException("Unknown material: " + materialName);
|
||||
}
|
||||
return material;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import java.util.LinkedHashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
|
@ -18,8 +17,32 @@ import org.bukkit.inventory.meta.ItemMeta;
|
|||
*/
|
||||
public class ItemData implements Cloneable {
|
||||
|
||||
private static final Consumer<String> SILENT_WARNING_HANDLER = (warning) -> {
|
||||
};
|
||||
public static class ItemDataDeserializeException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -6637983932875623362L;
|
||||
|
||||
public ItemDataDeserializeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ItemDataDeserializeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnknownItemTypeException extends ItemDataDeserializeException {
|
||||
|
||||
private static final long serialVersionUID = -6123823171023440870L;
|
||||
|
||||
public UnknownItemTypeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UnknownItemTypeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String META_TYPE_KEY = "meta-type";
|
||||
private static final String DISPLAY_NAME_KEY = "display-name";
|
||||
private static final String LORE_KEY = "lore";
|
||||
|
@ -27,16 +50,8 @@ public class ItemData implements Cloneable {
|
|||
// Special case: Omitting 'blockMaterial' for empty TILE_ENTITY item meta.
|
||||
private static final String TILE_ENTITY_BLOCK_MATERIAL_KEY = "blockMaterial";
|
||||
|
||||
public static ItemData deserialize(Object dataObject) {
|
||||
return deserialize(dataObject, null);
|
||||
}
|
||||
|
||||
// Only returns null if the input data is null, or if the data cannot be loaded (in which case the warning handler
|
||||
// is informed).
|
||||
public static ItemData deserialize(Object dataObject, Consumer<String> warningHandler) {
|
||||
if (warningHandler == null) {
|
||||
warningHandler = SILENT_WARNING_HANDLER; // Ignore all warnings
|
||||
}
|
||||
// Only returns null if the input data is null.
|
||||
public static ItemData deserialize(Object dataObject) throws ItemDataDeserializeException {
|
||||
if (dataObject == null) return null;
|
||||
|
||||
String typeName = null;
|
||||
|
@ -56,8 +71,7 @@ public class ItemData implements Cloneable {
|
|||
dataMap.put(entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
} else {
|
||||
warningHandler.accept("Unknown item data: " + dataObject);
|
||||
return null;
|
||||
throw new ItemDataDeserializeException("Unknown item data representation: " + dataObject);
|
||||
}
|
||||
assert dataMap != null; // Assert: dataMap is a (shallow) copy
|
||||
|
||||
|
@ -67,8 +81,7 @@ public class ItemData implements Cloneable {
|
|||
}
|
||||
if (typeName == null) {
|
||||
// Missing item type information:
|
||||
warningHandler.accept("Missing item type");
|
||||
return null;
|
||||
throw new ItemDataDeserializeException("Missing item type");
|
||||
}
|
||||
assert typeName != null;
|
||||
|
||||
|
@ -83,8 +96,7 @@ public class ItemData implements Cloneable {
|
|||
Material type = Material.matchMaterial(typeName);
|
||||
if (type == null) {
|
||||
// Unknown item type:
|
||||
warningHandler.accept("Unknown item type: " + typeName);
|
||||
return null;
|
||||
throw new UnknownItemTypeException("Unknown item type: " + typeName);
|
||||
}
|
||||
|
||||
// Create item stack (still misses meta data):
|
||||
|
|
|
@ -25,10 +25,11 @@ import org.junit.Assert;
|
|||
import org.junit.Test;
|
||||
|
||||
import com.nisovin.shopkeepers.testutil.AbstractBukkitTest;
|
||||
import com.nisovin.shopkeepers.util.ItemData.ItemDataDeserializeException;
|
||||
|
||||
public class ItemDataTest extends AbstractBukkitTest {
|
||||
|
||||
private static void testDeserialization(ItemData originalItemData) {
|
||||
private static void testDeserialization(ItemData originalItemData) throws ItemDataDeserializeException {
|
||||
YamlConfiguration config = new YamlConfiguration();
|
||||
Object serialized = originalItemData.serialize();
|
||||
config.set("key", serialized);
|
||||
|
@ -72,7 +73,7 @@ public class ItemDataTest extends AbstractBukkitTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializationSimple() {
|
||||
public void testDeserializationSimple() throws ItemDataDeserializeException {
|
||||
ItemStack itemStack = createItemStackSimple();
|
||||
ItemData itemData = new ItemData(itemStack);
|
||||
testDeserialization(itemData);
|
||||
|
@ -110,7 +111,7 @@ public class ItemDataTest extends AbstractBukkitTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializationMinimal() {
|
||||
public void testDeserializationMinimal() throws ItemDataDeserializeException {
|
||||
ItemStack itemStack = createItemStackMinimal();
|
||||
ItemData itemData = new ItemData(itemStack);
|
||||
testDeserialization(itemData);
|
||||
|
@ -209,7 +210,7 @@ public class ItemDataTest extends AbstractBukkitTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializationFull() {
|
||||
public void testDeserializationFull() throws ItemDataDeserializeException {
|
||||
ItemStack itemStack = createItemStackFull();
|
||||
ItemData itemData = new ItemData(itemStack);
|
||||
testDeserialization(itemData);
|
||||
|
@ -253,7 +254,7 @@ public class ItemDataTest extends AbstractBukkitTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializationUncommon() {
|
||||
public void testDeserializationUncommon() throws ItemDataDeserializeException {
|
||||
ItemStack itemStack = createItemStackUncommon();
|
||||
ItemData itemData = new ItemData(itemStack);
|
||||
testDeserialization(itemData);
|
||||
|
@ -286,7 +287,7 @@ public class ItemDataTest extends AbstractBukkitTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializationTileEntitySimple() {
|
||||
public void testDeserializationTileEntitySimple() throws ItemDataDeserializeException {
|
||||
ItemStack itemStack = createItemStackTileEntitySimple();
|
||||
ItemData itemData = new ItemData(itemStack);
|
||||
testDeserialization(itemData);
|
||||
|
@ -324,7 +325,7 @@ public class ItemDataTest extends AbstractBukkitTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializationTileEntityMinimal() {
|
||||
public void testDeserializationTileEntityMinimal() throws ItemDataDeserializeException {
|
||||
ItemStack itemStack = createItemStackTileEntityMinimal();
|
||||
ItemData itemData = new ItemData(itemStack);
|
||||
testDeserialization(itemData);
|
||||
|
|
Loading…
Reference in New Issue