package org.archstudio.bna.logics.tracking;
import static org.archstudio.sysutils.SystemUtils.filter;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.archstudio.bna.BNAModelEvent;
import org.archstudio.bna.IBNAModelListener;
import org.archstudio.bna.IBNAWorld;
import org.archstudio.bna.IThing;
import org.archstudio.bna.logics.AbstractThingLogic;
import org.archstudio.bna.utils.BNAUtils;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
public class ThingTypeTrackingLogic extends AbstractThingLogic implements IBNAModelListener {
private final LoadingCache<Class<? extends IThing>, Collection<Object>> classToThingIDsCache = CacheBuilder
.newBuilder().build(new CacheLoader<Class<? extends IThing>, Collection<Object>>() {
@Override
public Collection<Object> load(Class<? extends IThing> key) throws Exception {
Collection<Object> things = Lists.newArrayList();
for (IThing t : model.getAllThings()) {
if (key.isInstance(t)) {
things.add(t.getID());
}
}
return things;
}
});
public ThingTypeTrackingLogic(IBNAWorld world) {
super(world);
}
@Override
public void dispose() {
BNAUtils.checkLock();
classToThingIDsCache.invalidateAll();
super.dispose();
}
@Override
public void bnaModelChanged(BNAModelEvent evt) {
BNAUtils.checkLock();
switch (evt.getEventType()) {
case THING_ADDED: {
IThing t = evt.getTargetThing();
for (Map.Entry<Class<? extends IThing>, Collection<Object>> e : classToThingIDsCache.asMap().entrySet()) {
if (e.getKey().isInstance(t)) {
e.getValue().add(t.getID());
}
}
}
break;
case THING_REMOVED: {
IThing t = evt.getTargetThing();
for (Map.Entry<Class<? extends IThing>, Collection<Object>> e : classToThingIDsCache.asMap().entrySet()) {
if (e.getKey().isInstance(t)) {
e.getValue().remove(t.getID());
}
}
}
break;
default:
// do nothing
}
}
public List<Object> getThingIDs(Class<? extends IThing> ofType) {
BNAUtils.checkLock();
return Lists.newArrayList(classToThingIDsCache.getUnchecked(ofType));
}
public <T extends IThing> List<T> getThings(Class<T> ofType) {
BNAUtils.checkLock();
return filter(model.getThingsByID(classToThingIDsCache.getUnchecked(ofType)), ofType);
}
}