Use implicit string based lazily evaluating sets instead of explicit enum sets. Fixes MassiveCraft/Factions#730. Fixes MassiveCraft/Factions#733.

This commit is contained in:
Olof Larsson 2014-12-16 02:06:54 +01:00
parent d09d2b4169
commit 61df6a2242
5 changed files with 313 additions and 0 deletions

View File

@ -11,6 +11,7 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import com.massivecraft.massivecore.adapter.BackstringEnumSetAdapter;
import com.massivecraft.massivecore.adapter.InventoryAdapter;
import com.massivecraft.massivecore.adapter.ItemStackAdapter;
import com.massivecraft.massivecore.adapter.JsonElementAdapter;
@ -27,6 +28,7 @@ import com.massivecraft.massivecore.cmd.massivecore.CmdMassiveCoreBuffer;
import com.massivecraft.massivecore.cmd.massivecore.CmdMassiveCoreCmdurl;
import com.massivecraft.massivecore.cmd.massivecore.CmdMassiveCoreStore;
import com.massivecraft.massivecore.cmd.massivecore.CmdMassiveCoreUsys;
import com.massivecraft.massivecore.collections.BackstringEnumSet;
import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.collections.MassiveListDef;
import com.massivecraft.massivecore.collections.MassiveMap;
@ -112,6 +114,8 @@ public class MassiveCore extends MassivePlugin
.registerTypeAdapter(MassiveTreeSet.class, MassiveTreeSetAdapter.get())
.registerTypeAdapter(MassiveTreeSetDef.class, MassiveTreeSetAdapter.get())
.registerTypeAdapter(BackstringEnumSet.class, BackstringEnumSetAdapter.get())
.registerTypeAdapterFactory(ModdedEnumTypeAdapter.ENUM_FACTORY);
}

View File

@ -0,0 +1,54 @@
package com.massivecraft.massivecore.adapter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Set;
import com.massivecraft.massivecore.collections.BackstringEnumSet;
import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext;
import com.massivecraft.massivecore.xlib.gson.JsonDeserializer;
import com.massivecraft.massivecore.xlib.gson.JsonElement;
import com.massivecraft.massivecore.xlib.gson.JsonParseException;
import com.massivecraft.massivecore.xlib.gson.JsonSerializationContext;
import com.massivecraft.massivecore.xlib.gson.JsonSerializer;
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
public class BackstringEnumSetAdapter implements JsonDeserializer<BackstringEnumSet<?>>, JsonSerializer<BackstringEnumSet<?>>
{
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
public final static Type stringSetType = new TypeToken<Set<String>>(){}.getType();
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static BackstringEnumSetAdapter i = new BackstringEnumSetAdapter();
public static BackstringEnumSetAdapter get() { return i; }
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public JsonElement serialize(BackstringEnumSet<?> src, Type type, JsonSerializationContext context)
{
return context.serialize(src.getStringSet(), stringSetType);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public BackstringEnumSet<?> deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException
{
Set<String> stringSet = context.deserialize(json, stringSetType);
ParameterizedType ptype = (ParameterizedType) type;
Type[] args = ptype.getActualTypeArguments();
Class<?> clazz = (Class<?>) args[0];
return new BackstringEnumSet(clazz, stringSet);
}
}

View File

@ -0,0 +1,71 @@
package com.massivecraft.massivecore.collections;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
public class BackstringEnumSet<T extends Enum<?>> extends BackstringSet<T>
{
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
private Class<T> clazz;
private Map<String, T> name2enum = new LinkedHashMap<String, T>();
private void init(Class<T> clazz)
{
this.clazz = clazz;
for (T t : this.clazz.getEnumConstants())
{
name2enum.put(t.name(), t);
}
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public BackstringEnumSet(Class<T> clazz)
{
super();
init(clazz);
}
public BackstringEnumSet(Class<T> clazz, Collection<?> c)
{
super(c);
init(clazz);
}
public BackstringEnumSet(Class<T> clazz, Object... objects)
{
super(objects);
init(clazz);
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public T convertFromString(String string)
{
return this.name2enum.get(string);
}
@Override
public String convertToString(Object t)
{
if (t == null) return null;
if (t instanceof Enum<?>)
{
Enum<?> e = (Enum<?>)t;
return e.name();
}
return t.toString();
}
}

View File

@ -0,0 +1,72 @@
package com.massivecraft.massivecore.collections;
import java.util.Iterator;
public class BackstringIterator<E> implements Iterator<E>
{
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
private final Iterator<String> iterator;
private final BackstringSet<E> set;
private String next = null;
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public BackstringIterator(Iterator<String> iterator, BackstringSet<E> set)
{
this.iterator = iterator;
this.set = set;
this.prepareNext();
}
// -------------------------------------------- //
// INTERNAL
// -------------------------------------------- //
private void prepareNext()
{
String perhaps = null;
while (this.iterator.hasNext())
{
perhaps = this.iterator.next();
if (this.set.convertFromString(perhaps) != null)
{
this.next = perhaps;
break;
}
}
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public boolean hasNext()
{
return (this.next != null);
}
@Override
public E next()
{
String current = this.next;
this.prepareNext();
if (current == null) return null;
return this.set.convertFromString(current);
}
// -------------------------------------------- //
// EXTRAS
// -------------------------------------------- //
public String peek()
{
return next;
}
}

View File

@ -0,0 +1,112 @@
package com.massivecraft.massivecore.collections;
import java.util.AbstractSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
public abstract class BackstringSet<T> extends AbstractSet<T>
{
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
private Set<String> stringSet = new LinkedHashSet<String>();
public Set<String> getStringSet() { return this.stringSet; }
// -------------------------------------------- //
// ABSTRACT CONVERSION
// -------------------------------------------- //
public abstract T convertFromString(String string);
public abstract String convertToString(Object t);
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public BackstringSet()
{
}
public BackstringSet(Collection<?> c)
{
if (c != null)
{
for (Object o : c)
{
this.stringSet.add(this.convertToString(o));
}
}
}
public BackstringSet(Object... objects)
{
this(Arrays.asList(objects));
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public Iterator<T> iterator()
{
return new BackstringIterator<T>(this.stringSet.iterator(), this);
}
@Override
public int size()
{
return this.stringSet.size();
}
@Override
public boolean contains(Object o)
{
if (o == null)
{
return this.stringSet.contains(null);
}
else
{
return this.stringSet.contains(this.convertToString(o));
}
}
@Override
public boolean add(T e)
{
if (e == null)
{
return this.stringSet.add(null);
}
else
{
return this.stringSet.add(this.convertToString(e));
}
}
@Override
public boolean remove(Object o)
{
if (o == null)
{
return this.stringSet.remove(null);
}
else
{
return this.stringSet.remove(this.convertToString(o));
}
}
@Override
public void clear()
{
this.stringSet.clear();
}
}