package nebula.data.impl; import static com.google.common.base.Preconditions.checkNotNull; import java.util.List; import java.util.Map; import nebula.data.Entity; import nebula.data.db.DbPersister; import nebula.lang.Field; import nebula.lang.NebulaNative; import nebula.lang.Type; import nebula.lang.TypeStandalone; import com.google.common.base.Function; class DbMasterEntityDataStore extends EntityDataStore { final DbPersister<Entity> db; final IDGenerator idGenerator; final String key; boolean withID = false; DbMasterEntityDataStore(final DbDataRepos dataRepos, Type type, final DbPersister<Entity> exec) { this(IdMakerBuilder.getIDReader(type), dataRepos, type, exec); } DbMasterEntityDataStore(Function<Entity, Object> keyMaker, final DbDataRepos dataRepos, Type type, final DbPersister<Entity> exec) { super(keyMaker, dataRepos, type); this.db = exec; Field localKey = null; for (Field f : type.getFields()) { if (f.isKey()) { if (f.getType().getStandalone() == TypeStandalone.Basic) { localKey = f; break; } } } key = checkNotNull(localKey).getName(); if (localKey.getType().getName().equals("ID")) { idGenerator = IDGenerators.build(type); idGenerator.init(exec.getCurrentMaxID()); idGenerator.setSeed((long) type.getName().hashCode() % (1 << 8)); withID = true; } else { idGenerator = null; } List<Entity> list = exec.getAll(); for (Entity data : list) { loadin((EditableEntity)data); } } @Override public void apply(Entity newV) { EditableEntity newEntity = (EditableEntity) newV; if (newEntity.source != null) {// update assert newEntity.source instanceof DbEntity; DbEntity sourceEntity = (DbEntity) newEntity.source; assert sourceEntity == this.values.get(sourceEntity.index); Object id = null; lock.lock(); try { // DB if (withID) id = (Long) sourceEntity.get(key); else id = sourceEntity.getID(); NebulaNative.onSave(null, dataRepos, newEntity, type); db.update(newEntity, id); EntityImp newSource = loadin(sourceEntity, (EditableEntity)db.get(id)); newEntity.resetWith(newSource); } finally { lock.unlock(); } } else { // insert Object id = null; lock.lock(); try { if (withID) { id = idGenerator.nextValue(); newEntity.put(key, id); } else { id = (String) this.idMaker.apply(newEntity); } NebulaNative.onSave(null, dataRepos, newEntity, type); // DB db.insert(newEntity); EntityImp newSource = loadin((EditableEntity)db.get(id)); newEntity.resetWith(newSource); } finally { lock.unlock(); } } } class DbEntity extends EntityImp { final int index; DbEntity(DataStoreEx<Entity> store, Map<String, Object> data, int index) { super(store, data); this.index = index; } } private EntityImp loadin(EditableEntity entity) { entity.put(Entity.PRIMARY_KEY, idMaker.apply(entity)); DbEntity inner = new DbEntity(this, entity.newData, this.values.size()); NebulaNative.onLoad(null, dataRepos, entity, this.type); this.values.add(inner); return inner; } private EntityImp loadin(DbEntity sourceEntity, EditableEntity newEntity) { newEntity.put(Entity.PRIMARY_KEY, sourceEntity.getID()); DbEntity inner = new DbEntity(this, newEntity.newData, sourceEntity.index); NebulaNative.onLoad(null, dataRepos, newEntity, super.type); this.values.add(inner); return inner; } public void clearChanges() { db.deleteAll(); } @Override public void load() { // db.init(); } @Override public void unload() { db.close(); } }