wow. getting close to stable next major version \:D/

This commit is contained in:
Olof Larsson 2012-10-02 21:54:20 +02:00
parent 38aad961cc
commit 4e6a839d79
35 changed files with 78 additions and 1783 deletions

View File

@ -17,8 +17,6 @@ import org.bukkit.event.player.PlayerTeleportEvent;
import com.massivecraft.mcore4.event.MCoreAfterPlayerRespawnEvent;
import com.massivecraft.mcore4.event.MCoreAfterPlayerTeleportEvent;
import com.massivecraft.mcore4.event.MCorePlayerLeaveEvent;
import com.massivecraft.mcore4.persist.IClassManager;
import com.massivecraft.mcore4.persist.Persist;
import com.massivecraft.mcore4.store.Coll;
import com.massivecraft.mcore4.store.PlayerColl;
@ -33,6 +31,7 @@ public class InternalListener implements Listener
Bukkit.getServer().getPluginManager().registerEvents(this, this.p);
}
/*
@EventHandler(priority = EventPriority.LOW)
public void onPlayerLogin(PlayerLoginEvent event)
{
@ -47,7 +46,7 @@ public class InternalListener implements Listener
manager.create(id);
}
}
}
}*/
// -------------------------------------------- //
// AFTER EVENTS

View File

