From 61df6a2242d22f566b9a8ef319fe63e0307d0170 Mon Sep 17 00:00:00 2001 From: Olof Larsson Date: Tue, 16 Dec 2014 02:06:54 +0100 Subject: [PATCH] Use implicit string based lazily evaluating sets instead of explicit enum sets. Fixes MassiveCraft/Factions#730. Fixes MassiveCraft/Factions#733. --- .../massivecraft/massivecore/MassiveCore.java | 4 + .../adapter/BackstringEnumSetAdapter.java | 54 +++++++++ .../collections/BackstringEnumSet.java | 71 +++++++++++ .../collections/BackstringIterator.java | 72 +++++++++++ .../collections/BackstringSet.java | 112 ++++++++++++++++++ 5 files changed, 313 insertions(+) create mode 100644 src/main/java/com/massivecraft/massivecore/adapter/BackstringEnumSetAdapter.java create mode 100644 src/main/java/com/massivecraft/massivecore/collections/BackstringEnumSet.java create mode 100644 src/main/java/com/massivecraft/massivecore/collections/BackstringIterator.java create mode 100644 src/main/java/com/massivecraft/massivecore/collections/BackstringSet.java diff --git a/src/main/java/com/massivecraft/massivecore/MassiveCore.java b/src/main/java/com/massivecraft/massivecore/MassiveCore.java index e44e184c..f8620188 100644 --- a/src/main/java/com/massivecraft/massivecore/MassiveCore.java +++ b/src/main/java/com/massivecraft/massivecore/MassiveCore.java @@ -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); } diff --git a/src/main/java/com/massivecraft/massivecore/adapter/BackstringEnumSetAdapter.java b/src/main/java/com/massivecraft/massivecore/adapter/BackstringEnumSetAdapter.java new file mode 100644 index 00000000..a36b4749 --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/adapter/BackstringEnumSetAdapter.java @@ -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>, JsonSerializer> +{ + // -------------------------------------------- // + // CONSTANTS + // -------------------------------------------- // + + public final static Type stringSetType = new TypeToken>(){}.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 stringSet = context.deserialize(json, stringSetType); + + ParameterizedType ptype = (ParameterizedType) type; + Type[] args = ptype.getActualTypeArguments(); + Class clazz = (Class) args[0]; + + return new BackstringEnumSet(clazz, stringSet); + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/collections/BackstringEnumSet.java b/src/main/java/com/massivecraft/massivecore/collections/BackstringEnumSet.java new file mode 100644 index 00000000..ed230679 --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/collections/BackstringEnumSet.java @@ -0,0 +1,71 @@ +package com.massivecraft.massivecore.collections; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +public class BackstringEnumSet> extends BackstringSet +{ + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // + + private Class clazz; + private Map name2enum = new LinkedHashMap(); + + private void init(Class clazz) + { + this.clazz = clazz; + for (T t : this.clazz.getEnumConstants()) + { + name2enum.put(t.name(), t); + } + } + + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + public BackstringEnumSet(Class clazz) + { + super(); + init(clazz); + } + + public BackstringEnumSet(Class clazz, Collection c) + { + super(c); + init(clazz); + } + + public BackstringEnumSet(Class 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(); + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/collections/BackstringIterator.java b/src/main/java/com/massivecraft/massivecore/collections/BackstringIterator.java new file mode 100644 index 00000000..64626fdc --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/collections/BackstringIterator.java @@ -0,0 +1,72 @@ +package com.massivecraft.massivecore.collections; + +import java.util.Iterator; + +public class BackstringIterator implements Iterator +{ + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // + + private final Iterator iterator; + private final BackstringSet set; + private String next = null; + + // -------------------------------------------- // + // CONSTRUCT + // -------------------------------------------- // + + public BackstringIterator(Iterator iterator, BackstringSet 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; + } + +} diff --git a/src/main/java/com/massivecraft/massivecore/collections/BackstringSet.java b/src/main/java/com/massivecraft/massivecore/collections/BackstringSet.java new file mode 100644 index 00000000..a58cfff5 --- /dev/null +++ b/src/main/java/com/massivecraft/massivecore/collections/BackstringSet.java @@ -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 extends AbstractSet +{ + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // + + private Set stringSet = new LinkedHashSet(); + public Set 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 iterator() + { + return new BackstringIterator(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(); + } + +}