/**
* Copyright (c) 2013-2015 committers of YAKINDU and others.
* 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:
* committers of YAKINDU - initial API and implementation
*
*/
package org.yakindu.sct.ui.editor.modifications;
import java.util.Collections;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.IOperationHistory;
import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.core.commands.operations.OperationHistoryFactory;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
import org.eclipse.gmf.runtime.notation.View;
/**
* Implementation of {@link ISemanticModification} that wraps the modify call
* into an {@link ICommand} to execute on an {@link TransactionalEditingDomain}.
* Instances are stateful and refer to the {@link #targetView} property.
* Subclasses may add any other number of properties.
*
* Subclasses have to overwrite the hook methods {@link #check(EObject, View)}
* and {@link #execute(EObject, View)}.
*
* @author andreas muelder - Initial contribution and API
* @author terfloth
*
*/
public abstract class AbstractSemanticModification implements ISemanticModification {
protected View targetView;
@Override
public void setTargetView(View view) {
targetView = view;
}
@Override
public View getTargetView() {
return targetView;
}
/**
* This hook includes the logic, that is required to check if the modification can be applied.
*
* @param semanticObject
* @param view
* @return true if all preconditions for executing the command are valid and else false.
*/
protected abstract boolean check(final EObject semanticObject, final View view);
/**
* This hook method has to execute the concrete modification logic.
*
* @param semanticObject
* @param view
*/
protected abstract void execute(final EObject semanticObject, final View view);
@Override
public boolean isApplicable() {
if (getTargetView() == null) return false;
return check(getTargetView().getElement(), getTargetView());
}
/**
* Executes the modification in a transactional command.
*/
public void modify() {
if (! isApplicable()) throw new IllegalStateException("Modification " + getClass().getSimpleName() + " is not executable.");
final EObject semanticObject = getTargetView().getElement();
AbstractTransactionalCommand refactoringCommand = new AbstractTransactionalCommand(
TransactionUtil.getEditingDomain(semanticObject), getClass().getName(), Collections.EMPTY_LIST) {
@Override
protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info)
throws ExecutionException {
try {
AbstractSemanticModification.this.execute(semanticObject, getTargetView());
} catch (Exception ex) {
ex.printStackTrace();
return CommandResult.newErrorCommandResult(ex);
}
return CommandResult.newOKCommandResult();
}
};
executeCommand(refactoringCommand, semanticObject.eResource());
}
protected void executeCommand(IUndoableOperation command, Resource resource) {
IOperationHistory history = OperationHistoryFactory.getOperationHistory();
try {
history.execute(command, new NullProgressMonitor(), null);
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}