@ -11,7 +11,6 @@ import com.massivecraft.mcore4.adapter.InventoryAdapter;
import com.massivecraft.mcore4.adapter.ItemStackAdapter;
import com.massivecraft.mcore4.adapter.MongoURIAdapter;
import com.massivecraft.mcore4.adapter.PSAdapter;
import com.massivecraft.mcore4.persist.Persist;
import com.massivecraft.mcore4.store.Coll;
import com.massivecraft.mcore4.store.Db;
import com.massivecraft.mcore4.store.MStore;
@ -88,7 +87,6 @@ public class MCore extends MPlugin
{
// This is safe since all plugins using Persist should bukkit-depend this plugin.
// Note this one must be before preEnable. dooh.
Persist.instances.clear();
Coll.instances.clear();
if ( ! preEnable()) return;

View File

@ -9,25 +9,15 @@ import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
import com.massivecraft.mcore4.cmd.Cmd;
import com.massivecraft.mcore4.integration.Integration;
import com.massivecraft.mcore4.integration.IntegrationFeatures;
import com.massivecraft.mcore4.persist.One;
import com.massivecraft.mcore4.persist.Persist;
import com.massivecraft.mcore4.store.Coll;
import com.massivecraft.mcore4.util.LibLoader;
import com.massivecraft.mcore4.util.Txt;
import com.massivecraft.mcore4.xlib.gson.Gson;
import com.massivecraft.mcore4.xlib.gson.GsonBuilder;
public abstract class MPlugin extends JavaPlugin implements Listener
{
// Tools
public Cmd cmd;
public Persist persist;
public One one;
public LibLoader lib;
// Gson
public Gson gson;
@ -48,12 +38,6 @@ public abstract class MPlugin extends JavaPlugin implements Listener
// Create Gson
this.gson = this.getGsonBuilder().create();
// Create tools
this.cmd = new Cmd(); // TODO: Stop creating this asap :)
this.persist = new Persist(); // TODO: Stop creating this asap :)
this.one = new One(this); // TODO: Stop creating this asap :)
this.lib = new LibLoader(this); // TODO: Stop creating this asap :)
return true;
}
@ -68,11 +52,7 @@ public abstract class MPlugin extends JavaPlugin implements Listener
public void onDisable()
{
// Collection shutdowns for old system.
this.persist.saveAll();
Persist.instances.remove(this.persist);
// Collection shutdowns for new system.
// Collection shutdowns.
for (Coll<?, ?> coll : Coll.instances)
{
if (coll.getMplugin() != this) continue;

View File

@ -1,83 +0,0 @@
package com.massivecraft.mcore4.cmd;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.WorldType;
import org.bukkit.command.Command;
import org.bukkit.command.SimpleCommandMap;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.Player;
import com.massivecraft.mcore4.cmd.arg.old.AHAspect;
import com.massivecraft.mcore4.cmd.arg.old.AHBoolean;
import com.massivecraft.mcore4.cmd.arg.old.AHByte;
import com.massivecraft.mcore4.cmd.arg.old.AHDate;
import com.massivecraft.mcore4.cmd.arg.old.AHDouble;
import com.massivecraft.mcore4.cmd.arg.old.AHEnvironment;
import com.massivecraft.mcore4.cmd.arg.old.AHFloat;
import com.massivecraft.mcore4.cmd.arg.old.AHInteger;
import com.massivecraft.mcore4.cmd.arg.old.AHMaterial;
import com.massivecraft.mcore4.cmd.arg.old.AHMultiverse;
import com.massivecraft.mcore4.cmd.arg.old.AHPlayer;
import com.massivecraft.mcore4.cmd.arg.old.AHWorld;
import com.massivecraft.mcore4.cmd.arg.old.AHWorldType;
import com.massivecraft.mcore4.cmd.arg.old.IArgHandler;
import com.massivecraft.mcore4.usys.Aspect;
import com.massivecraft.mcore4.usys.Multiverse;
public class Cmd
{
// TODO: The cmd will no longer need to be instantiated.
// TODO: Perhaps I should remove the cmd system soon.
protected Map<Class<?>, IArgHandler<?>> argHandlers = new HashMap<Class<?>, IArgHandler<?>>();
public Map<Class<?>, IArgHandler<?>> getArgHandlers() { return this.argHandlers; }
@SuppressWarnings("unchecked")
public <T> IArgHandler<T> getArgHandler(Class<T> clazz) { return (IArgHandler<T>) this.argHandlers.get(clazz); }
public <T> void setArgHandler(Class<T> clazz, IArgHandler<T> handler) { this.argHandlers.put(clazz, handler); }
public Cmd()
{
this.setArgHandler(Aspect.class, new AHAspect());
this.setArgHandler(Boolean.class, new AHBoolean());
this.setArgHandler(Byte.class, new AHByte());
this.setArgHandler(Date.class, new AHDate());
this.setArgHandler(Double.class, new AHDouble());
this.setArgHandler(Environment.class, new AHEnvironment());
this.setArgHandler(Float.class, new AHFloat());
this.setArgHandler(Integer.class, new AHInteger());
this.setArgHandler(Material.class, new AHMaterial());
this.setArgHandler(Multiverse.class, new AHMultiverse());
this.setArgHandler(Player.class, new AHPlayer());
this.setArgHandler(World.class, new AHWorld());
this.setArgHandler(WorldType.class, new AHWorldType());
}
public static SimpleCommandMap getBukkitCommandMap()
{
CraftServer craftServer = (CraftServer)Bukkit.getServer();
return craftServer.getCommandMap();
}
@SuppressWarnings("unchecked")
public static Map<String, Command> getKnownCommandsFromSimpleCommandMap(SimpleCommandMap scm)
{
try
{
Field field = SimpleCommandMap.class.getDeclaredField("knownCommands");
field.setAccessible(true);
return (Map<String, Command>) field.get(scm);
}
catch (Exception e)
{
return null;
}
}
}

View File

@ -2,7 +2,6 @@ package com.massivecraft.mcore4.cmd;
import java.util.*;
import java.util.Map.Entry;
import java.util.logging.Level;
import lombok.Getter;
import lombok.Setter;
@ -16,9 +15,9 @@ import com.massivecraft.mcore4.Lang;
import com.massivecraft.mcore4.MPlugin;
import com.massivecraft.mcore4.cmd.arg.ArgReader;
import com.massivecraft.mcore4.cmd.arg.ArgResult;
import com.massivecraft.mcore4.cmd.arg.old.IArgHandler;
import com.massivecraft.mcore4.cmd.req.IReq;
import com.massivecraft.mcore4.cmd.req.ReqHasPerm;
import com.massivecraft.mcore4.util.BukkitCommandUtil;
import com.massivecraft.mcore4.util.Perm;
import com.massivecraft.mcore4.util.Txt;
@ -142,12 +141,12 @@ public abstract class MCommand
public boolean register(boolean override)
{
BukkitGlueCommand bgc = new BukkitGlueCommand(this);
SimpleCommandMap scm = Cmd.getBukkitCommandMap();
SimpleCommandMap scm = BukkitCommandUtil.getBukkitCommandMap();
if (override)
{
// Our commands are more important than your commands :P
Map<String, Command> knownCommands = Cmd.getKnownCommandsFromSimpleCommandMap(scm);
Map<String, Command> knownCommands = BukkitCommandUtil.getKnownCommandsFromSimpleCommandMap(scm);
String lowerLabel = bgc.getName().trim().toLowerCase();
knownCommands.remove(lowerLabel);
}
@ -464,7 +463,7 @@ public abstract class MCommand
// Argument Readers DEPRACATED TODO
// -------------------------------------------- //
@Deprecated
/*@Deprecated
public synchronized <T> T argAs(int idx, Class<T> clazz, String style, T defaultNotSet, T defaultNotFound)
{
if ( ! this.argIsSet(idx))
@ -516,6 +515,6 @@ public abstract class MCommand
{
return this.argAs(idx, clazz, (T)null, null);
}
*/
}

View File

@ -1,31 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
import org.bukkit.command.CommandSender;
import com.massivecraft.mcore4.MPlugin;
import com.massivecraft.mcore4.Permission;
import com.massivecraft.mcore4.usys.Aspect;
import com.massivecraft.mcore4.usys.AspectColl;
import com.massivecraft.mcore4.util.Txt;
public class AHAspect extends AHBase<Aspect>
{
@Override
public Aspect parse(String str, String style, CommandSender sender, MPlugin p)
{
this.error.clear();
Aspect ret = AspectColl.i.get(str);
if (ret == null)
{
this.error.add("<b>No aspect called \"<p>"+str+"<b>\".");
if (Permission.USYS_ASPECT_LIST.has(sender, false))
{
this.error.add("<i>Use "+Txt.implodeCommaAndDot(AspectColl.i.getIds(), "<h>%s", "<i>, ", " <i>or ", "<i>."));
}
}
return ret;
}
}

View File

@ -1,22 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
import java.util.ArrayList;
import java.util.Collection;
import org.bukkit.command.CommandSender;
import com.massivecraft.mcore4.MPlugin;
public abstract class AHBase<T> implements IArgHandler<T>
{
public Collection<String> error = new ArrayList<String>();
@Override
public abstract T parse(String str, String style, CommandSender sender, MPlugin p);
@Override
public Collection<String> getErrors()
{
return this.error;
}
}

View File

@ -1,22 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
public class AHBoolean extends AHPrimitive<Boolean>
{
@Override
protected String getPrimitiveName()
{
return "boolean";
}
@Override
protected Boolean unsafeConvert(String str) throws Exception
{
str = str.toLowerCase();
if (str.startsWith("y") || str.startsWith("t") || str.startsWith("on") || str.startsWith("+") || str.startsWith("1"))
{
return true;
}
return false;
}
}

View File

@ -1,17 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
public class AHByte extends AHPrimitive<Byte>
{
@Override
protected String getPrimitiveName()
{
return "byte";
}
@Override
protected Byte unsafeConvert(String str) throws Exception
{
return Byte.parseByte(str);
}
}

View File

@ -1,22 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class AHDate extends AHPrimitive<Date>
{
protected static DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
@Override
protected String getPrimitiveName()
{
return "YYYY-MM-DD date";
}
@Override
protected Date unsafeConvert(String str) throws Exception
{
return df.parse(str);
}
}

View File

@ -1,17 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
public class AHDouble extends AHPrimitive<Double>
{
@Override
protected String getPrimitiveName()
{
return "double";
}
@Override
protected Double unsafeConvert(String str) throws Exception
{
return Double.parseDouble(str);
}
}

View File

@ -1,46 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
import org.bukkit.World.Environment;
import org.bukkit.command.CommandSender;
import com.massivecraft.mcore4.MPlugin;
public class AHEnvironment extends AHBase<Environment>
{
@Override
public Environment parse(String str, String style, CommandSender sender, MPlugin p)
{
this.error.clear();
Environment ret = null;
// "THE_END" --> "end"
str = str.toLowerCase();
str = str.replace("_", "");
str = str.replace("the", "");
if (str.startsWith("no") || str.startsWith("d"))
{
// "normal" or "default"
ret = Environment.NORMAL;
}
else if (str.startsWith("ne"))
{
// "nether"
ret = Environment.NETHER;
}
else if (str.startsWith("e"))
{
// "end"
ret = Environment.THE_END;
}
if (ret == null)
{
this.error.add("<b>No environment matching \"<p>"+str+"<b>\".");
this.error.add("<i>Use <h>normal<i>, <h>end<i> or <h>nether<i>.");
}
return ret;
}
}

View File

@ -1,17 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
public class AHFloat extends AHPrimitive<Float>
{
@Override
protected String getPrimitiveName()
{
return "integer";
}
@Override
protected Float unsafeConvert(String str) throws Exception
{
return Float.parseFloat(str);
}
}

View File

@ -1,17 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
public class AHInteger extends AHPrimitive<Integer>
{
@Override
protected String getPrimitiveName()
{
return "integer";
}
@Override
protected Integer unsafeConvert(String str) throws Exception
{
return Integer.parseInt(str);
}
}

View File

@ -1,24 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import com.massivecraft.mcore4.MPlugin;
public class AHMaterial extends AHBase<Material>
{
@Override
public Material parse(String str, String style, CommandSender sender, MPlugin p)
{
this.error.clear();
Material ret = Material.matchMaterial(str);
if (ret == null)
{
this.error.add("<b>No material matching \"<p>"+str+"<b>\".");
this.error.add("<i>Suggestion: <aqua>http://www.minecraftwiki.net/wiki/Data_values");
}
return ret;
}
}

View File

@ -1,32 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
import org.bukkit.command.CommandSender;
import com.massivecraft.mcore4.MPlugin;
import com.massivecraft.mcore4.Permission;
import com.massivecraft.mcore4.usys.Multiverse;
import com.massivecraft.mcore4.usys.MultiverseColl;
import com.massivecraft.mcore4.util.Txt;
public class AHMultiverse extends AHBase<Multiverse>
{
@Override
public Multiverse parse(String str, String style, CommandSender sender, MPlugin p)
{
this.error.clear();
Multiverse ret = MultiverseColl.i.get(str);
if (ret == null)
{
this.error.add("<b>No multiverse called \"<p>"+str+"<b>\".");
if (Permission.USYS_MULTIVERSE_LIST.has(sender, false))
{
this.error.add("<i>Use "+Txt.implodeCommaAndDot(MultiverseColl.i.getIds(), "<h>%s", "<i>, ", " <i>or ", "<i>."));
}
}
return ret;
}
}

View File

@ -1,39 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.massivecraft.mcore4.MPlugin;
public class AHPlayer extends AHBase<Player>
{
@Override
public Player parse(String str, String style, CommandSender sender, MPlugin p)
{
this.error.clear();
if (str == null) return null;
if (style != null && style.equals("match"))
{
List<Player> players = Bukkit.getServer().matchPlayer(str);
if (players.size() > 0)
{
return players.get(0);
}
this.error.add("<b>No online player's name begins with \"<p>"+str+"<b>\".");
}
else
{
Player player = Bukkit.getServer().getPlayerExact(str);
if (player != null)
{
return player;
}
this.error.add("<b>No player online with the exact name \"<p>"+str+"<b>\".");
}
return null;
}
}

View File

@ -1,58 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
import org.bukkit.command.CommandSender;
import com.massivecraft.mcore4.MPlugin;
import com.massivecraft.mcore4.persist.IClassManager;
import com.massivecraft.mcore4.util.PlayerUtil;
import com.massivecraft.mcore4.util.Txt;
public abstract class AHPlayerWrapper<T> extends AHBase<T>
{
public abstract Class<T> getClazz();
public IClassManager<T> getManager(MPlugin p)
{
return p.persist.getManager(getClazz());
}
@Override
public T parse(String str, String style, CommandSender sender, MPlugin p)
{
this.error.clear();
if (str == null) return null;
IClassManager<T> manager = this.getManager(p);
T ret;
if (style != null && style.equalsIgnoreCase("match"))
{
ret = manager.getBestMatch(str);
if (ret != null)
{
return ret;
}
this.error.add("<b>No player name begins with \"<p>"+str+"<b>\".");
}
else if (style != null && style.equalsIgnoreCase("matchany"))
{
ret = manager.get(Txt.getBestCIStart(PlayerUtil.getAllVisitorNames(), str));
if (ret != null)
{
return ret;
}
this.error.add("<b>No player name begins with \"<p>"+str+"<b>\".");
}
else
{
ret = manager.get(str);
if (ret != null)
{
return ret;
}
this.error.add("<b>No player with the exact name \"<p>"+str+"<b>\".");
}
return null;
}
}

View File

@ -1,29 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
import org.bukkit.command.CommandSender;
import com.massivecraft.mcore4.MPlugin;
public abstract class AHPrimitive<T> extends AHBase<T>
{
protected abstract String getPrimitiveName();
protected abstract T unsafeConvert(String str) throws Exception;
@Override
public T parse(String str, String style, CommandSender sender, MPlugin p)
{
this.error.clear();
if (str == null) return null;
try
{
T ret = this.unsafeConvert(str);
return ret;
}
catch (Exception e)
{
this.error.add("<b>\"<p>"+str+"<b>\" is not a valid "+this.getPrimitiveName()+".");
}
return null;
}
}

View File

@ -1,26 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import com.massivecraft.mcore4.MPlugin;
public class AHWorld extends AHBase<World>
{
@Override
public World parse(String str, String style, CommandSender sender, MPlugin p)
{
this.error.clear();
if (str == null) return null;
World ret = Bukkit.getWorld(str);
if (ret == null)
{
this.error.add("<b>No world matching \"<p>"+str+"<b>\".");
}
return ret;
}
}

View File

@ -1,57 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
import org.bukkit.WorldType;
import org.bukkit.command.CommandSender;
import com.massivecraft.mcore4.MPlugin;
public class AHWorldType extends AHBase<WorldType>
{
@Override
public WorldType parse(String str, String style, CommandSender sender, MPlugin p)
{
this.error.clear();
WorldType ret = null;
// "DEFAULT_1_1" --> "11"
// "LARGE_BIOMES" --> "large"
// "Default" --> ""
str = str.toLowerCase();
str = str.replace("_", "");
str = str.replace(".", "");
str = str.replace("normal", "");
str = str.replace("default", "");
str = str.replace("large", "");
if (str.equals(""))
{
// "normal" or "default"
ret = WorldType.NORMAL;
}
else if (str.startsWith("flat"))
{
// "flat"
ret = WorldType.FLAT;
}
else if (str.contains("11"))
{
// "VERSION_1_1"
ret = WorldType.VERSION_1_1;
}
else if (str.contains("large"))
{
// "LARGE_BIOMES"
ret = WorldType.LARGE_BIOMES;
}
if (ret == null)
{
this.error.add("<b>No world type matching \"<p>"+str+"<b>\".");
this.error.add("<i>Use <h>normal<i>, <h>flat<i>, <h>1.1<i> or <h>largebiomes<i>.");
}
return ret;
}
}

View File

@ -1,16 +0,0 @@
package com.massivecraft.mcore4.cmd.arg.old;
import java.util.Collection;
import org.bukkit.command.CommandSender;
import com.massivecraft.mcore4.MPlugin;
public interface IArgHandler<T>
{
// Parse result returned - or null and something in the error message.
public T parse(String str, String style, CommandSender sender, MPlugin p);
// Error here - or null.
public Collection<String> getErrors();
}

View File

@ -1,45 +0,0 @@
package com.massivecraft.mcore4.persist;
/**
* Usage of this class is highly optional. You may persist anything. If you are
* creating the class to be persisted yourself, it might be handy to extend this
* Entity class. It just contains a set of shortcut methods.
*/
// Self referencing generic using the "getThis trick".
// http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ206
public abstract class Entity<T extends Entity<T>>
{
public abstract IClassManager<T> getManager();
protected abstract T getThis();
public String attach()
{
return this.getManager().attach(getThis());
}
public void detach()
{
this.getManager().detachEntity(getThis());
}
public boolean attached()
{
return this.getManager().containsEntity(getThis());
}
public boolean detached()
{
return ! this.attached();
}
public boolean save()
{
return this.getManager().saveEntity(getThis());
}
public String getId()
{
return this.getManager().id(getThis());
}
}

View File

@ -1,82 +0,0 @@
package com.massivecraft.mcore4.persist;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;
import com.massivecraft.mcore4.Predictate;
public interface IClassManager<T>
{
// What do we handle?
public Class<T> getManagedClass();
// This simply creates and returns a new instance
// It does not detach/attach or anything. Just creates a new instance.
public T createNewInstance();
// Creativeness
public boolean getIsCreative();
public void setIsCreative(boolean val);
// Create new instance with auto increment id
public T create();
// Create new instance with the requested id
public T create(Object oid);
// Add & Remove
public String attach(T entity);
public String attach(T entity, Object oid);
public void detachEntity(T entity);
public void detachId(Object oid);
public boolean containsEntity(T entity);
public boolean containsId(Object oid);
// Disc io triggers
public boolean saveEntity(T entity);
public boolean saveId(Object oid);
public boolean saveAll();
public boolean loaded(Object oid);
public T load(Object oid);
public boolean loadAll();
// Should that instance be saved or not?
// If it is default it should not be saved.
public boolean shouldBeSaved(T entity);
// Id handling
// Get the id for this entity. Return null if it does not have an ID
public String id(T entity);
// In some cases certain non string objects can represent a String id.
// This method is used as a wrapper for that.
// TODO: Javadoc: Should start with a null check as well as a String check.
public String idFix(Object oid);
public boolean idCanFix(Class<?> clazz);
// autoIncrement ids
public String idCurrent();
public String idNext(boolean advance);
public boolean idUpdateCurrentFor(Object oid);
// Get the entity for the id. If creative it is created if it does not exist else null.
public T get(Object oid, boolean creative);
public T get(Object oid);
// Get the entity that best matches the id.
public T getBestMatch(Object oid);
// Get all
public Collection<T> getAllLoaded();
public Collection<T> getAllLoaded(Predictate<T> where);
public Collection<T> getAllLoaded(Predictate<T> where, Comparator<T> orderby);
public Collection<T> getAllLoaded(Predictate<T> where, Comparator<T> orderby, Integer limit);
public Collection<T> getAllLoaded(Predictate<T> where, Comparator<T> orderby, Integer limit, Integer offset);
public Collection<T> getAll();
public Collection<T> getAll(Predictate<T> where);
public Collection<T> getAll(Predictate<T> where, Comparator<T> orderby);
public Collection<T> getAll(Predictate<T> where, Comparator<T> orderby, Integer limit);
public Collection<T> getAll(Predictate<T> where, Comparator<T> orderby, Integer limit, Integer offset);
public Collection<String> getIds();
public Map<String, T> getMap();
}

View File

@ -1,156 +0,0 @@
package com.massivecraft.mcore4.persist;
import java.io.File;
import java.lang.reflect.Type;
import java.util.logging.Level;
import com.massivecraft.mcore4.MPlugin;
import com.massivecraft.mcore4.util.DiscUtil;
// TODO: Give better name and place to differenciate from the entity-orm-ish system in "com.massivecraft.core.persist".
public class One {
private MPlugin p;
public One(MPlugin p)
{
this.p = p;
}
// ------------------------------------------------------------ //
// GET NAME - What should we call this type of object?
// ------------------------------------------------------------ //
public static String getName(Class<?> clazz)
{
return clazz.getSimpleName().toLowerCase();
}
public static String getName(Object o)
{
return getName(o.getClass());
}
public static String getName(Type type)
{
return getName(type.getClass());
}
// ------------------------------------------------------------ //
// GET FILE - In which file would we like to store this object?
// ------------------------------------------------------------ //
public File getFile(String name)
{
return new File(p.getDataFolder(), name+".json");
}
public File getFile(Class<?> clazz)
{
return getFile(getName(clazz));
}
public File getFile(Object obj)
{
return getFile(getName(obj));
}
public File getFile(Type type)
{
return getFile(getName(type));
}
// NICE WRAPPERS
public <T> T loadOrSaveDefault(T def, Class<T> clazz)
{
return loadOrSaveDefault(def, clazz, getFile(clazz));
}
public <T> T loadOrSaveDefault(T def, Class<T> clazz, String name)
{
return loadOrSaveDefault(def, clazz, getFile(name));
}
public <T> T loadOrSaveDefault(T def, Class<T> clazz, File file)
{
if ( ! file.exists())
{
p.log("Creating default: "+file);
this.save(def, file);
return def;
}
T loaded = this.load(clazz, file);
if (loaded == null)
{
p.log(Level.WARNING, "Using default as I failed to load: "+file);
return def;
}
return loaded;
}
// SAVE
public boolean save(Object instance)
{
return save(instance, getFile(instance));
}
public boolean save(Object instance, String name)
{
return save(instance, getFile(name));
}
public boolean save(Object instance, File file)
{
return DiscUtil.writeCatch(file, p.gson.toJson(instance));
}
// LOAD BY CLASS
public <T> T load(Class<T> clazz)
{
return load(clazz, getFile(clazz));
}
public <T> T load(Class<T> clazz, String name)
{
return load(clazz, getFile(name));
}
public <T> T load(Class<T> clazz, File file)
{
String content = DiscUtil.readCatch(file);
if (content == null)
{
return null;
}
T instance = p.gson.fromJson(content, clazz);
return instance;
}
// LOAD BY TYPE
@SuppressWarnings("unchecked")
public <T> T load(Type typeOfT, String name)
{
return (T) load(typeOfT, getFile(name));
}
@SuppressWarnings("unchecked")
public <T> T load(Type typeOfT, File file)
{
String content = DiscUtil.readCatch(file);
if (content == null) {
return null;
}
return (T) p.gson.fromJson(content, typeOfT);
}
}

View File

@ -1,177 +0,0 @@
package com.massivecraft.mcore4.persist;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.Timer;
import java.util.TreeSet;
import java.util.concurrent.CopyOnWriteArrayList;
import com.massivecraft.mcore4.Predictate;
public class Persist
{
public static List<Persist> instances = new CopyOnWriteArrayList<Persist>();
private Map<Class<?>, IClassManager<?>> classManagers = new HashMap<Class<?>, IClassManager<?>>();
public <T> void setManager(Class<T> clazz, IClassManager<T> manager)
{
this.classManagers.put(clazz, manager);
};
public Map<Class<?>, IClassManager<?>> getClassManagers()
{
return this.classManagers;
}
private Map<Class<?>, Timer> classSaveTimers = new HashMap<Class<?>, Timer>();
public synchronized <T> void setSaveInterval(Class<T> clazz, long interval)
{
// Clear old timer
Timer timer = this.classSaveTimers.get(clazz);
if (timer != null)
{
timer.cancel();
this.classSaveTimers.remove(clazz);
}
// Create new timer
timer = new Timer();
this.classSaveTimers.put(clazz, timer);
// Add the task to the timer
SaveTask<T> task = new SaveTask<T>(this, clazz);
timer.scheduleAtFixedRate(task, interval, interval);
};
@SuppressWarnings("unchecked")
public <T> IClassManager<T> getManager(Class<T> clazz)
{
return (IClassManager<T>) this.classManagers.get(clazz);
}
@SuppressWarnings("unchecked")
public <T extends Object> IClassManager<T> getManager(T entity)
{
return (IClassManager<T>) this.getManager(entity.getClass());
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public Persist()
{
instances.add(this);
}
// -------------------------------------------- //
// SAVE ALL
// -------------------------------------------- //
public void saveAll()
{
for (IClassManager<?> m : this.classManagers.values())
{
m.saveAll();
}
}
// -------------------------------------------- //
// UTILS
// -------------------------------------------- //
public static <T> ArrayList<T> uglySQL(Collection<T> items, Predictate<T> where, Comparator<T> orderby, Integer limit, Integer offset)
{
ArrayList<T> ret = new ArrayList<T>(items.size());
// WHERE
if (where == null)
{
ret.addAll(items);
}
else
{
for (T item : items)
{
if (where.apply(item))
{
ret.add(item);
}
}
}
// ORDERBY
if (orderby != null)
{
Collections.sort(ret, orderby);
}
// LIMIT AND OFFSET
// Parse args
int fromIndex = 0;
if (offset != null)
{
fromIndex = offset;
}
int toIndex = ret.size()-1;
if (limit != null)
{
toIndex = offset+limit;
}
// Clean args
if (fromIndex <= 0)
{
fromIndex = 0;
}
else if (fromIndex > ret.size()-1)
{
fromIndex = ret.size()-1;
}
if (toIndex < fromIndex)
{
toIndex = fromIndex;
}
else if (toIndex > ret.size()-1)
{
toIndex = ret.size()-1;
}
// No limit?
if (fromIndex == 0 && toIndex == ret.size()-1) return ret;
return new ArrayList<T>(ret.subList(fromIndex, toIndex));
}
// http://stackoverflow.com/questions/2864840/treemap-sort-by-value
public static <K,V extends Comparable<? super V>> SortedSet<Map.Entry<K,V>> entriesSortedByValues(Map<K,V> map, final boolean ascending)
{
SortedSet<Map.Entry<K,V>> sortedEntries = new TreeSet<Map.Entry<K,V>>(
new Comparator<Map.Entry<K,V>>()
{
@Override public int compare(Map.Entry<K,V> e1, Map.Entry<K,V> e2)
{
int res;
if (ascending)
{
res = e1.getValue().compareTo(e2.getValue());
}
else
{
res = e2.getValue().compareTo(e1.getValue());
}
return res != 0 ? res : 1;
}
}
);
sortedEntries.addAll(map.entrySet());
return sortedEntries;
}
}

View File

@ -1,79 +0,0 @@
package com.massivecraft.mcore4.persist;
import java.util.Collection;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;
import com.massivecraft.mcore4.util.Txt;
public abstract class PlayerEntity<T extends PlayerEntity<T>> extends Entity<T>
{
public Player getPlayer()
{
// There is no case sensitivity.
return Bukkit.getPlayerExact(this.getId());
}
public boolean isOnline()
{
return this.getPlayer() != null;
}
public boolean isOffline()
{
return ! isOnline();
}
// -------------------------------------------- //
// CHECKER UTILS
// -------------------------------------------- //
public boolean isGameMode(GameMode gm, boolean defaultIfOffline)
{
Player player = this.getPlayer();
if (player == null || ! player.isOnline()) return defaultIfOffline;
return player.getGameMode() == gm;
}
// -------------------------------------------- //
// Message Sending Helpers
// -------------------------------------------- //
public void sendMessage(String msg)
{
Player player = this.getPlayer();
if (player == null) return;
player.sendMessage(msg);
}
public void sendMessage(Collection<String> msgs)
{
Player player = this.getPlayer();
if (player == null) return;
for(String msg : msgs)
{
player.sendMessage(msg);
}
}
public void msg(String msg)
{
this.sendMessage(Txt.parse(msg));
}
public void msg(String msg, Object... args)
{
this.sendMessage(Txt.parse(msg, args));
}
public void msg(Collection<String> msgs)
{
Player player = this.getPlayer();
if (player == null) return;
for(String msg : msgs)
{
player.sendMessage(Txt.parse(msg));
}
}
}

View File

@ -1,35 +0,0 @@
package com.massivecraft.mcore4.persist;
import java.util.TimerTask;
public class SaveTask<T> extends TimerTask
{
private Persist persist;
private Class<T> clazz;
public Class<T> getToBeSavedClass() { return clazz; }
public SaveTask(Persist persist, Class<T> clazz)
{
this.persist = persist;
this.clazz = clazz;
}
public SaveTask(Persist persist)
{
this(persist, null);
}
@Override
public void run()
{
if (this.clazz == null)
{
this.persist.saveAll();
}
else
{
this.persist.getManager(this.clazz).saveAll();
}
}
}

View File

@ -1,496 +0,0 @@
package com.massivecraft.mcore4.persist.gson;
import java.io.File;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArraySet;
import com.massivecraft.mcore4.Predictate;
import com.massivecraft.mcore4.persist.IClassManager;
import com.massivecraft.mcore4.persist.Persist;
import com.massivecraft.mcore4.util.DiscUtil;
import com.massivecraft.mcore4.util.Txt;
import com.massivecraft.mcore4.xlib.gson.Gson;
public abstract class GsonClassManager<T> implements IClassManager<T>
{
// -------------------------------------------- //
// NON INTERFACE
// -------------------------------------------- //
protected final static String DOTJSON = ".json";
protected Set<String> ids;
protected Set<T> entities;
protected Map<String, T> id2entity;
protected Map<T, String> entity2id;
protected long idCurrent = 1;
protected Gson gson;
public Gson getGson() { return gson; }
public void setGson(Gson gson) { this.gson = gson; }
protected File folder;
public File getFolder() { return folder; }
public void setFolder(File val) { this.folder = val; }
protected boolean creative;
@Override
public boolean getIsCreative() { return this.creative; }
@Override
public void setIsCreative(boolean val) { this.creative = val; }
protected boolean didLoadAll = false;
protected void loadIds()
{
if ( ! this.getFolder().exists()) return;
for(File file : this.getFolder().listFiles(JsonFileFilter.getInstance()))
{
this.ids.add(this.idFromFile(file));
}
}
protected String idFromFile(File file)
{
if (file == null) return null;
String name = file.getName();
return name.substring(0, name.length()-5);
}
protected File fileFromId(Object oid)
{
String id = this.idFix(oid);
if (id == null) return null;
return new File(this.getFolder(), id+DOTJSON);
}
// -------------------------------------------- //
// CONSTRUCTORS
// -------------------------------------------- //
public GsonClassManager(Gson gson, File folder, boolean creative, boolean lazy, Set<String> ids, Set<T> entities, Map<String, T> id2entity, Map<T, String> entity2id)
{
this.gson = gson;
this.folder = folder;
this.creative = creative;
this.ids = ids;
this.entities = entities;
this.id2entity = id2entity;
this.entity2id = entity2id;
this.loadIds();
if ( ! lazy)
{
this.loadAll();
}
}
public GsonClassManager(Gson gson, File folder, boolean creative, boolean lazy)
{
this(
gson,
folder,
creative,
lazy,
new ConcurrentSkipListSet<String>(String.CASE_INSENSITIVE_ORDER),
new CopyOnWriteArraySet<T>(),
new ConcurrentSkipListMap<String, T>(String.CASE_INSENSITIVE_ORDER),
new ConcurrentHashMap<T, String>()
);
}
// -------------------------------------------- //
// INTERFACE IMPLEMENTATION
// -------------------------------------------- //
@Override
public abstract Class<T> getManagedClass();
@Override
public T createNewInstance()
{
try
{
return this.getManagedClass().newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
@Override
public synchronized T create()
{
return this.create(null);
}
@Override
public synchronized T create(Object oid)
{
T entity = this.createNewInstance();
if (this.attach(entity, oid) == null) return null;
return entity;
}
@Override
public synchronized String attach(T entity)
{
return this.attach(entity, null);
}
@Override
public synchronized String attach(T entity, Object oid)
{
return this.attach(entity, oid, false);
}
protected synchronized String attach(T entity, Object oid, boolean allowExistingIdUsage)
{
// Check entity
if (entity == null) return null;
String id = this.id(entity);
if (id != null) return id;
// Check/Fix id
if (oid == null)
{
id = this.idNext(true);
}
else
{
id = this.idFix(oid);
if (id == null) return null;
if (this.containsId(id) && ! allowExistingIdUsage) return null;
}
// Attach
this.ids.add(id);
this.entities.add(entity);
this.id2entity.put(id, entity);
this.entity2id.put(entity, id);
// Update Auto Increment
this.idUpdateCurrentFor(id);
return id;
}
@Override
public synchronized void detachEntity(T entity)
{
if (entity == null) return;
String id = this.entity2id.get(entity);
if (id == null) return;
this.detach(entity, id);
}
@Override
public synchronized void detachId(Object oid)
{
String id = this.idFix(oid);
if (id == null) return;
T entity = this.id2entity.get(id);
this.detach(entity, id);
}
// Assumes the id is correct! For internal use only!
protected synchronized void detach(T entity, String id)
{
if (id != null)
{
this.ids.remove(id);
this.id2entity.remove(id);
this.removeFile(id);
}
if (entity != null)
{
this.entities.remove(entity);
this.entity2id.remove(entity);
}
}
protected void removeFile(String id)
{
File file = this.fileFromId(id);
if (file.exists())
{
file.delete();
}
}
@Override
public boolean containsEntity(T entity)
{
return this.entity2id.containsKey(entity);
}
@Override
public boolean containsId(Object oid)
{
String id = this.idFix(oid);
if (id == null) return false;
return ids.contains(id);
}
@Override
public boolean saveEntity(T entity)
{
String id = this.id(entity);
return this.save(id, entity);
}
@Override
public boolean saveId(Object oid)
{
String id = this.idFix(oid);
T entity = this.get(id);
return this.save(id, entity);
}
protected boolean save(String id, T entity)
{
if (id == null) return false;
if (entity == null) return false;
if (this.shouldBeSaved(entity))
{
String json = this.getGson().toJson(entity);
File file = this.fileFromId(id);
return DiscUtil.writeCatch(file, json);
}
this.removeFile(id);
// TODO: Remove if loaded??
return true;
// TODO: Perhaps implement a logger in the interface?
}
@Override
public boolean saveAll()
{
// Delete all files we do not care about.
for (File file : this.getFolder().listFiles(JsonFileFilter.getInstance()))
{
String id = this.idFromFile(file);
if ( ! this.containsId(id))
{
file.delete();
}
}
// Save all loaded entites.
for (Entry<String, T> entry: this.id2entity.entrySet())
{
this.save(entry.getKey(), entry.getValue());
}
// TODO: Bogus! This should return if a single error was encountered!
return true;
}
@Override
public boolean loaded(Object oid)
{
String id = this.idFix(oid);
if (id == null) return false;
return this.id2entity.containsKey(id);
}
@Override
public synchronized T load(Object oid)
{
String id = this.idFix(oid);
if (id == null) return null;
T entity = this.id2entity.get(id);
if (entity != null) return entity;
if ( ! this.containsId(id)) return null;
File file = this.fileFromId(id);
String json = DiscUtil.readCatch(file);
if (json == null) return null;
entity = this.getGson().fromJson(json, this.getManagedClass());
this.attach(entity, id, true);
return entity;
}
@Override
public boolean loadAll()
{
if (this.didLoadAll) return false;
for (String id : this.ids)
{
this.load(id);
}
this.didLoadAll = true;
return true;
}
@Override
public boolean shouldBeSaved(T entity)
{
return true;
}
@Override
public String id(T entity)
{
return this.entity2id.get(entity);
}
@Override
public abstract String idFix(Object oid);
@Override
public abstract boolean idCanFix(Class<?> clazz);
@Override
public String idCurrent()
{
return Long.toString(this.idCurrent);
}
@Override
public synchronized String idNext(boolean advance)
{
long next = this.idCurrent;
String nextString = String.valueOf(next);
while (this.containsId(nextString))
{
next += 1;
nextString = String.valueOf(next);
}
if (advance)
{
this.idCurrent = next;
}
return nextString;
}
@Override
public synchronized boolean idUpdateCurrentFor(Object oid)
{
String id = this.idFix(oid);
if (id == null) return false;
long primid;
try
{
primid = Long.parseLong(id);
}
catch (Exception e)
{
// The id was not a number. No need to care about it.
return false;
}
if (this.idCurrent < primid)
{
this.idCurrent = primid;
return true;
}
return false;
}
@Override
public synchronized T get(Object oid, boolean creative)
{
String id = this.idFix(oid);
if (id == null) return null;
T ret = this.load(id);
if (ret != null)
{
return ret;
}
if ( ! creative) return null;
return this.create(id);
}
@Override
public T get(Object oid)
{
return this.get(oid, this.getIsCreative());
}
@Override
public Collection<T> getAllLoaded()
{
return entities;
}
@Override
public Collection<T> getAllLoaded(Predictate<T> where)
{
return Persist.uglySQL(this.getAllLoaded(), where, null, null, null);
}
@Override
public Collection<T> getAllLoaded(Predictate<T> where, Comparator<T> orderby)
{
return Persist.uglySQL(this.getAllLoaded(), where, orderby, null, null);
}
@Override
public Collection<T> getAllLoaded(Predictate<T> where, Comparator<T> orderby, Integer limit)
{
return Persist.uglySQL(this.getAllLoaded(), where, orderby, limit, null);
}
@Override
public Collection<T> getAllLoaded(Predictate<T> where, Comparator<T> orderby, Integer limit, Integer offset)
{
return Persist.uglySQL(this.getAllLoaded(), where, orderby, limit, offset);
}
@Override
public Collection<T> getAll()
{
this.loadAll();
return entities;
}
@Override
public Collection<T> getAll(Predictate<T> where)
{
return Persist.uglySQL(this.getAll(), where, null, null, null);
}
@Override
public Collection<T> getAll(Predictate<T> where, Comparator<T> orderby)
{
return Persist.uglySQL(this.getAll(), where, orderby, null, null);
}
@Override
public Collection<T> getAll(Predictate<T> where, Comparator<T> orderby, Integer limit)
{
return Persist.uglySQL(this.getAll(), where, orderby, limit, null);
}
@Override
public Collection<T> getAll(Predictate<T> where, Comparator<T> orderby, Integer limit, Integer offset)
{
return Persist.uglySQL(this.getAll(), where, orderby, limit, offset);
}
@Override
public Collection<String> getIds()
{
return this.ids;
}
@Override
public Map<String, T> getMap()
{
return this.id2entity;
}
@Override
public T getBestMatch(Object oid)
{
String start = this.idFix(oid);
if (start == null) return null;
String id = Txt.getBestCIStart(this.ids, start);
return this.get(id);
}
}

View File

@ -1,67 +0,0 @@
package com.massivecraft.mcore4.persist.gson;
import java.io.File;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerEvent;
import com.massivecraft.mcore4.Predictate;
import com.massivecraft.mcore4.persist.PlayerEntity;
import com.massivecraft.mcore4.xlib.gson.Gson;
public abstract class GsonPlayerEntityManager<T extends PlayerEntity<T>> extends GsonClassManager<T>
{
public GsonPlayerEntityManager(Gson gson, File folder, boolean creative, boolean lazy)
{
super(gson, folder, creative, lazy);
}
public GsonPlayerEntityManager(Gson gson, File folder, boolean creative, boolean lazy, Set<String> ids, Set<T> entities, Map<String, T> id2entity, Map<T, String> entity2id)
{
super(gson, folder, creative, lazy, ids, entities, id2entity, entity2id);
}
@Override
public String idFix(Object oid)
{
if (oid == null) return null;
if (oid instanceof String) return (String) oid;
if (oid instanceof Player) return ((Player)oid).getName();
if (oid instanceof PlayerEvent) return ((PlayerEvent)oid).getPlayer().getName();
return null;
}
@Override
public boolean idCanFix(Class<?> clazz)
{
if (clazz == null) return false;
if (String.class.equals(clazz)) return true;
if (Player.class.equals(clazz)) return true;
return false;
}
public Collection<T> getAllOnline()
{
return this.getAllLoaded(new Predictate<T>()
{
public boolean apply(T entity)
{
return entity.isOnline();
}
});
}
public Collection<T> getAllOffline()
{
return this.getAll(new Predictate<T>()
{
public boolean apply(T entity)
{
return entity.isOffline();
}
});
}
}

View File

@ -1,26 +0,0 @@
package com.massivecraft.mcore4.persist.gson;
import java.io.File;
import java.io.FileFilter;
public class JsonFileFilter implements FileFilter
{
private static JsonFileFilter instance = null;
private final static String DOTJSON = ".json";
public static JsonFileFilter getInstance()
{
if (instance == null)
{
instance = new JsonFileFilter();
}
return instance;
}
@Override
public boolean accept(File pathname)
{
return pathname.getName().toLowerCase().endsWith(DOTJSON);
}
private JsonFileFilter() {}
}

View File

@ -0,0 +1,33 @@
package com.massivecraft.mcore4.util;
import java.lang.reflect.Field;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.SimpleCommandMap;
import org.bukkit.craftbukkit.CraftServer;
public class BukkitCommandUtil
{
public static SimpleCommandMap getBukkitCommandMap()
{
CraftServer craftServer = (CraftServer)Bukkit.getServer();
return craftServer.getCommandMap();
}
@SuppressWarnings("unchecked")
public static Map<String, Command> getKnownCommandsFromSimpleCommandMap(SimpleCommandMap scm)
{
try
{
Field field = SimpleCommandMap.class.getDeclaredField("knownCommands");
field.setAccessible(true);
return (Map<String, Command>) field.get(scm);
}
catch (Exception e)
{
return null;
}
}
}

View File

@ -2,17 +2,12 @@ package com.massivecraft.mcore4.util;
import java.io.File;
import com.massivecraft.mcore4.MCore;
import com.massivecraft.mcore4.MPlugin;
public class LibLoader
{
MPlugin p;
public LibLoader(MPlugin p)
{
this.p = p;
}
public boolean require(String filename, String url)
public static boolean require(String filename, String url, MPlugin p)
{
if ( ! include(filename, url))
{
@ -23,7 +18,7 @@ public class LibLoader
return true;
}
public boolean include (String filename, String url)
public static boolean include (String filename, String url)
{
File file = getFile(filename);
if ( ! file.exists())
@ -31,14 +26,13 @@ public class LibLoader
File parent = file.getParentFile();
if (parent != null && !parent.exists()) parent.mkdirs();
p.log("Downloading library "+filename);
MCore.p.log("Downloading library "+filename);
if ( ! DiscUtil.downloadUrl(url, file))
{
p.log("Failed to download "+filename);
MCore.p.log(Txt.parse("<b>Failed to download <h>%s", filename));
return false;
}
}
return ClassLoadHack.load(file);
}

View File

@ -166,7 +166,7 @@ public class MUtil
// -------------------------------------------- //
//http://stackoverflow.com/questions/2864840/treemap-sort-by-value
public static <K,V extends Comparable<? super V>> SortedSet<Map.Entry<K,V>> entriesSortedByValues(Map<K,V> map) {
/*public static <K,V extends Comparable<? super V>> SortedSet<Map.Entry<K,V>> entriesSortedByValues(Map<K,V> map) {
SortedSet<Map.Entry<K,V>> sortedEntries = new TreeSet<Map.Entry<K,V>>(
new Comparator<Map.Entry<K,V>>() {
@Override public int compare(Map.Entry<K,V> e1, Map.Entry<K,V> e2) {
@ -177,6 +177,36 @@ public class MUtil
);
sortedEntries.addAll(map.entrySet());
return sortedEntries;
}*/
// http://stackoverflow.com/questions/2864840/treemap-sort-by-value
public static <K,V extends Comparable<? super V>> SortedSet<Map.Entry<K,V>> entriesSortedByValues(Map<K,V> map)
{
return entriesSortedByValues(map, true);
}
public static <K,V extends Comparable<? super V>> SortedSet<Map.Entry<K,V>> entriesSortedByValues(Map<K,V> map, final boolean ascending)
{
SortedSet<Map.Entry<K,V>> sortedEntries = new TreeSet<Map.Entry<K,V>>(
new Comparator<Map.Entry<K,V>>()
{
@Override public int compare(Map.Entry<K,V> e1, Map.Entry<K,V> e2)
{
int res;
if (ascending)
{
res = e1.getValue().compareTo(e2.getValue());
}
else
{
res = e2.getValue().compareTo(e1.getValue());
}
return res != 0 ? res : 1;
}
}
);
sortedEntries.addAll(map.entrySet());
return sortedEntries;
}
// -------------------------------------------- //

View File

@ -427,7 +427,7 @@ public class Txt
if (unitCountParts.size() == 0) return "just now";
ret += implodeCommaAndDot(unitCountParts);
ret += implodeCommaAnd(unitCountParts);
ret += " ";
if (millis <= 0)
{