Starting work on TypeAbstractChoice performance optimizations.

This commit is contained in:
Olof Larsson 2015-11-06 04:27:59 +01:00
parent 60a705ecf3
commit 52af87a4bd
3 changed files with 85 additions and 10 deletions

View File

@ -4,6 +4,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
@ -16,6 +17,7 @@ import com.massivecraft.massivecore.collections.MassiveMap;
import com.massivecraft.massivecore.collections.MassiveSet;
import com.massivecraft.massivecore.collections.MassiveTreeSet;
import com.massivecraft.massivecore.command.type.collection.AllAble;
import com.massivecraft.massivecore.util.ReflectionUtil;
import com.massivecraft.massivecore.util.Txt;
public abstract class TypeAbstractChoice<T> extends TypeAbstract<T> implements AllAble<T>
@ -41,6 +43,19 @@ public abstract class TypeAbstractChoice<T> extends TypeAbstract<T> implements A
public String getHelp() { return this.help; }
public TypeAbstractChoice<T> setHelp(String help) { this.help = help; return this; }
protected boolean canSeeOverridden = calcCanSeeOverriden();
public boolean isCanSeeOverridden() { return this.canSeeOverridden; }
public void setCanSeeOverridden(boolean canSeeOverridden) { this.canSeeOverridden = canSeeOverridden; }
public boolean calcCanSeeOverriden()
{
return ! TypeAbstractChoice.class.equals(ReflectionUtil.getSuperclassDeclaringMethod(this.getClass(), true, "canSee"));
}
// TODO: cache stuff... the options?
protected boolean cachable = false;
public boolean isCachable() { return this.cachable; }
public void setCachable(boolean cachable) { this.cachable = cachable; }
// -------------------------------------------- //
// OVERRIDE: TYPE
// -------------------------------------------- //
@ -51,13 +66,22 @@ public abstract class TypeAbstractChoice<T> extends TypeAbstract<T> implements A
// NPE Evade
if (arg == null) return null;
// Exact
T exact = this.getExactMatch(arg);
if (exact != null) return exact;
// Get All
Collection<T> all = this.getAll(sender);
// Get Options
// NOTE: These keys are prepared.
// TODO: Optimization should be possible here.
// TODO: If the "all" never changes AKA are cached... we can cache the options as well.
// TODO: If they are different for visibility but do not change... we can
Map<String, T> options = this.getOptions(all);
// Get Matches
// NOTE: I can probably not optimize this method further?
List<T> matches = this.getMatches(options, arg, false);
// Exact
@ -159,6 +183,9 @@ public abstract class TypeAbstractChoice<T> extends TypeAbstract<T> implements A
@Override
public Collection<T> getAll(CommandSender sender)
{
// No Can See Override?
if ( ! this.isCanSeeOverridden()) return this.getAll();
// Create
Set<T> ret = new MassiveSet<T>();
@ -192,24 +219,22 @@ public abstract class TypeAbstractChoice<T> extends TypeAbstract<T> implements A
@SuppressWarnings("unchecked")
public List<T> getMatches(Map<String, T> options, String arg, boolean levenshtein)
{
// Exact
T exact = this.getExactMatch(arg);
if (exact != null) return new MassiveList<T>(exact);
// Create
List<T> ret = new MassiveList<T>();
// Prepare
arg = this.prepareKey(arg);
// Exact
T exact = options.get(arg);
if (exact != null) return new MassiveList<T>(exact);
// Fill
for (Entry<String, T> entry : options.entrySet())
{
String key = entry.getKey();
T value = entry.getValue();
if (arg.equals(key)) return new MassiveList<T>(value);
if (levenshtein)
{
if ( ! isLevenshteinSimilar(arg, key)) continue;
@ -292,12 +317,14 @@ public abstract class TypeAbstractChoice<T> extends TypeAbstract<T> implements A
}
// The purpose of this method is to strip down a string to a comparable string key.
protected static Pattern PATTERN_KEY_UNWANTED = Pattern.compile("[_\\-\\s]+");
public String prepareKey(String string)
{
if (string == null) return null;
string = string.trim();
string = string.toLowerCase();
string = string.replaceAll("[_\\-\\s]+", "");
// SLOW: string = string.replaceAll("[_\\-\\s]+", "");
string = PATTERN_KEY_UNWANTED.matcher(string).replaceAll("");
return string;
}

View File

@ -1,10 +1,13 @@
package com.massivecraft.massivecore.util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import com.massivecraft.massivecore.Predicate;
public class ReflectionUtil
{
// -------------------------------------------- //
@ -174,6 +177,50 @@ public class ReflectionUtil
return transferFields(clazz, from, to, null);
}
// -------------------------------------------- //
// SUPERCLASSES
// -------------------------------------------- //
public static List<Class<?>> getSuperclasses(Class<?> clazz, boolean includeSelf)
{
// Create
List<Class<?>> ret = new ArrayList<Class<?>>();
// Fill
if ( ! includeSelf) clazz = clazz.getSuperclass();
while (clazz != null)
{
ret.add(clazz);
clazz = clazz.getSuperclass();
}
// Return
return ret;
}
public static Class<?> getSuperclassPredicate(Class<?> clazz, boolean includeSelf, Predicate<Class<?>> predicate)
{
for (Class<?> superClazz : getSuperclasses(clazz, includeSelf))
{
if (predicate.apply(superClazz)) return superClazz;
}
return null;
}
public static Class<?> getSuperclassDeclaringMethod(Class<?> clazz, boolean includeSelf, final String methodName)
{
return getSuperclassPredicate(clazz, includeSelf, new Predicate<Class<?>>()
{
@Override
public boolean apply(Class<?> clazz)
{
for (Method method : clazz.getDeclaredMethods())
{
if (method.getName().equals(methodName)) return true;
}
return false;
}
});
}
}

View File

@ -400,10 +400,11 @@ public class Txt
// Material name tools
// -------------------------------------------- //
protected static Pattern PATTERN_ENUM_SPLIT = Pattern.compile("[\\s_]+");
public static String getNicedEnumString(String str)
{
List<String> parts = new ArrayList<String>();
for (String part : str.toLowerCase().split("[\\s_]+"))
for (String part : PATTERN_ENUM_SPLIT.split(str.toLowerCase()))
{
parts.add(upperCaseFirst(part));
}