Minimalizing and simplifying MStore. Also adding default sorting to entities and collections.

This commit is contained in:
Olof Larsson 2013-01-09 09:41:14 +01:00
parent 9a66c7ce2c
commit 514162387f
15 changed files with 84 additions and 85 deletions

View File

@ -9,6 +9,7 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import com.massivecraft.mcore5.MCore; 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.idstrategy.IdStrategy;
import com.massivecraft.mcore5.store.storeadapter.StoreAdapter; import com.massivecraft.mcore5.store.storeadapter.StoreAdapter;
public class Coll<E, L> implements CollInterface<E, L> public class Coll<E, L extends Comparable<? super L>> implements CollInterface<E, L>
{ {
// -------------------------------------------- // // -------------------------------------------- //
// GLOBAL REGISTRY // GLOBAL REGISTRY
@ -72,7 +73,7 @@ public class Coll<E, L> implements CollInterface<E, L>
protected Set<L> ids = Collections.newSetFromMap(new ConcurrentHashMap<L, Boolean>()); protected Set<L> ids = Collections.newSetFromMap(new ConcurrentHashMap<L, Boolean>());
@Override public Collection<L> getIds() { return Collections.unmodifiableCollection(this.ids); } @Override public Collection<L> getIds() { return Collections.unmodifiableCollection(this.ids); }
@Override public Collection<L> getIdsRemote() { return this.getDb().getDriver().getIds(this); } @Override public Collection<L> 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 @Override
public boolean containsId(Object oid) public boolean containsId(Object oid)
{ {
@ -81,8 +82,9 @@ public class Coll<E, L> implements CollInterface<E, L>
return this.ids.contains(id); return this.ids.contains(id);
} }
// We use a ConcurrentSkipListSet here in order for the entities to keep their natural ordering
protected Set<E> entities = Collections.newSetFromMap(new ConcurrentHashMap<E, Boolean>()); // You may want to have your entities implement the Comparable interface
protected Set<E> entities = new ConcurrentSkipListSet<E>();
@Override public Collection<E> getAll() { return Collections.unmodifiableCollection(this.entities); } @Override public Collection<E> getAll() { return Collections.unmodifiableCollection(this.entities); }
@Override public Collection<E> getAll(Predictate<E> where) { return MStoreUtil.uglySQL(this.getAll(), where, null, null, null); } @Override public Collection<E> getAll(Predictate<E> where) { return MStoreUtil.uglySQL(this.getAll(), where, null, null, null); }
@Override public Collection<E> getAll(Predictate<E> where, Comparator<E> orderby) { return MStoreUtil.uglySQL(this.getAll(), where, orderby, null, null); } @Override public Collection<E> getAll(Predictate<E> where, Comparator<E> orderby) { return MStoreUtil.uglySQL(this.getAll(), where, orderby, null, null); }
@ -114,7 +116,7 @@ public class Coll<E, L> implements CollInterface<E, L>
// Get the id for this entity. // Get the id for this entity.
protected Map<E, L> entity2id = new ConcurrentHashMap<E, L>(); protected Map<E, L> entity2id = new ConcurrentHashMap<E, L>();
@Override public Map<E, L> getEntity2id() { return Collections.unmodifiableMap(this.entity2id); } @Override public Map<E, L> 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 @Override
public L fixId(Object oid) public L fixId(Object oid)
@ -228,18 +230,18 @@ public class Coll<E, L> implements CollInterface<E, L>
if (this.ids.contains(id)) return null; 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. // Set this as the coll if possible.
if (entity instanceof Entity) if (entity instanceof Entity)
{ {
((Entity)entity).setColl(this); ((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 // Make note of the change
if (noteChange) if (noteChange)
{ {

View File

@ -9,7 +9,7 @@ import com.massivecraft.mcore5.Predictate;
import com.massivecraft.mcore5.store.idstrategy.IdStrategy; import com.massivecraft.mcore5.store.idstrategy.IdStrategy;
import com.massivecraft.mcore5.store.storeadapter.StoreAdapter; import com.massivecraft.mcore5.store.storeadapter.StoreAdapter;
public interface CollInterface<E, L> public interface CollInterface<E, L extends Comparable<? super L>>
{ {
// -------------------------------------------- // // -------------------------------------------- //
// WHAT DO WE HANDLE? // WHAT DO WE HANDLE?
@ -37,7 +37,7 @@ public interface CollInterface<E, L>
public Collection<L> getIds(); public Collection<L> getIds();
public Collection<L> getIdsRemote(); public Collection<L> getIdsRemote();
public boolean containsId(Object oid); public boolean containsId(Object oid);
public boolean containsEntity(E entity); public boolean containsEntity(Object entity);
public Collection<E> getAll(); public Collection<E> getAll();
public Collection<E> getAll(Predictate<E> where); public Collection<E> getAll(Predictate<E> where);
@ -50,7 +50,7 @@ public interface CollInterface<E, L>
public E get(Object oid, boolean creative); public E get(Object oid, boolean creative);
public Map<E, L> getEntity2id(); public Map<E, L> getEntity2id();
public L getId(E entity); public L getId(Object entity);
public L fixId(Object oid); public L fixId(Object oid);
// -------------------------------------------- // // -------------------------------------------- //

View File

@ -9,7 +9,7 @@ import com.massivecraft.mcore5.usys.Aspect;
import com.massivecraft.mcore5.usys.Multiverse; import com.massivecraft.mcore5.usys.Multiverse;
import com.massivecraft.mcore5.util.MUtil; import com.massivecraft.mcore5.util.MUtil;
public abstract class Colls<C extends Coll<E, L>, E, L> public abstract class Colls<C extends Coll<E, L>, E, L extends Comparable<? super L>>
{ {
protected Map<String, C> name2coll = new HashMap<String, C>(); protected Map<String, C> name2coll = new HashMap<String, C>();

View File

@ -22,7 +22,7 @@ public interface Driver<R>
// This is some sort of database specific id strategy with built in adapter // This is some sort of database specific id strategy with built in adapter
public boolean registerIdStrategy(IdStrategy<?, ?> idStrategy); public boolean registerIdStrategy(IdStrategy<?, ?> idStrategy);
public <L> IdStrategy<L, ?> getIdStrategy(String idStrategyName); public <L extends Comparable<? super L>> IdStrategy<L, ?> getIdStrategy(String idStrategyName);
// Get the default store adapter for the driver. // Get the default store adapter for the driver.
public StoreAdapter getStoreAdapter(); public StoreAdapter getStoreAdapter();
@ -34,25 +34,25 @@ public interface Driver<R>
public Set<String> getCollnames(Db<?> db); public Set<String> getCollnames(Db<?> db);
// Is id X in the collection? // Is id X in the collection?
public <L> boolean containsId(Coll<?, L> coll, L id); public <L extends Comparable<? super L>> boolean containsId(Coll<?, L> coll, L id);
// When was X last altered? // When was X last altered?
public <L> Long getMtime(Coll<?, L> coll, L id); public <L extends Comparable<? super L>> Long getMtime(Coll<?, L> coll, L id);
// What ids are in the collection? // What ids are in the collection?
public <L> Collection<L> getIds(Coll<?, L> coll); public <L extends Comparable<? super L>> Collection<L> getIds(Coll<?, L> coll);
// Return a map of all ids with their corresponding mtimes // Return a map of all ids with their corresponding mtimes
public <L> Map<L, Long> getId2mtime(Coll<?, L> coll); public <L extends Comparable<? super L>> Map<L, Long> getId2mtime(Coll<?, L> coll);
// Load the raw data for X. The second part of the entry is the remote mtime at the load. // Load the raw data for X. The second part of the entry is the remote mtime at the load.
public <L> Entry<R, Long> load(Coll<?, L> coll, L id); public <L extends Comparable<? super L>> Entry<R, Long> load(Coll<?, L> coll, L id);
// Save raw data as X // Save raw data as X
// Return value is the new mtime (we caused the change). // Return value is the new mtime (we caused the change).
// If the mtime is null something failed. // If the mtime is null something failed.
public <L> Long save(Coll<?, L> coll, L id, final Object rawData); public <L extends Comparable<? super L>> Long save(Coll<?, L> coll, L id, final Object rawData);
// Delete X // Delete X
public <L> void delete(Coll<?, L> coll, L id); public <L extends Comparable<? super L>> void delete(Coll<?, L> coll, L id);
} }

View File

@ -26,7 +26,7 @@ public abstract class DriverAbstract<R> implements Driver<R>
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public <L> IdStrategy<L, ?> getIdStrategy(String idStrategyName) public <L extends Comparable<? super L>> IdStrategy<L, ?> getIdStrategy(String idStrategyName)
{ {
IdStrategy<?, ?> idStrategy = idStrategies.get(idStrategyName); IdStrategy<?, ?> idStrategy = idStrategies.get(idStrategyName);
return (IdStrategy<L, ?>) idStrategy; return (IdStrategy<L, ?>) idStrategy;

View File

@ -72,13 +72,13 @@ public class DriverGson extends DriverAbstract<JsonElement>
} }
@Override @Override
public <L> boolean containsId(Coll<?, L> coll, L id) public <L extends Comparable<? super L>> boolean containsId(Coll<?, L> coll, L id)
{ {
return fileFromId(coll, id).isFile(); return fileFromId(coll, id).isFile();
} }
@Override @Override
public <L> Long getMtime(Coll<?, L> coll, L id) public <L extends Comparable<? super L>> Long getMtime(Coll<?, L> coll, L id)
{ {
File file = fileFromId(coll, id); File file = fileFromId(coll, id);
if ( ! file.isFile()) return null; if ( ! file.isFile()) return null;
@ -86,7 +86,7 @@ public class DriverGson extends DriverAbstract<JsonElement>
} }
@Override @Override
public <L> Collection<L> getIds(Coll<?, L> coll) public <L extends Comparable<? super L>> Collection<L> getIds(Coll<?, L> coll)
{ {
List<L> ret = new ArrayList<L>(); List<L> ret = new ArrayList<L>();
@ -105,7 +105,7 @@ public class DriverGson extends DriverAbstract<JsonElement>
} }
@Override @Override
public <L> Map<L, Long> getId2mtime(Coll<?, L> coll) public <L extends Comparable<? super L>> Map<L, Long> getId2mtime(Coll<?, L> coll)
{ {
Map<L, Long> ret = new HashMap<L, Long>(); Map<L, Long> ret = new HashMap<L, Long>();
@ -124,7 +124,7 @@ public class DriverGson extends DriverAbstract<JsonElement>
} }
@Override @Override
public <L> Entry<JsonElement, Long> load(Coll<?, L> coll, L id) public <L extends Comparable<? super L>> Entry<JsonElement, Long> load(Coll<?, L> coll, L id)
{ {
File file = fileFromId(coll, id); File file = fileFromId(coll, id);
Long mtime = file.lastModified(); Long mtime = file.lastModified();
@ -137,7 +137,7 @@ public class DriverGson extends DriverAbstract<JsonElement>
} }
@Override @Override
public <L> Long save(Coll<?, L> coll, L id, Object rawData) public <L extends Comparable<? super L>> Long save(Coll<?, L> coll, L id, Object rawData)
{ {
File file = fileFromId(coll, id); File file = fileFromId(coll, id);
String content = coll.getMplugin().gson.toJson((JsonElement)rawData); String content = coll.getMplugin().gson.toJson((JsonElement)rawData);
@ -146,7 +146,7 @@ public class DriverGson extends DriverAbstract<JsonElement>
} }
@Override @Override
public <L> void delete(Coll<?, L> coll, L id) public <L extends Comparable<? super L>> void delete(Coll<?, L> coll, L id)
{ {
File file = fileFromId(coll, id); File file = fileFromId(coll, id);
file.delete(); file.delete();
@ -168,7 +168,7 @@ public class DriverGson extends DriverAbstract<JsonElement>
return name.substring(0, name.length()-5); return name.substring(0, name.length()-5);
} }
protected static <L> File fileFromId(Coll<?, L> coll, L id) protected static <L extends Comparable<? super L>> File fileFromId(Coll<?, L> coll, L id)
{ {
File collDir = getCollDir(coll); File collDir = getCollDir(coll);
String idString = (String)coll.getIdStrategy().localToRemote(id); String idString = (String)coll.getIdStrategy().localToRemote(id);

View File

@ -72,7 +72,7 @@ public class DriverMongo extends DriverAbstract<BasicDBObject>
} }
@Override @Override
public <L> boolean containsId(Coll<?, L> coll, L id) public <L extends Comparable<? super L>> boolean containsId(Coll<?, L> coll, L id)
{ {
DBCollection dbcoll = fixColl(coll); DBCollection dbcoll = fixColl(coll);
DBCursor cursor = dbcoll.find(new BasicDBObject(ID_FIELD, coll.getIdStrategy().localToRemote(id))); DBCursor cursor = dbcoll.find(new BasicDBObject(ID_FIELD, coll.getIdStrategy().localToRemote(id)));
@ -80,7 +80,7 @@ public class DriverMongo extends DriverAbstract<BasicDBObject>
} }
@Override @Override
public <L> Long getMtime(Coll<?, L> coll, L id) public <L extends Comparable<? super L>> Long getMtime(Coll<?, L> coll, L id)
{ {
DBCollection dbcoll = fixColl(coll); DBCollection dbcoll = fixColl(coll);
BasicDBObject found = (BasicDBObject)dbcoll.findOne(new BasicDBObject(ID_FIELD, coll.getIdStrategy().localToRemote(id)), dboKeysMtime); BasicDBObject found = (BasicDBObject)dbcoll.findOne(new BasicDBObject(ID_FIELD, coll.getIdStrategy().localToRemote(id)), dboKeysMtime);
@ -90,7 +90,7 @@ public class DriverMongo extends DriverAbstract<BasicDBObject>
} }
@Override @Override
public <L> Collection<L> getIds(Coll<?, L> coll) public <L extends Comparable<? super L>> Collection<L> getIds(Coll<?, L> coll)
{ {
List<L> ret = null; List<L> ret = null;
@ -116,7 +116,7 @@ public class DriverMongo extends DriverAbstract<BasicDBObject>
} }
@Override @Override
public <L> Map<L, Long> getId2mtime(Coll<?, L> coll) public <L extends Comparable<? super L>> Map<L, Long> getId2mtime(Coll<?, L> coll)
{ {
Map<L, Long> ret = null; Map<L, Long> ret = null;
@ -145,7 +145,7 @@ public class DriverMongo extends DriverAbstract<BasicDBObject>
} }
@Override @Override
public <L> Entry<BasicDBObject, Long> load(Coll<?, L> coll, L id) public <L extends Comparable<? super L>> Entry<BasicDBObject, Long> load(Coll<?, L> coll, L id)
{ {
DBCollection dbcoll = fixColl(coll); DBCollection dbcoll = fixColl(coll);
BasicDBObject raw = (BasicDBObject)dbcoll.findOne(new BasicDBObject(ID_FIELD, coll.getIdStrategy().localToRemote(id))); BasicDBObject raw = (BasicDBObject)dbcoll.findOne(new BasicDBObject(ID_FIELD, coll.getIdStrategy().localToRemote(id)));
@ -155,7 +155,7 @@ public class DriverMongo extends DriverAbstract<BasicDBObject>
} }
@Override @Override
public <L> Long save(Coll<?, L> coll, L id, Object rawData) public <L extends Comparable<? super L>> Long save(Coll<?, L> coll, L id, Object rawData)
{ {
DBCollection dbcoll = fixColl(coll); DBCollection dbcoll = fixColl(coll);
@ -172,7 +172,7 @@ public class DriverMongo extends DriverAbstract<BasicDBObject>
} }
@Override @Override
public <L> void delete(Coll<?, L> coll, L id) public <L extends Comparable<? super L>> void delete(Coll<?, L> coll, L id)
{ {
fixColl(coll).remove(new BasicDBObject(ID_FIELD, coll.getIdStrategy().localToRemote(id))); fixColl(coll).remove(new BasicDBObject(ID_FIELD, coll.getIdStrategy().localToRemote(id)));
} }

View File

@ -12,17 +12,12 @@ import com.massivecraft.mcore5.xlib.gson.Gson;
// Self referencing generic using the "getThis trick". // Self referencing generic using the "getThis trick".
// http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ206 // http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ206
public abstract class Entity<E extends Entity<E, L>, L> public abstract class Entity<E extends Entity<E, L>, L extends Comparable<? super L>> implements Comparable<E>
{ {
protected transient Coll<E, L> coll; protected transient Coll<E, L> coll;
protected void setColl(Coll<E, L> val) { this.coll = val; } protected void setColl(Coll<E, L> val) { this.coll = val; }
public Coll<E, L> getColl() { return this.coll; } public Coll<E, L> getColl() { return this.coll; }
protected abstract E getThis();
protected abstract Class<E> getClazz();
public abstract E getDefaultInstance();
public String getUniverse() public String getUniverse()
{ {
Coll<E, L> coll = this.getColl(); Coll<E, L> coll = this.getColl();
@ -31,9 +26,10 @@ public abstract class Entity<E extends Entity<E, L>, L>
return coll.getUniverse(); return coll.getUniverse();
} }
@SuppressWarnings("unchecked")
public L attach(Coll<E, L> coll) public L attach(Coll<E, L> coll)
{ {
return coll.attach(getThis()); return coll.attach((E) this);
} }
public E detach() public E detach()
@ -41,7 +37,7 @@ public abstract class Entity<E extends Entity<E, L>, L>
Coll<E, L> coll = this.getColl(); Coll<E, L> coll = this.getColl();
if (coll == null) return null; if (coll == null) return null;
return coll.detach(getThis()); return coll.detach(this);
} }
public boolean attached() public boolean attached()
@ -49,7 +45,7 @@ public abstract class Entity<E extends Entity<E, L>, L>
Coll<E, L> coll = this.getColl(); Coll<E, L> coll = this.getColl();
if (coll == null) return false; if (coll == null) return false;
return coll.getAll().contains(getThis()); return coll.getAll().contains(this);
} }
public boolean detached() public boolean detached()
@ -61,7 +57,7 @@ public abstract class Entity<E extends Entity<E, L>, L>
{ {
Coll<E, L> coll = this.getColl(); Coll<E, L> coll = this.getColl();
if (coll == null) return null; if (coll == null) return null;
return coll.getId(this.getThis()); return coll.getId(this);
} }
public void changed() public void changed()
@ -102,18 +98,39 @@ public abstract class Entity<E extends Entity<E, L>, L>
Coll<E, L> coll = this.getColl(); Coll<E, L> coll = this.getColl();
if (coll != null) gson = coll.getMplugin().gson; if (coll != null) gson = coll.getMplugin().gson;
return this.getClazz().getSimpleName()+gson.toJson(this, this.getClazz()); return this.getClass().getSimpleName()+gson.toJson(this, this.getClass());
}
public E loadDefaults()
{
Accessor.get(this.getClazz()).copy(this.getDefaultInstance(), this.getThis());
return this.getThis();
} }
@SuppressWarnings("unchecked")
public E load(E that) public E load(E that)
{ {
Accessor.get(this.getClazz()).copy(that, this.getThis()); Accessor.get(this.getClass()).copy(that, this);
return this.getThis(); 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;
} }
} }

View File

@ -1,6 +1,6 @@
package com.massivecraft.mcore5.store; package com.massivecraft.mcore5.store;
public class ExamineThread<E, L> extends Thread public class ExamineThread<E, L extends Comparable<? super L>> extends Thread
{ {
protected Coll<E, L> coll; protected Coll<E, L> coll;

View File

@ -17,9 +17,9 @@ public class MStore
drivers.put(driver.getName(), driver); drivers.put(driver.getName(), driver);
return true; return true;
} }
public static Driver<?> getDriver(String id) public static Driver<?> getDriver(String id)
{ {
return drivers.get(id); return drivers.get(id);
} }

View File

@ -11,7 +11,7 @@ import com.massivecraft.mcore5.store.CollInterface;
* Thus you will find multiple implementations with the name "ai" (auto increment). * Thus you will find multiple implementations with the name "ai" (auto increment).
* There must be one implementation per driver. * There must be one implementation per driver.
*/ */
public interface IdStrategy<L, R> public interface IdStrategy<L extends Comparable<? super L>, R>
{ {
// The name of the strategy (such as "auto_increment") // The name of the strategy (such as "auto_increment")
public String getName(); public String getName();

View File

@ -4,7 +4,7 @@ import java.util.Collection;
import com.massivecraft.mcore5.store.CollInterface; import com.massivecraft.mcore5.store.CollInterface;
public abstract class IdStrategyAbstract<L, R> implements IdStrategy<L, R> public abstract class IdStrategyAbstract<L extends Comparable<? super L>, R> implements IdStrategy<L, R>
{ {
public IdStrategyAbstract(String name, Class<L> localClass, Class<R> remoteClass) public IdStrategyAbstract(String name, Class<L> localClass, Class<R> remoteClass)
{ {

View File

@ -17,12 +17,6 @@ public class Aspect extends Entity<Aspect, String>
// META // META
// -------------------------------------------- // // -------------------------------------------- //
@Override protected Aspect getThis() { return this; }
private final static transient Aspect defaultInstance = new Aspect();
@Override public Aspect getDefaultInstance(){ return defaultInstance; }
@Override protected Class<Aspect> getClazz() { return Aspect.class; }
public static Aspect get(Object oid) public static Aspect get(Object oid)
{ {
return AspectColl.i.get(oid); return AspectColl.i.get(oid);

View File

@ -19,12 +19,6 @@ public class Multiverse extends Entity<Multiverse, String>
// META // META
// -------------------------------------------- // // -------------------------------------------- //
@Override protected Multiverse getThis() { return this; }
private final static transient Multiverse defaultInstance = new Multiverse();
@Override public Multiverse getDefaultInstance(){ return defaultInstance; }
@Override protected Class<Multiverse> getClazz() { return Multiverse.class; }
public static Multiverse get(Object oid) public static Multiverse get(Object oid)
{ {
return MultiverseColl.i.get(oid); return MultiverseColl.i.get(oid);

View File

@ -231,21 +231,13 @@ public class MUtil
} }
// -------------------------------------------- // // -------------------------------------------- //
// LE NICE EQUALS // LE NICE EQUALS and compare
// -------------------------------------------- // // -------------------------------------------- //
public static boolean equals(Object herp, Object derp) public static boolean equals(Object herp, Object derp)
{ {
if (herp == null && derp == null) if (herp == null && derp == null) return true;
{ if (herp == null || derp == null) return false;
return true;
}
if (herp == null || derp == null)
{
return false;
}
return herp.equals(derp); return herp.equals(derp);
} }