Internal entities
This commit is contained in:
parent
fe81648eb7
commit
5c416c3a1d
@ -3,6 +3,7 @@ package com.massivecraft.massivecore;
|
||||
import com.massivecraft.massivecore.adapter.AdapterBackstringSet;
|
||||
import com.massivecraft.massivecore.adapter.AdapterBannerPatterns;
|
||||
import com.massivecraft.massivecore.adapter.AdapterEntry;
|
||||
import com.massivecraft.massivecore.adapter.AdapterEntityInternalMap;
|
||||
import com.massivecraft.massivecore.adapter.AdapterInventory;
|
||||
import com.massivecraft.massivecore.adapter.AdapterItemStack;
|
||||
import com.massivecraft.massivecore.adapter.AdapterJsonElement;
|
||||
@ -38,6 +39,7 @@ import com.massivecraft.massivecore.nms.NmsItemStackCreate17R4P;
|
||||
import com.massivecraft.massivecore.ps.PS;
|
||||
import com.massivecraft.massivecore.ps.PSAdapter;
|
||||
import com.massivecraft.massivecore.store.Coll;
|
||||
import com.massivecraft.massivecore.store.EntityInternalMap;
|
||||
import com.massivecraft.massivecore.store.ModificationPollerLocal;
|
||||
import com.massivecraft.massivecore.store.ModificationPollerRemote;
|
||||
import com.massivecraft.massivecore.util.BoardUtil;
|
||||
@ -165,6 +167,9 @@ public class MassiveCore extends MassivePlugin
|
||||
ret.registerTypeAdapter(Inventory.class, AdapterInventory.get());
|
||||
ret.registerTypeAdapter(PlayerInventory.class, AdapterPlayerInventory.get());
|
||||
|
||||
// Storage
|
||||
ret.registerTypeAdapter(EntityInternalMap.class, AdapterEntityInternalMap.get());
|
||||
|
||||
// Return
|
||||
return ret;
|
||||
}
|
||||
|
@ -0,0 +1,70 @@
|
||||
package com.massivecraft.massivecore.adapter;
|
||||
|
||||
import com.massivecraft.massivecore.store.EntityInternal;
|
||||
import com.massivecraft.massivecore.store.EntityInternalMap;
|
||||
import com.massivecraft.massivecore.xlib.gson.*;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class AdapterEntityInternalMap implements JsonDeserializer<EntityInternalMap<?>>, JsonSerializer<EntityInternalMap<?>>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE & CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static final AdapterEntityInternalMap i = new AdapterEntityInternalMap();
|
||||
public static AdapterEntityInternalMap get() { return i; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// OVERRIDE
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(EntityInternalMap<?> src, Type type, JsonSerializationContext context)
|
||||
{
|
||||
// NULL
|
||||
if (src == null) return JsonNull.INSTANCE;
|
||||
|
||||
// Get value
|
||||
Map<String, ?> contents = src.getIdToEntity();
|
||||
|
||||
// Create ret
|
||||
JsonElement ret = context.serialize(contents);
|
||||
|
||||
// Return Ret
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityInternalMap<?> deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
// NULL
|
||||
if (json == null) return null;
|
||||
if (json instanceof JsonNull) return null;
|
||||
|
||||
// Get type
|
||||
Class<? extends EntityInternal> entityType = (Class) ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||
|
||||
// Create ret
|
||||
EntityInternalMap ret = new EntityInternalMap<>(entityType);
|
||||
|
||||
// Fill ret
|
||||
JsonObject jsonObject = (JsonObject) json;
|
||||
for (Entry<String, JsonElement> entry : jsonObject.entrySet())
|
||||
{
|
||||
String id = entry.getKey();
|
||||
JsonElement value = entry.getValue();
|
||||
|
||||
EntityInternal obj = context.deserialize(value, entityType);
|
||||
|
||||
ret.getIdToEntityRaw().put(id, obj);
|
||||
}
|
||||
|
||||
// Return ret
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
@ -854,17 +854,17 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand
|
||||
}
|
||||
|
||||
public void setDescPermission(String descPermission) { this.descPermission = descPermission; }
|
||||
public String getDescPermission()
|
||||
{
|
||||
if (this.descPermission != null) return this.descPermission;
|
||||
// Otherwise we try to find one.
|
||||
for (Requirement requirement : this.getRequirements())
|
||||
public String getDescPermission()
|
||||
{
|
||||
if ( ! (requirement instanceof RequirementHasPerm)) continue;
|
||||
return ((RequirementHasPerm)requirement).getPermissionId();
|
||||
if (this.descPermission != null) return this.descPermission;
|
||||
// Otherwise we try to find one.
|
||||
for (Requirement requirement : this.getRequirements())
|
||||
{
|
||||
if ( ! (requirement instanceof RequirementHasPerm)) continue;
|
||||
return ((RequirementHasPerm)requirement).getPermissionId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setHelp(List<?> val) { this.help = val; }
|
||||
public void setHelp(Object... val) { this.help = Arrays.asList(val); }
|
||||
|
@ -3,12 +3,9 @@ package com.massivecraft.massivecore.store;
|
||||
import com.massivecraft.massivecore.MassiveCore;
|
||||
import com.massivecraft.massivecore.MassiveCoreMConf;
|
||||
import com.massivecraft.massivecore.MassivePlugin;
|
||||
import com.massivecraft.massivecore.Named;
|
||||
import com.massivecraft.massivecore.collections.MassiveList;
|
||||
import com.massivecraft.massivecore.comparator.ComparatorNaturalOrder;
|
||||
import com.massivecraft.massivecore.mixin.MixinModification;
|
||||
import com.massivecraft.massivecore.predicate.Predicate;
|
||||
import com.massivecraft.massivecore.predicate.PredicateEqualsIgnoreCase;
|
||||
import com.massivecraft.massivecore.store.migrator.MigratorUtil;
|
||||
import com.massivecraft.massivecore.util.ReflectionUtil;
|
||||
import com.massivecraft.massivecore.util.Txt;
|
||||
@ -131,249 +128,20 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
|
||||
// -------------------------------------------- //
|
||||
|
||||
// Loaded
|
||||
protected Map<String, E> id2entity;
|
||||
protected Map<String, E> idToEntity;
|
||||
|
||||
@Override
|
||||
public String fixId(Object oid)
|
||||
{
|
||||
if (oid == null) return null;
|
||||
@Override public Map<String, E> getIdToEntityRaw() { return this.idToEntity; }
|
||||
|
||||
String ret = null;
|
||||
if (oid instanceof String) ret = (String) oid;
|
||||
else if (oid.getClass() == this.getEntityClass()) ret = ((Entity<?>) oid).getId();
|
||||
if (ret == null) return null;
|
||||
|
||||
return this.isLowercasing() ? ret.toLowerCase() : ret;
|
||||
}
|
||||
|
||||
@Override public Map<String, E> getId2entity() { return Collections.unmodifiableMap(this.id2entity); }
|
||||
@Override
|
||||
public E getFixed(String id, boolean creative)
|
||||
{
|
||||
return this.getFixed(id, creative, true);
|
||||
}
|
||||
protected E getFixed(String id, boolean creative, boolean noteModification)
|
||||
{
|
||||
if (id == null) return null;
|
||||
E ret = this.id2entity.get(id);
|
||||
if (ret != null) return ret;
|
||||
if ( ! creative) return null;
|
||||
return this.create(id, noteModification);
|
||||
}
|
||||
|
||||
@Override public Collection<String> getIds() { return Collections.unmodifiableCollection(this.id2entity.keySet()); }
|
||||
@Override public Collection<String> getIdsRemote() { return this.getDb().getIds(this); }
|
||||
@Override
|
||||
public boolean containsIdFixed(String id)
|
||||
{
|
||||
if (id == null) return false;
|
||||
return this.id2entity.containsKey(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsEntity(Object entity)
|
||||
{
|
||||
return this.id2entity.containsValue(entity);
|
||||
}
|
||||
|
||||
@Override public Collection<E> getAll()
|
||||
{
|
||||
return Collections.unmodifiableCollection(this.id2entity.values());
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// BEHAVIOR
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected boolean creative;
|
||||
@Override public boolean isCreative() { return this.creative; }
|
||||
@Override public void setCreative(boolean creative) { this.creative = creative; }
|
||||
|
||||
// "Lowercasing" means that the ids are always converted to lower case when fixed.
|
||||
// This is highly recommended for sender colls.
|
||||
// The senderIds are case insensitive by nature and some times you simply can't know the correct casing.
|
||||
protected boolean lowercasing;
|
||||
@Override public boolean isLowercasing() { return this.lowercasing; }
|
||||
@Override public void setLowercasing(boolean lowercasing) { this.lowercasing = lowercasing; }
|
||||
|
||||
// Should that instance be saved or not?
|
||||
// If it is default it should not be saved.
|
||||
@Override
|
||||
public boolean isDefault(E entity)
|
||||
{
|
||||
return entity.isDefault();
|
||||
}
|
||||
|
||||
// What entity version do we want?
|
||||
protected final int entityTargetVersion;
|
||||
@Override public int getEntityTargetVersion() { return this.entityTargetVersion; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// COPY AND CREATE
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public void copy(E efrom, E eto)
|
||||
{
|
||||
if (efrom == null) throw new NullPointerException("efrom");
|
||||
if (eto == null) throw new NullPointerException("eto");
|
||||
|
||||
eto.load(efrom);
|
||||
}
|
||||
|
||||
// This simply creates and returns a new instance
|
||||
// It does not detach/attach or anything. Just creates a new instance.
|
||||
@Override
|
||||
public E createNewInstance()
|
||||
{
|
||||
try
|
||||
{
|
||||
return this.getEntityClass().newInstance();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Create new instance with the requested id
|
||||
@Override
|
||||
public synchronized E create(Object oid)
|
||||
{
|
||||
return this.create(oid, true);
|
||||
}
|
||||
|
||||
public synchronized E create(Object oid, boolean noteModification)
|
||||
{
|
||||
E entity = this.createNewInstance();
|
||||
if (this.attach(entity, oid, noteModification) == null) return null;
|
||||
return entity;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ATTACH AND DETACH
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public String attach(E entity, Object oid)
|
||||
{
|
||||
return this.attach(entity, oid, true);
|
||||
}
|
||||
|
||||
protected synchronized String attach(E entity, Object oid, boolean noteModification)
|
||||
{
|
||||
// Check entity
|
||||
if (entity == null) return null;
|
||||
if (entity.attached()) return entity.getId();
|
||||
|
||||
String id;
|
||||
// Check/Fix id
|
||||
if (oid == null)
|
||||
{
|
||||
id = MStore.createId();
|
||||
}
|
||||
else
|
||||
{
|
||||
id = this.fixId(oid);
|
||||
if (id == null) return null;
|
||||
if (this.id2entity.containsKey(id)) return null;
|
||||
}
|
||||
|
||||
// PRE
|
||||
this.preAttach(entity, id);
|
||||
|
||||
// Add entity reference info
|
||||
entity.setColl(this);
|
||||
entity.setId(id);
|
||||
|
||||
// Attach
|
||||
this.id2entity.put(id, entity);
|
||||
|
||||
// Identify Modification
|
||||
if (noteModification)
|
||||
{
|
||||
this.identifiedModifications.put(id, Modification.LOCAL_ATTACH);
|
||||
}
|
||||
|
||||
// POST
|
||||
this.postAttach(entity, id);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E detachEntity(E entity)
|
||||
{
|
||||
if (entity == null) throw new NullPointerException("entity");
|
||||
|
||||
String id = entity.getId();
|
||||
if (id == null)
|
||||
{
|
||||
// It seems the entity is already detached.
|
||||
// In such case just silently return it.
|
||||
return entity;
|
||||
}
|
||||
|
||||
this.detachFixed(entity, id);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E detachIdFixed(String id)
|
||||
{
|
||||
if (id == null) throw new NullPointerException("id");
|
||||
|
||||
E e = this.get(id, false);
|
||||
if (e == null) return null;
|
||||
|
||||
this.detachFixed(e, id);
|
||||
return e;
|
||||
}
|
||||
|
||||
private void detachFixed(E entity, String id)
|
||||
{
|
||||
if (entity == null) throw new NullPointerException("entity");
|
||||
if (id == null) throw new NullPointerException("id");
|
||||
|
||||
// PRE
|
||||
this.preDetach(entity, id);
|
||||
|
||||
// Remove @ local
|
||||
this.removeAtLocalFixed(id);
|
||||
|
||||
// Identify Modification
|
||||
this.identifiedModifications.put(id, Modification.LOCAL_DETACH);
|
||||
|
||||
// POST
|
||||
this.postDetach(entity, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preAttach(E entity, String id)
|
||||
{
|
||||
entity.preAttach(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postAttach(E entity, String id)
|
||||
{
|
||||
entity.postAttach(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preDetach(E entity, String id)
|
||||
{
|
||||
entity.preDetach(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDetach(E entity, String id)
|
||||
{
|
||||
entity.postDetach(id);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IDENTIFIED MODIFICATIONS
|
||||
// -------------------------------------------- //
|
||||
@ -438,12 +206,12 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
|
||||
|
||||
this.removeIdentifiedModificationFixed(id);
|
||||
|
||||
E entity = this.id2entity.remove(id);
|
||||
E entity = this.idToEntity.remove(id);
|
||||
if (entity == null) return null;
|
||||
entity.clearSyncLogFields();
|
||||
|
||||
// Remove entity reference info
|
||||
entity.setColl(null);
|
||||
entity.setContainer(null);
|
||||
entity.setId(null);
|
||||
|
||||
return entity;
|
||||
@ -467,7 +235,7 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
|
||||
|
||||
this.removeIdentifiedModificationFixed(id);
|
||||
|
||||
E entity = this.id2entity.get(id);
|
||||
E entity = this.idToEntity.get(id);
|
||||
if (entity == null) return;
|
||||
entity.clearSyncLogFields();
|
||||
|
||||
@ -623,7 +391,7 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
|
||||
// }
|
||||
if (current != null && current.hasTopPriority()) return current;
|
||||
|
||||
E localEntity = this.id2entity.get(id);
|
||||
E localEntity = this.idToEntity.get(id);
|
||||
if (remoteMtime == null && remote)
|
||||
{
|
||||
// TODO: This is slow
|
||||
@ -713,7 +481,7 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
|
||||
Modification actualModification = this.examineIdFixed(id, remoteMtime, true, true);
|
||||
if (MassiveCoreMConf.get().warnOnLocalAlter && modification == Modification.UNKNOWN_LOG && actualModification.isModified())
|
||||
{
|
||||
E entity = this.id2entity.get(id);
|
||||
E entity = this.idToEntity.get(id);
|
||||
if (entity != null)
|
||||
{
|
||||
this.logModification(entity, actualModification);
|
||||
@ -831,10 +599,10 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
|
||||
Map<String, Long> id2RemoteMtime = this.getDb().getId2mtime(this);
|
||||
|
||||
// Java 8
|
||||
//this.id2entity.keySet().forEach(id -> id2RemoteMtime.putIfAbsent(id, 0));
|
||||
//this.idToEntity.keySet().forEach(id -> id2RemoteMtime.putIfAbsent(id, 0));
|
||||
|
||||
// Java 8 >
|
||||
for (String id : this.id2entity.keySet())
|
||||
for (String id : this.idToEntity.keySet())
|
||||
{
|
||||
if (id2RemoteMtime.containsKey(id)) continue;
|
||||
id2RemoteMtime.put(id, 0L);
|
||||
@ -859,7 +627,7 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
|
||||
@Override
|
||||
public void identifyLocalModifications(Modification veto)
|
||||
{
|
||||
for (String id : id2entity.keySet())
|
||||
for (String id : idToEntity.keySet())
|
||||
{
|
||||
this.identifyLocalModificationFixed(id, veto);
|
||||
}
|
||||
@ -883,10 +651,10 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
|
||||
//Note: We must also check local ids, in case of remote detach.
|
||||
|
||||
// Java 8
|
||||
//this.id2entity.keySet().forEach(id -> id2RemoteMtime.putIfAbsent(id, 0));
|
||||
//this.idToEntity.keySet().forEach(id -> id2RemoteMtime.putIfAbsent(id, 0));
|
||||
|
||||
// Java 8 >
|
||||
for (String id : this.id2entity.keySet())
|
||||
for (String id : this.idToEntity.keySet())
|
||||
{
|
||||
if (id2RemoteMtime.containsKey(id)) continue;
|
||||
id2RemoteMtime.put(id, 0L);
|
||||
@ -996,7 +764,7 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
|
||||
this.collDriverObject = db.createCollDriverObject(this);
|
||||
|
||||
// Collections
|
||||
this.id2entity = new ConcurrentHashMap<>();
|
||||
this.idToEntity = new ConcurrentHashMap<>();
|
||||
this.identifiedModifications = new ConcurrentHashMap<>();
|
||||
|
||||
// Migration
|
||||
@ -1075,6 +843,12 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
|
||||
return MStore.getDb();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Coll<E> getColl()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ACTIVE
|
||||
// -------------------------------------------- //
|
||||
@ -1085,6 +859,8 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
|
||||
return name2instance.containsKey(this.getName());
|
||||
}
|
||||
|
||||
@Override public boolean isLive() { return this.isActive(); }
|
||||
|
||||
@Override
|
||||
public void setActive(boolean active)
|
||||
{
|
||||
@ -1141,31 +917,4 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
|
||||
this.setActive(plugin != null);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// NAME UTILITIES
|
||||
// -------------------------------------------- //
|
||||
|
||||
public E getByName(String name)
|
||||
{
|
||||
if (name == null) throw new NullPointerException("name");
|
||||
|
||||
Predicate<String> predicate = PredicateEqualsIgnoreCase.get(name);
|
||||
for (E entity : this.getAll())
|
||||
{
|
||||
if (entity == null) continue;
|
||||
|
||||
if ( ! (entity instanceof Named)) continue;
|
||||
Named named = (Named)entity;
|
||||
|
||||
if (predicate.apply(named.getName())) return entity;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isNameTaken(String str)
|
||||
{
|
||||
return this.getByName(str) != null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,16 +1,11 @@
|
||||
package com.massivecraft.massivecore.store;
|
||||
|
||||
import com.massivecraft.massivecore.predicate.Predicate;
|
||||
import com.massivecraft.massivecore.util.MUtil;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
|
||||
public abstract class CollAbstract<E extends Entity<E>> implements CollInterface<E>
|
||||
public abstract class CollAbstract<E extends Entity<E>> extends EntityContainerAbstract<E> implements CollInterface<E>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// WHAT DO WE HANDLE?
|
||||
@ -22,140 +17,6 @@ public abstract class CollAbstract<E extends Entity<E>> implements CollInterface
|
||||
return this.getId();
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SUPPORTING SYSTEM
|
||||
// -------------------------------------------- //
|
||||
// This is all placed in the implementation.
|
||||
|
||||
// -------------------------------------------- //
|
||||
// STORAGE
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public String fixIdOrThrow(Object oid) throws IllegalArgumentException
|
||||
{
|
||||
String ret = this.fixId(oid);
|
||||
if (ret == null) throw new IllegalArgumentException(String.valueOf(oid) + " is not a valid id.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(Object oid)
|
||||
{
|
||||
return this.getFixed(this.fixId(oid));
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(Object oid, boolean creative)
|
||||
{
|
||||
return this.getFixed(this.fixId(oid), creative);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getFixed(String id)
|
||||
{
|
||||
return this.getFixed(id, this.isCreative());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsId(Object oid)
|
||||
{
|
||||
return this.containsIdFixed(this.fixId(oid));
|
||||
}
|
||||
|
||||
@Override public List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Comparator<? super E> orderby, Integer limit, Integer offset) { return MUtil.transform(this.getAll(oids), where, orderby, limit, offset); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Comparator<? super E> orderby, Integer limit) { return MUtil.transform(this.getAll(oids), where, orderby, limit); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Comparator<? super E> orderby) { return MUtil.transform(this.getAll(oids), where, orderby); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Integer limit, Integer offset) { return MUtil.transform(this.getAll(oids), where, limit, offset); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Integer limit) { return MUtil.transform(this.getAll(oids), where, limit); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Comparator<? super E> orderby, Integer limit, Integer offset) { return MUtil.transform(this.getAll(oids), limit, offset); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Comparator<? super E> orderby, Integer limit) { return MUtil.transform(this.getAll(oids), limit); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Predicate<? super E> where) { return MUtil.transform(this.getAll(oids), where); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Comparator<? super E> orderby) { return MUtil.transform(this.getAll(oids), orderby); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Integer limit, Integer offset) { return MUtil.transform(this.getAll(oids), limit, offset); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Integer limit) { return MUtil.transform(this.getAll(oids), limit); }
|
||||
|
||||
@Override public List<E> getAll(Iterable<?> oids)
|
||||
{
|
||||
// Return Create
|
||||
List<E> ret = new ArrayList<>();
|
||||
|
||||
// Return Fill
|
||||
for (Object oid : oids)
|
||||
{
|
||||
E e = this.get(oid);
|
||||
if (e == null) continue;
|
||||
ret.add(e);
|
||||
}
|
||||
|
||||
// Return Return
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override public List<E> getAll(Predicate<? super E> where, Comparator<? super E> orderby, Integer limit, Integer offset) { return MUtil.transform(this.getAll(), where, orderby, limit, offset); }
|
||||
@Override public List<E> getAll(Predicate<? super E> where, Comparator<? super E> orderby, Integer limit) { return MUtil.transform(this.getAll(), where, orderby, limit); }
|
||||
@Override public List<E> getAll(Predicate<? super E> where, Comparator<? super E> orderby) { return MUtil.transform(this.getAll(), where, orderby); }
|
||||
@Override public List<E> getAll(Predicate<? super E> where, Integer limit, Integer offset) { return MUtil.transform(this.getAll(), where, limit, offset); }
|
||||
@Override public List<E> getAll(Predicate<? super E> where, Integer limit) { return MUtil.transform(this.getAll(), where, limit); }
|
||||
@Override public List<E> getAll(Comparator<? super E> orderby, Integer limit, Integer offset) { return MUtil.transform(this.getAll(), limit, offset); }
|
||||
@Override public List<E> getAll(Comparator<? super E> orderby, Integer limit) { return MUtil.transform(this.getAll(), limit); }
|
||||
@Override public List<E> getAll(Predicate<? super E> where) { return MUtil.transform(this.getAll(), where); }
|
||||
@Override public List<E> getAll(Comparator<? super E> orderby) { return MUtil.transform(this.getAll(), orderby); }
|
||||
@Override public List<E> getAll(Integer limit, Integer offset) { return MUtil.transform(this.getAll(), limit, offset); }
|
||||
@Override public List<E> getAll(Integer limit) { return MUtil.transform(this.getAll(), limit); }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// BEHAVIOR
|
||||
// -------------------------------------------- //
|
||||
// This is all placed in the implementation.
|
||||
|
||||
// -------------------------------------------- //
|
||||
// COPY AND CREATE
|
||||
// -------------------------------------------- //
|
||||
|
||||
// Create new instance with automatic id
|
||||
@Override
|
||||
public E create()
|
||||
{
|
||||
return this.create(null);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ATTACH AND DETACH
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public String attach(E entity)
|
||||
{
|
||||
return this.attach(entity, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E detachId(Object oid)
|
||||
{
|
||||
if (oid == null) throw new NullPointerException("oid");
|
||||
return this.detachIdFixed(this.fixIdOrThrow(oid));
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IDENTIFIED MODIFICATIONS
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public void putIdentifiedModification(Object oid, Modification modification)
|
||||
{
|
||||
if (oid == null) throw new NullPointerException("oid");
|
||||
this.putIdentifiedModificationFixed(this.fixIdOrThrow(oid), modification);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeIdentifiedModification(Object oid)
|
||||
{
|
||||
if (oid == null) throw new NullPointerException("oid");
|
||||
this.removeIdentifiedModificationFixed(this.fixIdOrThrow(oid));
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SYNC LOG
|
||||
// -------------------------------------------- //
|
||||
@ -242,14 +103,4 @@ public abstract class CollAbstract<E extends Entity<E>> implements CollInterface
|
||||
return this.syncIdFixed(id, modification, null);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SYNC RUNNABLES / SCHEDULING
|
||||
// -------------------------------------------- //
|
||||
// This is all in the implementation
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
// This is all in the implementation;
|
||||
|
||||
}
|
||||
|
@ -4,16 +4,13 @@ import com.massivecraft.massivecore.Active;
|
||||
import com.massivecraft.massivecore.Identified;
|
||||
import com.massivecraft.massivecore.MassivePlugin;
|
||||
import com.massivecraft.massivecore.Named;
|
||||
import com.massivecraft.massivecore.predicate.Predicate;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public interface CollInterface<E extends Entity<E>> extends Named, Active, Identified
|
||||
public interface CollInterface<E extends Entity<E>> extends Named, Active, Identified, EntityContainer<E>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// WHAT DO WE HANDLE?
|
||||
@ -42,117 +39,18 @@ public interface CollInterface<E extends Entity<E>> extends Named, Active, Ident
|
||||
// STORAGE
|
||||
// -------------------------------------------- //
|
||||
|
||||
String fixId(Object oid);
|
||||
String fixIdOrThrow(Object oid) throws IllegalArgumentException;
|
||||
|
||||
Map<String, E> getId2entity();
|
||||
E get(Object oid);
|
||||
E get(Object oid, boolean creative);
|
||||
E getFixed(String id);
|
||||
E getFixed(String id, boolean creative);
|
||||
Collection<String> getIds();
|
||||
Collection<String> getIdsRemote();
|
||||
boolean containsId(Object oid);
|
||||
boolean containsIdFixed(String id);
|
||||
|
||||
boolean containsEntity(Object entity);
|
||||
|
||||
Collection<E> getAll();
|
||||
|
||||
List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Comparator<? super E> orderby, Integer limit, Integer offset);
|
||||
List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Comparator<? super E> orderby, Integer limit);
|
||||
List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Comparator<? super E> orderby);
|
||||
List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Integer limit, Integer offset);
|
||||
List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Integer limit);
|
||||
List<E> getAll(Iterable<?> oids, Comparator<? super E> orderby, Integer limit, Integer offset);
|
||||
List<E> getAll(Iterable<?> oids, Comparator<? super E> orderby, Integer limit);
|
||||
List<E> getAll(Iterable<?> oids, Predicate<? super E> where);
|
||||
List<E> getAll(Iterable<?> oids, Comparator<? super E> orderby);
|
||||
List<E> getAll(Iterable<?> oids, Integer limit, Integer offset);
|
||||
List<E> getAll(Iterable<?> oids, Integer limit);
|
||||
List<E> getAll(Iterable<?> oids);
|
||||
|
||||
List<E> getAll(Predicate<? super E> where, Comparator<? super E> orderby, Integer limit, Integer offset);
|
||||
List<E> getAll(Predicate<? super E> where, Comparator<? super E> orderby, Integer limit);
|
||||
List<E> getAll(Predicate<? super E> where, Comparator<? super E> orderby);
|
||||
List<E> getAll(Predicate<? super E> where, Integer limit, Integer offset);
|
||||
List<E> getAll(Predicate<? super E> where, Integer limit);
|
||||
List<E> getAll(Comparator<? super E> orderby, Integer limit, Integer offset);
|
||||
List<E> getAll(Comparator<? super E> orderby, Integer limit);
|
||||
List<E> getAll(Predicate<? super E> where);
|
||||
List<E> getAll(Comparator<? super E> orderby);
|
||||
List<E> getAll(Integer limit, Integer offset);
|
||||
List<E> getAll(Integer limit);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// BEHAVIOR
|
||||
// -------------------------------------------- //
|
||||
|
||||
boolean isCreative();
|
||||
void setCreative(boolean creative);
|
||||
|
||||
boolean isLowercasing();
|
||||
void setLowercasing(boolean lowercasing);
|
||||
|
||||
// A default entity will not be saved.
|
||||
// This is often used together with creative collections to save disc space.
|
||||
boolean isDefault(E entity);
|
||||
|
||||
int getEntityTargetVersion();
|
||||
|
||||
// -------------------------------------------- //
|
||||
// COPY AND CREATE
|
||||
// -------------------------------------------- //
|
||||
|
||||
void copy(E fromo, E too);
|
||||
|
||||
// This simply creates and returns a new instance
|
||||
// It does not detach/attach or anything. Just creates a new instance.
|
||||
E createNewInstance();
|
||||
|
||||
// Create new instance with automatic id
|
||||
E create();
|
||||
// Create new instance with the requested id
|
||||
E create(Object oid);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ATTACH AND DETACH
|
||||
// -------------------------------------------- //
|
||||
|
||||
String attach(E entity);
|
||||
String attach(E entity, Object oid);
|
||||
|
||||
E detachEntity(E entity);
|
||||
E detachId(Object oid);
|
||||
E detachIdFixed(String id);
|
||||
|
||||
void preAttach(E entity, String id);
|
||||
void postAttach(E entity, String id);
|
||||
|
||||
void preDetach(E entity, String id);
|
||||
void postDetach(E entity, String id);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IDENTIFIED MODIFICATIONS
|
||||
// -------------------------------------------- //
|
||||
|
||||
void putIdentifiedModification(Object oid, Modification modification);
|
||||
void putIdentifiedModificationFixed(String id, Modification modification);
|
||||
|
||||
void removeIdentifiedModification(Object oid);
|
||||
void removeIdentifiedModificationFixed(String id);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SYNC LOG
|
||||
// -------------------------------------------- //
|
||||
|
||||
/*
|
||||
public Map<L, Long> lastMtime();
|
||||
public Map<L, Object> lastRaw();
|
||||
public Set<L> lastDefault();
|
||||
public void clearSynclog(Object oid);
|
||||
*/
|
||||
|
||||
Map<String, Long> getSyncMap(boolean in);
|
||||
long getSyncCountFixed(String name, boolean in);
|
||||
void addSyncCountFixed(String name, boolean in);
|
||||
@ -162,13 +60,11 @@ public interface CollInterface<E extends Entity<E>> extends Named, Active, Ident
|
||||
// -------------------------------------------- //
|
||||
|
||||
// oid
|
||||
E removeAtLocal(Object oid);
|
||||
void removeAtRemote(Object oid);
|
||||
void saveToRemote(Object oid);
|
||||
void loadFromRemote(Object oid, Entry<JsonObject, Long> remoteEntry);
|
||||
|
||||
// Fixed id
|
||||
E removeAtLocalFixed(String id);
|
||||
void removeAtRemoteFixed(String id);
|
||||
void saveToRemoteFixed(String id);
|
||||
void loadFromRemoteFixed(String id, Entry<JsonObject, Long> remoteEntry);
|
||||
|
@ -1,13 +1,7 @@
|
||||
package com.massivecraft.massivecore.store;
|
||||
|
||||
import com.massivecraft.massivecore.Identified;
|
||||
import com.massivecraft.massivecore.MassiveCore;
|
||||
import com.massivecraft.massivecore.store.accessor.Accessor;
|
||||
import com.massivecraft.massivecore.xlib.gson.Gson;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -16,23 +10,17 @@ import java.util.Objects;
|
||||
|
||||
// Self referencing generic.
|
||||
// http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ206
|
||||
public class Entity<E extends Entity<E>> implements Identified
|
||||
public class Entity<E extends Entity<E>> extends EntityInternal<E>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected transient Coll<E> coll;
|
||||
protected void setColl(Coll<E> val) { this.coll = val; }
|
||||
public Coll<E> getColl() { return this.coll; }
|
||||
|
||||
protected transient String id;
|
||||
protected void setId(String id) { this.id = id; }
|
||||
@Override public String getId() { return this.id; }
|
||||
public Coll<?> getColl() { return (Coll<?>) this.getContainer(); }
|
||||
|
||||
public String getUniverse()
|
||||
{
|
||||
Coll<E> coll = this.getColl();
|
||||
Coll<?> coll = this.getColl();
|
||||
if (coll == null) return null;
|
||||
|
||||
return coll.getUniverse();
|
||||
@ -62,154 +50,43 @@ public class Entity<E extends Entity<E>> implements Identified
|
||||
// -------------------------------------------- //
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public String attach(Coll<E> coll)
|
||||
public String attach(EntityContainer<E> container)
|
||||
{
|
||||
return coll.attach((E) this);
|
||||
if (!(container instanceof Coll)) throw new IllegalArgumentException(container.getClass().getName() + " is not a Coll.");
|
||||
return container.attach((E) this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public E detach()
|
||||
{
|
||||
Coll<E> coll = this.getColl();
|
||||
EntityContainer<E> coll = this.getContainer();
|
||||
if (coll == null) return (E)this;
|
||||
|
||||
return coll.detachEntity((E) this);
|
||||
}
|
||||
|
||||
public boolean attached()
|
||||
{
|
||||
return this.getColl() != null && this.getId() != null;
|
||||
}
|
||||
|
||||
public boolean detached()
|
||||
{
|
||||
return ! this.attached();
|
||||
}
|
||||
|
||||
|
||||
public void preAttach(String id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void postAttach(String id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void preDetach(String id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void postDetach(String id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SYNC AND IO ACTIONS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public boolean isLive()
|
||||
{
|
||||
String id = this.getId();
|
||||
if (id == null) return false;
|
||||
|
||||
Coll<E> coll = this.getColl();
|
||||
if (coll == null) return false;
|
||||
|
||||
if ( ! coll.isActive()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void changed()
|
||||
{
|
||||
if ( ! this.isLive()) return;
|
||||
|
||||
//System.out.println(this.getColl().getName() + ": " +this.getId() + " was modified locally");
|
||||
|
||||
// UNKNOWN is very unimportant really.
|
||||
// LOCAL_ATTACH is for example much more important and should not be replaced.
|
||||
this.getColl().putIdentifiedModificationFixed(this.getId(), Modification.UNKNOWN);
|
||||
}
|
||||
|
||||
public Modification sync()
|
||||
{
|
||||
if ( ! this.isLive()) return Modification.UNKNOWN;
|
||||
if (!this.isLive()) return Modification.UNKNOWN;
|
||||
return this.getColl().syncIdFixed(id);
|
||||
}
|
||||
|
||||
public void saveToRemote()
|
||||
{
|
||||
if ( ! this.isLive()) return;
|
||||
if (!this.isLive()) return;
|
||||
|
||||
this.getColl().saveToRemoteFixed(id);
|
||||
}
|
||||
|
||||
public void loadFromRemote()
|
||||
{
|
||||
if ( ! this.isLive()) return;
|
||||
if (!this.isLive()) return;
|
||||
|
||||
this.getColl().loadFromRemoteFixed(id, null);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// DERPINGTON
|
||||
// -------------------------------------------- //
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public E load(E that)
|
||||
{
|
||||
Accessor.get(this.getClass()).copy(that, this);
|
||||
return (E) this;
|
||||
}
|
||||
|
||||
public boolean isDefault()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONVENIENCE: DATABASE
|
||||
// -------------------------------------------- //
|
||||
|
||||
// GENERIC
|
||||
public <T> T convertGet(T value, T standard)
|
||||
{
|
||||
return value != null ? value : standard;
|
||||
}
|
||||
|
||||
public <T> T convertSet(T value, T standard)
|
||||
{
|
||||
this.changed();
|
||||
return Objects.equals(value, standard) ? null : value;
|
||||
}
|
||||
|
||||
// BOOLEAN
|
||||
public boolean convertGet(Boolean value)
|
||||
{
|
||||
return convertGet(value, false);
|
||||
}
|
||||
|
||||
public Boolean convertSet(Boolean value)
|
||||
{
|
||||
return convertSet(value, false);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// STANDARDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
Gson gson = MassiveCore.gson;
|
||||
Coll<E> coll = this.getColl();
|
||||
if (coll != null) gson = coll.getGson();
|
||||
|
||||
return this.getClass().getSimpleName()+gson.toJson(this, this.getClass());
|
||||
}
|
||||
|
||||
}
|
||||
|
149
src/com/massivecraft/massivecore/store/EntityContainer.java
Normal file
149
src/com/massivecraft/massivecore/store/EntityContainer.java
Normal file
@ -0,0 +1,149 @@
|
||||
package com.massivecraft.massivecore.store;
|
||||
|
||||
import com.massivecraft.massivecore.predicate.Predicate;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
// Most base EntityContainer
|
||||
public interface EntityContainer<E>
|
||||
{
|
||||
String attach(E entity);
|
||||
String attach(E entity, Object oid);
|
||||
|
||||
E detachEntity(E entity);
|
||||
E detachId(Object oid);
|
||||
E detachIdFixed(String id);
|
||||
|
||||
boolean isLive();
|
||||
|
||||
Coll<?> getColl();
|
||||
|
||||
// -------------------------------------------- //
|
||||
// WHAT DO WE HANDLE?
|
||||
// -------------------------------------------- //
|
||||
|
||||
Class<E> getEntityClass();
|
||||
|
||||
// -------------------------------------------- //
|
||||
// STORAGE
|
||||
// -------------------------------------------- //
|
||||
|
||||
String fixId(Object oid);
|
||||
String fixIdOrThrow(Object oid) throws IllegalArgumentException;
|
||||
|
||||
Map<String, E> getIdToEntityRaw();
|
||||
Map<String, E> getIdToEntity();
|
||||
E get(Object oid);
|
||||
E get(Object oid, boolean creative);
|
||||
E getFixed(String id);
|
||||
E getFixed(String id, boolean creative);
|
||||
Collection<String> getIds();
|
||||
boolean containsId(Object oid);
|
||||
boolean containsIdFixed(String id);
|
||||
|
||||
boolean containsEntity(Object entity);
|
||||
|
||||
Collection<E> getAll();
|
||||
|
||||
List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Comparator<? super E> orderby, Integer limit, Integer offset);
|
||||
List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Comparator<? super E> orderby, Integer limit);
|
||||
List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Comparator<? super E> orderby);
|
||||
List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Integer limit, Integer offset);
|
||||
List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Integer limit);
|
||||
List<E> getAll(Iterable<?> oids, Comparator<? super E> orderby, Integer limit, Integer offset);
|
||||
List<E> getAll(Iterable<?> oids, Comparator<? super E> orderby, Integer limit);
|
||||
List<E> getAll(Iterable<?> oids, Predicate<? super E> where);
|
||||
List<E> getAll(Iterable<?> oids, Comparator<? super E> orderby);
|
||||
List<E> getAll(Iterable<?> oids, Integer limit, Integer offset);
|
||||
List<E> getAll(Iterable<?> oids, Integer limit);
|
||||
List<E> getAll(Iterable<?> oids);
|
||||
|
||||
List<E> getAll(Predicate<? super E> where, Comparator<? super E> orderby, Integer limit, Integer offset);
|
||||
List<E> getAll(Predicate<? super E> where, Comparator<? super E> orderby, Integer limit);
|
||||
List<E> getAll(Predicate<? super E> where, Comparator<? super E> orderby);
|
||||
List<E> getAll(Predicate<? super E> where, Integer limit, Integer offset);
|
||||
List<E> getAll(Predicate<? super E> where, Integer limit);
|
||||
List<E> getAll(Comparator<? super E> orderby, Integer limit, Integer offset);
|
||||
List<E> getAll(Comparator<? super E> orderby, Integer limit);
|
||||
List<E> getAll(Predicate<? super E> where);
|
||||
List<E> getAll(Comparator<? super E> orderby);
|
||||
List<E> getAll(Integer limit, Integer offset);
|
||||
List<E> getAll(Integer limit);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// BEHAVIOR
|
||||
// -------------------------------------------- //
|
||||
|
||||
boolean isCreative();
|
||||
void setCreative(boolean creative);
|
||||
|
||||
boolean isLowercasing();
|
||||
void setLowercasing(boolean lowercasing);
|
||||
|
||||
// A default entity will not be saved.
|
||||
// This is often used together with creative collections to save disc space.
|
||||
boolean isDefault(E entity);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// COPY AND CREATE
|
||||
// -------------------------------------------- //
|
||||
|
||||
void copy(E fromo, E too);
|
||||
|
||||
// This simply creates and returns a new instance
|
||||
// It does not detach/attach or anything. Just creates a new instance.
|
||||
E createNewInstance();
|
||||
|
||||
// Create new instance with automatic id
|
||||
E create();
|
||||
// Create new instance with the requested id
|
||||
E create(Object oid);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ATTACH AND DETACH
|
||||
// -------------------------------------------- //
|
||||
|
||||
/*String attach(E entity);
|
||||
String attach(E entity, Object oid);
|
||||
|
||||
E detachEntity(E entity);
|
||||
E detachId(Object oid);
|
||||
E detachIdFixed(String id);*/
|
||||
|
||||
void preAttach(E entity, String id);
|
||||
void postAttach(E entity, String id);
|
||||
|
||||
void preDetach(E entity, String id);
|
||||
void postDetach(E entity, String id);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IDENTIFIED MODIFICATIONS
|
||||
// -------------------------------------------- //
|
||||
|
||||
void putIdentifiedModification(Object oid, Modification modification);
|
||||
void putIdentifiedModificationFixed(String id, Modification modification);
|
||||
|
||||
void removeIdentifiedModification(Object oid);
|
||||
void removeIdentifiedModificationFixed(String id);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SYNC LOWLEVEL IO ACTIONS
|
||||
// -------------------------------------------- //
|
||||
|
||||
// oid
|
||||
E removeAtLocal(Object oid);
|
||||
|
||||
// fixed
|
||||
E removeAtLocalFixed(String id);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// NAME UTILITIES
|
||||
// -------------------------------------------- //
|
||||
|
||||
E getByName(String name);
|
||||
boolean isNameTaken(String str);
|
||||
|
||||
}
|
@ -0,0 +1,416 @@
|
||||
package com.massivecraft.massivecore.store;
|
||||
|
||||
import com.massivecraft.massivecore.Named;
|
||||
import com.massivecraft.massivecore.predicate.Predicate;
|
||||
import com.massivecraft.massivecore.predicate.PredicateEqualsIgnoreCase;
|
||||
import com.massivecraft.massivecore.util.MUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
// Calls fixId when necessary
|
||||
public abstract class EntityContainerAbstract<E extends EntityInternal<E>> implements EntityContainer<E>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// STORAGE
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override public Map<String, E> getIdToEntity() { return Collections.unmodifiableMap(this.getIdToEntityRaw()); }
|
||||
|
||||
@Override
|
||||
public String fixId(Object oid)
|
||||
{
|
||||
if (oid == null) return null;
|
||||
|
||||
String ret = null;
|
||||
if (oid instanceof String) ret = (String) oid;
|
||||
else if (oid.getClass() == this.getEntityClass()) ret = ((Entity<?>) oid).getId();
|
||||
if (ret == null) return null;
|
||||
|
||||
return this.isLowercasing() ? ret.toLowerCase() : ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fixIdOrThrow(Object oid) throws IllegalArgumentException
|
||||
{
|
||||
String ret = this.fixId(oid);
|
||||
if (ret == null) throw new IllegalArgumentException(String.valueOf(oid) + " is not a valid id.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(Object oid)
|
||||
{
|
||||
return this.getFixed(this.fixId(oid));
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(Object oid, boolean creative)
|
||||
{
|
||||
return this.getFixed(this.fixId(oid), creative);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getFixed(String id)
|
||||
{
|
||||
return this.getFixed(id, this.isCreative());
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getFixed(String id, boolean creative)
|
||||
{
|
||||
return this.getFixed(id, creative, true);
|
||||
}
|
||||
protected E getFixed(String id, boolean creative, boolean noteModification)
|
||||
{
|
||||
if (id == null) return null;
|
||||
E ret = this.getIdToEntity().get(id);
|
||||
if (ret != null) return ret;
|
||||
if ( ! creative) return null;
|
||||
return this.create(id, noteModification);
|
||||
}
|
||||
|
||||
@Override public Collection<String> getIds() { return this.getIdToEntity().keySet(); }
|
||||
|
||||
@Override
|
||||
public boolean containsId(Object oid)
|
||||
{
|
||||
return this.containsIdFixed(this.fixId(oid));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsIdFixed(String id)
|
||||
{
|
||||
if (id == null) return false;
|
||||
return this.getIdToEntity().containsKey(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsEntity(Object entity)
|
||||
{
|
||||
return this.getIdToEntity().containsValue(entity);
|
||||
}
|
||||
|
||||
@Override public Collection<E> getAll()
|
||||
{
|
||||
return this.getIdToEntity().values();
|
||||
}
|
||||
|
||||
@Override public List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Comparator<? super E> orderby, Integer limit, Integer offset) { return MUtil.transform(this.getAll(oids), where, orderby, limit, offset); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Comparator<? super E> orderby, Integer limit) { return MUtil.transform(this.getAll(oids), where, orderby, limit); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Comparator<? super E> orderby) { return MUtil.transform(this.getAll(oids), where, orderby); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Integer limit, Integer offset) { return MUtil.transform(this.getAll(oids), where, limit, offset); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Predicate<? super E> where, Integer limit) { return MUtil.transform(this.getAll(oids), where, limit); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Comparator<? super E> orderby, Integer limit, Integer offset) { return MUtil.transform(this.getAll(oids), limit, offset); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Comparator<? super E> orderby, Integer limit) { return MUtil.transform(this.getAll(oids), limit); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Predicate<? super E> where) { return MUtil.transform(this.getAll(oids), where); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Comparator<? super E> orderby) { return MUtil.transform(this.getAll(oids), orderby); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Integer limit, Integer offset) { return MUtil.transform(this.getAll(oids), limit, offset); }
|
||||
@Override public List<E> getAll(Iterable<?> oids, Integer limit) { return MUtil.transform(this.getAll(oids), limit); }
|
||||
|
||||
@Override public List<E> getAll(Iterable<?> oids)
|
||||
{
|
||||
// Return Create
|
||||
List<E> ret = new ArrayList<>();
|
||||
|
||||
// Return Fill
|
||||
for (Object oid : oids)
|
||||
{
|
||||
E e = this.get(oid);
|
||||
if (e == null) continue;
|
||||
ret.add(e);
|
||||
}
|
||||
|
||||
// Return Return
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override public List<E> getAll(Predicate<? super E> where, Comparator<? super E> orderby, Integer limit, Integer offset) { return MUtil.transform(this.getAll(), where, orderby, limit, offset); }
|
||||
@Override public List<E> getAll(Predicate<? super E> where, Comparator<? super E> orderby, Integer limit) { return MUtil.transform(this.getAll(), where, orderby, limit); }
|
||||
@Override public List<E> getAll(Predicate<? super E> where, Comparator<? super E> orderby) { return MUtil.transform(this.getAll(), where, orderby); }
|
||||
@Override public List<E> getAll(Predicate<? super E> where, Integer limit, Integer offset) { return MUtil.transform(this.getAll(), where, limit, offset); }
|
||||
@Override public List<E> getAll(Predicate<? super E> where, Integer limit) { return MUtil.transform(this.getAll(), where, limit); }
|
||||
@Override public List<E> getAll(Comparator<? super E> orderby, Integer limit, Integer offset) { return MUtil.transform(this.getAll(), limit, offset); }
|
||||
@Override public List<E> getAll(Comparator<? super E> orderby, Integer limit) { return MUtil.transform(this.getAll(), limit); }
|
||||
@Override public List<E> getAll(Predicate<? super E> where) { return MUtil.transform(this.getAll(), where); }
|
||||
@Override public List<E> getAll(Comparator<? super E> orderby) { return MUtil.transform(this.getAll(), orderby); }
|
||||
@Override public List<E> getAll(Integer limit, Integer offset) { return MUtil.transform(this.getAll(), limit, offset); }
|
||||
@Override public List<E> getAll(Integer limit) { return MUtil.transform(this.getAll(), limit); }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// BEHAVIOR
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected boolean creative;
|
||||
@Override public boolean isCreative() { return this.creative; }
|
||||
@Override public void setCreative(boolean creative) { this.creative = creative; }
|
||||
|
||||
// "Lowercasing" means that the ids are always converted to lower case when fixed.
|
||||
// This is highly recommended for sender colls.
|
||||
// The senderIds are case insensitive by nature and some times you simply can't know the correct casing.
|
||||
protected boolean lowercasing;
|
||||
@Override public boolean isLowercasing() { return this.lowercasing; }
|
||||
@Override public void setLowercasing(boolean lowercasing) { this.lowercasing = lowercasing; }
|
||||
|
||||
// Should that instance be saved or not?
|
||||
// If it is default it should not be saved.
|
||||
@Override
|
||||
public boolean isDefault(E entity)
|
||||
{
|
||||
return entity.isDefault();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// COPY AND CREATE
|
||||
// -------------------------------------------- //
|
||||
|
||||
// Create new instance with automatic id
|
||||
@Override
|
||||
public E create()
|
||||
{
|
||||
return this.create(null);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// COPY AND CREATE
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public void copy(E efrom, E eto)
|
||||
{
|
||||
if (efrom == null) throw new NullPointerException("efrom");
|
||||
if (eto == null) throw new NullPointerException("eto");
|
||||
|
||||
eto.load(efrom);
|
||||
}
|
||||
|
||||
// This simply creates and returns a new instance
|
||||
// It does not detach/attach or anything. Just creates a new instance.
|
||||
@Override
|
||||
public E createNewInstance()
|
||||
{
|
||||
try
|
||||
{
|
||||
return this.getEntityClass().newInstance();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Create new instance with the requested id
|
||||
@Override
|
||||
public synchronized E create(Object oid)
|
||||
{
|
||||
return this.create(oid, true);
|
||||
}
|
||||
|
||||
public synchronized E create(Object oid, boolean noteModification)
|
||||
{
|
||||
E entity = this.createNewInstance();
|
||||
if (this.attach(entity, oid, noteModification) == null) return null;
|
||||
return entity;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ATTACH AND DETACH
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public String attach(E entity)
|
||||
{
|
||||
return this.attach(entity, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String attach(E entity, Object oid)
|
||||
{
|
||||
return this.attach(entity, oid, true);
|
||||
}
|
||||
|
||||
protected synchronized String attach(E entity, Object oid, boolean noteModification)
|
||||
{
|
||||
// Check entity
|
||||
if (entity == null) return null;
|
||||
if (entity.attached()) return entity.getId();
|
||||
|
||||
String id;
|
||||
// Check/Fix id
|
||||
if (oid == null)
|
||||
{
|
||||
id = MStore.createId();
|
||||
}
|
||||
else
|
||||
{
|
||||
id = this.fixId(oid);
|
||||
if (id == null) return null;
|
||||
if (this.getIdToEntity().containsKey(id)) return null;
|
||||
}
|
||||
|
||||
// PRE
|
||||
this.preAttach(entity, id);
|
||||
|
||||
// Add entity reference info
|
||||
entity.setContainer(this);
|
||||
entity.setId(id);
|
||||
|
||||
// Attach
|
||||
this.getIdToEntityRaw().put(id, entity);
|
||||
|
||||
// Identify Modification
|
||||
if (noteModification)
|
||||
{
|
||||
this.putIdentifiedModificationFixed(id, Modification.LOCAL_ATTACH);
|
||||
}
|
||||
|
||||
// POST
|
||||
this.postAttach(entity, id);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E detachId(Object oid)
|
||||
{
|
||||
if (oid == null) throw new NullPointerException("oid");
|
||||
return this.detachIdFixed(this.fixIdOrThrow(oid));
|
||||
}
|
||||
|
||||
@Override
|
||||
public E detachEntity(E entity)
|
||||
{
|
||||
if (entity == null) throw new NullPointerException("entity");
|
||||
|
||||
String id = entity.getId();
|
||||
if (id == null)
|
||||
{
|
||||
// It seems the entity is already detached.
|
||||
// In such case just silently return it.
|
||||
return entity;
|
||||
}
|
||||
|
||||
this.detachFixed(entity, id);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E detachIdFixed(String id)
|
||||
{
|
||||
if (id == null) throw new NullPointerException("id");
|
||||
|
||||
E e = this.get(id, false);
|
||||
if (e == null) return null;
|
||||
|
||||
this.detachFixed(e, id);
|
||||
return e;
|
||||
}
|
||||
|
||||
protected void detachFixed(E entity, String id)
|
||||
{
|
||||
if (entity == null) throw new NullPointerException("entity");
|
||||
if (id == null) throw new NullPointerException("id");
|
||||
|
||||
// PRE
|
||||
this.preDetach(entity, id);
|
||||
|
||||
// Remove @ local
|
||||
this.removeAtLocalFixed(id);
|
||||
|
||||
// Identify Modification
|
||||
this.putIdentifiedModificationFixed(id, Modification.LOCAL_DETACH);
|
||||
|
||||
// POST
|
||||
this.postDetach(entity, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preAttach(E entity, String id)
|
||||
{
|
||||
entity.preAttach(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postAttach(E entity, String id)
|
||||
{
|
||||
entity.postAttach(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preDetach(E entity, String id)
|
||||
{
|
||||
entity.preDetach(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDetach(E entity, String id)
|
||||
{
|
||||
entity.postDetach(id);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IDENTIFIED MODIFICATIONS
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public void putIdentifiedModification(Object oid, Modification modification)
|
||||
{
|
||||
if (oid == null) throw new NullPointerException("oid");
|
||||
this.putIdentifiedModificationFixed(this.fixIdOrThrow(oid), modification);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeIdentifiedModification(Object oid)
|
||||
{
|
||||
if (oid == null) throw new NullPointerException("oid");
|
||||
this.removeIdentifiedModificationFixed(this.fixIdOrThrow(oid));
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SYNC LOWLEVEL IO ACTIONS
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public E removeAtLocal(Object oid)
|
||||
{
|
||||
if (oid == null) throw new NullPointerException("oid");
|
||||
return this.removeAtLocalFixed(this.fixIdOrThrow(oid));
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// NAME UTILITIES
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public E getByName(String name)
|
||||
{
|
||||
if (name == null) throw new NullPointerException("name");
|
||||
|
||||
Predicate<String> predicate = PredicateEqualsIgnoreCase.get(name);
|
||||
for (E entity : this.getAll())
|
||||
{
|
||||
if (entity == null) continue;
|
||||
|
||||
if ( ! (entity instanceof Named)) continue;
|
||||
Named named = (Named)entity;
|
||||
|
||||
if (predicate.apply(named.getName())) return entity;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNameTaken(String str)
|
||||
{
|
||||
return this.getByName(str) != null;
|
||||
}
|
||||
|
||||
}
|
159
src/com/massivecraft/massivecore/store/EntityInternal.java
Normal file
159
src/com/massivecraft/massivecore/store/EntityInternal.java
Normal file
@ -0,0 +1,159 @@
|
||||
package com.massivecraft.massivecore.store;
|
||||
|
||||
import com.massivecraft.massivecore.MassiveCore;
|
||||
import com.massivecraft.massivecore.store.accessor.Accessor;
|
||||
import com.massivecraft.massivecore.xlib.gson.Gson;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
|
||||
public class EntityInternal<E extends EntityInternal<E>>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected transient WeakReference<EntityContainer<E>> container = new WeakReference<>(null);
|
||||
protected void setContainer(EntityContainer<E> container)
|
||||
{
|
||||
this.container = new WeakReference<>(container);
|
||||
}
|
||||
public EntityContainer<E> getContainer()
|
||||
{
|
||||
return this.container.get();
|
||||
}
|
||||
|
||||
public Coll<?> getColl()
|
||||
{
|
||||
return this.getContainer().getColl();
|
||||
}
|
||||
|
||||
protected transient String id;
|
||||
protected void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
public String getId()
|
||||
{
|
||||
return this.id;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// ATTACH AND DETACH
|
||||
// -------------------------------------------- //
|
||||
|
||||
public boolean attached()
|
||||
{
|
||||
return this.getContainer() != null && this.getId() != null;
|
||||
}
|
||||
|
||||
public boolean detached()
|
||||
{
|
||||
return !this.attached();
|
||||
}
|
||||
|
||||
public void preAttach(String id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void postAttach(String id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void preDetach(String id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void postDetach(String id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SYNC AND IO ACTIONS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public boolean isLive()
|
||||
{
|
||||
String id = this.getId();
|
||||
if (id == null) return false;
|
||||
|
||||
EntityContainer<E> container = this.getContainer();
|
||||
if (container == null) return false;
|
||||
|
||||
if (!container.isLive()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void changed()
|
||||
{
|
||||
if (!this.isLive()) return;
|
||||
|
||||
//System.out.println(this.getColl().getName() + ": " +this.getId() + " was modified locally");
|
||||
|
||||
this.getContainer().putIdentifiedModificationFixed(this.getId(), Modification.UNKNOWN);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// DERPINGTON
|
||||
// -------------------------------------------- //
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public E load(E that)
|
||||
{
|
||||
Objects.requireNonNull(that, "that");
|
||||
Accessor.get(this.getClass()).copy(that, this);
|
||||
return (E) this;
|
||||
}
|
||||
|
||||
public boolean isDefault()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONVENIENCE: DATABASE
|
||||
// -------------------------------------------- //
|
||||
|
||||
// GENERIC
|
||||
public <T> T convertGet(T value, T standard)
|
||||
{
|
||||
return value != null ? value : standard;
|
||||
}
|
||||
|
||||
public <T> T convertSet(T value, T standard)
|
||||
{
|
||||
this.changed();
|
||||
return Objects.equals(value, standard) ? null : value;
|
||||
}
|
||||
|
||||
// BOOLEAN
|
||||
public boolean convertGet(Boolean value)
|
||||
{
|
||||
return convertGet(value, false);
|
||||
}
|
||||
|
||||
public Boolean convertSet(Boolean value)
|
||||
{
|
||||
return convertSet(value, false);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// STANDARDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
Gson gson = MassiveCore.gson;
|
||||
Coll<?> coll = this.getColl();
|
||||
if (coll != null) gson = coll.getGson();
|
||||
|
||||
return this.getClass().getSimpleName() + gson.toJson(this, this.getClass());
|
||||
}
|
||||
|
||||
}
|
228
src/com/massivecraft/massivecore/store/EntityInternalMap.java
Normal file
228
src/com/massivecraft/massivecore/store/EntityInternalMap.java
Normal file
@ -0,0 +1,228 @@
|
||||
package com.massivecraft.massivecore.store;
|
||||
|
||||
import com.massivecraft.massivecore.collections.MassiveSet;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class EntityInternalMap<E extends EntityInternal<E>> extends EntityContainerAbstract<E>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
private EntityInternalMap()
|
||||
{
|
||||
this.entityClass = null;
|
||||
}
|
||||
|
||||
public EntityInternalMap(Class<E> entityClass)
|
||||
{
|
||||
this.entityClass = entityClass;
|
||||
}
|
||||
|
||||
public EntityInternalMap(EntityInternal<?> entity, Class<E> entityClass)
|
||||
{
|
||||
Objects.requireNonNull(entity, "entity");
|
||||
Objects.requireNonNull(entityClass, "entityClass");
|
||||
|
||||
this.setEntity(entity);
|
||||
this.entityClass = entityClass;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// REFERENCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected transient WeakReference<EntityInternal<?>> entity = new WeakReference<>(null);
|
||||
protected void setEntity(EntityInternal<?> entity) { this.entity = new WeakReference<EntityInternal<?>>(entity); }
|
||||
public EntityInternal<?> getEntity() { return this.entity.get(); }
|
||||
|
||||
@Override
|
||||
public boolean isLive()
|
||||
{
|
||||
EntityInternal<?> entity = this.getEntity();
|
||||
if (entity == null) return false;
|
||||
|
||||
if (!entity.isLive()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// WHAT DO WE HANDLE?
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected final transient Class<E> entityClass;
|
||||
@Override public Class<E> getEntityClass() { return this.entityClass; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// STORAGE
|
||||
// -------------------------------------------- //
|
||||
|
||||
private final ConcurrentHashMap<String, E> id2Entity = new ConcurrentHashMap<>();
|
||||
|
||||
@Override public Map<String, E> getIdToEntityRaw() { return this.id2Entity; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// REFERENCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public Coll<?> getColl()
|
||||
{
|
||||
return this.getEntity().getContainer().getColl();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// LOAD
|
||||
// -------------------------------------------- //
|
||||
|
||||
public EntityInternalMap<E> load(EntityInternalMap<E> that)
|
||||
{
|
||||
Objects.requireNonNull(that, "that");
|
||||
|
||||
// Loop over all the entities in that
|
||||
for (Entry<String, E> entry : that.id2Entity.entrySet())
|
||||
{
|
||||
String id = entry.getKey();
|
||||
E entity = entry.getValue();
|
||||
|
||||
E current = this.id2Entity.get(id);
|
||||
if (current != null)
|
||||
{
|
||||
// Load if present
|
||||
current.load(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
// attach if not present
|
||||
this.attach(entity, id);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean entities of those that are not in that
|
||||
if (this.id2Entity.size() != that.id2Entity.size())
|
||||
{
|
||||
// Avoid CME
|
||||
Set<Entry<String, E>> removals = new MassiveSet<>();
|
||||
|
||||
// Loop over all current entries ...
|
||||
for (Iterator<Entry<String, E>> it = this.id2Entity.entrySet().iterator(); it.hasNext(); )
|
||||
{
|
||||
Entry<String, E> entry = it.next();
|
||||
String id = entry.getKey();
|
||||
|
||||
// ... if it is not present in those ...
|
||||
if (that.id2Entity.containsKey(id)) continue;
|
||||
|
||||
// ... remove.
|
||||
removals.add(entry);
|
||||
}
|
||||
|
||||
// Remove
|
||||
for (Entry<String, E> removal : removals)
|
||||
{
|
||||
this.detachFixed(removal.getValue(), removal.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IDENTIFIED MODIFICATIONS
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected Map<String, Modification> identifiedModifications;
|
||||
|
||||
@Override
|
||||
public synchronized void putIdentifiedModificationFixed(String id, Modification modification)
|
||||
{
|
||||
Objects.requireNonNull(id, "id");
|
||||
this.changed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void removeIdentifiedModificationFixed(String id)
|
||||
{
|
||||
Objects.requireNonNull(id, "id");
|
||||
this.changed();
|
||||
}
|
||||
|
||||
private void changed()
|
||||
{
|
||||
if (!this.isLive()) return;
|
||||
|
||||
//System.out.println(this.getColl().getName() + ": " +this.getId() + " was modified locally");
|
||||
|
||||
this.getEntity().changed();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// SYNC LOWLEVEL IO ACTIONS
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public synchronized E removeAtLocalFixed(String id)
|
||||
{
|
||||
Objects.requireNonNull(id, "id");
|
||||
|
||||
this.removeIdentifiedModificationFixed(id);
|
||||
|
||||
E entity = this.getIdToEntity().remove(id);
|
||||
if (entity == null) return null;
|
||||
|
||||
// Remove entity reference info
|
||||
entity.setContainer(null);
|
||||
entity.setId(null);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// MAP DELEGATION
|
||||
// -------------------------------------------- //
|
||||
|
||||
public Set<Entry<String, E>> entrySet()
|
||||
{
|
||||
return this.getIdToEntityRaw().entrySet();
|
||||
}
|
||||
public Set<String> keySet()
|
||||
{
|
||||
return this.getIdToEntity().keySet();
|
||||
}
|
||||
|
||||
public boolean containsKey(String id)
|
||||
{
|
||||
Objects.requireNonNull(id, "id");
|
||||
return this.getIdToEntityRaw().containsKey(id);
|
||||
}
|
||||
|
||||
public E remove(String id)
|
||||
{
|
||||
Objects.requireNonNull(id, "id");
|
||||
return this.getIdToEntityRaw().remove(id);
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return this.getIdToEntityRaw().size();
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return this.getIdToEntityRaw().isEmpty();
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
this.getIdToEntityRaw().clear();
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package com.massivecraft.massivecore.store.accessor;
|
||||
|
||||
import com.massivecraft.massivecore.store.EntityInternalMap;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
@ -72,11 +74,23 @@ public class Accessor
|
||||
{
|
||||
String fieldName = entry.getKey();
|
||||
Field field = entry.getValue();
|
||||
FieldAccessor fieldAccessor = new FieldAccessor(field);
|
||||
FieldAccessor fieldAccessor = createFieldAccessor(field);
|
||||
this.setFieldAccessor(fieldName, fieldAccessor);
|
||||
}
|
||||
}
|
||||
|
||||
public static FieldAccessor createFieldAccessor(Field field)
|
||||
{
|
||||
if (EntityInternalMap.class.isAssignableFrom(field.getType()))
|
||||
{
|
||||
return new FieldAccessorInternalEntityMap(field);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new FieldAccessorSimple(field);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// GET & SET & COPY
|
||||
// -------------------------------------------- //
|
||||
|
@ -1,54 +1,8 @@
|
||||
package com.massivecraft.massivecore.store.accessor;
|
||||
|
||||
import com.massivecraft.massivecore.util.ReflectionUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class FieldAccessor
|
||||
public interface FieldAccessor
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
private final Field field;
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public FieldAccessor(Field field)
|
||||
{
|
||||
ReflectionUtil.makeAccessible(field);
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CORE
|
||||
// -------------------------------------------- //
|
||||
|
||||
public Object get(Object entity)
|
||||
{
|
||||
try
|
||||
{
|
||||
return this.field.get(entity);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void set(Object entity, Object val)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.field.set(entity, val);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public Object get(Object entity);
|
||||
public void set(Object entity, Object val);
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
package com.massivecraft.massivecore.store.accessor;
|
||||
|
||||
import com.massivecraft.massivecore.store.EntityInternalMap;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class FieldAccessorInternalEntityMap extends FieldAccessorSimple
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public FieldAccessorInternalEntityMap(Field field)
|
||||
{
|
||||
super(field);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CORE
|
||||
// -------------------------------------------- //
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void set(Object entity, Object val)
|
||||
{
|
||||
EntityInternalMap entityMap = (EntityInternalMap) this.get(entity);
|
||||
EntityInternalMap that = (EntityInternalMap) val;
|
||||
|
||||
entityMap.load(that);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.massivecraft.massivecore.store.accessor;
|
||||
|
||||
import com.massivecraft.massivecore.util.ReflectionUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class FieldAccessorSimple implements FieldAccessor
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
private final Field field;
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public FieldAccessorSimple(Field field)
|
||||
{
|
||||
ReflectionUtil.makeAccessible(field);
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CORE
|
||||
// -------------------------------------------- //
|
||||
|
||||
public Object get(Object entity)
|
||||
{
|
||||
if (!field.getDeclaringClass().isAssignableFrom(entity.getClass())) throw new IllegalArgumentException(field.getDeclaringClass() + " : " + entity.getClass());
|
||||
|
||||
try
|
||||
{
|
||||
return this.field.get(entity);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void set(Object entity, Object val)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.field.set(entity, val);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user