Adds support for ItemStack storage in non-YAML databases.

Fixes https://github.com/BentoBoxWorld/BentoBox/issues/501
This commit is contained in:
tastybento 2019-01-28 18:29:17 -08:00
parent 8cddb1e69f
commit 46cc901c23
3 changed files with 183 additions and 4 deletions

View File

@ -1,15 +1,19 @@
package world.bentobox.bentobox.database.json;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffectType;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.potion.PotionEffectType;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.database.AbstractDatabaseHandler;
import world.bentobox.bentobox.database.DatabaseConnector;
import world.bentobox.bentobox.database.json.adapters.FlagAdapter;
import world.bentobox.bentobox.database.json.adapters.ItemStackTypeAdapter;
import world.bentobox.bentobox.database.json.adapters.LocationAdapter;
import world.bentobox.bentobox.database.json.adapters.PotionEffectTypeAdapter;
import world.bentobox.bentobox.database.json.adapters.WorldAdapter;
@ -18,7 +22,7 @@ import world.bentobox.bentobox.database.json.adapters.WorldAdapter;
* Abstract class that handles insert/select-operations into/from a database.
* It also provides {@link #getGson()}.
*
* @author Poslovitch
* @author Poslovitch, tastybento
*
* @param <T>
*/
@ -47,6 +51,7 @@ public abstract class AbstractJSONDatabaseHandler<T> extends AbstractDatabaseHan
builder.registerTypeAdapter(World.class, new WorldAdapter(plugin));
builder.registerTypeAdapter(Flag.class, new FlagAdapter(plugin));
builder.registerTypeAdapter(PotionEffectType.class, new PotionEffectTypeAdapter());
builder.registerTypeAdapter(ItemStack.class, new ItemStackTypeAdapter());
// Keep null in the database
builder.serializeNulls();
// Allow characters like < or > without escaping them

View File

@ -0,0 +1,52 @@
/**
*
*/
package world.bentobox.bentobox.database.json.adapters;
import java.io.IOException;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.inventory.ItemStack;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
/**
* Serializes ItemStack to JSON and back.
* I'm going to cheat and use Bukkit's built in YAML serializer/deserializer.
* This will have the best chance of backwards compatibility with new server versions.
* @author tastybento
*
*/
public class ItemStackTypeAdapter extends TypeAdapter<ItemStack> {
@Override
public void write(JsonWriter out, ItemStack value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
YamlConfiguration c = new YamlConfiguration();
c.set("is", value);
out.value(c.saveToString());
}
@Override
public ItemStack read(JsonReader reader) throws IOException {
if (reader.peek() == JsonToken.NULL) {
reader.nextNull();
return null;
}
YamlConfiguration c = new YamlConfiguration();
try {
c.loadFromString(reader.nextString());
return c.getItemStack("is");
} catch (InvalidConfigurationException e) {
throw new IOException(e.getMessage());
}
}
}

View File

@ -0,0 +1,122 @@
/**
*
*/
package world.bentobox.bentobox.database.json.adapters;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.IOException;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.UnsafeValues;
import org.bukkit.inventory.ItemFactory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.PluginManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
/**
* Tests the ItemStack type adapter for GSON
* @author tastybento
*
*/
@SuppressWarnings("deprecation")
@RunWith(PowerMockRunner.class)
@PrepareForTest( {Bukkit.class} )
public class ItemStackTypeAdapterTest {
private ItemStackTypeAdapter isa;
private JsonWriter out;
private JsonReader reader;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
Server server = mock(Server.class);
PluginManager pluginManager = mock(PluginManager.class);
when(server.getPluginManager()).thenReturn(pluginManager);
ItemFactory itemFactory = mock(ItemFactory.class);
when(server.getItemFactory()).thenReturn(itemFactory);
PowerMockito.mockStatic(Bukkit.class);
when(Bukkit.getServer()).thenReturn(server);
ItemMeta meta = mock(ItemMeta.class);
when(itemFactory.getItemMeta(any())).thenReturn(meta);
when(Bukkit.getItemFactory()).thenReturn(itemFactory);
UnsafeValues unsafe = mock(UnsafeValues.class);
when(unsafe.getDataVersion()).thenReturn(777);
when(Bukkit.getUnsafe()).thenReturn(unsafe);
isa = new ItemStackTypeAdapter();
out = mock(JsonWriter.class);
reader = mock(JsonReader.class);
when(reader.peek()).thenReturn(JsonToken.STRING);
}
/**
* Test method for {@link world.bentobox.bentobox.database.json.adapters.ItemStackTypeAdapter#write(com.google.gson.stream.JsonWriter, org.bukkit.inventory.ItemStack)}.
* @throws IOException
*/
@Test
public void testWriteJsonWriterItemStack() throws IOException {
ItemStack stack = new ItemStack(Material.STICK, 4);
isa.write(out, stack);
Mockito.verify(out).value(Mockito.contains("==: org.bukkit.inventory.ItemStack"));
Mockito.verify(out).value(Mockito.contains("type: STICK"));
Mockito.verify(out).value(Mockito.contains("amount: 4"));
}
/**
* Test method for {@link world.bentobox.bentobox.database.json.adapters.ItemStackTypeAdapter#write(com.google.gson.stream.JsonWriter, org.bukkit.inventory.ItemStack)}.
* @throws IOException
*/
@Test
public void testWriteJsonWriterItemStackNull() throws IOException {
isa.write(out, null);
Mockito.verify(out).nullValue();
}
/**
* Test method for {@link world.bentobox.bentobox.database.json.adapters.ItemStackTypeAdapter#read(com.google.gson.stream.JsonReader)}.
* @throws IOException
*/
@Test
public void testReadJsonReaderNull() throws IOException {
when(reader.peek()).thenReturn(JsonToken.NULL);
assertNull(isa.read(reader));
}
/**
* Test method for {@link world.bentobox.bentobox.database.json.adapters.ItemStackTypeAdapter#read(com.google.gson.stream.JsonReader)}.
* @throws IOException
*/
@Test
public void testReadJsonReader() throws IOException {
when(reader.nextString()).thenReturn("is:\n ==: org.bukkit.inventory.ItemStack\n v: 777\n type: STICK\n amount: 4\n");
ItemStack i = isa.read(reader);
assertTrue(i.getType().equals(Material.STICK));
assertTrue(i.getAmount() == 4);
}
}