blob: e84d951d555873100d8a22c59accc13bfbd711a6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008-2011 Chair for Applied Software Engineering,
* Technische Universitaet Muenchen.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Otto von Wesendonk, Edgar Mueller, Maximilian Koegel - initial API and implementation
* Johannes Faltermeier - Pluggable storage, Decoupled Projects
******************************************************************************/
package org.eclipse.emf.emfstore.internal.client.model.impl;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
import org.eclipse.emf.ecore.util.EcoreUtil.UsageCrossReferencer;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
import org.eclipse.emf.emfstore.client.ESUsersession;
import org.eclipse.emf.emfstore.client.callbacks.ESCommitCallback;
import org.eclipse.emf.emfstore.client.callbacks.ESUpdateCallback;
import org.eclipse.emf.emfstore.client.changetracking.ESCommandStack;
import org.eclipse.emf.emfstore.client.handler.ESRunnableContext;
import org.eclipse.emf.emfstore.client.observer.ESLoginObserver;
import org.eclipse.emf.emfstore.client.observer.ESMergeObserver;
import org.eclipse.emf.emfstore.client.provider.ESEditingDomainProvider;
import org.eclipse.emf.emfstore.client.util.ClientURIUtil;
import org.eclipse.emf.emfstore.client.util.RunESCommand;
import org.eclipse.emf.emfstore.common.ESResourceSetProvider;
import org.eclipse.emf.emfstore.common.extensionpoint.ESExtensionElement;
import org.eclipse.emf.emfstore.common.extensionpoint.ESExtensionPoint;
import org.eclipse.emf.emfstore.common.extensionpoint.ESPriorityComparator;
import org.eclipse.emf.emfstore.internal.client.importexport.impl.ExportChangesController;
import org.eclipse.emf.emfstore.internal.client.importexport.impl.ExportProjectController;
import org.eclipse.emf.emfstore.internal.client.model.CompositeOperationHandle;
import org.eclipse.emf.emfstore.internal.client.model.Configuration;
import org.eclipse.emf.emfstore.internal.client.model.ESWorkspaceProviderImpl;
import org.eclipse.emf.emfstore.internal.client.model.ProjectSpace;
import org.eclipse.emf.emfstore.internal.client.model.Usersession;
import org.eclipse.emf.emfstore.internal.client.model.changeTracking.commands.EMFStoreBasicCommandStack;
import org.eclipse.emf.emfstore.internal.client.model.changeTracking.merging.ConflictResolver;
import org.eclipse.emf.emfstore.internal.client.model.changeTracking.notification.recording.NotificationRecorder;
import org.eclipse.emf.emfstore.internal.client.model.connectionmanager.ConnectionManager;
import org.eclipse.emf.emfstore.internal.client.model.connectionmanager.ServerCall;
import org.eclipse.emf.emfstore.internal.client.model.controller.CommitController;
import org.eclipse.emf.emfstore.internal.client.model.controller.ShareController;
import org.eclipse.emf.emfstore.internal.client.model.controller.UpdateController;
import org.eclipse.emf.emfstore.internal.client.model.exceptions.ChangeConflictException;
import org.eclipse.emf.emfstore.internal.client.model.exceptions.IllegalProjectSpaceStateException;
import org.eclipse.emf.emfstore.internal.client.model.exceptions.MEUrlResolutionException;
import org.eclipse.emf.emfstore.internal.client.model.exceptions.PropertyNotFoundException;
import org.eclipse.emf.emfstore.internal.client.model.filetransfer.FileDownloadStatus;
import org.eclipse.emf.emfstore.internal.client.model.filetransfer.FileInformation;
import org.eclipse.emf.emfstore.internal.client.model.filetransfer.FileTransferManager;
import org.eclipse.emf.emfstore.internal.client.model.impl.api.ESLocalProjectImpl;
import org.eclipse.emf.emfstore.internal.client.model.util.WorkspaceUtil;
import org.eclipse.emf.emfstore.internal.client.observers.DeleteProjectSpaceObserver;
import org.eclipse.emf.emfstore.internal.client.properties.PropertyManager;
import org.eclipse.emf.emfstore.internal.common.APIUtil;
import org.eclipse.emf.emfstore.internal.common.EMFStoreResource;
import org.eclipse.emf.emfstore.internal.common.ESDisposable;
import org.eclipse.emf.emfstore.internal.common.ExtensionRegistry;
import org.eclipse.emf.emfstore.internal.common.model.ModelElementId;
import org.eclipse.emf.emfstore.internal.common.model.Project;
import org.eclipse.emf.emfstore.internal.common.model.impl.IdentifiableElementImpl;
import org.eclipse.emf.emfstore.internal.common.model.impl.ProjectImpl;
import org.eclipse.emf.emfstore.internal.common.model.util.ModelUtil;
import org.eclipse.emf.emfstore.internal.common.model.util.SerializationException;
import org.eclipse.emf.emfstore.internal.server.conflictDetection.ChangeConflictSet;
import org.eclipse.emf.emfstore.internal.server.conflictDetection.ConflictBucket;
import org.eclipse.emf.emfstore.internal.server.conflictDetection.ConflictDetector;
import org.eclipse.emf.emfstore.internal.server.exceptions.FileTransferException;
import org.eclipse.emf.emfstore.internal.server.exceptions.InvalidVersionSpecException;
import org.eclipse.emf.emfstore.internal.server.model.FileIdentifier;
import org.eclipse.emf.emfstore.internal.server.model.ProjectInfo;
import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.ACUser;
import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.OrgUnitProperty;
import org.eclipse.emf.emfstore.internal.server.model.url.ModelElementUrlFragment;
import org.eclipse.emf.emfstore.internal.server.model.versioning.BranchInfo;
import org.eclipse.emf.emfstore.internal.server.model.versioning.BranchVersionSpec;
import org.eclipse.emf.emfstore.internal.server.model.versioning.ChangePackage;
import org.eclipse.emf.emfstore.internal.server.model.versioning.LogMessage;
import org.eclipse.emf.emfstore.internal.server.model.versioning.PrimaryVersionSpec;
import org.eclipse.emf.emfstore.internal.server.model.versioning.TagVersionSpec;
import org.eclipse.emf.emfstore.internal.server.model.versioning.VersionSpec;
import org.eclipse.emf.emfstore.internal.server.model.versioning.VersioningFactory;
import org.eclipse.emf.emfstore.internal.server.model.versioning.Versions;
import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.AbstractOperation;
import org.eclipse.emf.emfstore.server.exceptions.ESException;
import org.eclipse.emf.emfstore.server.model.ESChangePackage;
/**
* Project space base class that contains custom user methods.
*
* @author koegel
* @author wesendon
* @author emueller
* @author jfaltermeier
*
*/
public abstract class ProjectSpaceBase extends IdentifiableElementImpl implements ProjectSpace, ESLoginObserver,
ESDisposable {
private ESLocalProjectImpl esLocalProjectImpl;
private boolean initCompleted;
private boolean isTransient;
private boolean disposed;
private boolean closed;
private FileTransferManager fileTransferManager;
private OperationManager operationManager;
private PropertyManager propertyManager;
private final Map<String, OrgUnitProperty> propertyMap;
private ResourceSet resourceSet;
private ResourceSet contentResourceSet;
private EditingDomain contentEditingDomain;
private ResourcePersister resourcePersister;
private ECrossReferenceAdapter crossReferenceAdapter;
private ESRunnableContext runnableContext;
/**
* Constructor.
*/
public ProjectSpaceBase() {
propertyMap = new LinkedHashMap<String, OrgUnitProperty>();
initRunnableContext();
}
/**
* <p>
* Provides a context in which a {@link Runnable} is executed.
* </p>
* <p>
* This may be used to provide a context while applying operations on a
* {@link org.eclipse.emf.emfstore.client.ESLocalProject}.
* </p>
*
* @param runnableContext
* the runnable context to be set
*/
public void setRunnableContext(ESRunnableContext runnableContext) {
this.runnableContext = runnableContext;
}
private void initRunnableContext() {
runnableContext = ExtensionRegistry.INSTANCE.get(
RUNNABLE_CONTEXT_ID,
ESRunnableContext.class,
new DefaultRunnableContext(), true);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#addFile(java.io.File)
*/
public FileIdentifier addFile(File file) throws FileTransferException {
return fileTransferManager.addFile(file);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#addOperations(java.util.List)
*/
public void addOperations(List<? extends AbstractOperation> operations) {
getOperations().addAll(operations);
updateDirtyState();
for (final AbstractOperation op : operations) {
operationManager.notifyOperationExecuted(op);
}
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#addTag(org.eclipse.emf.emfstore.internal.server.model.versioning.PrimaryVersionSpec,
* org.eclipse.emf.emfstore.internal.server.model.versioning.TagVersionSpec)
*/
public void addTag(PrimaryVersionSpec versionSpec, TagVersionSpec tag) throws ESException {
final ConnectionManager cm = ESWorkspaceProviderImpl.getInstance().getConnectionManager();
cm.addTag(getUsersession().getSessionId(), getProjectId(), versionSpec, tag);
}
/**
* Helper method which applies merged changes on the ProjectSpace. This
* method is used by merge mechanisms in update as well as branch merging.
*
* @param baseSpec
* new base version
* @param incoming
* changes from the current branch
* @param myChanges
* merged changes
* @param progressMonitor
* an {@link IProgressMonitor} to inform about the progress of the UpdateCallback in case it is called
* @param runChecksumTestOnBaseSpec
* whether the checksum check is performed while applying the changes
*
* @throws ESException in case the checksum comparison failed and the activated IChecksumErrorHandler
* also failed
*/
public void applyChanges(PrimaryVersionSpec baseSpec, List<ChangePackage> incoming, ChangePackage myChanges,
IProgressMonitor progressMonitor, boolean runChecksumTestOnBaseSpec) throws ESException {
// revert local changes
notifyPreRevertMyChanges(getLocalChangePackage());
revert();
notifyPostRevertMyChanges();
// apply changes from repo. incoming (aka theirs)
applyChangePackages(incoming, false);
notifyPostApplyTheirChanges(incoming);
if (runChecksumTestOnBaseSpec) {
runChecksumTests(baseSpec, incoming, progressMonitor);
}
// reapply local changes
applyOperations(myChanges.getOperations(), true);
notifyPostApplyMergedChanges(myChanges);
setBaseVersion(baseSpec);
saveProjectSpaceOnly();
}
private void runChecksumTests(PrimaryVersionSpec baseSpec, List<ChangePackage> incoming,
IProgressMonitor progressMonitor)
throws ESException {
progressMonitor.subTask("Computing checksum");
if (!performChecksumCheck(baseSpec, getProject())) {
progressMonitor.subTask("Invalid checksum. Activating checksum error handler.");
final boolean errorHandled = Configuration.getClientBehavior().getChecksumErrorHandler()
.execute(toAPI(), baseSpec.toAPI(),
progressMonitor);
if (!errorHandled) {
// rollback
for (int i = incoming.size() - 1; i >= 0; i--) {
applyChangePackage(incoming.get(i).reverse(), false);
}
applyChangePackage(getLocalChangePackage(), true);
throw new ESException("Update cancelled by checksum error handler due to invalid checksum.");
}
}
}
private void applyChangePackage(ChangePackage changePackage, boolean addOperations) {
applyOperations(changePackage.getOperations(), addOperations);
}
private void applyChangePackages(List<ChangePackage> changePackages, boolean addOperations) {
for (final ChangePackage changePackage : changePackages) {
applyChangePackage(changePackage, addOperations);
}
}
private boolean performChecksumCheck(PrimaryVersionSpec baseVersion, Project project) {
if (Configuration.getClientBehavior().isChecksumCheckActive()) {
final long expectedChecksum = baseVersion.getProjectStateChecksum();
try {
final long computedChecksum = ModelUtil.computeChecksum(project);
return expectedChecksum == computedChecksum;
} catch (final SerializationException e) {
WorkspaceUtil.logWarning("Could not compute checksum while applying changes.", e);
}
}
return true;
}
/**
* Applies a list of operations to the project. The change tracking will be
* stopped meanwhile.
*
*
* @param operations
* the list of operations to be applied upon the project space
* @param addOperations
* whether the operations should be saved in project space
*
*/
public void applyOperations(List<AbstractOperation> operations, boolean addOperations) {
executeRunnable(new ApplyOperationsRunnable(this, operations, addOperations));
}
/**
* Executes a given {@link Runnable} in the context of this {@link ProjectSpace}.<br>
* The {@link Runnable} usually modifies the Project contained in the {@link ProjectSpace}.
*
* @param runnable
* the {@link Runnable} to be executed in the context of this {@link ProjectSpace}
*/
public void executeRunnable(Runnable runnable) {
getRunnableContext().executeRunnable(runnable);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#beginCompositeOperation()
*/
public CompositeOperationHandle beginCompositeOperation() {
return operationManager.beginCompositeOperation();
}
/**
* Removes the elements that are marked as cutted from the project.
*/
public void cleanCutElements() {
final List<EObject> cutElements = new ArrayList<EObject>(getProject().getCutElements());
for (final EObject cutElement : cutElements) {
getProject().deleteModelElement(cutElement);
}
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#commit(org.eclipse.core.runtime.IProgressMonitor)
*/
public PrimaryVersionSpec commit(IProgressMonitor monitor) throws ESException {
return new CommitController(this, null, null, monitor).execute();
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#commit(java.lang.String,
* org.eclipse.emf.emfstore.client.callbacks.ESCommitCallback, org.eclipse.core.runtime.IProgressMonitor)
*/
public PrimaryVersionSpec commit(String logMessage, ESCommitCallback callback, IProgressMonitor monitor)
throws ESException {
return new CommitController(this, logMessage, callback, monitor).execute();
}
/**
* {@inheritDoc}
*/
public PrimaryVersionSpec commitToBranch(BranchVersionSpec branch, String logMessage,
ESCommitCallback callback,
IProgressMonitor monitor) throws ESException {
return new CommitController(this, branch, logMessage, callback, monitor).execute();
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#exportLocalChanges(java.io.File,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public void exportLocalChanges(File file, IProgressMonitor progressMonitor) throws IOException {
new ExportChangesController(this).execute(file, progressMonitor);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#exportLocalChanges(java.io.File)
*/
public void exportLocalChanges(File file) throws IOException {
new ExportChangesController(this).execute(file, new NullProgressMonitor());
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#exportProject(java.io.File,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public void exportProject(File file, IProgressMonitor progressMonitor) throws IOException {
new ExportProjectController(this).execute(file, progressMonitor);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#exportProject(java.io.File)
*/
public void exportProject(File file) throws IOException {
new ExportProjectController(this).execute(file, new NullProgressMonitor());
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#getChanges(org.eclipse.emf.emfstore.internal.server.model.versioning.VersionSpec,
* org.eclipse.emf.emfstore.internal.server.model.versioning.VersionSpec)
*/
public List<ChangePackage> getChanges(VersionSpec sourceVersion, VersionSpec targetVersion)
throws InvalidVersionSpecException, ESException {
// TODO: is this a server call?
final ConnectionManager connectionManager = ESWorkspaceProviderImpl.getInstance().getConnectionManager();
final List<ChangePackage> changes = connectionManager.getChanges(getUsersession().getSessionId(),
getProjectId(),
sourceVersion, targetVersion);
return changes;
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#getFile(org.eclipse.emf.emfstore.internal.server.model.FileIdentifier)
*/
public FileDownloadStatus getFile(FileIdentifier fileIdentifier) throws FileTransferException {
return fileTransferManager.getFile(fileIdentifier, false);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#getFileInfo(org.eclipse.emf.emfstore.internal.server.model.FileIdentifier)
*/
public FileInformation getFileInfo(FileIdentifier fileIdentifier) {
return fileTransferManager.getFileInfo(fileIdentifier);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#getLocalChangePackage()
*/
public ChangePackage getLocalChangePackage(boolean canonize) {
final ChangePackage changePackage = VersioningFactory.eINSTANCE.createChangePackage();
// copy operations from ProjectSpace
for (final AbstractOperation abstractOperation : getOperations()) {
final AbstractOperation copy = ModelUtil.clone(abstractOperation);
changePackage.getOperations().add(copy);
}
final LogMessage logMessage = VersioningFactory.eINSTANCE.createLogMessage();
if (getUsersession() != null) {
logMessage.setAuthor(getUsersession().getUsername());
}
else {
logMessage.setAuthor("<Unkown>");
}
logMessage.setClientDate(new Date());
changePackage.setLogMessage(logMessage);
return changePackage;
}
/**
* Get the current notification recorder.
*
* @return the recorder
*/
public NotificationRecorder getNotificationRecorder() {
return operationManager.getNotificationRecorder();
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#getOperationManager()
*/
public OperationManager getOperationManager() {
return operationManager;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#getOperations()
*/
public List<AbstractOperation> getOperations() {
ChangePackage localChangePackage = getLocalChangePackage();
if (localChangePackage == null) {
setLocalChangePackage(VersioningFactory.eINSTANCE.createChangePackage());
localChangePackage = getLocalChangePackage();
}
return localChangePackage.getOperations();
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#getProjectInfo()
*/
public ProjectInfo getProjectInfo() {
final ProjectInfo projectInfo = org.eclipse.emf.emfstore.internal.server.model.ModelFactory.eINSTANCE
.createProjectInfo();
projectInfo.setProjectId(ModelUtil.clone(getProjectId()));
projectInfo.setName(getProjectName());
projectInfo.setDescription(getProjectDescription());
projectInfo.setVersion(ModelUtil.clone(getBaseVersion()));
return projectInfo;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#getPropertyManager()
*/
public PropertyManager getPropertyManager() {
if (propertyManager == null) {
propertyManager = new PropertyManager(this);
}
return propertyManager;
}
/**
* getter for a string argument - see {@link #setProperty(OrgUnitProperty)}.
*/
private OrgUnitProperty getProperty(String name) throws PropertyNotFoundException {
// sanity checks
if (getUsersession() != null && getUsersession().getACUser() != null) {
final OrgUnitProperty orgUnitProperty = propertyMap.get(name);
if (orgUnitProperty != null) {
return orgUnitProperty;
}
}
throw new PropertyNotFoundException(MessageFormat.format(
"Property {0} not found.", name));
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#importLocalChanges(java.lang.String)
*/
public void importLocalChanges(String fileName) throws IOException {
final ResourceSetImpl resourceSet = new ResourceSetImpl();
final Resource resource = resourceSet.getResource(URI.createFileURI(fileName), true);
final EList<EObject> directContents = resource.getContents();
// sanity check
if (directContents.size() != 1 && !(directContents.get(0) instanceof ChangePackage)) {
throw new IOException("File is corrupt, does not contain Changes.");
}
final ChangePackage changePackage = (ChangePackage) directContents.get(0);
if (!initCompleted) {
init();
}
applyOperations(changePackage.getOperations(), true);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#init()
*/
public void init() {
final ResourceSet contentResourceSet = getResourceSetForContents();
if (contentEditingDomain == null) {
contentEditingDomain = getEditingDomainForContents(contentResourceSet);
}
if (getProject().eResource() != null) {
contentResourceSet.getResources().add(getProject().eResource());
} else {
final Resource resource = contentResourceSet.createResource(ClientURIUtil.createProjectURI(this));
resource.getContents().add(getProject());
}
if (getLocalChangePackage() != null) {
if (getLocalChangePackage().eResource() != null) {
contentResourceSet.getResources().add(getLocalChangePackage().eResource());
} else {
final Resource resource = contentResourceSet.createResource(ClientURIUtil.createOperationsURI(this));
resource.getContents().add(getLocalChangePackage());
}
}
initCrossReferenceAdapter();
final ESCommandStack commandStack = (ESCommandStack)
contentEditingDomain.getCommandStack();
fileTransferManager = new FileTransferManager(this);
operationManager = new OperationManager(this);
initResourcePersister();
commandStack.addCommandStackObserver(operationManager);
commandStack.addCommandStackObserver(resourcePersister);
// initialization order is important!
getProject().addIdEObjectCollectionChangeObserver(operationManager);
getProject().addIdEObjectCollectionChangeObserver(resourcePersister);
if (getProject() instanceof ProjectImpl) {
((ProjectImpl) getProject()).setUndetachable(operationManager);
((ProjectImpl) getProject()).setUndetachable(resourcePersister);
}
initPropertyMap();
startChangeRecording();
cleanCutElements();
initCompleted = true;
}
/**
* Returns the {@link ResourceSet} for the project and the local change package of this project space. If the
* resource set was null, it will be created.
*
* @return the resource set
*/
private ResourceSet getResourceSetForContents() {
if (contentResourceSet == null) {
final ESExtensionPoint extensionPoint = new ESExtensionPoint(
"org.eclipse.emf.emfstore.client.resourceSetProvider", //$NON-NLS-1$
true);
extensionPoint.setComparator(new ESPriorityComparator("priority", true)); //$NON-NLS-1$
extensionPoint.reload();
final ESResourceSetProvider resourceSetProvider = extensionPoint.getElementWithHighestPriority().getClass(
"class", //$NON-NLS-1$
ESResourceSetProvider.class);
contentResourceSet = resourceSetProvider.getResourceSet();
}
return contentResourceSet;
}
/**
* Returns the {@link EditingDomain} for this project space's project and local change package.
*
* @param resourceSet the {@link ResourceSet} of the project and local change package
* @return
*/
private EditingDomain getEditingDomainForContents(ResourceSet resourceSet) {
final ESEditingDomainProvider domainProvider = getDomainProvider();
if (domainProvider != null) {
return domainProvider.getEditingDomain(resourceSet);
}
AdapterFactory adapterFactory = new ComposedAdapterFactory(
ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
adapterFactory = new ComposedAdapterFactory(new AdapterFactory[] { adapterFactory,
new ReflectiveItemProviderAdapterFactory() });
final AdapterFactoryEditingDomain domain = new AdapterFactoryEditingDomain(adapterFactory,
new EMFStoreBasicCommandStack(), resourceSet);
resourceSet.eAdapters().add(new AdapterFactoryEditingDomain.EditingDomainProvider(domain));
return domain;
}
private ESEditingDomainProvider getDomainProvider() {
// TODO EXPT PRIO
return new ESExtensionPoint("org.eclipse.emf.emfstore.client.editingDomainProvider")
.getClass("class",
ESEditingDomainProvider.class);
}
@SuppressWarnings("unchecked")
private void initPropertyMap() {
// TODO: deprecated, OrgUnitPropertiy will be removed soon
if (getUsersession() != null) {
ESWorkspaceProviderImpl.getObserverBus().register(this, ESLoginObserver.class);
final ACUser acUser = getUsersession().getACUser();
if (acUser != null) {
for (final OrgUnitProperty p : acUser.getProperties()) {
if (p.getProject() != null && p.getProject().equals(getProjectId())) {
propertyMap.put(p.getName(), p);
}
}
}
}
}
private void initCrossReferenceAdapter() {
// default
boolean useCrossReferenceAdapter = true;
for (final ESExtensionElement element : new ESExtensionPoint(
"org.eclipse.emf.emfstore.client.inverseCrossReferenceCache") //$NON-NLS-1$
.getExtensionElements()) {
useCrossReferenceAdapter &= element.getBoolean("activated"); //$NON-NLS-1$
}
if (useCrossReferenceAdapter) {
crossReferenceAdapter = new ECrossReferenceAdapter();
getProject().eAdapters().add(crossReferenceAdapter);
}
}
private void initResourcePersister() {
resourcePersister = new ResourcePersister(getProject());
if (!isTransient) {
resourcePersister.addResource(eResource());
resourcePersister.addResource(getLocalChangePackage().eResource());
resourcePersister.addResource(getProject().eResource());
resourcePersister.addDirtyStateChangeLister(new ESLocalProjectSaveStateNotifier(toAPI()));
ESWorkspaceProviderImpl.getObserverBus().register(resourcePersister);
}
}
/**
* Returns the file transfer manager.
*
* @return the file transfer manager
*/
public FileTransferManager getFileTransferManager() {
return fileTransferManager;
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#initResources(org.eclipse.emf.ecore.resource.ResourceSet)
*/
public void initResources(ResourceSet resourceSet) {
this.resourceSet = resourceSet;
initCompleted = true;
final URI projectSpaceURI = ClientURIUtil.createProjectSpaceURI(this);
final URI operationsURI = ClientURIUtil.createOperationsURI(this);
final URI projectURI = ClientURIUtil.createProjectURI(this);
setResourceCount(0);
final List<Resource> resources = new ArrayList<Resource>();
final Resource resource = resourceSet.createResource(projectURI);
// if resource splitting fails, we need a reference to the old resource
resource.getContents().add(getProject());
resources.add(resource);
setResourceCount(getResourceCount() + 1);
for (final EObject modelElement : getProject().getAllModelElements()) {
((EMFStoreResource) resource).setID(modelElement, getProject().getModelElementId(modelElement).getId());
}
final Resource localChangePackageResource = resourceSet.createResource(operationsURI);
if (this.getLocalChangePackage() == null) {
setLocalChangePackage(VersioningFactory.eINSTANCE.createChangePackage());
}
localChangePackageResource.getContents().add(this.getLocalChangePackage());
resources.add(localChangePackageResource);
final Resource projectSpaceResource = resourceSet.createResource(projectSpaceURI);
projectSpaceResource.getContents().add(this);
resources.add(projectSpaceResource);
// save all resources that have been created
for (final Resource currentResource : resources) {
try {
ModelUtil.saveResource(currentResource, WorkspaceUtil.getResourceLogger());
} catch (final IOException e) {
WorkspaceUtil.logException("Project Space resource init failed!", e);
}
}
init();
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#delete(org.eclipse.core.runtime.IProgressMonitor)
*/
public void delete(IProgressMonitor monitor) throws IOException {
ESWorkspaceProviderImpl.getObserverBus().notify(DeleteProjectSpaceObserver.class).projectSpaceDeleted(this);
// delete project to notify listeners
getProject().delete();
// remove resources from resource set and delete them
deleteResource(getProject().eResource());
deleteResource(eResource());
deleteResource(getLocalChangePackage().eResource());
// TODO: remove project space from workspace, this is not the case if delete
// is performed via Workspace#deleteProjectSpace
ESWorkspaceProviderImpl.getInstance().getInternalWorkspace().getProjectSpaces().remove(this);
dispose();
}
private void deleteResource(Resource resource) throws IOException {
if (resource != null) {
resource.delete(null);
}
}
/**
* Returns the {@link ECrossReferenceAdapter}, if available.
*
* @param modelElement
* the model element for which to find inverse cross references
*
* @return the {@link ECrossReferenceAdapter}
*/
public Collection<Setting> findInverseCrossReferences(EObject modelElement) {
if (crossReferenceAdapter != null) {
return crossReferenceAdapter.getInverseReferences(modelElement);
}
return UsageCrossReferencer.find(modelElement, resourceSet);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#getResourceSet()
*/
public ResourceSet getResourceSet() {
return resourceSet;
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#setResourceSet(org.eclipse.emf.ecore.resource.ResourceSet)
*/
public void setResourceSet(ResourceSet resourceSet) {
this.resourceSet = resourceSet;
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#isTransient()
*/
public boolean isTransient() {
return isTransient;
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#isUpdated()
*/
public boolean isUpdated() throws ESException {
final PrimaryVersionSpec headVersion = resolveVersionSpec(Versions.createHEAD(getBaseVersion()),
new NullProgressMonitor());
return getBaseVersion().equals(headVersion);
}
/**
* {@inheritDoc}
*/
public void loginCompleted(ESUsersession session) {
// TODO Implement possibility in observerbus to register only for
// certain notifier
if (getUsersession() == null || !getUsersession().toAPI().equals(session)) {
return;
}
try {
transmitProperties();
// BEGIN SUPRESS CATCH EXCEPTION
} catch (final RuntimeException e) {
// END SUPRESS CATCH EXCEPTION
WorkspaceUtil.logException("Resuming file transfers or transmitting properties failed!", e);
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#makeTransient()
*/
public void makeTransient() {
if (initCompleted) {
throw new IllegalAccessError("Project Space cannot be set to transient after init.");
}
isTransient = true;
}
/**
* {@inheritDoc}
*/
public void mergeBranch(final PrimaryVersionSpec branchSpec, final ConflictResolver conflictResolver,
final IProgressMonitor monitor)
throws ESException {
if (branchSpec == null || conflictResolver == null) {
throw new IllegalArgumentException("Arguments must not be null.");
}
if (Versions.isSameBranch(getBaseVersion(), branchSpec)) {
throw new InvalidVersionSpecException("Can't merge branch with itself.");
}
final PrimaryVersionSpec commonAncestor = new ServerCall<PrimaryVersionSpec>(this) {
@Override
protected PrimaryVersionSpec run() throws ESException {
return resolveVersionSpec(Versions.createANCESTOR(getBaseVersion(),
branchSpec), monitor);
}
}.execute();
final List<ChangePackage> baseChanges = getChanges(commonAncestor, getBaseVersion());
final List<ChangePackage> branchChanges = getChanges(commonAncestor, branchSpec);
final ChangeConflictSet conflictSet = new ConflictDetector().calculateConflicts(branchChanges,
baseChanges, getProject());
if (conflictResolver.resolveConflicts(getProject(), conflictSet)) {
final ChangePackage resolvedConflicts = mergeResolvedConflicts(conflictSet, branchChanges, baseChanges);
RunESCommand.WithException.run(ESException.class, new Callable<Void>() {
public Void call() throws Exception {
applyChanges(getBaseVersion(), baseChanges, resolvedConflicts, monitor, false);
setMergedVersion(ModelUtil.clone(branchSpec));
return null;
}
}, getContentEditingDomain());
}
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#mergeResolvedConflicts(org.eclipse.emf.emfstore.internal.server.conflictDetection.ChangeConflictSet,
* java.util.List, java.util.List)
*/
public ChangePackage mergeResolvedConflicts(ChangeConflictSet conflictSet,
List<ChangePackage> myChangePackages, List<ChangePackage> theirChangePackages)
throws ChangeConflictException {
final Set<AbstractOperation> accceptedMineSet = new LinkedHashSet<AbstractOperation>();
final Set<AbstractOperation> rejectedTheirsSet = new LinkedHashSet<AbstractOperation>();
for (final ConflictBucket conflict : conflictSet.getConflictBuckets()) {
if (!conflict.isResolved()) {
throw new ChangeConflictException(
"Conflict during update occured and callback failed to resolve all conflicts!",
conflictSet);
}
accceptedMineSet.addAll(conflict.getAcceptedLocalOperations());
rejectedTheirsSet.addAll(conflict.getRejectedRemoteOperations());
}
final List<AbstractOperation> acceptedMineList = new LinkedList<AbstractOperation>();
for (final ChangePackage locChangePackage : myChangePackages) {
for (final AbstractOperation myOp : locChangePackage.getOperations()) {
if (conflictSet.getNotInvolvedInConflict().contains(myOp)) {
acceptedMineList.add(myOp);
} else if (accceptedMineSet.contains(myOp)) {
acceptedMineList.add(myOp);
}
accceptedMineSet.remove(myOp);
}
}
// add all remaining operations in acceptedMineSet (they have been generated during merge)
accceptedMineSet.addAll(accceptedMineSet);
final List<AbstractOperation> rejectedTheirsList = new LinkedList<AbstractOperation>();
for (final ChangePackage theirCP : theirChangePackages) {
for (final AbstractOperation theirOp : theirCP.getOperations()) {
if (rejectedTheirsSet.contains(theirOp)) {
rejectedTheirsList.add(theirOp);
}
}
}
final List<AbstractOperation> mergeResult = new ArrayList<AbstractOperation>(rejectedTheirsList.size()
+ acceptedMineList.size());
for (final AbstractOperation operationToReverse : rejectedTheirsList) {
mergeResult.add(0, operationToReverse.reverse());
}
mergeResult.addAll(acceptedMineList);
final ChangePackage result = VersioningFactory.eINSTANCE.createChangePackage();
result.getOperations().addAll(mergeResult);
return result;
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#getBranches()
*/
public List<BranchInfo> getBranches() throws ESException {
return new ServerCall<List<BranchInfo>>(this) {
@Override
protected List<BranchInfo> run() throws ESException {
final ConnectionManager cm = ESWorkspaceProviderImpl.getInstance().getConnectionManager();
return cm.getBranches(getSessionId(), getProjectId());
}
}.execute();
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#removeTag(org.eclipse.emf.emfstore.internal.server.model.versioning.PrimaryVersionSpec,
* org.eclipse.emf.emfstore.internal.server.model.versioning.TagVersionSpec)
*/
public void removeTag(PrimaryVersionSpec versionSpec, TagVersionSpec tag) throws ESException {
final ConnectionManager cm = ESWorkspaceProviderImpl.getInstance().getConnectionManager();
cm.removeTag(getUsersession().getSessionId(), getProjectId(), versionSpec, tag);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#resolve(org.eclipse.emf.emfstore.internal.server.model.url.ModelElementUrlFragment)
*/
public EObject resolve(ModelElementUrlFragment modelElementUrlFragment) throws MEUrlResolutionException {
final ModelElementId modelElementId = modelElementUrlFragment.getModelElementId();
final EObject modelElement = getProject().getModelElement(modelElementId);
if (modelElement == null) {
throw new MEUrlResolutionException();
}
return modelElement;
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#resolveVersionSpec(org.eclipse.emf.emfstore.internal.server.model.versioning.VersionSpec,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public PrimaryVersionSpec resolveVersionSpec(final VersionSpec versionSpec, IProgressMonitor monitor)
throws InvalidVersionSpecException, ESException {
return new ServerCall<PrimaryVersionSpec>(this, monitor) {
@Override
protected PrimaryVersionSpec run() throws ESException {
return getConnectionManager().resolveVersionSpec(
getSessionId(),
getProjectId(),
versionSpec);
}
}.execute();
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#revert()
*/
public void revert() {
while (!getOperations().isEmpty()) {
undoLastOperation();
}
updateDirtyState();
}
/**
* Saves the project space itself only, no containment children.
*/
public void saveProjectSpaceOnly() {
saveResource(eResource());
}
/**
* Saves the project space.
*/
public void save() {
saveProjectSpaceOnly();
saveChangePackage();
resourcePersister.saveDirtyResources(true);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#hasUnsavedChanges()
*/
public boolean hasUnsavedChanges() {
if (resourcePersister != null) {
return resourcePersister.isDirty();
}
// in case the project space has not been initialized yet
return false;
}
private void saveChangePackage() {
final ChangePackage localChangePackage = getLocalChangePackage();
if (localChangePackage.eResource() != null) {
saveResource(localChangePackage.eResource());
}
}
/**
* Save the given resource that is part of the project space resource set.
*
* @param resource
* the resource
*/
public void saveResource(Resource resource) {
try {
if (resource == null) {
if (!isTransient) {
WorkspaceUtil.logException("Resources of project space are not properly initialized!",
new IllegalProjectSpaceStateException("Resource to save is null"));
}
return;
}
ModelUtil.saveResource(resource, WorkspaceUtil.getResourceLogger());
} catch (final IOException e) {
WorkspaceUtil.logException("An error in the data was detected during save!"
+ " The safest way to deal with this problem is to delete this project and checkout again.", e);
}
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#setProperty(org.eclipse.emf.emfstore.internal.server.model.accesscontrol.OrgUnitProperty)
*/
public void setProperty(OrgUnitProperty property) {
// sanity checks
if (getUsersession() != null && getUsersession().getACUser() != null) {
try {
if (property.getProject() == null) {
property.setProject(ModelUtil.clone(getProjectId()));
} else if (!property.getProject().equals(getProjectId())) {
return;
}
final OrgUnitProperty prop = getProperty(property.getName());
prop.setValue(property.getValue());
} catch (final PropertyNotFoundException e) {
getUsersession().getACUser().getProperties().add(property);
propertyMap.put(property.getName(), property);
}
// the properties that have been altered are retained in a separate
// list
for (final OrgUnitProperty changedProperty : getUsersession().getChangedProperties()) {
if (changedProperty.getName().equals(property.getName())
&& changedProperty.getProject().equals(getProjectId())) {
changedProperty.setValue(property.getValue());
ESWorkspaceProviderImpl.getInstance().getWorkspace().toInternalAPI().save();
return;
}
}
getUsersession().getChangedProperties().add(property);
ESWorkspaceProviderImpl.getInstance().getWorkspace().toInternalAPI().save();
}
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#shareProject(org.eclipse.core.runtime.IProgressMonitor)
*/
public ProjectInfo shareProject(IProgressMonitor monitor) throws ESException {
return shareProject(null, monitor);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#shareProject(org.eclipse.emf.emfstore.internal.client.model.Usersession,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public ProjectInfo shareProject(Usersession session, IProgressMonitor monitor) throws ESException {
return new ShareController(this, session, monitor).execute();
}
/**
* Starts change recording on this workspace, resumes previous recordings if
* there are any.
*/
public void startChangeRecording() {
operationManager.startChangeRecording();
updateDirtyState();
}
/**
* Stops current recording of changes and adds recorded changes to this
* project spaces changes.
*/
public void stopChangeRecording() {
if (operationManager != null) {
operationManager.stopChangeRecording();
}
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#transmitProperties()
*/
public void transmitProperties() {
final List<OrgUnitProperty> temp = new ArrayList<OrgUnitProperty>();
for (final OrgUnitProperty changedProperty : getUsersession().getChangedProperties()) {
if (changedProperty.getProject() != null && changedProperty.getProject().equals(getProjectId())) {
temp.add(changedProperty);
}
}
final ListIterator<OrgUnitProperty> iterator = temp.listIterator();
while (iterator.hasNext()) {
try {
ESWorkspaceProviderImpl
.getInstance()
.getConnectionManager()
.transmitProperty(getUsersession().getSessionId(), iterator.next(), getUsersession().getACUser(),
getProjectId());
iterator.remove();
} catch (final ESException e) {
WorkspaceUtil.logException("Transmission of properties failed with exception", e);
}
}
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#undoLastOperation()
*/
public void undoLastOperation() {
undoLastOperations(1);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#undoLastOperation()
*/
public void undoLastOperations(int numberOfOperations) {
if (numberOfOperations <= 0) {
return;
}
if (!getOperations().isEmpty()) {
final List<AbstractOperation> operations = getOperations();
final AbstractOperation lastOperation = operations.get(operations.size() - 1);
applyOperations(Collections.singletonList(lastOperation.reverse()), false);
operationManager.notifyOperationUndone(lastOperation);
operations.remove(lastOperation);
undoLastOperations(--numberOfOperations);
}
updateDirtyState();
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#update(org.eclipse.core.runtime.IProgressMonitor)
*/
public PrimaryVersionSpec update(IProgressMonitor monitor) throws ESException {
return update(Versions.createHEAD(getBaseVersion()), null, monitor);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#update(org.eclipse.emf.emfstore.internal.server.model.versioning.VersionSpec)
*/
public PrimaryVersionSpec update(final VersionSpec version) throws ESException {
return update(version, null, null);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#update(org.eclipse.emf.emfstore.internal.server.model.versioning.VersionSpec,
* org.eclipse.emf.emfstore.client.callbacks.ESUpdateCallback, org.eclipse.core.runtime.IProgressMonitor)
*/
public PrimaryVersionSpec update(VersionSpec version, ESUpdateCallback callback, IProgressMonitor progress)
throws ESException {
return new UpdateController(this, version, callback, progress).execute();
}
/**
* Updates the dirty state of the project space.
*/
public void updateDirtyState() {
setDirty(!getOperations().isEmpty());
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.common.ESDisposable#dispose()
*/
@SuppressWarnings("unchecked")
public void dispose() {
if (disposed) {
return;
}
stopChangeRecording();
if (crossReferenceAdapter != null) {
getProject().eAdapters().remove(crossReferenceAdapter);
}
final ESCommandStack commandStack = (ESCommandStack) contentEditingDomain.getCommandStack();
commandStack.removeCommandStackObserver(operationManager);
commandStack.removeCommandStackObserver(resourcePersister);
getProject().removeIdEObjectCollectionChangeObserver(operationManager);
getProject().removeIdEObjectCollectionChangeObserver(resourcePersister);
ESWorkspaceProviderImpl.getObserverBus().unregister(resourcePersister);
ESWorkspaceProviderImpl.getObserverBus().unregister(this, ESLoginObserver.class);
ESWorkspaceProviderImpl.getObserverBus().unregister(this);
operationManager.dispose();
resourcePersister.dispose();
operationManager = null;
resourcePersister = null;
if (getProject().eResource() != null) {
getProject().eResource().getResourceSet().getResources().remove(getProject().eResource());
}
if (getLocalChangePackage().eResource() != null) {
getLocalChangePackage().eResource().getResourceSet().getResources()
.remove(getLocalChangePackage().eResource());
}
if (eResource() instanceof EMFStoreResource) {
final EMFStoreResource emfStoreResource = (EMFStoreResource) eResource();
emfStoreResource.getEObjectToIDMap().clear();
emfStoreResource.getIDToEObjectMap().clear();
}
if (getProject().eResource() instanceof EMFStoreResource) {
final EMFStoreResource emfStoreResource = (EMFStoreResource) getProject().eResource();
emfStoreResource.getEObjectToIDMap().clear();
emfStoreResource.getIDToEObjectMap().clear();
}
if (getLocalChangePackage().eResource() instanceof EMFStoreResource) {
final EMFStoreResource emfStoreResource = (EMFStoreResource) getLocalChangePackage().eResource();
emfStoreResource.getEObjectToIDMap().clear();
emfStoreResource.getIDToEObjectMap().clear();
}
contentEditingDomain.getCommandStack().flush();
disposed = true;
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#isShared()
*/
public boolean isShared() {
return getUsersession() != null;
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#isClosed()
*/
public boolean isClosed() {
return closed;
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#close(boolean)
*/
public void close(boolean saveBeforeClose) {
if (saveBeforeClose) {
save();
}
getWorkspace().removeProjectToProjectSpaceEntry(this);
dispose();
closed = true;
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#open()
*/
public void open() {
closed = false;
init();
getWorkspace().addProjectToProjectSpaceEntry(this);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#getContentEditingDomain()
*/
public EditingDomain getContentEditingDomain() {
return contentEditingDomain;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.client.model.ProjectSpace#flushContentCommandStack()
*/
public void flushContentCommandStack() {
if (contentEditingDomain != null) {
contentEditingDomain.getCommandStack().flush();
}
}
private void notifyPreRevertMyChanges(final ChangePackage changePackage) {
ESWorkspaceProviderImpl.getObserverBus().notify(ESMergeObserver.class)
.preRevertMyChanges(toAPI(), changePackage.toAPI());
}
private void notifyPostRevertMyChanges() {
ESWorkspaceProviderImpl.getObserverBus().notify(ESMergeObserver.class).postRevertMyChanges(toAPI());
}
private void notifyPostApplyTheirChanges(List<ChangePackage> theirChangePackages) {
// TODO ASYNC review this cancel
ESWorkspaceProviderImpl.getObserverBus().notify(ESMergeObserver.class)
.postApplyTheirChanges(toAPI(), APIUtil.mapToAPI(ESChangePackage.class, theirChangePackages));
}
private void notifyPostApplyMergedChanges(ChangePackage changePackage) {
ESWorkspaceProviderImpl.getObserverBus().notify(ESMergeObserver.class)
.postApplyMergedChanges(
toAPI(), changePackage.toAPI());
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.common.api.APIDelegate#toAPI()
*/
public ESLocalProjectImpl toAPI() {
if (esLocalProjectImpl == null) {
esLocalProjectImpl = createAPI();
}
return esLocalProjectImpl;
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.common.api.APIDelegate#createAPI()
*/
public ESLocalProjectImpl createAPI() {
return new ESLocalProjectImpl(this);
}
/**
* Returns the {@link ESRunnableContext} operations are applied in.
*
* @return the runnable context operations are executed in
*/
public ESRunnableContext getRunnableContext() {
return runnableContext;
}
}