blob: f0d4797b10872f694a50c62b47396180c03467f4 [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:
******************************************************************************/
package org.eclipse.emf.emfstore.internal.server.model.versioning.impl;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.ReversedLinesFileReader;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.impl.EObjectImpl;
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.EObjectContainmentEList;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.emfstore.internal.common.ResourceFactoryRegistry;
import org.eclipse.emf.emfstore.internal.common.model.Project;
import org.eclipse.emf.emfstore.internal.common.model.util.FileUtil;
import org.eclipse.emf.emfstore.internal.server.model.impl.api.ESFileBasedChangePackageImpl;
import org.eclipse.emf.emfstore.internal.server.model.versioning.FileBasedChangePackage;
import org.eclipse.emf.emfstore.internal.server.model.versioning.LogMessage;
import org.eclipse.emf.emfstore.internal.server.model.versioning.OperationProxy;
import org.eclipse.emf.emfstore.internal.server.model.versioning.VersioningFactory;
import org.eclipse.emf.emfstore.internal.server.model.versioning.VersioningPackage;
import org.eclipse.emf.emfstore.internal.server.model.versioning.impl.persistent.Direction;
import org.eclipse.emf.emfstore.internal.server.model.versioning.impl.persistent.FileBasedOperationIterable;
import org.eclipse.emf.emfstore.internal.server.model.versioning.impl.persistent.HasChangePackage;
import org.eclipse.emf.emfstore.internal.server.model.versioning.impl.persistent.OperationEmitter;
import org.eclipse.emf.emfstore.internal.server.model.versioning.impl.persistent.ReadLineCapable;
import org.eclipse.emf.emfstore.internal.server.model.versioning.impl.persistent.XmlTags;
import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.AbstractOperation;
import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.CompositeOperation;
import org.eclipse.emf.emfstore.server.ESCloseableIterable;
import org.eclipse.emf.emfstore.server.model.ESChangePackage;
import com.google.common.base.Optional;
/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>File Based Change Package</b></em>'.
* <!-- end-user-doc -->
* <p>
* The following features are implemented:
* <ul>
* <li>{@link org.eclipse.emf.emfstore.internal.server.model.versioning.impl.FileBasedChangePackageImpl#getLogMessage
* <em>Log Message</em>}</li>
* <li>{@link org.eclipse.emf.emfstore.internal.server.model.versioning.impl.FileBasedChangePackageImpl#getFilePath <em>
* File Path</em>}</li>
* <li>
* {@link org.eclipse.emf.emfstore.internal.server.model.versioning.impl.FileBasedChangePackageImpl#getOperationProxies
* <em>Operation Proxies</em>}</li>
* </ul>
* </p>
*
* @generated
*/
public class FileBasedChangePackageImpl extends EObjectImpl implements FileBasedChangePackage
{
/**
* The cached value of the '{@link #getLogMessage() <em>Log Message</em>}' containment reference.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @see #getLogMessage()
* @generated
* @ordered
*/
protected LogMessage logMessage;
/**
* Resource loading options.
*
* @generated NOT
*/
private static Map<Object, Object> loadingOptions;
/**
* The API representation of this change package.
*
* @generated NOT
*/
private ESChangePackage apiImpl;
/**
* Whether this change package has been initialized.
*
* TODO: move to Ecore? Maybe we don't even need this
*
* @generated NOT
*/
private boolean needsInit;
/**
* The default value of the '{@link #getFilePath() <em>File Path</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @see #getFilePath()
* @generated
* @ordered
*/
protected static final String FILE_PATH_EDEFAULT = null;
/**
* The cached value of the '{@link #getFilePath() <em>File Path</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @see #getFilePath()
* @generated
* @ordered
*/
protected String filePath = FILE_PATH_EDEFAULT;
/**
* The cached value of the '{@link #getOperationProxies() <em>Operation Proxies</em>}' containment reference list.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @see #getOperationProxies()
* @generated
* @ordered
*/
protected EList<OperationProxy> operationProxies;
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @generated
*/
protected FileBasedChangePackageImpl()
{
super();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @generated
*/
@Override
protected EClass eStaticClass()
{
return VersioningPackage.Literals.FILE_BASED_CHANGE_PACKAGE;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @generated
*/
public LogMessage getLogMessage()
{
if (logMessage != null && logMessage.eIsProxy())
{
final InternalEObject oldLogMessage = (InternalEObject) logMessage;
logMessage = (LogMessage) eResolveProxy(oldLogMessage);
if (logMessage != oldLogMessage)
{
final InternalEObject newLogMessage = (InternalEObject) logMessage;
NotificationChain msgs = oldLogMessage.eInverseRemove(this, EOPPOSITE_FEATURE_BASE
- VersioningPackage.FILE_BASED_CHANGE_PACKAGE__LOG_MESSAGE, null, null);
if (newLogMessage.eInternalContainer() == null)
{
msgs = newLogMessage.eInverseAdd(this, EOPPOSITE_FEATURE_BASE
- VersioningPackage.FILE_BASED_CHANGE_PACKAGE__LOG_MESSAGE, null, msgs);
}
if (msgs != null) {
msgs.dispatch();
}
if (eNotificationRequired()) {
eNotify(new ENotificationImpl(this, Notification.RESOLVE,
VersioningPackage.FILE_BASED_CHANGE_PACKAGE__LOG_MESSAGE, oldLogMessage, logMessage));
}
}
}
return logMessage;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @generated
*/
public LogMessage basicGetLogMessage()
{
return logMessage;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @generated
*/
public NotificationChain basicSetLogMessage(LogMessage newLogMessage, NotificationChain msgs)
{
final LogMessage oldLogMessage = logMessage;
logMessage = newLogMessage;
if (eNotificationRequired())
{
final ENotificationImpl notification = new ENotificationImpl(this, Notification.SET,
VersioningPackage.FILE_BASED_CHANGE_PACKAGE__LOG_MESSAGE, oldLogMessage, newLogMessage);
if (msgs == null) {
msgs = notification;
} else {
msgs.add(notification);
}
}
return msgs;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @generated
*/
public void setLogMessage(LogMessage newLogMessage)
{
if (newLogMessage != logMessage)
{
NotificationChain msgs = null;
if (logMessage != null) {
msgs = ((InternalEObject) logMessage).eInverseRemove(this, EOPPOSITE_FEATURE_BASE
- VersioningPackage.FILE_BASED_CHANGE_PACKAGE__LOG_MESSAGE, null, msgs);
}
if (newLogMessage != null) {
msgs = ((InternalEObject) newLogMessage).eInverseAdd(this, EOPPOSITE_FEATURE_BASE
- VersioningPackage.FILE_BASED_CHANGE_PACKAGE__LOG_MESSAGE, null, msgs);
}
msgs = basicSetLogMessage(newLogMessage, msgs);
if (msgs != null) {
msgs.dispatch();
}
}
else if (eNotificationRequired()) {
eNotify(new ENotificationImpl(this, Notification.SET,
VersioningPackage.FILE_BASED_CHANGE_PACKAGE__LOG_MESSAGE, newLogMessage, newLogMessage));
}
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @generated
*/
public String getFilePath()
{
return filePath;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @generated
*/
public void setFilePath(String newFilePath)
{
final String oldFilePath = filePath;
filePath = newFilePath;
if (eNotificationRequired()) {
eNotify(new ENotificationImpl(this, Notification.SET,
VersioningPackage.FILE_BASED_CHANGE_PACKAGE__FILE_PATH, oldFilePath, filePath));
}
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @generated
*/
public EList<OperationProxy> getOperationProxies()
{
if (operationProxies == null)
{
operationProxies = new EObjectContainmentEList.Resolving<OperationProxy>(OperationProxy.class, this,
VersioningPackage.FILE_BASED_CHANGE_PACKAGE__OPERATION_PROXIES);
}
return operationProxies;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @generated
*/
@Override
public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs)
{
switch (featureID)
{
case VersioningPackage.FILE_BASED_CHANGE_PACKAGE__LOG_MESSAGE:
return basicSetLogMessage(null, msgs);
case VersioningPackage.FILE_BASED_CHANGE_PACKAGE__OPERATION_PROXIES:
return ((InternalEList<?>) getOperationProxies()).basicRemove(otherEnd, msgs);
}
return super.eInverseRemove(otherEnd, featureID, msgs);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @generated
*/
@Override
public Object eGet(int featureID, boolean resolve, boolean coreType)
{
switch (featureID)
{
case VersioningPackage.FILE_BASED_CHANGE_PACKAGE__LOG_MESSAGE:
if (resolve) {
return getLogMessage();
}
return basicGetLogMessage();
case VersioningPackage.FILE_BASED_CHANGE_PACKAGE__FILE_PATH:
return getFilePath();
case VersioningPackage.FILE_BASED_CHANGE_PACKAGE__OPERATION_PROXIES:
return getOperationProxies();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @generated
*/
@SuppressWarnings("unchecked")
@Override
public void eSet(int featureID, Object newValue)
{
switch (featureID)
{
case VersioningPackage.FILE_BASED_CHANGE_PACKAGE__LOG_MESSAGE:
setLogMessage((LogMessage) newValue);
return;
case VersioningPackage.FILE_BASED_CHANGE_PACKAGE__FILE_PATH:
setFilePath((String) newValue);
return;
case VersioningPackage.FILE_BASED_CHANGE_PACKAGE__OPERATION_PROXIES:
getOperationProxies().clear();
getOperationProxies().addAll((Collection<? extends OperationProxy>) newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @generated
*/
@Override
public void eUnset(int featureID)
{
switch (featureID)
{
case VersioningPackage.FILE_BASED_CHANGE_PACKAGE__LOG_MESSAGE:
setLogMessage((LogMessage) null);
return;
case VersioningPackage.FILE_BASED_CHANGE_PACKAGE__FILE_PATH:
setFilePath(FILE_PATH_EDEFAULT);
return;
case VersioningPackage.FILE_BASED_CHANGE_PACKAGE__OPERATION_PROXIES:
getOperationProxies().clear();
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @generated
*/
@Override
public boolean eIsSet(int featureID)
{
switch (featureID)
{
case VersioningPackage.FILE_BASED_CHANGE_PACKAGE__LOG_MESSAGE:
return logMessage != null;
case VersioningPackage.FILE_BASED_CHANGE_PACKAGE__FILE_PATH:
return FILE_PATH_EDEFAULT == null ? filePath != null : !FILE_PATH_EDEFAULT.equals(filePath);
case VersioningPackage.FILE_BASED_CHANGE_PACKAGE__OPERATION_PROXIES:
return operationProxies != null && !operationProxies.isEmpty();
}
return super.eIsSet(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*
* @generated
*/
@Override
public String toString()
{
if (eIsProxy()) {
return super.toString();
}
final StringBuffer result = new StringBuffer(super.toString());
result.append(" (filePath: "); //$NON-NLS-1$
result.append(filePath);
result.append(')');
return result.toString();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.common.api.APIDelegate#toAPI()
*/
public ESChangePackage toAPI() {
if (apiImpl == null) {
apiImpl = createAPI();
}
return apiImpl;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.common.api.APIDelegate#createAPI()
*/
public ESChangePackage createAPI() {
return new ESFileBasedChangePackageImpl(this);
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage#addAll(java.util.List)
*/
public void addAll(List<AbstractOperation> ops) {
// TODO: LCP - file is reopened for each op
for (final AbstractOperation op : ops) {
add(op);
}
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage#add(org.eclipse.emf.emfstore.internal.server.model.versioning.operations.AbstractOperation)
*/
public void add(final AbstractOperation op) {
final Resource resource = createVirtualResource();
resource.getContents().add(op);
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
RandomAccessFile raf = null;
try {
outputStream.write(asBytes(XmlTags.OPERATIONS_START_TAG + XmlTags.NEWLINE));
resource.save(outputStream, loadingOptions());
outputStream.write((XmlTags.OPERATIONS_END_TAG + XmlTags.NEWLINE).getBytes());
final File file = new File(getFilePath());
if (needsInit) {
needsInit = false;
final FileWriter writer = new FileWriter(file);
writer.write(XmlTags.XML_HEADER + XmlTags.CHANGE_PACKAGE_START);
writer.write(XmlTags.CHANGE_PACKAGE_END);
writer.close();
}
raf = new RandomAccessFile(getFilePath(), "rw"); //$NON-NLS-1$
raf.skipBytes((int) (raf.length() - XmlTags.CHANGE_PACKAGE_END.getBytes().length));
raf.write(outputStream.toByteArray());
raf.write(XmlTags.CHANGE_PACKAGE_END.getBytes());
} catch (final IOException e) {
// avoid checked exception since this would lead to cluttered code
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(raf);
}
}
/**
*
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage#reverse()
*/
public FileBasedChangePackage reverse() {
final FileBasedChangePackage reversedChangePackage = VersioningFactory.eINSTANCE.createFileBasedChangePackage();
// TODO LCP: where should we put the file
try {
final File tempFile = File.createTempFile("temp-", ".eoc"); //$NON-NLS-1$ //$NON-NLS-2$
tempFile.deleteOnExit();
reversedChangePackage.initialize(tempFile.getAbsolutePath());
} catch (final IOException ex) {
// TODO
ex.printStackTrace();
}
final ESCloseableIterable<AbstractOperation> operationsHandle = reversedOperations();
try {
final Iterable<AbstractOperation> operations = operationsHandle.iterable();
for (final AbstractOperation operation : operations) {
final AbstractOperation reversedOperation = operation.reverse();
reversedChangePackage.add(reversedOperation);
}
} finally {
operationsHandle.close();
}
return reversedChangePackage;
}
public FileBasedChangePackage copy() {
final FileBasedChangePackage changePackage = VersioningFactory.eINSTANCE.createFileBasedChangePackage();
// TODO LCP: where should we put the file
try {
final File tempFile = File.createTempFile("temp-", ".eoc"); //$NON-NLS-1$ //$NON-NLS-2$
tempFile.deleteOnExit();
changePackage.initialize(tempFile.getAbsolutePath());
} catch (final IOException ex) {
// TODO
ex.printStackTrace();
}
final ESCloseableIterable<AbstractOperation> operationsHandle = operations();
try {
final Iterable<AbstractOperation> operations = operationsHandle.iterable();
for (final AbstractOperation operation : operations) {
changePackage.add(operation);
}
} finally {
operationsHandle.close();
}
return changePackage;
}
public ESCloseableIterable<AbstractOperation> reversedOperations() {
return new FileBasedOperationIterable(getFilePath(), Direction.Backward);
}
private static Map<Object, Object> loadingOptions() {
if (loadingOptions == null) {
loadingOptions = new LinkedHashMap<Object, Object>();
loadingOptions.put(XMLResource.OPTION_DECLARE_XML, Boolean.FALSE);
loadingOptions.put(XMLResource.OPTION_RECORD_ANY_TYPE_NAMESPACE_DECLARATIONS, Boolean.TRUE);
}
return loadingOptions;
}
private static byte[] asBytes(String s) {
return s.getBytes();
}
private static Resource createVirtualResource() {
final ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.setResourceFactoryRegistry(new ResourceFactoryRegistry());
return resourceSet.createResource(URI.createURI("virtualResource.xmi")); //$NON-NLS-1$
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage#size()
*/
public int size() {
int counter = 0;
ReversedLinesFileReader reversedLinesFileReader = null;
try {
reversedLinesFileReader = new ReversedLinesFileReader(new File(getFilePath()));
String line;
while ((line = reversedLinesFileReader.readLine()) != null) {
if (line.contains(XmlTags.OPERATIONS_END_TAG)) {
counter++;
}
}
} catch (final IOException ex) {
// TODO
ex.printStackTrace();
} finally {
IOUtils.closeQuietly(reversedLinesFileReader);
}
return counter;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage#operations()
*/
public ESCloseableIterable<AbstractOperation> operations() {
return new FileBasedOperationIterable(getFilePath(), Direction.Forward);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage#isEmpty()
*/
public boolean isEmpty() {
BufferedReader reader = null;
try {
final File file = new File(getFilePath());
if (!file.exists()) {
return true;
}
// TODO: move reader into operationemitter
reader = new BufferedReader(new FileReader(file));
final OperationEmitter operationEmitter = new OperationEmitter(Direction.Forward);
final ReadLineCapable create = ReadLineCapable.INSTANCE.create(reader);
return !operationEmitter.tryEmit(create).isPresent();
} catch (final IOException ex) {
throw new RuntimeException(ex);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (final IOException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage#removeAtEnd(int)
*/
public List<AbstractOperation> removeAtEnd(int n) {
ReversedLinesFileReader reversedLinesFileReader = null;
int counter = n;
try {
reversedLinesFileReader = new ReversedLinesFileReader(new File(getFilePath()));
final OperationEmitter operationEmitter = new OperationEmitter(Direction.Backward);
AbstractOperation operation;
final List<AbstractOperation> ops = new ArrayList<AbstractOperation>();
final ReadLineCapable reader = ReadLineCapable.INSTANCE.create(reversedLinesFileReader);
final Optional<AbstractOperation> optionalOperation = operationEmitter.tryEmit(reader);
while (counter > 0 && optionalOperation.isPresent()) {
operation = optionalOperation.get();
ops.add(operation);
counter -= 1;
}
// TODO: reuse readlinecapable?
final long offset = operationEmitter.getOffset();
final RandomAccessFile raf = new RandomAccessFile(getFilePath(), "rw"); //$NON-NLS-1$
final long skip = raf.length() + 1 - offset;
raf.seek(skip);
// TODO: duplicate code
final byte[] bytes = (XmlTags.NEWLINE + XmlTags.CHANGE_PACKAGE_END).getBytes();
raf.write(bytes);
raf.setLength(skip + bytes.length);
raf.close();
return ops;
} catch (final IOException ex) {
ex.printStackTrace();
} finally {
IOUtils.closeQuietly(reversedLinesFileReader);
}
return null;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage#clear()
*/
public void clear() {
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(getFilePath(), "rw"); //$NON-NLS-1$
raf.seek(0);
final String emptyChangePackage =
XmlTags.XML_HEADER + XmlTags.CHANGE_PACKAGE_START + XmlTags.CHANGE_PACKAGE_END;
raf.write(emptyChangePackage.getBytes());
raf.setLength(emptyChangePackage.length());
} catch (final FileNotFoundException ex) {
throw new RuntimeException(ex);
} catch (final IOException ex) {
throw new RuntimeException(ex);
} finally {
if (raf != null) {
try {
raf.close();
} catch (final IOException ex) {
ex.printStackTrace();
}
}
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage#attachToProjectSpace(org.eclipse.emf.emfstore.internal.server.model.versioning.impl.persistent.HasChangePackage)
*/
public void attachToProjectSpace(HasChangePackage changePackageHolder) {
// final URI operationsURI = ESClientURIUtil.createOperationsURI(getProjectSpace());
// final URI normalizedOperationUri = ESWorkspaceProviderImpl.getInstance().getInternalWorkspace()
// .getResourceSet().getURIConverter().normalize(operationsURI);
final URI changePackageUri = changePackageHolder.getChangePackageUri();
final String operationFileString = changePackageUri.toFileString();
final File operationFile = new File(operationFileString);
operationFile.delete();
final File thisFile = new File(getFilePath());
try {
FileUtil.moveAndOverwrite(thisFile, operationFile);
setFilePath(operationFileString);
changePackageHolder.setChangePackage(this);
} catch (final IOException ex) {
// TODO: LCP
ex.printStackTrace();
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage#leafSize()
*/
public int leafSize() {
final ESCloseableIterable<AbstractOperation> operationHandle = operations();
try {
return countLeafOperations(operationHandle.iterable());
} finally {
operationHandle.close();
}
}
private static int getSize(CompositeOperation compositeOperation) {
int ret = 0;
final EList<AbstractOperation> subOperations = compositeOperation.getSubOperations();
for (final AbstractOperation abstractOperation : subOperations) {
if (abstractOperation instanceof CompositeOperation) {
ret = ret + getSize((CompositeOperation) abstractOperation);
} else {
ret++;
}
}
return ret;
}
private static int countLeafOperations(Iterable<AbstractOperation> operations) {
int ret = 0;
for (final AbstractOperation operation : operations) {
if (operation instanceof CompositeOperation) {
ret = ret + getSize((CompositeOperation) operation);
} else {
ret++;
}
}
return ret;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.server.model.versioning.FileBasedChangePackage#initialize(java.lang.String)
*/
public void initialize(String filePath) {
setFilePath(filePath);
needsInit = false;
try {
final FileWriter writer = new FileWriter(filePath);
writer.write(XmlTags.XML_HEADER + XmlTags.CHANGE_PACKAGE_START);
writer.write(XmlTags.CHANGE_PACKAGE_END);
writer.close();
} catch (final IOException ex) {
// TODO LCP
ex.printStackTrace();
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage#apply(org.eclipse.emf.emfstore.internal.common.model.Project)
*/
public void apply(Project project) {
apply(project, false);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage#apply(org.eclipse.emf.emfstore.internal.common.model.Project,
* boolean)
*/
public void apply(Project project, boolean forceApplication) {
final ESCloseableIterable<AbstractOperation> operations = operations();
try {
final Iterable<AbstractOperation> operationsIterable = operations.iterable();
for (final AbstractOperation operation : operationsIterable) {
try {
operation.apply(project);
} catch (final IllegalStateException e) {
if (!forceApplication) {
throw e;
}
}
}
} finally {
operations.close();
}
}
} // FileBasedChangePackageImpl