/******************************************************************************* * 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; import java.util.Date; import java.util.HashSet; import java.util.Set; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.emfstore.client.model.exceptions.InvalidHandleException; import org.eclipse.emf.emfstore.client.model.impl.OperationRecorder; import org.eclipse.emf.emfstore.common.model.ModelElementId; import org.eclipse.emf.emfstore.server.model.versioning.operations.CompositeOperation; import org.eclipse.emf.emfstore.server.model.versioning.operations.semantic.SemanticCompositeOperation; /** * A handle to control a composite operation during recording. * * @author koegel */ public class CompositeOperationHandle { private boolean isValid; private CompositeOperation compositeOperation; private OperationRecorder operationRecorder; private Set<EObject> removedElements; /** * Default constructor. * * @param operationManager * the change tracker this composite is tracked on * @param compositeOperation * the composite operation to be handled */ public CompositeOperationHandle(OperationRecorder operationRecorder, CompositeOperation compositeOperation) { this.operationRecorder = operationRecorder; removedElements = new HashSet<EObject>(); removedElements.addAll(operationRecorder.getRemovedElements()); this.compositeOperation = compositeOperation; isValid = true; } /** * Returns whether the handle is still valid. * * @return false if the composite operation is already completed or aborted. */ public boolean isValid() { return isValid; } /** * Aborts a composite operation. The state before starting the composite * operation will be recovered. * * @throws InvalidHandleException * if the handle is invalid */ public void abort() throws InvalidHandleException { checkAndCloseHandle(); operationRecorder.getRemovedElements().retainAll(removedElements); operationRecorder.abortCompositeOperation(); dropAllReferences(); } private void dropAllReferences() { compositeOperation = null; operationRecorder = null; removedElements = null; } private void checkAndCloseHandle() throws InvalidHandleException { if (!isValid) { throw new InvalidHandleException(); } isValid = false; } /** * Completes a composite operation. * * @param name * the name for the operation * @param description * the description of the operation * @param modelElementId * the id of the model element that is most important for the * operation * @throws InvalidHandleException * if the handle is invalid */ public void end(String name, String description, ModelElementId modelElementId) throws InvalidHandleException { checkAndCloseHandle(); compositeOperation.setCompositeName(name); compositeOperation.setCompositeDescription(description); compositeOperation.setClientDate(new Date()); compositeOperation.setReversed(false); compositeOperation.setModelElementId(modelElementId); operationRecorder.endCompositeOperation(); dropAllReferences(); } /** * Completes a the given semantic composite operation. * * @param semanticCompositeOperation * a semanticCompositeOperation that was executed and represents * the composite * @throws InvalidHandleException * if the handle is invalid */ public void end(SemanticCompositeOperation semanticCompositeOperation) throws InvalidHandleException { checkAndCloseHandle(); semanticCompositeOperation.setClientDate(new Date()); semanticCompositeOperation.setReversed(false); semanticCompositeOperation.getSubOperations().addAll( compositeOperation.getSubOperations()); operationRecorder.endCompositeOperation(semanticCompositeOperation); } }