package org.archstudio.xadl.bna.logics.mapping; import static org.archstudio.sysutils.SystemUtils.firstOrNull; import java.util.Set; import org.archstudio.bna.IBNAModelListener; import org.archstudio.bna.IBNAWorld; import org.archstudio.bna.IThing; import org.archstudio.bna.keys.IThingKey; import org.archstudio.bna.keys.IThingMetakey; import org.archstudio.bna.keys.IThingRefKey; import org.archstudio.bna.keys.ThingMetakey; import org.archstudio.bna.logics.AbstractKeyCoordinatingThingLogic; import org.archstudio.bna.utils.BNAUtils; import org.archstudio.xadl.bna.facets.IHasObjRef; import org.archstudio.xarchadt.ObjRef; import com.google.common.collect.Sets; public class SynchronizeThingIDAndObjRefLogic extends AbstractKeyCoordinatingThingLogic implements IBNAModelListener { private static final String OBJREF_KEY_NAME = ".objRef"; private final Set<IThingMetakey<?, IThingRefKey<?>, ObjRef>> objRefMetakeys = Sets.newHashSet(); public SynchronizeThingIDAndObjRefLogic(IBNAWorld world) { super(world, true); track(IHasObjRef.OBJREF_KEY); } public IThingMetakey<?, IThingRefKey<?>, ObjRef> syncObjRefKeyToThingIDKey(IThingRefKey<?> thingRefKey) { BNAUtils.checkLock(); track(thingRefKey); IThingMetakey<?, IThingRefKey<?>, ObjRef> objRefMetakey = _syncObjRefKeyToThingIDKey(thingRefKey); objRefMetakeys.add(objRefMetakey); track(objRefMetakey); return objRefMetakey; } private IThingMetakey<?, IThingRefKey<?>, ObjRef> _syncObjRefKeyToThingIDKey(IThingRefKey<?> thingRefKey) { return ThingMetakey.<String, IThingRefKey<?>, ObjRef> create(OBJREF_KEY_NAME, thingRefKey); } @Override protected void update(IThing thing, IThingKey<?> key) { if (IHasObjRef.OBJREF_KEY.equals(key)) { ObjRef objRef = thing.get(IHasObjRef.OBJREF_KEY); if (objRef != null) { for (IThingMetakey<?, IThingRefKey<?>, ObjRef> objRefKey : objRefMetakeys) { for (IThing thingWithObjRef : valueLogic.getThings(objRefKey, objRef)) { thingWithObjRef.set(objRefKey.getKey(), thing.getID()); } } } } else if (key instanceof IThingMetakey && OBJREF_KEY_NAME.equals(((IThingMetakey<?, ?, ?>) key).getName())) { @SuppressWarnings("unchecked") IThingMetakey<?, IThingRefKey<?>, ObjRef> objRefKey = (IThingMetakey<?, IThingRefKey<?>, ObjRef>) key; ObjRef objRef = thing.get(objRefKey); if (objRef != null) { thing.set(objRefKey.getKey(), firstOrNull(valueLogic.getThingIDs(IHasObjRef.OBJREF_KEY, objRef))); } else { thing.remove(objRefKey.getKey()); } } else if (key instanceof IThingRefKey) { IThingRefKey<?> refKey = (IThingRefKey<?>) key; IThingMetakey<?, IThingRefKey<?>, ObjRef> objRefKey = _syncObjRefKeyToThingIDKey(refKey); ObjRef objRef = null; if (thing.has(refKey)) { IThing referencedThing = refKey.get(thing, model); objRef = referencedThing != null ? referencedThing.get(IHasObjRef.OBJREF_KEY) : null; } if (objRef != null) { thing.set(objRefKey, objRef); } else { thing.remove(objRefKey); } } } }