MassiveCore - Performance improvement for command argument readers.

This commit is contained in:
Olof Larsson 2014-07-31 16:43:17 +02:00
parent 9f3a284cc4
commit 8a7f4d1718
14 changed files with 140 additions and 408 deletions

View File

@ -2,35 +2,20 @@ package com.massivecraft.massivecore.cmd.arg;
import org.bukkit.entity.Player;
import com.massivecraft.massivecore.store.SenderIdSource;
import com.massivecraft.massivecore.store.SenderIdSourceMixinAllSenderIds;
import com.massivecraft.massivecore.util.IdUtil;
public class ARPlayer extends ARSenderIdAbstractPredsource<Player>
public class ARPlayer extends ARSenderIdAbstract<Player>
{
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static final ARPlayer full = getFull(SenderIdSourceMixinAllSenderIds.get());
public static ARPlayer getFull() { return full; }
private static final ARPlayer start = getStart(SenderIdSourceMixinAllSenderIds.get());
public static ARPlayer getStart() { return start; }
public static ARPlayer getFull(SenderIdSource source)
private static final ARPlayer i = new ARPlayer();
public static ARPlayer get() { return i; }
private ARPlayer()
{
return new ARPlayer(source, "player", ArgPredictateStringEqualsLC.get());
}
public static ARPlayer getStart(SenderIdSource source)
{
return new ARPlayer(source, "player", ArgPredictateStringStartsLC.get());
}
private ARPlayer(SenderIdSource source, String typename, ArgPredictate<String> argPredictate)
{
super(source, typename, argPredictate);
super(SenderIdSourceMixinAllSenderIds.get());
}
// -------------------------------------------- //
@ -40,6 +25,7 @@ public class ARPlayer extends ARSenderIdAbstractPredsource<Player>
@Override
public Player getResultForSenderId(String senderId)
{
if (senderId == null) return null;
return IdUtil.getPlayer(senderId);
}

View File

@ -2,35 +2,20 @@ package com.massivecraft.massivecore.cmd.arg;
import org.bukkit.command.CommandSender;
import com.massivecraft.massivecore.store.SenderIdSource;
import com.massivecraft.massivecore.store.SenderIdSourceMixinAllSenderIds;
import com.massivecraft.massivecore.util.IdUtil;
public class ARSender extends ARSenderIdAbstractPredsource<CommandSender>
public class ARSender extends ARSenderIdAbstract<CommandSender>
{
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static final ARSender full = getFull(SenderIdSourceMixinAllSenderIds.get());
public static ARSender getFull() { return full; }
private static final ARSender start = getStart(SenderIdSourceMixinAllSenderIds.get());
public static ARSender getStart() { return start; }
public static ARSender getFull(SenderIdSource source)
private static final ARSender i = new ARSender();
public static ARSender get() { return i; }
private ARSender()
{
return new ARSender(source, "player", ArgPredictateStringEqualsLC.get());
}
public static ARSender getStart(SenderIdSource source)
{
return new ARSender(source, "player", ArgPredictateStringStartsLC.get());
}
private ARSender(SenderIdSource source, String typename, ArgPredictate<String> argPredictate)
{
super(source, typename, argPredictate);
super(SenderIdSourceMixinAllSenderIds.get());
}
// -------------------------------------------- //
@ -40,6 +25,7 @@ public class ARSender extends ARSenderIdAbstractPredsource<CommandSender>
@Override
public CommandSender getResultForSenderId(String senderId)
{
if (senderId == null) return null;
return IdUtil.getSender(senderId);
}

View File

@ -2,10 +2,8 @@ package com.massivecraft.massivecore.cmd.arg;
import com.massivecraft.massivecore.store.SenderColl;
import com.massivecraft.massivecore.store.SenderEntity;
import com.massivecraft.massivecore.store.SenderIdSource;
import com.massivecraft.massivecore.util.IdUtil;
public class ARSenderEntity<T extends SenderEntity<T>> extends ARSenderIdAbstractPredsource<T>
public class ARSenderEntity<T extends SenderEntity<T>> extends ARSenderIdAbstract<T>
{
// -------------------------------------------- //
// FIELDS
@ -14,43 +12,28 @@ public class ARSenderEntity<T extends SenderEntity<T>> extends ARSenderIdAbstrac
private final SenderColl<T> coll;
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// CONSTRUCT
// -------------------------------------------- //
public static <T extends SenderEntity<T>> ARSenderEntity<T> getFullAny(SenderColl<T> coll) { return getFullAny(coll, coll.isCreative() ? coll.getMixinedIdSource() : coll); }
public static <T extends SenderEntity<T>> ARSenderEntity<T> getStartAny(SenderColl<T> coll) { return getStartAny(coll, coll.isCreative() ? coll.getMixinedIdSource() : coll); }
public static <T extends SenderEntity<T>> ARSenderEntity<T> getFullOnline(SenderColl<T> coll) { return getFullOnline(coll, coll.isCreative() ? coll.getMixinedIdSource() : coll); }
public static <T extends SenderEntity<T>> ARSenderEntity<T> getStartOnline(SenderColl<T> coll) { return getStartOnline(coll, coll.isCreative() ? coll.getMixinedIdSource() : coll); }
public static <T extends SenderEntity<T>> ARSenderEntity<T> getFullOnline(SenderColl<T> coll, SenderIdSource source)
private ARSenderEntity(SenderColl<T> coll, boolean online)
{
return new ARSenderEntity<T>(coll, source, "player", new ArgPredictateAnd<String>(ArgPredictateStringEqualsLC.get(), ArgPredictateStringIsOnlineSenderId.get()));
}
public static <T extends SenderEntity<T>> ARSenderEntity<T> getStartOnline(SenderColl<T> coll, SenderIdSource source)
{
return new ARSenderEntity<T>(coll, source, "player", new ArgPredictateAnd<String>(ArgPredictateStringStartsLC.get(), ArgPredictateStringIsOnlineSenderId.get()));
}
public static <T extends SenderEntity<T>> ARSenderEntity<T> getFullAny(SenderColl<T> coll, SenderIdSource source)
{
return new ARSenderEntity<T>(coll, source, "player", ArgPredictateStringEqualsLC.get());
}
public static <T extends SenderEntity<T>> ARSenderEntity<T> getStartAny(SenderColl<T> coll, SenderIdSource source)
{
return new ARSenderEntity<T>(coll, source, "player", ArgPredictateStringStartsLC.get());
}
private ARSenderEntity(SenderColl<T> coll, SenderIdSource source, String typename, ArgPredictate<String> argPredictate)
{
super(source, typename, argPredictate);
super(coll, online);
this.coll = coll;
}
private ARSenderEntity(SenderColl<T> coll)
{
super(coll);
this.coll = coll;
}
// -------------------------------------------- //
// GET
// -------------------------------------------- //
public static <T extends SenderEntity<T>> ARSenderEntity<T> get(SenderColl<T> coll, boolean online) { return new ARSenderEntity<T>(coll, online); }
public static <T extends SenderEntity<T>> ARSenderEntity<T> get(SenderColl<T> coll) { return new ARSenderEntity<T>(coll); }
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@ -59,11 +42,6 @@ public class ARSenderEntity<T extends SenderEntity<T>> extends ARSenderIdAbstrac
public T getResultForSenderId(String senderId)
{
if (senderId == null) return null;
// Convert names to ids so we can handle both
String betterId = IdUtil.getId(senderId);
if (betterId != null) return this.coll.get(betterId);
return this.coll.get(senderId);
}

View File

@ -2,34 +2,36 @@ package com.massivecraft.massivecore.cmd.arg;
import com.massivecraft.massivecore.store.SenderIdSource;
import com.massivecraft.massivecore.store.SenderIdSourceMixinAllSenderIds;
import com.massivecraft.massivecore.util.IdUtil;
public class ARSenderId extends ARSenderIdAbstractPredsource<String>
public class ARSenderId extends ARSenderIdAbstract<String>
{
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// CONSTRUCT
// -------------------------------------------- //
private static final ARSenderId full = getFull(SenderIdSourceMixinAllSenderIds.get());
public static ARSenderId getFull() { return full; }
private static final ARSenderId start = getStart(SenderIdSourceMixinAllSenderIds.get());
public static ARSenderId getStart() { return start; }
public static ARSenderId getFull(SenderIdSource source)
private ARSenderId(SenderIdSource source, boolean online)
{
return new ARSenderId(source, "player", ArgPredictateStringEqualsLC.get());
super(source, online);
}
public static ARSenderId getStart(SenderIdSource source)
private ARSenderId(SenderIdSource source)
{
return new ARSenderId(source, "player", ArgPredictateStringStartsLC.get());
super(source);
}
private ARSenderId(SenderIdSource source, String typename, ArgPredictate<String> argPredictate)
{
super(source, typename, argPredictate);
}
// -------------------------------------------- //
// INSTANCE
// -------------------------------------------- //
private static final ARSenderId i = new ARSenderId(SenderIdSourceMixinAllSenderIds.get());
public static ARSenderId get() { return i; }
// -------------------------------------------- //
// GET
// -------------------------------------------- //
public static ARSenderId get(SenderIdSource source, boolean online) { return new ARSenderId(source, online); }
public static ARSenderId get(SenderIdSource source) { return new ARSenderId(source); }
// -------------------------------------------- //
// OVERRIDE
@ -38,12 +40,6 @@ public class ARSenderId extends ARSenderIdAbstractPredsource<String>
@Override
public String getResultForSenderId(String senderId)
{
if (senderId == null) return null;
// Convert names to ids so we can handle both
String betterId = IdUtil.getId(senderId);
if (betterId != null) return betterId;
return senderId;
}

View File

@ -4,27 +4,40 @@ import java.util.Collection;
import org.bukkit.command.CommandSender;
import com.massivecraft.massivecore.mixin.Mixin;
import com.massivecraft.massivecore.store.SenderIdSource;
import com.massivecraft.massivecore.util.IdUtil;
import com.massivecraft.massivecore.util.Txt;
public abstract class ARSenderIdAbstract<T> extends ArgReaderAbstract<T>
{
// -------------------------------------------- //
// CONSTANTS
// FIELDS
// -------------------------------------------- //
public final static int MAX_COUNT = 10;
private final SenderIdSource source;
private final boolean online;
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public ARSenderIdAbstract(SenderIdSource source, boolean online)
{
this.source = source;
this.online = online;
}
public ARSenderIdAbstract(SenderIdSource source)
{
this(source, false);
}
// -------------------------------------------- //
// ABSTRACT
// -------------------------------------------- //
public abstract String getTypename();
public abstract T getResultForSenderId(String senderId);
public abstract Collection<String> getSenderIdsFor(String arg, CommandSender sender);
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@ -32,44 +45,57 @@ public abstract class ARSenderIdAbstract<T> extends ArgReaderAbstract<T>
@Override
public ArgResult<T> read(String arg, CommandSender sender)
{
// Create Ret
ArgResult<T> ret = new ArgResult<T>();
Collection<String> senderIds = this.getSenderIdsFor(arg, sender);
// arg --> senderId
String senderId = this.getSenderIdFor(arg);
if (senderIds.size() == 0)
// Populate Ret
if (senderId == null)
{
// No alternatives found
ret.setErrors("<b>No "+this.getTypename()+" matches \"<h>"+arg+"<b>\".");
}
else if (senderIds.size() == 1)
{
// Only one alternative found
String senderId = senderIds.iterator().next();
ret.setResult(this.getResultForSenderId(senderId));
}
else if (senderIds.contains(arg))
{
// Exact match
String senderId = IdUtil.getName(arg);
ret.setResult(this.getResultForSenderId(senderId));
ret.setErrors("<b>No player matches \"<h>"+arg+"<b>\".");
}
else
{
// Ambigious!
ret.getErrors().add("<b>"+this.getTypename()+" matching \"<h>"+arg+"<b>\" is ambigious.");
if (senderIds.size() >= MAX_COUNT)
{
// To many to list
ret.getErrors().add("<b>More than "+MAX_COUNT+" possible alternatives.");
}
else
{
// List the alternatives
ret.getErrors().add("<b>Did you mean "+Txt.implodeCommaAndDot(senderIds, "<h>%s", "<b>, ", " <b>or ", "<b>?"));
}
ret.setResult(this.getResultForSenderId(senderId));
}
// Return Ret
return ret;
}
// -------------------------------------------- //
// UTIL
// -------------------------------------------- //
public String getSenderIdFor(String arg)
{
// Get senderId from the arg.
// Usually it's just the lowercase form.
// It might also be a name resolution.
String senderId = arg.toLowerCase();
String betterId = IdUtil.getId(senderId);
if (betterId != null) senderId = betterId;
for (Collection<String> coll : this.source.getSenderIdCollections())
{
// If the senderId exists ...
if (!coll.contains(senderId)) continue;
// ... and the online check passes ...
if (this.online && !Mixin.isOnline(senderId)) continue;
// ... and the result is non null ...
T result = this.getResultForSenderId(senderId);
if (result == null) continue;
// ... then we are go!
return senderId;
}
return null;
}
}

View File

@ -1,80 +0,0 @@
package com.massivecraft.massivecore.cmd.arg;
import java.util.Collection;
import java.util.TreeSet;
import org.bukkit.command.CommandSender;
import com.massivecraft.massivecore.store.SenderIdSource;
public abstract class ARSenderIdAbstractPredsource<T> extends ARSenderIdAbstract<T>
{
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
private final SenderIdSource source;
private final String typename;
private final ArgPredictate<String> argPredictate;
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public ARSenderIdAbstractPredsource(SenderIdSource source, String typename, ArgPredictate<String> argPredictate)
{
this.source = source;
this.typename = typename;
this.argPredictate = argPredictate;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public String getTypename()
{
return this.typename;
}
@Override
public Collection<String> getSenderIdsFor(String arg, CommandSender sender)
{
arg = arg.toLowerCase();
TreeSet<String> ret = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
for (Collection<String> coll : this.source.getSenderIdCollections())
{
for (String senderId : coll)
{
if (this.isSenderIdOk(senderId, arg, sender))
{
ret.add(senderId);
if (ret.size() >= MAX_COUNT)
{
return ret;
}
}
}
}
return ret;
}
protected boolean isSenderIdOk(String senderId, String arg, CommandSender sender)
{
// If the predictate applies ...
if (!this.argPredictate.apply(senderId, arg, sender)) return false;
// ... and the result is non null ...
T result = this.getResultForSenderId(senderId);
if (result == null) return false;
// ... then the senderId is ok.
return true;
}
}

View File

@ -1,8 +0,0 @@
package com.massivecraft.massivecore.cmd.arg;
import org.bukkit.command.CommandSender;
public interface ArgPredictate<T>
{
public boolean apply(T type, String arg, CommandSender sender);
}

View File

@ -1,35 +0,0 @@
package com.massivecraft.massivecore.cmd.arg;
import org.bukkit.command.CommandSender;
public class ArgPredictateAnd<T> implements ArgPredictate<T>
{
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
private final ArgPredictate<T> one;
private final ArgPredictate<T> two;
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public ArgPredictateAnd(ArgPredictate<T> one, ArgPredictate<T>two)
{
this.one = one;
this.two = two;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public boolean apply(T type, String arg, CommandSender sender)
{
if (!this.one.apply(type, arg, sender)) return false;
return this.two.apply(type, arg, sender);
}
}

View File

@ -1,24 +0,0 @@
package com.massivecraft.massivecore.cmd.arg;
import org.bukkit.command.CommandSender;
public class ArgPredictateStringEqualsLC implements ArgPredictate<String>
{
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static ArgPredictateStringEqualsLC i = new ArgPredictateStringEqualsLC();
public static ArgPredictateStringEqualsLC get() { return i; }
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public boolean apply(String string, String arg, CommandSender sender)
{
return string.toLowerCase().equals(arg);
}
}

View File

@ -1,26 +0,0 @@
package com.massivecraft.massivecore.cmd.arg;
import org.bukkit.command.CommandSender;
import com.massivecraft.massivecore.mixin.Mixin;
public class ArgPredictateStringIsOnlineSenderId implements ArgPredictate<String>
{
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static ArgPredictateStringIsOnlineSenderId i = new ArgPredictateStringIsOnlineSenderId();
public static ArgPredictateStringIsOnlineSenderId get() { return i; }
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public boolean apply(String string, String arg, CommandSender sender)
{
return Mixin.isOnline(string);
}
}

View File

@ -1,24 +0,0 @@
package com.massivecraft.massivecore.cmd.arg;
import org.bukkit.command.CommandSender;
public class ArgPredictateStringStartsLC implements ArgPredictate<String>
{
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static ArgPredictateStringStartsLC i = new ArgPredictateStringStartsLC();
public static ArgPredictateStringStartsLC get() { return i; }
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public boolean apply(String string, String arg, CommandSender sender)
{
return string.toLowerCase().startsWith(arg);
}
}

View File

@ -9,17 +9,12 @@ import org.bukkit.command.CommandSender;
import org.bukkit.plugin.Plugin;
import com.massivecraft.massivecore.Predictate;
import com.massivecraft.massivecore.cmd.arg.ARSenderEntity;
import com.massivecraft.massivecore.cmd.arg.ARSenderId;
import com.massivecraft.massivecore.util.IdUtil;
public class SenderColl<E extends SenderEntity<E>> extends Coll<E> implements SenderIdSource
{
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
protected final SenderIdSource mixinedIdSource = new SenderIdSourceCombined(this, SenderIdSourceMixinAllSenderIds.get());
public SenderIdSource getMixinedIdSource() { return this.mixinedIdSource; }
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
@ -70,22 +65,45 @@ public class SenderColl<E extends SenderEntity<E>> extends Coll<E> implements Se
public Collection<Collection<String>> getSenderIdCollections()
{
List<Collection<String>> ret = new ArrayList<Collection<String>>();
ret.add(this.getIds());
List<String> names = new ArrayList<String>();
for (String id : this.getIds())
// For creative collections we must add all known ids.
// You could say the corresponding entities latently exist in the collection because it's creative.
if (this.isCreative())
{
String name = IdUtil.getName(id);
if (name == null) continue;
names.add(name);
ret.add(IdUtil.getAllIds());
}
ret.add(names);
return ret;
}
// -------------------------------------------- //
// EXTRAS
// ARGUMENT READERS
// -------------------------------------------- //
public ARSenderEntity<E> getAREntity()
{
return ARSenderEntity.get(this);
}
public ARSenderEntity<E> getAREntity(boolean online)
{
return ARSenderEntity.get(this, online);
}
public ARSenderId getARId()
{
return ARSenderId.get(this);
}
public ARSenderId getARId(boolean online)
{
return ARSenderId.get(this, online);
}
// -------------------------------------------- //
// GET ALL ONLINE / OFFLINE
// -------------------------------------------- //
public Collection<E> getAllOnline()
@ -131,20 +149,5 @@ public class SenderColl<E extends SenderEntity<E>> extends Coll<E> implements Se
senderColl.setSenderReference(senderId, sender);
}
}
// -------------------------------------------- //
// ARGUMENT READERS
// -------------------------------------------- //
// TODO: Why were these removed?
/*public ArgReader<E> getARFullAny()
{
return ARSenderEntity.getFullAny(this);
}
public ArgReader<E> getARStartAny()
{
return ARSenderEntity.getStartAny(this);
}*/
}

View File

@ -1,45 +0,0 @@
package com.massivecraft.massivecore.store;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class SenderIdSourceCombined implements SenderIdSource
{
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
private final List<SenderIdSource> sources;
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public SenderIdSourceCombined(SenderIdSource... sources)
{
this.sources = new ArrayList<SenderIdSource>(Arrays.asList(sources));
}
public SenderIdSourceCombined(Collection<SenderIdSource> sources)
{
this.sources = new ArrayList<SenderIdSource>(sources);
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public Collection<Collection<String>> getSenderIdCollections()
{
List<Collection<String>> ret = new ArrayList<Collection<String>>();
for (SenderIdSource source : this.sources)
{
ret.addAll(source.getSenderIdCollections());
}
return ret;
}
}

View File

@ -23,7 +23,6 @@ public class SenderIdSourceMixinAllSenderIds implements SenderIdSource
public Collection<Collection<String>> getSenderIdCollections()
{
List<Collection<String>> ret = new ArrayList<Collection<String>>();
ret.add(IdUtil.getAllNames());
ret.add(IdUtil.getAllIds());
return ret;
}