/*******************************************************************************
* 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.server.core.helper;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
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.xmi.XMIResource;
import org.eclipse.emf.emfstore.common.model.ModelElementId;
import org.eclipse.emf.emfstore.common.model.Project;
import org.eclipse.emf.emfstore.common.model.util.ModelUtil;
import org.eclipse.emf.emfstore.server.ServerConfiguration;
import org.eclipse.emf.emfstore.server.exceptions.FatalEmfStoreException;
import org.eclipse.emf.emfstore.server.exceptions.StorageException;
import org.eclipse.emf.emfstore.server.model.ProjectHistory;
import org.eclipse.emf.emfstore.server.model.ProjectId;
import org.eclipse.emf.emfstore.server.model.ServerSpace;
import org.eclipse.emf.emfstore.server.model.versioning.ChangePackage;
import org.eclipse.emf.emfstore.server.model.versioning.PrimaryVersionSpec;
import org.eclipse.emf.emfstore.server.model.versioning.Version;
import org.eclipse.emf.emfstore.server.model.versioning.operations.AbstractOperation;
import org.eclipse.emf.emfstore.server.model.versioning.operations.CreateDeleteOperation;
import org.eclipse.emf.emfstore.server.model.versioning.operations.impl.CreateDeleteOperationImpl;
/**
* Helper for creating resources etc.
*
* @author wesendon
*/
public class ResourceHelper {
private final ServerSpace serverSpace;
/**
* Default constructor.
*
* @param serverSpace
* serverspace
* @throws FatalEmfStoreException
* in case of failure
*/
public ResourceHelper(ServerSpace serverSpace) throws FatalEmfStoreException {
this.serverSpace = serverSpace;
}
/**
* Creates a resource for project history.
*
* @param projectHistory
* project history
* @throws FatalEmfStoreException
* if saving fails
*/
public void createResourceForProjectHistory(ProjectHistory projectHistory) throws FatalEmfStoreException {
String fileName = getProjectFolder(projectHistory.getProjectId()) + "projectHistory"
+ ServerConfiguration.FILE_EXTENSION_PROJECTHISTORY;
saveInResource(projectHistory, fileName);
}
/**
* Creates a resource for a new version.
*
* @param version
* version
* @param projectId
* project id
* @throws FatalEmfStoreException
* if saving fails
*/
public void createResourceForVersion(Version version, ProjectId projectId) throws FatalEmfStoreException {
String fileName = getProjectFolder(projectId) + ServerConfiguration.FILE_PREFIX_VERSION
+ version.getPrimarySpec().getIdentifier() + ServerConfiguration.FILE_EXTENSION_VERSION;
saveInResource(version, fileName);
}
/**
* Creates a resource for a new project.
*
* @param project
* project
* @param projectId
* projectid
* @param versionId
* versionid
* @throws FatalEmfStoreException
* if saving fails
*/
public void createResourceForProject(Project project, PrimaryVersionSpec versionId, ProjectId projectId)
throws FatalEmfStoreException {
String filename = getProjectFolder(projectId) + getProjectFile(versionId.getIdentifier());
saveInResourceWithProject(project, filename, project);
}
/**
* Creates a resource for a changepackage.
*
* @param changePackage
* changepackage
* @param versionId
* versionId
* @param projectId
* projectId
* @throws FatalEmfStoreException
* if saving fails
*/
public void createResourceForChangePackage(ChangePackage changePackage, PrimaryVersionSpec versionId,
ProjectId projectId) throws FatalEmfStoreException {
String filename = getProjectFolder(projectId) + getChangePackageFile(versionId.getIdentifier());
List<Map.Entry<EObject, ModelElementId>> ignoredDatatypes = new ArrayList<Map.Entry<EObject, ModelElementId>>();
for (AbstractOperation op : changePackage.getOperations()) {
if (op instanceof CreateDeleteOperation) {
CreateDeleteOperation createDeleteOp = (CreateDeleteOperation) op;
for (Map.Entry<EObject, ModelElementId> e : ((CreateDeleteOperationImpl) createDeleteOp)
.getEObjectToIdMap().entrySet()) {
XMIResource res = (XMIResource) e.getKey().eResource();
EObject modelElement = e.getKey();
if (ModelUtil.isIgnoredDatatype(modelElement)) {
ignoredDatatypes.add(e);
continue;
}
if (res != null) {
res.setID(e.getKey(), e.getValue().getId());
}
}
// remove types to be ignored from mapping
createDeleteOp.getEObjectToIdMap().removeAll(ignoredDatatypes);
}
}
saveInResource(changePackage, filename);
}
/**
* Deletes a projectstate. The {@link Resource} the project is contained in
* will be unloaded as well as deleted.
*
* @param version
* the version to be deleted
* @param projectId
* the ID of the project to be deleted
*/
public void deleteProjectState(Version version, ProjectId projectId) {
int lastVersion = version.getPrimarySpec().getIdentifier();
Resource projectResource = version.getProjectState().eResource();
File file = new File(getProjectFolder(projectId) + getProjectFile(lastVersion));
version.setProjectState(null);
file.delete();
if (projectResource.isLoaded()) {
projectResource.unload();
}
projectResource.getResourceSet().getResources().remove(projectResource);
}
/**
* Gets and checks a number from a given server property. This number -
* referred as x - describes the size of an interval between projectstates.
* It's needed to determine whether a projectstate should be saved or be
* backuped.
*
* @see ServerConfiguration#PROJECTSTATE_VERSION_BACKUP_PERSISTENCE_EVERYXVERSIONS_X
* @see ServerConfiguration#PROJECTSTATE_VERSION_PERSISTENCE_EVERYXVERSIONS_X
* @param policy
* policy name from server configuration
* @param defaultPolicy
* default policy name from server configuration
* @param allowZero
* allow zero for x
* @return x
*/
public int getXFromPolicy(String policy, String defaultPolicy, boolean allowZero) {
int x;
try {
x = Integer.parseInt(ServerConfiguration.getProperties().getProperty(policy, defaultPolicy));
} catch (NumberFormatException e) {
x = 1;
ModelUtil.logWarning("Couldn't read property: " + policy + " , x set to 1", e);
}
if (x < 0) {
x = 1;
ModelUtil.logWarning("Policy " + policy + " with x < 0 not possible, x set to 1.");
}
if (!allowZero && x == 0) {
x = 1;
ModelUtil.logWarning("Policy " + policy + " with x = 0 not possible, x set to 1.");
}
return x;
}
/**
* Returns the file path to a given project.
*
* @param projectId
* the project id
* @return file path
*/
public String getProjectFolder(ProjectId projectId) {
return ServerConfiguration.getServerHome() + ServerConfiguration.FILE_PREFIX_PROJECTFOLDER + projectId.getId()
+ File.separatorChar;
}
private String getProjectFile(int versionNumber) {
return ServerConfiguration.FILE_PREFIX_PROJECTSTATE + versionNumber
+ ServerConfiguration.FILE_EXTENSION_PROJECTSTATE;
}
private String getChangePackageFile(int versionNumber) {
return ServerConfiguration.FILE_PREFIX_CHANGEPACKAGE + versionNumber
+ ServerConfiguration.FILE_EXTENSION_CHANGEPACKAGE;
}
private void saveInResource(EObject obj, String fileName) throws FatalEmfStoreException {
Resource resource = serverSpace.eResource().getResourceSet().createResource(URI.createFileURI(fileName));
resource.getContents().add(obj);
save(obj);
}
private void saveInResourceWithProject(EObject obj, String fileName, Project project) throws FatalEmfStoreException {
Resource resource = serverSpace.eResource().getResourceSet().createResource(URI.createFileURI(fileName));
resource.getContents().add(obj);
if (resource instanceof XMIResource) {
XMIResource xmiResource = (XMIResource) resource;
for (EObject modelElement : project.getAllModelElements()) {
ModelElementId modelElementId = project.getModelElementId(modelElement);
xmiResource.setID(modelElement, modelElementId.getId());
}
}
save(obj);
}
/**
* Saves the given EObject and sets the IDs on the eObject's resource for
* all model elements contained in the given project.
*
* @param eObject
* the EObject to be saved
* @param project
* the project, that is used to set the IDs of all model elements
* within the project on the resource
* @throws FatalEmfStoreException
* in case of failure
*/
public void saveWithProject(EObject eObject, Project project) throws FatalEmfStoreException {
Resource resource = eObject.eResource();
if (resource instanceof XMIResource) {
XMIResource xmiResource = (XMIResource) resource;
for (EObject modelElement : project.getAllModelElements()) {
ModelElementId modelElementId = project.getModelElementId(modelElement);
xmiResource.setID(modelElement, modelElementId.getId());
}
}
save(eObject);
}
/**
* Saves an eObject.
*
* @param object
* the object
* @throws FatalEmfStoreException
* in case of failure
*/
public void save(EObject object) throws FatalEmfStoreException {
try {
object.eResource().save(ModelUtil.getResourceSaveOptions());
// BEGIN SUPRESS CATCH EXCEPTION
} catch (Exception e) {
throw new FatalEmfStoreException(StorageException.NOSAVE, e);
}
// END SUPRESS CATCH EXCEPTION
}
/**
* Saves all modified resources in the serverspace's resource set.
*
* @throws FatalEmfStoreException
* in case of failure
*/
public void saveAll() throws FatalEmfStoreException {
for (Resource res : serverSpace.eResource().getResourceSet().getResources()) {
if (res.isLoaded() && res.isModified()) {
try {
res.save(ModelUtil.getResourceSaveOptions());
// BEGIN SUPRESS CATCH EXCEPTION
} catch (Exception e) {
throw new FatalEmfStoreException(StorageException.NOSAVE, e);
}
// END SUPRESS CATCH EXCEPTION
}
}
}
}