From 514162387fa80b78aa7be667ab94131d4a6aa125 Mon Sep 17 00:00:00 2001 From: Olof Larsson Date: Wed, 9 Jan 2013 09:41:14 +0100 Subject: [PATCH] Minimalizing and simplifying MStore. Also adding default sorting to entities and collections. --- src/com/massivecraft/mcore5/store/Coll.java | 24 ++++---- .../mcore5/store/CollInterface.java | 6 +- src/com/massivecraft/mcore5/store/Colls.java | 2 +- src/com/massivecraft/mcore5/store/Driver.java | 16 +++--- .../mcore5/store/DriverAbstract.java | 2 +- .../massivecraft/mcore5/store/DriverGson.java | 16 +++--- .../mcore5/store/DriverMongo.java | 14 ++--- src/com/massivecraft/mcore5/store/Entity.java | 55 ++++++++++++------- .../mcore5/store/ExamineThread.java | 2 +- src/com/massivecraft/mcore5/store/MStore.java | 2 +- .../mcore5/store/idstrategy/IdStrategy.java | 2 +- .../store/idstrategy/IdStrategyAbstract.java | 2 +- src/com/massivecraft/mcore5/usys/Aspect.java | 6 -- .../massivecraft/mcore5/usys/Multiverse.java | 6 -- src/com/massivecraft/mcore5/util/MUtil.java | 14 +---- 15 files changed, 84 insertions(+), 85 deletions(-) diff --git a/src/com/massivecraft/mcore5/store/Coll.java b/src/com/massivecraft/mcore5/store/Coll.java index 9586a186..5310ceb3 100644 --- a/src/com/massivecraft/mcore5/store/Coll.java +++ b/src/com/massivecraft/mcore5/store/Coll.java @@ -9,6 +9,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.CopyOnWriteArrayList; import com.massivecraft.mcore5.MCore; @@ -18,7 +19,7 @@ import com.massivecraft.mcore5.store.accessor.Accessor; import com.massivecraft.mcore5.store.idstrategy.IdStrategy; import com.massivecraft.mcore5.store.storeadapter.StoreAdapter; -public class Coll implements CollInterface +public class Coll> implements CollInterface { // -------------------------------------------- // // GLOBAL REGISTRY @@ -72,7 +73,7 @@ public class Coll implements CollInterface protected Set ids = Collections.newSetFromMap(new ConcurrentHashMap()); @Override public Collection getIds() { return Collections.unmodifiableCollection(this.ids); } @Override public Collection getIdsRemote() { return this.getDb().getDriver().getIds(this); } - @Override public boolean containsEntity(E entity) { return this.entities.contains(entity); }; + @Override public boolean containsEntity(Object entity) { return this.entities.contains(entity); }; @Override public boolean containsId(Object oid) { @@ -81,8 +82,9 @@ public class Coll implements CollInterface return this.ids.contains(id); } - - protected Set entities = Collections.newSetFromMap(new ConcurrentHashMap()); + // We use a ConcurrentSkipListSet here in order for the entities to keep their natural ordering + // You may want to have your entities implement the Comparable interface + protected Set entities = new ConcurrentSkipListSet(); @Override public Collection getAll() { return Collections.unmodifiableCollection(this.entities); } @Override public Collection getAll(Predictate where) { return MStoreUtil.uglySQL(this.getAll(), where, null, null, null); } @Override public Collection getAll(Predictate where, Comparator orderby) { return MStoreUtil.uglySQL(this.getAll(), where, orderby, null, null); } @@ -114,7 +116,7 @@ public class Coll implements CollInterface // Get the id for this entity. protected Map entity2id = new ConcurrentHashMap(); @Override public Map getEntity2id() { return Collections.unmodifiableMap(this.entity2id); } - @Override public L getId(E entity) { return this.entity2id.get(entity); } + @Override public L getId(Object entity) { return this.entity2id.get(entity); } @Override public L fixId(Object oid) @@ -228,18 +230,18 @@ public class Coll implements CollInterface if (this.ids.contains(id)) return null; } - // Attach - this.ids.add(id); - this.entities.add(entity); - this.id2entity.put(id, entity); - this.entity2id.put(entity, id); - // Set this as the coll if possible. if (entity instanceof Entity) { ((Entity)entity).setColl(this); } + // Attach + this.id2entity.put(id, entity); + this.entity2id.put(entity, id); + this.ids.add(id); + this.entities.add(entity); + // Make note of the change if (noteChange) { diff --git a/src/com/massivecraft/mcore5/store/CollInterface.java b/src/com/massivecraft/mcore5/store/CollInterface.java index e0f810fe..bfba3e92 100644 --- a/src/com/massivecraft/mcore5/store/CollInterface.java +++ b/src/com/massivecraft/mcore5/store/CollInterface.java @@ -9,7 +9,7 @@ import com.massivecraft.mcore5.Predictate; import com.massivecraft.mcore5.store.idstrategy.IdStrategy; import com.massivecraft.mcore5.store.storeadapter.StoreAdapter; -public interface CollInterface +public interface CollInterface> { // -------------------------------------------- // // WHAT DO WE HANDLE? @@ -37,7 +37,7 @@ public interface CollInterface public Collection getIds(); public Collection getIdsRemote(); public boolean containsId(Object oid); - public boolean containsEntity(E entity); + public boolean containsEntity(Object entity); public Collection getAll(); public Collection getAll(Predictate where); @@ -50,7 +50,7 @@ public interface CollInterface public E get(Object oid, boolean creative); public Map getEntity2id(); - public L getId(E entity); + public L getId(Object entity); public L fixId(Object oid); // -------------------------------------------- // diff --git a/src/com/massivecraft/mcore5/store/Colls.java b/src/com/massivecraft/mcore5/store/Colls.java index f529d8b7..46169e1e 100644 --- a/src/com/massivecraft/mcore5/store/Colls.java +++ b/src/com/massivecraft/mcore5/store/Colls.java @@ -9,7 +9,7 @@ import com.massivecraft.mcore5.usys.Aspect; import com.massivecraft.mcore5.usys.Multiverse; import com.massivecraft.mcore5.util.MUtil; -public abstract class Colls, E, L> +public abstract class Colls, E, L extends Comparable> { protected Map name2coll = new HashMap(); diff --git a/src/com/massivecraft/mcore5/store/Driver.java b/src/com/massivecraft/mcore5/store/Driver.java index df73debd..51163f11 100644 --- a/src/com/massivecraft/mcore5/store/Driver.java +++ b/src/com/massivecraft/mcore5/store/Driver.java @@ -22,7 +22,7 @@ public interface Driver // This is some sort of database specific id strategy with built in adapter public boolean registerIdStrategy(IdStrategy idStrategy); - public IdStrategy getIdStrategy(String idStrategyName); + public > IdStrategy getIdStrategy(String idStrategyName); // Get the default store adapter for the driver. public StoreAdapter getStoreAdapter(); @@ -34,25 +34,25 @@ public interface Driver public Set getCollnames(Db db); // Is id X in the collection? - public boolean containsId(Coll coll, L id); + public > boolean containsId(Coll coll, L id); // When was X last altered? - public Long getMtime(Coll coll, L id); + public > Long getMtime(Coll coll, L id); // What ids are in the collection? - public Collection getIds(Coll coll); + public > Collection getIds(Coll coll); // Return a map of all ids with their corresponding mtimes - public Map getId2mtime(Coll coll); + public > Map getId2mtime(Coll coll); // Load the raw data for X. The second part of the entry is the remote mtime at the load. - public Entry load(Coll coll, L id); + public > Entry load(Coll coll, L id); // Save raw data as X // Return value is the new mtime (we caused the change). // If the mtime is null something failed. - public Long save(Coll coll, L id, final Object rawData); + public > Long save(Coll coll, L id, final Object rawData); // Delete X - public void delete(Coll coll, L id); + public > void delete(Coll coll, L id); } diff --git a/src/com/massivecraft/mcore5/store/DriverAbstract.java b/src/com/massivecraft/mcore5/store/DriverAbstract.java index 7ebb7e09..7a086d92 100644 --- a/src/com/massivecraft/mcore5/store/DriverAbstract.java +++ b/src/com/massivecraft/mcore5/store/DriverAbstract.java @@ -26,7 +26,7 @@ public abstract class DriverAbstract implements Driver @SuppressWarnings("unchecked") @Override - public IdStrategy getIdStrategy(String idStrategyName) + public > IdStrategy getIdStrategy(String idStrategyName) { IdStrategy idStrategy = idStrategies.get(idStrategyName); return (IdStrategy) idStrategy; diff --git a/src/com/massivecraft/mcore5/store/DriverGson.java b/src/com/massivecraft/mcore5/store/DriverGson.java index 75aa7d4c..ad06b2e8 100644 --- a/src/com/massivecraft/mcore5/store/DriverGson.java +++ b/src/com/massivecraft/mcore5/store/DriverGson.java @@ -72,13 +72,13 @@ public class DriverGson extends DriverAbstract } @Override - public boolean containsId(Coll coll, L id) + public > boolean containsId(Coll coll, L id) { return fileFromId(coll, id).isFile(); } @Override - public Long getMtime(Coll coll, L id) + public > Long getMtime(Coll coll, L id) { File file = fileFromId(coll, id); if ( ! file.isFile()) return null; @@ -86,7 +86,7 @@ public class DriverGson extends DriverAbstract } @Override - public Collection getIds(Coll coll) + public > Collection getIds(Coll coll) { List ret = new ArrayList(); @@ -105,7 +105,7 @@ public class DriverGson extends DriverAbstract } @Override - public Map getId2mtime(Coll coll) + public > Map getId2mtime(Coll coll) { Map ret = new HashMap(); @@ -124,7 +124,7 @@ public class DriverGson extends DriverAbstract } @Override - public Entry load(Coll coll, L id) + public > Entry load(Coll coll, L id) { File file = fileFromId(coll, id); Long mtime = file.lastModified(); @@ -137,7 +137,7 @@ public class DriverGson extends DriverAbstract } @Override - public Long save(Coll coll, L id, Object rawData) + public > Long save(Coll coll, L id, Object rawData) { File file = fileFromId(coll, id); String content = coll.getMplugin().gson.toJson((JsonElement)rawData); @@ -146,7 +146,7 @@ public class DriverGson extends DriverAbstract } @Override - public void delete(Coll coll, L id) + public > void delete(Coll coll, L id) { File file = fileFromId(coll, id); file.delete(); @@ -168,7 +168,7 @@ public class DriverGson extends DriverAbstract return name.substring(0, name.length()-5); } - protected static File fileFromId(Coll coll, L id) + protected static > File fileFromId(Coll coll, L id) { File collDir = getCollDir(coll); String idString = (String)coll.getIdStrategy().localToRemote(id); diff --git a/src/com/massivecraft/mcore5/store/DriverMongo.java b/src/com/massivecraft/mcore5/store/DriverMongo.java index 0320f6e6..5946052d 100644 --- a/src/com/massivecraft/mcore5/store/DriverMongo.java +++ b/src/com/massivecraft/mcore5/store/DriverMongo.java @@ -72,7 +72,7 @@ public class DriverMongo extends DriverAbstract } @Override - public boolean containsId(Coll coll, L id) + public > boolean containsId(Coll coll, L id) { DBCollection dbcoll = fixColl(coll); DBCursor cursor = dbcoll.find(new BasicDBObject(ID_FIELD, coll.getIdStrategy().localToRemote(id))); @@ -80,7 +80,7 @@ public class DriverMongo extends DriverAbstract } @Override - public Long getMtime(Coll coll, L id) + public > Long getMtime(Coll coll, L id) { DBCollection dbcoll = fixColl(coll); BasicDBObject found = (BasicDBObject)dbcoll.findOne(new BasicDBObject(ID_FIELD, coll.getIdStrategy().localToRemote(id)), dboKeysMtime); @@ -90,7 +90,7 @@ public class DriverMongo extends DriverAbstract } @Override - public Collection getIds(Coll coll) + public > Collection getIds(Coll coll) { List ret = null; @@ -116,7 +116,7 @@ public class DriverMongo extends DriverAbstract } @Override - public Map getId2mtime(Coll coll) + public > Map getId2mtime(Coll coll) { Map ret = null; @@ -145,7 +145,7 @@ public class DriverMongo extends DriverAbstract } @Override - public Entry load(Coll coll, L id) + public > Entry load(Coll coll, L id) { DBCollection dbcoll = fixColl(coll); BasicDBObject raw = (BasicDBObject)dbcoll.findOne(new BasicDBObject(ID_FIELD, coll.getIdStrategy().localToRemote(id))); @@ -155,7 +155,7 @@ public class DriverMongo extends DriverAbstract } @Override - public Long save(Coll coll, L id, Object rawData) + public > Long save(Coll coll, L id, Object rawData) { DBCollection dbcoll = fixColl(coll); @@ -172,7 +172,7 @@ public class DriverMongo extends DriverAbstract } @Override - public void delete(Coll coll, L id) + public > void delete(Coll coll, L id) { fixColl(coll).remove(new BasicDBObject(ID_FIELD, coll.getIdStrategy().localToRemote(id))); } diff --git a/src/com/massivecraft/mcore5/store/Entity.java b/src/com/massivecraft/mcore5/store/Entity.java index 94d16f10..59762d48 100644 --- a/src/com/massivecraft/mcore5/store/Entity.java +++ b/src/com/massivecraft/mcore5/store/Entity.java @@ -12,17 +12,12 @@ import com.massivecraft.mcore5.xlib.gson.Gson; // Self referencing generic using the "getThis trick". // http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ206 -public abstract class Entity, L> +public abstract class Entity, L extends Comparable> implements Comparable { protected transient Coll coll; protected void setColl(Coll val) { this.coll = val; } public Coll getColl() { return this.coll; } - protected abstract E getThis(); - protected abstract Class getClazz(); - - public abstract E getDefaultInstance(); - public String getUniverse() { Coll coll = this.getColl(); @@ -31,9 +26,10 @@ public abstract class Entity, L> return coll.getUniverse(); } + @SuppressWarnings("unchecked") public L attach(Coll coll) { - return coll.attach(getThis()); + return coll.attach((E) this); } public E detach() @@ -41,7 +37,7 @@ public abstract class Entity, L> Coll coll = this.getColl(); if (coll == null) return null; - return coll.detach(getThis()); + return coll.detach(this); } public boolean attached() @@ -49,7 +45,7 @@ public abstract class Entity, L> Coll coll = this.getColl(); if (coll == null) return false; - return coll.getAll().contains(getThis()); + return coll.getAll().contains(this); } public boolean detached() @@ -61,7 +57,7 @@ public abstract class Entity, L> { Coll coll = this.getColl(); if (coll == null) return null; - return coll.getId(this.getThis()); + return coll.getId(this); } public void changed() @@ -102,18 +98,39 @@ public abstract class Entity, L> Coll coll = this.getColl(); if (coll != null) gson = coll.getMplugin().gson; - return this.getClazz().getSimpleName()+gson.toJson(this, this.getClazz()); - } - - public E loadDefaults() - { - Accessor.get(this.getClazz()).copy(this.getDefaultInstance(), this.getThis()); - return this.getThis(); + return this.getClass().getSimpleName()+gson.toJson(this, this.getClass()); } + @SuppressWarnings("unchecked") public E load(E that) { - Accessor.get(this.getClazz()).copy(that, this.getThis()); - return this.getThis(); + Accessor.get(this.getClass()).copy(that, this); + return (E) this; + } + + @Override + public int compareTo(E that) + { + if (that == null) throw new NullPointerException("You cannot compare with null"); + + if (this.equals(that)) return 0; + + L thisId = this.getId(); + L thatId = that.getId(); + + if (thisId == null) return -1; + if (thatId == null) return +1; + + int ret = thisId.compareTo(thatId); + + // The id's may be the same if these are objects from different collections + // We avoid zero in an ugly way like this. + // TODO: Improve by comparing collections and then databases. + if (ret == 0) + { + ret = -1; + } + + return ret; } } diff --git a/src/com/massivecraft/mcore5/store/ExamineThread.java b/src/com/massivecraft/mcore5/store/ExamineThread.java index a411991c..dbee4c7a 100644 --- a/src/com/massivecraft/mcore5/store/ExamineThread.java +++ b/src/com/massivecraft/mcore5/store/ExamineThread.java @@ -1,6 +1,6 @@ package com.massivecraft.mcore5.store; -public class ExamineThread extends Thread +public class ExamineThread> extends Thread { protected Coll coll; diff --git a/src/com/massivecraft/mcore5/store/MStore.java b/src/com/massivecraft/mcore5/store/MStore.java index d5bd55c8..a08f9c2f 100644 --- a/src/com/massivecraft/mcore5/store/MStore.java +++ b/src/com/massivecraft/mcore5/store/MStore.java @@ -17,9 +17,9 @@ public class MStore drivers.put(driver.getName(), driver); return true; } + public static Driver getDriver(String id) { - return drivers.get(id); } diff --git a/src/com/massivecraft/mcore5/store/idstrategy/IdStrategy.java b/src/com/massivecraft/mcore5/store/idstrategy/IdStrategy.java index 23d30760..6ae79964 100644 --- a/src/com/massivecraft/mcore5/store/idstrategy/IdStrategy.java +++ b/src/com/massivecraft/mcore5/store/idstrategy/IdStrategy.java @@ -11,7 +11,7 @@ import com.massivecraft.mcore5.store.CollInterface; * Thus you will find multiple implementations with the name "ai" (auto increment). * There must be one implementation per driver. */ -public interface IdStrategy +public interface IdStrategy, R> { // The name of the strategy (such as "auto_increment") public String getName(); diff --git a/src/com/massivecraft/mcore5/store/idstrategy/IdStrategyAbstract.java b/src/com/massivecraft/mcore5/store/idstrategy/IdStrategyAbstract.java index 7cb6eaa0..75e38909 100644 --- a/src/com/massivecraft/mcore5/store/idstrategy/IdStrategyAbstract.java +++ b/src/com/massivecraft/mcore5/store/idstrategy/IdStrategyAbstract.java @@ -4,7 +4,7 @@ import java.util.Collection; import com.massivecraft.mcore5.store.CollInterface; -public abstract class IdStrategyAbstract implements IdStrategy +public abstract class IdStrategyAbstract, R> implements IdStrategy { public IdStrategyAbstract(String name, Class localClass, Class remoteClass) { diff --git a/src/com/massivecraft/mcore5/usys/Aspect.java b/src/com/massivecraft/mcore5/usys/Aspect.java index ad64877b..23d954b6 100644 --- a/src/com/massivecraft/mcore5/usys/Aspect.java +++ b/src/com/massivecraft/mcore5/usys/Aspect.java @@ -17,12 +17,6 @@ public class Aspect extends Entity // META // -------------------------------------------- // - @Override protected Aspect getThis() { return this; } - - private final static transient Aspect defaultInstance = new Aspect(); - @Override public Aspect getDefaultInstance(){ return defaultInstance; } - @Override protected Class getClazz() { return Aspect.class; } - public static Aspect get(Object oid) { return AspectColl.i.get(oid); diff --git a/src/com/massivecraft/mcore5/usys/Multiverse.java b/src/com/massivecraft/mcore5/usys/Multiverse.java index 302a4f9d..a3772c02 100644 --- a/src/com/massivecraft/mcore5/usys/Multiverse.java +++ b/src/com/massivecraft/mcore5/usys/Multiverse.java @@ -19,12 +19,6 @@ public class Multiverse extends Entity // META // -------------------------------------------- // - @Override protected Multiverse getThis() { return this; } - - private final static transient Multiverse defaultInstance = new Multiverse(); - @Override public Multiverse getDefaultInstance(){ return defaultInstance; } - @Override protected Class getClazz() { return Multiverse.class; } - public static Multiverse get(Object oid) { return MultiverseColl.i.get(oid); diff --git a/src/com/massivecraft/mcore5/util/MUtil.java b/src/com/massivecraft/mcore5/util/MUtil.java index 0befd400..7a100b92 100644 --- a/src/com/massivecraft/mcore5/util/MUtil.java +++ b/src/com/massivecraft/mcore5/util/MUtil.java @@ -231,21 +231,13 @@ public class MUtil } // -------------------------------------------- // - // LE NICE EQUALS + // LE NICE EQUALS and compare // -------------------------------------------- // public static boolean equals(Object herp, Object derp) { - if (herp == null && derp == null) - { - return true; - } - - if (herp == null || derp == null) - { - return false; - } - + if (herp == null && derp == null) return true; + if (herp == null || derp == null) return false; return herp.equals(derp); }