package de.hub.emffrag.fragmentation; import java.util.Collection; import java.util.HashMap; import java.util.Map; import org.apache.commons.collections.MultiMap; import org.apache.commons.collections.map.MultiValueMap; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.util.EcoreUtil; public class NoReferencesIdSemantics extends IndexBasedIdSemantics { private final MultiMap saves = new MultiValueMap(); // Sometimes a reference is not yet contained (thus no actual fragmented // model URI exists) elements are references by objects that can unloaded. When // their are loaded, also their references are resolved. We use special // save://<id> URIs for these elements. private final Map<String, FInternalObjectImpl> saveKeyToSavedObject = new HashMap<String, FInternalObjectImpl>(); private final Map<FInternalObjectImpl, String> savedObjectToSaveKey = new HashMap<FInternalObjectImpl, String>(); private long unique = 0; public NoReferencesIdSemantics(IdBehaviour behavior) { super(behavior); } @Override public void onObjectAsReferenced(FInternalObjectImpl internalObject) { // nothing } @Override public URI getURI(FInternalObjectImpl internalObject, FragmentedModel model, boolean forceIssue, SaveURI save) { if (internalObject.eIsProxy()) { return internalObject.eProxyURI(); } else if (internalObject.getFragment() == null) { Collection<?> saves = (Collection<?>) this.saves.get(internalObject); if (save == null) { throw new RuntimeException("No save given for an object that is not contained in a fragment. Cannot create a URI for this object: [x:" + internalObject.eClass().getName() + "]"); } else { if (saves == null || !saves.contains(save)) { // The save is later used to save the real URI, once we can // assign it. This is usually done, when the resource of // the not yet contained element is added and then saved. this.saves.put(internalObject, save); // The save URI is used, as long no real URI could be saved. String saveKey = "" + unique++; saveKeyToSavedObject.put(saveKey, internalObject); savedObjectToSaveKey.put(internalObject, saveKey); return URI.createURI("save://" + saveKey); } else { return URI.createURI("save://" + savedObjectToSaveKey.get(internalObject)); } } } else { URI uri = EcoreUtil.getURI(internalObject); return uri; } } @Override public void onObjectSaved(FInternalObjectImpl internalObject) { Collection<?> saves = (Collection<?>) this.saves.get(internalObject); if (saves != null) { Fragment fragment = internalObject.getFragment(); URI uri = null; if (fragment != null) { // the object not longer needs a save, since is has been added // to the fragmented model uri = EcoreUtil.getURI(internalObject); this.saves.remove(internalObject); this.saveKeyToSavedObject.remove(savedObjectToSaveKey.get(internalObject)); this.savedObjectToSaveKey.remove(internalObject); } else { // as long as the object is not part of the model, we use a save // reference to refer to this object uri = URI.createURI("save://" + savedObjectToSaveKey.get(internalObject)); } for (Object saveObj : saves) { ((SaveURI) saveObj).saveURI(uri); } } } @Override public void onContainerChange(FInternalObjectImpl object, FragmentedModel model) { // nothing } @Override public FInternalObject resolveURI(URI uri, FragmentedModel model) { if (uri.scheme().equals("save")) { String saveKey = uri.device(); return saveKeyToSavedObject.get(saveKey); } else if (uri.scheme().equals("mongodb") || uri.scheme().equals("hbase") || uri.scheme().equals("memory")) { // TODO this looks not right return (FInternalObject) model.getInternalResourceSet().getEObject(uri, true); } else { throw new RuntimeException("Discovered an unknown URI."); } } }