From 03d224e95307b52027e4887484277f33b52ea5e2 Mon Sep 17 00:00:00 2001 From: Olof Larsson Date: Wed, 3 Feb 2016 14:00:38 +0100 Subject: [PATCH] MassiveCore - More work on Comparators, Container and Editor --- .../command/editor/CommandEditAbstract.java | 2 +- .../editor/CommandEditContainerAbstract.java | 5 +- .../editor/CommandEditContainerRemove.java | 2 +- .../massivecore/command/type/Type.java | 21 +- .../command/type/TypeAbstract.java | 163 +++----------- .../command/type/combined/TypeEntry.java | 9 +- .../command/type/container/TypeContainer.java | 15 +- .../ComparatorEntityId.java | 4 +- .../comparator/ComparatorHashCode.java | 3 - .../ComparatorIdentityHashCode.java | 27 +++ .../comparator/ComparatorLenient.java | 12 +- .../comparator/ComparatorPriority.java | 1 - .../massivecore/util/ContainerUtil.java | 199 ++++++++++++++++++ 13 files changed, 289 insertions(+), 174 deletions(-) rename src/com/massivecraft/massivecore/{store => comparator}/ComparatorEntityId.java (88%) create mode 100644 src/com/massivecraft/massivecore/comparator/ComparatorIdentityHashCode.java create mode 100644 src/com/massivecraft/massivecore/util/ContainerUtil.java diff --git a/src/com/massivecraft/massivecore/command/editor/CommandEditAbstract.java b/src/com/massivecraft/massivecore/command/editor/CommandEditAbstract.java index 99bcc852..ad2f75ed 100644 --- a/src/com/massivecraft/massivecore/command/editor/CommandEditAbstract.java +++ b/src/com/massivecraft/massivecore/command/editor/CommandEditAbstract.java @@ -108,7 +108,7 @@ public class CommandEditAbstract extends MassiveCommand // NoChange // We check, inform and cancel on equality. - if (this.getValueType().equals(before, after, true)) + if (this.getValueType().equals(before, after)) { msg("%s for %s already: %s", descProperty, descObject, descValue); return; diff --git a/src/com/massivecraft/massivecore/command/editor/CommandEditContainerAbstract.java b/src/com/massivecraft/massivecore/command/editor/CommandEditContainerAbstract.java index 31cf3f0d..41d5f937 100644 --- a/src/com/massivecraft/massivecore/command/editor/CommandEditContainerAbstract.java +++ b/src/com/massivecraft/massivecore/command/editor/CommandEditContainerAbstract.java @@ -7,6 +7,7 @@ import com.massivecraft.massivecore.MassiveException; import com.massivecraft.massivecore.command.requirement.RequirementEditorPropertyCreated; import com.massivecraft.massivecore.command.type.Type; import com.massivecraft.massivecore.command.type.TypeNullable; +import com.massivecraft.massivecore.util.ContainerUtil; public abstract class CommandEditContainerAbstract extends CommandEditAbstract { @@ -59,11 +60,11 @@ public abstract class CommandEditContainerAbstract extends CommandEditAbst // After V after = this.getValueType().createNewInstance(); - this.getValueType().addContainerElements(after, elements); + ContainerUtil.addElements(after, elements); // Order elements = this.getValueType().getContainerElementsOrdered(after); - this.getValueType().setContainerElements(after, elements); + ContainerUtil.setElements(after, elements); // Apply this.attemptSet(after); diff --git a/src/com/massivecraft/massivecore/command/editor/CommandEditContainerRemove.java b/src/com/massivecraft/massivecore/command/editor/CommandEditContainerRemove.java index 4cddbc7e..f432950b 100644 --- a/src/com/massivecraft/massivecore/command/editor/CommandEditContainerRemove.java +++ b/src/com/massivecraft/massivecore/command/editor/CommandEditContainerRemove.java @@ -56,7 +56,7 @@ public class CommandEditContainerRemove extends CommandEditContainerAbstra while (iterator.hasNext()) { Object other = iterator.hasNext(); - if ( ! this.getValueInnerType().equals(other, element, false)) continue; + if ( ! this.getValueInnerType().equals(other, element)) continue; iterator.remove(); } } diff --git a/src/com/massivecraft/massivecore/command/type/Type.java b/src/com/massivecraft/massivecore/command/type/Type.java index 13ba87ac..37c5b3f4 100644 --- a/src/com/massivecraft/massivecore/command/type/Type.java +++ b/src/com/massivecraft/massivecore/command/type/Type.java @@ -107,10 +107,8 @@ public interface Type public boolean allowSpaceAfterTab(); // -------------------------------------------- // - // CONTAINER + // CONTAINER > IS // -------------------------------------------- // - // The "Container" is an imaginary super type for "Collection" and "Map". - // The Element class E is the entry for a map. public boolean isContainer(); public boolean isContainerMap(); @@ -120,27 +118,22 @@ public interface Type public boolean isContainerOrdered(); public boolean isContainerSorted(); + // -------------------------------------------- // + // CONTAINER > COMPARATOR + // -------------------------------------------- // + public Comparator getContainerComparator(); public void setContainerComparator(Comparator container); public List getContainerElementsOrdered(Iterable elements); public List getContainerElementsOrdered(T container); - public boolean isContainerEmpty(T container); - public void clearContainer(T container); - - public Collection getContainerElements(T container); - public void setContainerElements(T container, Iterable elements); - - public boolean addContainerElement(T container, E element); - public void addContainerElements(T container, Iterable elements); - // -------------------------------------------- // // EQUALS // -------------------------------------------- // - public boolean equals(T type1, T type2, boolean strict); - public boolean equalsInner(T type1, T type2, boolean strict); + public boolean equals(T type1, T type2); + public boolean equalsInner(T type1, T type2); // -------------------------------------------- // // EDITOR diff --git a/src/com/massivecraft/massivecore/command/type/TypeAbstract.java b/src/com/massivecraft/massivecore/command/type/TypeAbstract.java index 558a71d5..dab3b94f 100644 --- a/src/com/massivecraft/massivecore/command/type/TypeAbstract.java +++ b/src/com/massivecraft/massivecore/command/type/TypeAbstract.java @@ -5,16 +5,10 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; -import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.ListIterator; -import java.util.Map; import java.util.Set; -import java.util.SortedMap; -import java.util.SortedSet; -import java.util.Map.Entry; - import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; @@ -28,7 +22,7 @@ import com.massivecraft.massivecore.command.editor.Property; import com.massivecraft.massivecore.comparator.ComparatorHashCode; import com.massivecraft.massivecore.store.Entity; import com.massivecraft.massivecore.store.SenderEntity; -import com.massivecraft.massivecore.util.MUtil; +import com.massivecraft.massivecore.util.ContainerUtil; import com.massivecraft.massivecore.util.Txt; public abstract class TypeAbstract implements Type @@ -402,72 +396,42 @@ public abstract class TypeAbstract implements Type } // -------------------------------------------- // - // CONTAINER + // CONTAINER > IS // -------------------------------------------- // - public boolean isContainer() - { - return this.isContainerCollection() || this.isContainerMap(); - } + private Boolean container = null; + public boolean isContainer() { this.calcContainer(); return this.container; } private Boolean containerMap = null; - public boolean isContainerMap() - { - if (this.containerMap == null) this.containerMap = this.calcContainerMap(); - return this.containerMap; - } - protected boolean calcContainerMap() - { - T instance = this.createNewInstance(); - if (instance instanceof Map) return true; - return false; - } + public boolean isContainerMap() { this.calcContainer(); return this.containerMap; } private Boolean containerCollection = null; - public boolean isContainerCollection() - { - if (this.containerCollection == null) this.containerCollection = this.calcContainerCollection(); - return this.containerCollection; - } - protected boolean calcContainerCollection() + public boolean isContainerCollection() { this.calcContainer(); return this.containerCollection; } + + private Boolean containerIndexed = null; + public boolean isContainerIndexed() { this.calcContainer(); return this.containerIndexed; } + + private Boolean containerOrdered = null; + public boolean isContainerOrdered() { this.calcContainer(); return this.containerOrdered; } + + private Boolean containerSorted = null; + public boolean isContainerSorted() { this.calcContainer(); return this.containerSorted; } + + private void calcContainer() { + if (this.container != null) return; T instance = this.createNewInstance(); - if (instance instanceof Collection) return true; - return false; + this.container = ContainerUtil.isContainer(instance); + this.containerMap = ContainerUtil.isMap(instance); + this.containerCollection = ContainerUtil.isCollection(instance); + this.containerIndexed = ContainerUtil.isIndexed(instance); + this.containerOrdered = ContainerUtil.isOrdered(instance); + this.containerSorted = ContainerUtil.isSorted(instance); } - public boolean isContainerIndexed() - { - return this.isContainerOrdered() || this.isContainerSorted(); - } - - private Boolean collectionOrdered = null; - public boolean isContainerOrdered() - { - if (this.collectionOrdered == null) this.collectionOrdered = this.calcContainerOrdered(); - return this.collectionOrdered; - } - protected boolean calcContainerOrdered() - { - T instance = this.createNewInstance(); - if (instance instanceof List) return true; - if (instance instanceof LinkedHashMap) return true; - return false; - } - - private Boolean collectionSorted = null; - public boolean isContainerSorted() - { - if (this.collectionSorted == null) this.collectionSorted = this.calcContainerSorted(); - return this.collectionSorted; - } - protected boolean calcContainerSorted() - { - T instance = this.createNewInstance(); - if (instance instanceof SortedSet) return true; - if (instance instanceof SortedMap) return true; - return false; - } + // -------------------------------------------- // + // CONTAINER > COMPARATOR + // -------------------------------------------- // private Comparator elementComparator = null; @SuppressWarnings("unchecked") @@ -507,87 +471,22 @@ public abstract class TypeAbstract implements Type @Override public List getContainerElementsOrdered(T container) { - Collection elements = this.getContainerElements(container); + Collection elements = ContainerUtil.getElements(container); return this.getContainerElementsOrdered(elements); } - public boolean isContainerEmpty(T container) - { - return this.getContainerElements(container).isEmpty(); - } - - @Override - public void clearContainer(T container) - { - this.getContainerElements(container).clear(); - } - - @SuppressWarnings("unchecked") - public Collection getContainerElements(T container) - { - if (container instanceof Collection) - { - Collection collection = (Collection)container; - return collection; - } - - if (container instanceof Map) - { - Map map = (Map)container; - return (Collection) map.entrySet(); - } - - throw new UnsupportedOperationException("not implemented"); - } - - public void setContainerElements(T container, Iterable elements) - { - this.clearContainer(container); - this.addContainerElements(container, elements); - } - - @SuppressWarnings("unchecked") - public boolean addContainerElement(T container, E element) - { - if (container instanceof Collection) - { - Collection collection = (Collection)container; - return collection.add(element); - } - - if (container instanceof Map) - { - Map map = (Map)container; - Entry entry = (Entry)element; - Object key = entry.getKey(); - Object after = entry.getValue(); - Object before = map.put(key, after); - return ! MUtil.equals(after, before); - } - - throw new UnsupportedOperationException("not implemented"); - } - - public void addContainerElements(T container, Iterable elements) - { - for (E element : elements) - { - this.addContainerElement(container, element); - } - } - // -------------------------------------------- // // EQUALS // -------------------------------------------- // - public boolean equals(T type1, T type2, boolean strict) + public boolean equals(T type1, T type2) { if (type1 == null) return type2 == null; if (type2 == null) return type1 == null; - return this.equalsInner(type1, type2, strict); + return this.equalsInner(type1, type2); } - public boolean equalsInner(T type1, T type2, boolean strict) + public boolean equalsInner(T type1, T type2) { return type1.equals(type2); } diff --git a/src/com/massivecraft/massivecore/command/type/combined/TypeEntry.java b/src/com/massivecraft/massivecore/command/type/combined/TypeEntry.java index d75ce93d..b7676834 100644 --- a/src/com/massivecraft/massivecore/command/type/combined/TypeEntry.java +++ b/src/com/massivecraft/massivecore/command/type/combined/TypeEntry.java @@ -74,20 +74,17 @@ public class TypeEntry extends TypeCombined> } @Override - public boolean equalsInner(Entry type1, Entry type2, boolean strict) + public boolean equalsInner(Entry type1, Entry type2) { // Compare Keys K key1 = type1.getKey(); K key2 = type2.getKey(); - if ( ! this.getKeyType().equals(key1, key2, strict)) return false; - - // Strict - if ( ! strict) return true; + if ( ! this.getKeyType().equals(key1, key2)) return false; // Compare Values V value1 = type1.getValue(); V value2 = type2.getValue(); - if ( ! this.getValueType().equals(value1, value2, strict)) return false; + if ( ! this.getValueType().equals(value1, value2)) return false; // Done return true; diff --git a/src/com/massivecraft/massivecore/command/type/container/TypeContainer.java b/src/com/massivecraft/massivecore/command/type/container/TypeContainer.java index 7d4886db..096f6965 100644 --- a/src/com/massivecraft/massivecore/command/type/container/TypeContainer.java +++ b/src/com/massivecraft/massivecore/command/type/container/TypeContainer.java @@ -14,6 +14,7 @@ import com.massivecraft.massivecore.command.editor.EditSettings; import com.massivecraft.massivecore.command.editor.Property; import com.massivecraft.massivecore.command.type.Type; import com.massivecraft.massivecore.command.type.TypeAbstract; +import com.massivecraft.massivecore.util.ContainerUtil; import com.massivecraft.massivecore.util.Txt; public abstract class TypeContainer extends TypeAbstract @@ -50,7 +51,7 @@ public abstract class TypeContainer extends TypeAbstract public String getVisualInner(C container, CommandSender sender) { // Empty - if (this.isContainerEmpty(container)) return EMPTY; + if (ContainerUtil.isEmpty(container)) return EMPTY; // Create List parts = new MassiveList(); @@ -78,7 +79,7 @@ public abstract class TypeContainer extends TypeAbstract public String getNameInner(C container) { // Empty - if (this.isContainerEmpty(container)) return ""; + if (ContainerUtil.isEmpty(container)) return ""; // Create List parts = new MassiveList(); @@ -104,7 +105,7 @@ public abstract class TypeContainer extends TypeAbstract public String getIdInner(C container) { // Empty - if (this.isContainerEmpty(container)) return ""; + if (ContainerUtil.isEmpty(container)) return ""; // Create List parts = new MassiveList(); @@ -139,7 +140,7 @@ public abstract class TypeContainer extends TypeAbstract AllAble allAble = (AllAble)this.getInnerType(); if (arg.equalsIgnoreCase("all")) { - this.addContainerElements(ret, allAble.getAll(sender)); + ContainerUtil.addElements(ret, allAble.getAll(sender)); return ret; } } @@ -150,7 +151,7 @@ public abstract class TypeContainer extends TypeAbstract { Type innerType = this.getInnerType(); E element = innerType.read(elementArg, sender); - this.addContainerElement(ret, element); + ContainerUtil.addElement(ret, element); } // Return @@ -188,7 +189,7 @@ public abstract class TypeContainer extends TypeAbstract // -------------------------------------------- // @Override - public boolean equalsInner(C container1, C container2, boolean strict) + public boolean equalsInner(C container1, C container2) { List ordered1 = this.getContainerElementsOrdered(container1); List ordered2 = this.getContainerElementsOrdered(container2); @@ -201,7 +202,7 @@ public abstract class TypeContainer extends TypeAbstract E element1 = ordered1.get(index); E element2 = ordered2.get(index); - if ( ! innerType.equals(element1, element2, strict)) return false; + if ( ! innerType.equals(element1, element2)) return false; } return true; diff --git a/src/com/massivecraft/massivecore/store/ComparatorEntityId.java b/src/com/massivecraft/massivecore/comparator/ComparatorEntityId.java similarity index 88% rename from src/com/massivecraft/massivecore/store/ComparatorEntityId.java rename to src/com/massivecraft/massivecore/comparator/ComparatorEntityId.java index c79dce73..44907a41 100644 --- a/src/com/massivecraft/massivecore/store/ComparatorEntityId.java +++ b/src/com/massivecraft/massivecore/comparator/ComparatorEntityId.java @@ -1,8 +1,8 @@ -package com.massivecraft.massivecore.store; +package com.massivecraft.massivecore.comparator; import java.util.Comparator; -import com.massivecraft.massivecore.comparator.ComparatorNaturalOrder; +import com.massivecraft.massivecore.store.Entity; public class ComparatorEntityId implements Comparator> { diff --git a/src/com/massivecraft/massivecore/comparator/ComparatorHashCode.java b/src/com/massivecraft/massivecore/comparator/ComparatorHashCode.java index 89c31bfb..9d1f9ce4 100644 --- a/src/com/massivecraft/massivecore/comparator/ComparatorHashCode.java +++ b/src/com/massivecraft/massivecore/comparator/ComparatorHashCode.java @@ -23,9 +23,6 @@ public class ComparatorHashCode extends ComparatorAbstract ret = Integer.compare(Objects.hashCode(object1), Objects.hashCode(object2)); if (ret != 0) return ret; - ret = Integer.compare(System.identityHashCode(object1), System.identityHashCode(object2)); - if (ret != 0) return ret; - return ret; } diff --git a/src/com/massivecraft/massivecore/comparator/ComparatorIdentityHashCode.java b/src/com/massivecraft/massivecore/comparator/ComparatorIdentityHashCode.java new file mode 100644 index 00000000..59a01a32 --- /dev/null +++ b/src/com/massivecraft/massivecore/comparator/ComparatorIdentityHashCode.java @@ -0,0 +1,27 @@ +package com.massivecraft.massivecore.comparator; + +public class ComparatorIdentityHashCode extends ComparatorAbstract +{ + // -------------------------------------------- // + // INSTANCE & CONSTRUCT + // -------------------------------------------- // + + private static transient ComparatorIdentityHashCode i = new ComparatorIdentityHashCode(); + public static ComparatorIdentityHashCode get() { return i; } + + // -------------------------------------------- // + // OVERRIDE + // -------------------------------------------- // + + @Override + public int compareInner(Object object1, Object object2) + { + int ret; + + ret = Integer.compare(System.identityHashCode(object1), System.identityHashCode(object2)); + if (ret != 0) return ret; + + return ret; + } + +} diff --git a/src/com/massivecraft/massivecore/comparator/ComparatorLenient.java b/src/com/massivecraft/massivecore/comparator/ComparatorLenient.java index 9eace19c..3d175764 100644 --- a/src/com/massivecraft/massivecore/comparator/ComparatorLenient.java +++ b/src/com/massivecraft/massivecore/comparator/ComparatorLenient.java @@ -21,13 +21,15 @@ public class ComparatorLenient extends ComparatorAbstractWrapper @Override public int compare(T type1, T type2) { - int ret = this.getComparator().compare(type1, type2); + int ret; + + ret = this.getComparator().compare(type1, type2); if (ret != 0) return ret; - int hash1 = type1.hashCode(); - int hash2 = type2.hashCode(); - - ret = Integer.compare(hash1, hash2); + ret = ComparatorHashCode.get().compare(type1, type2); + if (ret != 0) return ret; + + ret = ComparatorIdentityHashCode.get().compare(type1, type2); if (ret != 0) return ret; return 1; diff --git a/src/com/massivecraft/massivecore/comparator/ComparatorPriority.java b/src/com/massivecraft/massivecore/comparator/ComparatorPriority.java index c79ac683..d8838047 100644 --- a/src/com/massivecraft/massivecore/comparator/ComparatorPriority.java +++ b/src/com/massivecraft/massivecore/comparator/ComparatorPriority.java @@ -1,7 +1,6 @@ package com.massivecraft.massivecore.comparator; import com.massivecraft.massivecore.Prioritized; -import com.massivecraft.massivecore.store.ComparatorEntityId; import com.massivecraft.massivecore.store.Entity; public class ComparatorPriority extends ComparatorAbstract diff --git a/src/com/massivecraft/massivecore/util/ContainerUtil.java b/src/com/massivecraft/massivecore/util/ContainerUtil.java new file mode 100644 index 00000000..15ff7a85 --- /dev/null +++ b/src/com/massivecraft/massivecore/util/ContainerUtil.java @@ -0,0 +1,199 @@ +package com.massivecraft.massivecore.util; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.Map.Entry; + +/** + * The ContainerUtil provides an imaginary super class to Collection and Map. + * In Java they do not have a common interface yet many methods are similar and exists in both. + * This some times results in twice the amount of source code, which we aim to remedy with this utility class. + * + * We take an approach where we largely see a Map as a Collection of entries. + * The "Container" class is simply an Object. + * The return values are auto cast generics. + * + * We have also added some information gatherers related to sorting and order. + */ +public class ContainerUtil +{ + // -------------------------------------------- // + // IS > CORE + // -------------------------------------------- // + + public static boolean isContainer(Object container) + { + return isCollection(container) || isMap(container); + } + + public static boolean isCollection(Object container) + { + return container instanceof Collection; + } + + public static boolean isMap(Object container) + { + return container instanceof Map; + } + + // -------------------------------------------- // + // IS > BEHAVIOR + // -------------------------------------------- // + + public static boolean isIndexed(Object container) + { + return isOrdered(container) || isSorted(container); + } + + public static boolean isOrdered(Object container) + { + return container instanceof List || container instanceof LinkedHashMap; + } + + public static boolean isSorted(Object container) + { + return container instanceof SortedSet || container instanceof SortedMap; + } + + // -------------------------------------------- // + // AS > CORE + // -------------------------------------------- // + + @SuppressWarnings("unchecked") + public static > C asCollection(Object container) + { + if ( ! isCollection(container)) return null; + return (C)container; + } + + @SuppressWarnings("unchecked") + public static > M asMap(Object container) + { + if ( ! isMap(container)) return null; + return (M)container; + } + + // -------------------------------------------- // + // METHODS > SIZE + // -------------------------------------------- // + + public static boolean isEmpty(Object container) + { + Collection collection = asCollection(container); + if (collection != null) + { + return collection.isEmpty(); + } + + Map map = asMap(container); + if (map != null) + { + return map.isEmpty(); + } + + throw new IllegalArgumentException(); + } + + public static int size(Object container) + { + Collection collection = asCollection(container); + if (collection != null) + { + return collection.size(); + } + + Map map = asMap(container); + if (map != null) + { + return map.size(); + } + + throw new IllegalArgumentException(); + } + + // -------------------------------------------- // + // METHODS > GET + // -------------------------------------------- // + + @SuppressWarnings("unchecked") + public static Collection getElements(Object container) + { + Collection collection = asCollection(container); + if (collection != null) + { + return collection; + } + + Map map = asMap(container); + if (map != null) + { + return (Collection) map.entrySet(); + } + + throw new IllegalArgumentException(); + } + + // -------------------------------------------- // + // METHODS > SET + // -------------------------------------------- // + + public static void clear(Object container) + { + Collection collection = asCollection(container); + if (collection != null) + { + collection.clear(); + return; + } + + Map map = asMap(container); + if (map != null) + { + map.clear(); + return; + } + + throw new IllegalArgumentException(); + } + + public static void setElements(Object container, Iterable elements) + { + clear(container); + addElements(container, elements); + } + + @SuppressWarnings("unchecked") + public static boolean addElement(Object container, Object element) + { + Collection collection = asCollection(container); + if (collection != null) + { + return collection.add(element); + } + + Map map = asMap(container); + if (map != null) + { + Entry entry = (Entry)element; + Object key = entry.getKey(); + Object after = entry.getValue(); + Object before = map.put(key, after); + return ! MUtil.equals(after, before); + } + + throw new IllegalArgumentException(); + } + + public static void addElements(Object container, Iterable elements) + { + for (Object element : elements) + { + addElement(container, element); + } + } + +}