/*******************************************************************************
* 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:
******************************************************************************/
package org.eclipse.emf.emfstore.client.model.impl;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.common.util.BasicEMap;
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.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.emf.emfstore.client.model.CompositeOperationHandle;
import org.eclipse.emf.emfstore.client.model.Configuration;
import org.eclipse.emf.emfstore.client.model.ModelFactory;
import org.eclipse.emf.emfstore.client.model.ModifiedModelElementsCache;
import org.eclipse.emf.emfstore.client.model.OperationComposite;
import org.eclipse.emf.emfstore.client.model.ProjectSpace;
import org.eclipse.emf.emfstore.client.model.Usersession;
import org.eclipse.emf.emfstore.client.model.WorkspaceManager;
import org.eclipse.emf.emfstore.client.model.changeTracking.commands.EMFStoreCommandStack;
import org.eclipse.emf.emfstore.client.model.changeTracking.notification.recording.NotificationRecorder;
import org.eclipse.emf.emfstore.client.model.connectionmanager.ConnectionManager;
import org.eclipse.emf.emfstore.client.model.controller.CommitController;
import org.eclipse.emf.emfstore.client.model.controller.ShareController;
import org.eclipse.emf.emfstore.client.model.controller.UpdateController;
import org.eclipse.emf.emfstore.client.model.controller.callbacks.CommitCallback;
import org.eclipse.emf.emfstore.client.model.controller.callbacks.UpdateCallback;
import org.eclipse.emf.emfstore.client.model.exceptions.IllegalProjectSpaceStateException;
import org.eclipse.emf.emfstore.client.model.exceptions.MEUrlResolutionException;
import org.eclipse.emf.emfstore.client.model.exceptions.PropertyNotFoundException;
import org.eclipse.emf.emfstore.client.model.filetransfer.FileDownloadStatus;
import org.eclipse.emf.emfstore.client.model.filetransfer.FileInformation;
import org.eclipse.emf.emfstore.client.model.filetransfer.FileTransferManager;
import org.eclipse.emf.emfstore.client.model.importexport.impl.ExportChangesController;
import org.eclipse.emf.emfstore.client.model.importexport.impl.ExportProjectController;
import org.eclipse.emf.emfstore.client.model.observers.ConflictResolver;
import org.eclipse.emf.emfstore.client.model.observers.LoginObserver;
import org.eclipse.emf.emfstore.client.model.util.WorkspaceUtil;
import org.eclipse.emf.emfstore.client.properties.PropertyManager;
import org.eclipse.emf.emfstore.common.model.ModelElementId;
import org.eclipse.emf.emfstore.common.model.Project;
import org.eclipse.emf.emfstore.common.model.impl.IdentifiableElementImpl;
import org.eclipse.emf.emfstore.common.model.impl.ProjectImpl;
import org.eclipse.emf.emfstore.common.model.util.AutoSplitAndSaveResourceContainmentList;
import org.eclipse.emf.emfstore.common.model.util.ModelUtil;
import org.eclipse.emf.emfstore.server.exceptions.EmfStoreException;
import org.eclipse.emf.emfstore.server.exceptions.FileTransferException;
import org.eclipse.emf.emfstore.server.model.FileIdentifier;
import org.eclipse.emf.emfstore.server.model.ProjectInfo;
import org.eclipse.emf.emfstore.server.model.accesscontrol.ACUser;
import org.eclipse.emf.emfstore.server.model.accesscontrol.OrgUnitProperty;
import org.eclipse.emf.emfstore.server.model.url.ModelElementUrlFragment;
import org.eclipse.emf.emfstore.server.model.versioning.ChangePackage;
import org.eclipse.emf.emfstore.server.model.versioning.HistoryInfo;
import org.eclipse.emf.emfstore.server.model.versioning.HistoryQuery;
import org.eclipse.emf.emfstore.server.model.versioning.LogMessage;
import org.eclipse.emf.emfstore.server.model.versioning.PrimaryVersionSpec;
import org.eclipse.emf.emfstore.server.model.versioning.TagVersionSpec;
import org.eclipse.emf.emfstore.server.model.versioning.VersionSpec;
import org.eclipse.emf.emfstore.server.model.versioning.VersioningFactory;
import org.eclipse.emf.emfstore.server.model.versioning.operations.AbstractOperation;
import org.eclipse.emf.emfstore.server.model.versioning.operations.CompositeOperation;
import org.eclipse.emf.emfstore.server.model.versioning.operations.semantic.SemanticCompositeOperation;
/**
* Project space base class that contains custom user methods.
*
* @author emueller
*
*/
public abstract class ProjectSpaceBase extends IdentifiableElementImpl implements ProjectSpace, LoginObserver {
private FileTransferManager fileTransferManager;
private boolean initCompleted;
private boolean isTransient;
private ModifiedModelElementsCache modifiedModelElementsCache;
private AutoSplitAndSaveResourceContainmentList<AbstractOperation> operationsList;
private OperationManager operationManager;
private OperationRecorder operationRecorder;
private PropertyManager propertyManager;
private HashMap<String, OrgUnitProperty> propertyMap;
private StatePersister statePersister;
/**
* Constructor.
*/
public ProjectSpaceBase() {
this.propertyMap = new HashMap<String, OrgUnitProperty>();
modifiedModelElementsCache = new ModifiedModelElementsCache(this);
WorkspaceManager.getObserverBus().register(modifiedModelElementsCache);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#addFile(java.io.File)
*/
public FileIdentifier addFile(File file) throws FileTransferException {
return fileTransferManager.addFile(file);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#addOperations(java.util.List)
*/
public void addOperations(List<? extends AbstractOperation> operations) {
getOperations().addAll(operations);
updateDirtyState();
for (AbstractOperation op : operations) {
// do not notify on composite start, wait until completion
if (op instanceof CompositeOperation) {
// check of automatic composite if yes then continue
if (((CompositeOperation) op).getMainOperation() == null) {
return;
}
}
operationManager.notifyOperationExecuted(op);
}
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#addTag(org.eclipse.emf.emfstore.server.model.versioning.PrimaryVersionSpec,
* org.eclipse.emf.emfstore.server.model.versioning.TagVersionSpec)
*/
public void addTag(PrimaryVersionSpec versionSpec, TagVersionSpec tag) throws EmfStoreException {
final ConnectionManager cm = WorkspaceManager.getInstance().getConnectionManager();
cm.addTag(getUsersession().getSessionId(), getProjectId(), versionSpec, tag);
}
/**
* Applies a list of operations to the project. The change tracking will be
* stopped meanwhile and the operations are added to the project space.
*
* @param operations
* the list of operations to be applied upon the project space
*/
public void applyOperations(List<AbstractOperation> operations) {
applyOperations(operations, 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
*
* @see #applyOperationsWithRecording(List, boolean)
*/
public void applyOperations(List<AbstractOperation> operations, boolean addOperations) {
stopChangeRecording();
try {
for (AbstractOperation operation : operations) {
try {
operation.apply(getProject());
// BEGIN SUPRESS CATCH EXCEPTION
} catch (RuntimeException e) {
WorkspaceUtil.handleException(e);
}
// END SUPRESS CATCH EXCEPTION
}
if (addOperations) {
addOperations(operations);
}
} finally {
startChangeRecording();
}
}
/**
* Applies a list of operations to the project. This method is used by {@link #importLocalChanges(String)}. This
* method redirects to {@link #applyOperationsWithRecording(List, boolean, boolean)}, using
* false for semantic apply.
*
* @param operations
* the list of operations to be applied upon the project space
* @param force
* if true, no exception is thrown if
* {@link AbstractOperation#apply(org.eclipse.emf.emfstore.common.model.IdEObjectCollection)} fails
*/
public void applyOperationsWithRecording(List<AbstractOperation> operations, boolean force) {
applyOperationsWithRecording(operations, force, false);
}
/**
* Applies a list of operations to the project. It is possible to force
* import operations. Change tracking is not stopped while applying the
* changes.
*
* @param operations
* the list of operations to be applied upon the project space
* @param force
* if true, no exception is thrown if
* {@link AbstractOperation#apply(org.eclipse.emf.emfstore.common.model.IdEObjectCollection)} fails
* @param semanticApply
* if true, performs a semanticApply, if possible (see {@link SemanticCompositeOperation})
*/
public void applyOperationsWithRecording(List<AbstractOperation> operations, boolean force, boolean semanticApply) {
for (AbstractOperation operation : operations) {
try {
if (semanticApply && operation instanceof SemanticCompositeOperation) {
((SemanticCompositeOperation) operation).semanticApply(getProject());
} else {
operation.apply(getProject());
}
} catch (IllegalStateException e) {
if (!force) {
throw e;
}
}
}
}
private void assignElementToResource(Resource resource, EObject modelElement) {
resource.getContents().add(modelElement);
// FIXME: this is not nice!
((XMIResource) resource).setID(modelElement, getProject().getModelElementId(modelElement).getId());
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#beginCompositeOperation()
*/
public CompositeOperationHandle beginCompositeOperation() {
return this.operationManager.beginCompositeOperation();
}
public void cleanCutElements() {
for (EObject cutElement : getProject().getCutElements()) {
getProject().deleteModelElement(cutElement);
}
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#commit(org.eclipse.emf.emfstore.server.model.versioning.LogMessage,
* org.eclipse.emf.emfstore.client.model.controller.callbacks.CommitCallback,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public PrimaryVersionSpec commit(LogMessage logMessage, CommitCallback callback, IProgressMonitor monitor)
throws EmfStoreException {
return new CommitController(this, logMessage, callback, monitor).execute();
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.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.client.model.ProjectSpace#exportLocalChanges(java.io.File)
*/
public void exportLocalChanges(File file) throws IOException {
new ExportChangesController(this).execute(file, new NullProgressMonitor());
}
public void exportProject(File file, IProgressMonitor progressMonitor) throws IOException {
new ExportProjectController(this).execute(file, progressMonitor);
}
public void exportProject(File file) throws IOException {
new ExportProjectController(this).execute(file, new NullProgressMonitor());
}
/**
* {@inheritDoc}
*
* @generated NOT
*/
public List<ChangePackage> getChanges(VersionSpec sourceVersion, VersionSpec targetVersion)
throws EmfStoreException {
final ConnectionManager connectionManager = WorkspaceManager.getInstance().getConnectionManager();
List<ChangePackage> changes = connectionManager.getChanges(getUsersession().getSessionId(), getProjectId(),
sourceVersion, targetVersion);
return changes;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#getFile(org.eclipse.emf.emfstore.server.model.FileIdentifier,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public FileDownloadStatus getFile(FileIdentifier fileIdentifier) throws FileTransferException {
return fileTransferManager.getFile(fileIdentifier);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#getFileInfo(org.eclipse.emf.emfstore.server.model.FileIdentifier)
*/
public FileInformation getFileInfo(FileIdentifier fileIdentifier) {
return fileTransferManager.getFileInfo(fileIdentifier);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#getHistoryInfo(org.eclipse.emf.emfstore.server.model.versioning.HistoryQuery)
*/
public List<HistoryInfo> getHistoryInfo(HistoryQuery query) throws EmfStoreException {
return getWorkspace().getHistoryInfo(getUsersession(), getProjectId(), query);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#getLocalChangePackage()
*/
public ChangePackage getLocalChangePackage(boolean canonize) {
ChangePackage changePackage = VersioningFactory.eINSTANCE.createChangePackage();
// copy operations from ProjectSpace
for (AbstractOperation abstractOperation : getOperations()) {
AbstractOperation copy = EcoreUtil.copy(abstractOperation);
changePackage.getOperations().add(copy);
}
return changePackage;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#getModifiedModelElementsCache()
*/
public ModifiedModelElementsCache getModifiedModelElementsCache() {
return modifiedModelElementsCache;
}
/**
* Get the current notification recorder.
*
* @return the recorder
*/
public NotificationRecorder getNotificationRecorder() {
return this.operationRecorder.getNotificationRecorder();
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#getOperationManager()
*/
public OperationManager getOperationManager() {
return operationManager;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#getOperations()
*/
public List<AbstractOperation> getOperations() {
// check if operation composite exists
OperationComposite operationComposite = this.getLocalOperations();
if (operationComposite == null) {
this.setLocalOperations(ModelFactory.eINSTANCE.createOperationComposite());
operationComposite = getLocalOperations();
}
if (isTransient) {
return operationComposite.getOperations();
}
if (operationsList == null) {
operationsList = new AutoSplitAndSaveResourceContainmentList<AbstractOperation>(operationComposite,
operationComposite.getOperations(), this.eResource().getResourceSet(),
Configuration.getWorkspaceDirectory() + "ps-" + getIdentifier() + File.separatorChar + "operations",
".off");
}
return operationsList;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#getProjectInfo()
* @generated NOT
*/
public ProjectInfo getProjectInfo() {
ProjectInfo projectInfo = org.eclipse.emf.emfstore.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.client.model.ProjectSpace#getPropertyManager()
*/
public PropertyManager getPropertyManager() {
if (this.propertyManager == null) {
this.propertyManager = new PropertyManager(this);
}
return this.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) {
OrgUnitProperty orgUnitProperty = propertyMap.get(name);
if (orgUnitProperty != null) {
return orgUnitProperty;
}
}
throw new PropertyNotFoundException();
}
/**
* Returns the {@link StatePersister}.
*
* @return persister
*/
public StatePersister getStatePersister() {
return statePersister;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#importLocalChanges(java.lang.String)
*/
public void importLocalChanges(String fileName) throws IOException {
ResourceSetImpl resourceSet = new ResourceSetImpl();
Resource resource = resourceSet.getResource(URI.createFileURI(fileName), true);
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.");
}
ChangePackage changePackage = (ChangePackage) directContents.get(0);
applyOperationsWithRecording(changePackage.getOperations(), true);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#init()
* @generated NOT
*/
@SuppressWarnings("unchecked")
public void init() {
initCompleted = true;
// getProject().initCaches();
this.fileTransferManager = new FileTransferManager(this);
// EObjectChangeNotifier changeNotifier = new EObjectChangeNotifier(
// this.getProject());
this.operationRecorder = new OperationRecorder(this.getProject(),
((ProjectImpl) this.getProject()).getChangeNotifier());
this.operationManager = new OperationManager(operationRecorder, this);
this.operationManager.addOperationListener(modifiedModelElementsCache);
statePersister = new StatePersister(((ProjectImpl) this.getProject()).getChangeNotifier(),
((EMFStoreCommandStack) Configuration.getEditingDomain().getCommandStack()), this.getProject());
// TODO: initialization order important
this.getProject().addIdEObjectCollectionChangeObserver(this.operationRecorder);
this.getProject().addIdEObjectCollectionChangeObserver(statePersister);
if (getProject() instanceof ProjectImpl) {
((ProjectImpl) this.getProject()).setUndetachable(operationRecorder);
((ProjectImpl) this.getProject()).setUndetachable(statePersister);
}
if (getUsersession() != null) {
WorkspaceManager.getObserverBus().register(this, LoginObserver.class);
ACUser acUser = getUsersession().getACUser();
if (acUser != null) {
for (OrgUnitProperty p : acUser.getProperties()) {
if (p.getProject() != null && p.getProject().equals(getProjectId())) {
propertyMap.put(p.getName(), p);
}
}
}
}
modifiedModelElementsCache.initializeCache();
startChangeRecording();
cleanCutElements();
}
public FileTransferManager getFileTransferManager() {
return fileTransferManager;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#initResources(org.eclipse.emf.ecore.resource.ResourceSet)
* @generated NOT
*/
public void initResources(ResourceSet resourceSet) {
initCompleted = true;
String projectSpaceFileNamePrefix = Configuration.getWorkspaceDirectory()
+ Configuration.getProjectSpaceDirectoryPrefix() + getIdentifier() + File.separatorChar;
String projectSpaceFileName = projectSpaceFileNamePrefix + this.getIdentifier()
+ Configuration.getProjectSpaceFileExtension();
String operationsCompositeFileName = projectSpaceFileNamePrefix + this.getIdentifier()
+ Configuration.getOperationCompositeFileExtension();
String projectFragementsFileNamePrefix = projectSpaceFileNamePrefix + Configuration.getProjectFolderName()
+ File.separatorChar;
URI projectSpaceURI = URI.createFileURI(projectSpaceFileName);
URI operationCompositeURI = URI.createFileURI(operationsCompositeFileName);
setResourceCount(0);
String fileName = projectFragementsFileNamePrefix + getResourceCount()
+ Configuration.getProjectFragmentFileExtension();
URI fileURI = URI.createFileURI(fileName);
List<Resource> resources = new ArrayList<Resource>();
Resource resource = resourceSet.createResource(fileURI);
// if resource splitting fails, we need a reference to the old resource
resource.getContents().add(this.getProject());
resources.add(resource);
setResourceCount(getResourceCount() + 1);
if (Configuration.isResourceSplittingEnabled()) {
splitResources(resourceSet, projectFragementsFileNamePrefix, resources, this.getProject());
} else {
for (EObject modelElement : getProject().getAllModelElements()) {
((XMIResource) resource).setID(modelElement, getProject().getModelElementId(modelElement).getId());
}
}
Resource operationCompositeResource = resourceSet.createResource(operationCompositeURI);
if (this.getLocalOperations() == null) {
this.setLocalOperations(ModelFactory.eINSTANCE.createOperationComposite());
}
operationCompositeResource.getContents().add(this.getLocalOperations());
resources.add(operationCompositeResource);
Resource projectSpaceResource = resourceSet.createResource(projectSpaceURI);
projectSpaceResource.getContents().add(this);
resources.add(projectSpaceResource);
// save all resources that have been created
for (Resource currentResource : resources) {
try {
currentResource.save(Configuration.getResourceSaveOptions());
} catch (IOException e) {
WorkspaceUtil.logException("Project Space resource init failed!", e);
}
}
init();
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#isTransient()
*/
public boolean isTransient() {
return isTransient;
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#isUpdated()
*/
public boolean isUpdated() throws EmfStoreException {
PrimaryVersionSpec headVersion = resolveVersionSpec(VersionSpec.HEAD_VERSION);
return getBaseVersion().equals(headVersion);
}
/**
* {@inheritDoc}
*/
public void loginCompleted(Usersession session) {
// TODO Implement possibility in observerbus to register only for
// certain notifier
if (getUsersession() == null || !getUsersession().equals(session)) {
return;
}
try {
transmitProperties();
// BEGIN SUPRESS CATCH EXCEPTION
} catch (RuntimeException e) {
// END SUPRESS CATCH EXCEPTION
WorkspaceUtil.logException("Resuming file transfers or transmitting properties failed!", e);
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.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 boolean merge(PrimaryVersionSpec target, ConflictResolver conflictResolver) throws EmfStoreException {
// merge the conflicts
ChangePackage myCp = this.getLocalChangePackage(true);
List<ChangePackage> theirCps = this.getChanges(getBaseVersion(), target);
if (conflictResolver.resolveConflicts(getProject(), theirCps, myCp, getBaseVersion(), target)) {
// revert the local operations and apply all their operations
this.revert();
for (ChangePackage changePackage : theirCps) {
applyOperations(changePackage.getOperations(), false);
}
// generate merge result and apply to local workspace
List<AbstractOperation> acceptedMine = conflictResolver.getAcceptedMine();
List<AbstractOperation> rejectedTheirs = conflictResolver.getRejectedTheirs();
List<AbstractOperation> mergeResult = new ArrayList<AbstractOperation>();
for (AbstractOperation operationToReverse : rejectedTheirs) {
mergeResult.add(0, operationToReverse.reverse());
}
mergeResult.addAll(acceptedMine);
applyOperations(mergeResult, true);
this.setBaseVersion(target);
saveProjectSpaceOnly();
return true;
} else {
// merge could not proceed
return false;
}
}
/**
* {@inheritDoc}
*
* @generated NOT
*/
public void removeTag(PrimaryVersionSpec versionSpec, TagVersionSpec tag) throws EmfStoreException {
final ConnectionManager cm = WorkspaceManager.getInstance().getConnectionManager();
cm.removeTag(getUsersession().getSessionId(), getProjectId(), versionSpec, tag);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#resolve(org.eclipse.emf.emfstore.server.model.url.ModelElementUrlFragment)
*/
public EObject resolve(ModelElementUrlFragment modelElementUrlFragment) throws MEUrlResolutionException {
ModelElementId modelElementId = modelElementUrlFragment.getModelElementId();
EObject modelElement = getProject().getModelElement(modelElementId);
if (modelElement == null) {
throw new MEUrlResolutionException();
}
return modelElement;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#resolveVersionSpec(org.eclipse.emf.emfstore.server.model.versioning.VersionSpec)
* @throws EmfStoreException
* @generated NOT
*/
public PrimaryVersionSpec resolveVersionSpec(VersionSpec versionSpec) throws EmfStoreException {
ConnectionManager connectionManager = WorkspaceManager.getInstance().getConnectionManager();
return connectionManager.resolveVersionSpec(getUsersession().getSessionId(), getProjectId(), versionSpec);
}
/**
* {@inheritDoc}
*
* @generated NOT
*/
public void revert() {
while (!getOperations().isEmpty()) {
undoLastOperation();
}
updateDirtyState();
}
/**
* Saves the project space itself only, no containment children.
*/
public void saveProjectSpaceOnly() {
saveResource(this.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;
}
resource.save(Configuration.getResourceSaveOptions());
} catch (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.client.model.ProjectSpace#setProperty(org.eclipse.emf.emfstore.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;
}
OrgUnitProperty prop = getProperty(property.getName());
prop.setValue(property.getValue());
} catch (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 (OrgUnitProperty changedProperty : getUsersession().getChangedProperties()) {
if (changedProperty.getName().equals(property.getName())
&& changedProperty.getProject().equals(getProjectId())) {
changedProperty.setValue(property.getValue());
WorkspaceManager.getInstance().getCurrentWorkspace().save();
return;
}
}
getUsersession().getChangedProperties().add(property);
WorkspaceManager.getInstance().getCurrentWorkspace().save();
}
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#shareProject()
*/
public void shareProject() throws EmfStoreException {
shareProject(null, null);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#shareProject(org.eclipse.emf.emfstore.client.model.Usersession,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public void shareProject(Usersession session, IProgressMonitor monitor) throws EmfStoreException {
new ShareController(this, session, monitor).execute();
}
private void splitResources(ResourceSet resourceSet, String projectFragementsFileNamePrefix,
List<Resource> resources, Project project) {
String fileName;
URI fileURI;
Resource resource = project.eResource();
int counter = 0;
for (EObject modelElement : project.getAllModelElements()) {
// never split maps
if (modelElement instanceof BasicEMap.Entry) {
((XMIResource) modelElement.eContainer().eResource()).setID(modelElement, getProject()
.getModelElementId(modelElement).getId());
continue;
}
if (counter > Configuration.getMaxMECountPerResource()) {
fileName = projectFragementsFileNamePrefix + getResourceCount()
+ Configuration.getProjectFragmentFileExtension();
fileURI = URI.createFileURI(fileName);
resource = resourceSet.createResource(fileURI);
setResourceCount(getResourceCount() + 1);
resources.add(resource);
counter = 0;
}
counter++;
assignElementToResource(resource, modelElement);
}
}
/**
* Starts change recording on this workspace, resumes previous recordings if
* there are any.
*
* @generated NOT
*/
public void startChangeRecording() {
this.operationRecorder.startChangeRecording();
updateDirtyState();
}
/**
* Stops current recording of changes and adds recorded changes to this
* project spaces changes.
*
* @generated NOT
*/
public void stopChangeRecording() {
this.operationRecorder.stopChangeRecording();
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#transmitProperties()
*/
public void transmitProperties() {
List<OrgUnitProperty> temp = new ArrayList<OrgUnitProperty>();
for (OrgUnitProperty changedProperty : getUsersession().getChangedProperties()) {
if (changedProperty.getProject() != null && changedProperty.getProject().equals(getProjectId())) {
temp.add(changedProperty);
}
}
ListIterator<OrgUnitProperty> iterator = temp.listIterator();
while (iterator.hasNext()) {
try {
WorkspaceManager
.getInstance()
.getConnectionManager()
.transmitProperty(getUsersession().getSessionId(), iterator.next(), getUsersession().getACUser(),
getProjectId());
iterator.remove();
} catch (EmfStoreException e) {
WorkspaceUtil.logException("Transmission of properties failed with exception", e);
}
}
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#undoLastOperation()
*/
public void undoLastOperation() {
if (!this.getOperations().isEmpty()) {
List<AbstractOperation> operations = this.getOperations();
AbstractOperation lastOperation = operations.get(operations.size() - 1);
stopChangeRecording();
try {
lastOperation.reverse().apply(getProject());
operationManager.notifyOperationUndone(lastOperation);
// BEGIN SUPRESS CATCH EXCEPTION
} catch (RuntimeException exception) {
// END SUPRESS CATCH EXCEPTION
WorkspaceUtil.handleException(exception);
} finally {
startChangeRecording();
}
operations.remove(lastOperation);
}
updateDirtyState();
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#update()
*/
public PrimaryVersionSpec update() throws EmfStoreException {
return update(VersionSpec.HEAD_VERSION);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#update(org.eclipse.emf.emfstore.server.model.versioning.VersionSpec)
*/
public PrimaryVersionSpec update(final VersionSpec version) throws EmfStoreException {
return update(version, null, null);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.client.model.ProjectSpace#update(org.eclipse.emf.emfstore.server.model.versioning.VersionSpec,
* org.eclipse.emf.emfstore.client.model.controller.callbacks.UpdateCallback,
* org.eclipse.core.runtime.IProgressMonitor)
*/
public PrimaryVersionSpec update(VersionSpec version, UpdateCallback callback, IProgressMonitor progress)
throws EmfStoreException {
return new UpdateController(this, version, callback, progress).execute();
}
/**
* Updates the dirty state of the project space.
*/
public void updateDirtyState() {
setDirty(!getOperations().isEmpty());
}
}