blob: ae437b06d0c2fdcb2ad6e95cf203a47dd2971918 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2016 CEA LIST.
*
*
* 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:
* CEA LIST - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.refactoring.core;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
import org.eclipse.papyrus.infra.core.resource.NotFoundException;
import org.eclipse.papyrus.infra.services.validation.internal.EcoreDiagnostician;
import org.eclipse.papyrus.refactoring.Activator;
import org.eclipse.papyrus.refactoring.messages.Messages;
import org.eclipse.papyrus.refactoring.refactoringOnElement.AbstractTransformationOnElement;
import org.eclipse.papyrus.refactoring.refactoringOnElement.PapyrusCompositeChange;
import org.eclipse.papyrus.uml.tools.model.UmlModel;
import org.eclipse.papyrus.uml.tools.model.UmlUtils;
import org.eclipse.swt.widgets.Display;
/**
* This class represents the {@link Refactoring} for Papyrus refactoring.
*
* @noextend This class is not intended to be extended by clients.
*
*/
@SuppressWarnings("restriction")
public class PapyrusRefactoring extends Refactoring {
/** The human readable name */
protected String fName;
/** The ModelSet to be modified */
protected ModelSet fModelSet;
/** The {@link AbstractPapyrusTransformation} corresponding to this Papyrus refactoring */
protected AbstractPapyrusTransformation fPapyrusRefactoringTransformation;
/** Parameter used to remove duplicates when running the diagnostic on the preview and the getting the related change */
private Change change;
/**
* A {@link Runnable} to check final conditions before executing the transformation
*/
private class FinalConditionsRunnable implements Runnable {
private RefactoringStatus finalRefactoringStatus;
@Override
public void run() {
finalRefactoringStatus = fPapyrusRefactoringTransformation.checkFinalConditions();
}
public RefactoringStatus getfinalRefactoringStatus() {
return finalRefactoringStatus;
}
}
/**
* A {@link Runnable} to check initial conditions before executing the transformation
*/
private class InitialConditionsRunnable implements Runnable {
private RefactoringStatus initialRefactoringStatus;
@Override
public void run() {
initialRefactoringStatus = fPapyrusRefactoringTransformation.checkInitialConditions();
}
public RefactoringStatus getInitialRefactoringStatus() {
return initialRefactoringStatus;
}
}
/**
* Constructor.
*
* @param name
* The name associated to this transformation
* @param modelSet
* The modelSet to modify
* @param papyrusRefactoringTransformation
* The transformation to execute (rename, mutation,...)
*/
public PapyrusRefactoring(String name, ModelSet modelSet, AbstractPapyrusTransformation papyrusRefactoringTransformation) {
fName = name;
fModelSet = modelSet;
fPapyrusRefactoringTransformation = papyrusRefactoringTransformation;
}
@Override
public String getName() {
return fName;
}
/**
* Verify that the modelSet to transform has been provided prior to the execution
*
* @see org.eclipse.ltk.core.refactoring.Refactoring#checkInitialConditions(org.eclipse.core.runtime.IProgressMonitor)
*
* @param pm
* @return
* OK status if the modelSet was provided, null otherwise
* @throws CoreException
* @throws OperationCanceledException
*/
@Override
public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException {
RefactoringStatus status = new RefactoringStatus();
try {
pm.beginTask(Messages.PAPYRUSREFACTORING_CHECKPRECONDITIONS, 1);
if (fModelSet == null) {
status.merge(RefactoringStatus.createFatalErrorStatus(Messages.PAPYRUSREFACTORING_RESOURCEOPEN_ERROR));
} else {
InitialConditionsRunnable initialConditionsRunnable = new InitialConditionsRunnable();
Display.getDefault().syncExec(initialConditionsRunnable);
// Display.getDefault().asyncExec(initialConditionsRunnable);
return initialConditionsRunnable.getInitialRefactoringStatus();
}
} finally {
pm.done();
}
return null;
}
/**
* Verify that the transformation has not been canceled and that the transformation executed itself without errors
*
* @see org.eclipse.ltk.core.refactoring.Refactoring#checkFinalConditions(org.eclipse.core.runtime.IProgressMonitor)
*
* @param pm
* @return
* @throws CoreException
* @throws OperationCanceledException
*/
@Override
public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException {
try {
pm.beginTask(Messages.PAPYRUSREFACTORING_MODELVALIDITY, 2);
FinalConditionsRunnable finalConditionRunnable = new FinalConditionsRunnable();
Display.getDefault().syncExec(finalConditionRunnable);
// Display.getDefault().asyncExec(finalConditionRunnable);
RefactoringStatus status = finalConditionRunnable.getfinalRefactoringStatus();
if (status.getSeverity() != RefactoringStatus.FATAL) {
Diagnostic diagnostic = diagnosticRefactoring();
if (diagnostic != null && diagnostic.getSeverity() != Diagnostic.OK) {
status.addError(Messages.PAPYRUSREFACTORING_MODELVALIDITY_ERROR, new PapyrusRefactoringValidationStatusContext(diagnostic));
}
}
return status;
} finally {
pm.done();
}
}
/**
* Verify if the refactoring will affect the model validity.
*
* @return a Diagnostic of the impact of the refactoring.
*/
private Diagnostic diagnosticRefactoring() {
ModelSet previewModelSet = null;
if (fPapyrusRefactoringTransformation instanceof AbstractTransformationOnElement) {
change = new PapyrusCompositeChange((AbstractTransformationOnElement) fPapyrusRefactoringTransformation, fModelSet);
// previewModelSet = change.getCompositePreviewModelSet();
previewModelSet = ((PapyrusCompositeChange) change).getChangePreviewModelSet();
} else {
change = new PapyrusChange(fPapyrusRefactoringTransformation, fName, fModelSet);
previewModelSet = ((PapyrusChange) change).getChangePreviewModelSet();
}
if (previewModelSet != null) {
UmlModel umlModel = UmlUtils.getUmlModel(previewModelSet);
if (umlModel != null) {
EObject root;
try {
root = umlModel.lookupRoot();
TransactionalEditingDomain domain = previewModelSet.getTransactionalEditingDomain();
EcoreDiagnostician diagnostician = new EcoreDiagnostician();
AdapterFactory adapterFactory = domain instanceof AdapterFactoryEditingDomain ? ((AdapterFactoryEditingDomain) domain).getAdapterFactory() : null;
diagnostician.initialize(adapterFactory, new NullProgressMonitor());
return diagnostician.validate(root);
} catch (NotFoundException e) {
Activator.log.error(e);
}
}
}
return null;
}
@Override
public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException {
try {
pm.beginTask(Messages.PAPYRUSREFACTORING_EXECUTE, 1);
if (fPapyrusRefactoringTransformation instanceof AbstractTransformationOnElement) {
fPapyrusRefactoringTransformation.setModelSet(fModelSet);
// PapyrusCompositeChange compositeChange = new PapyrusCompositeChange((AbstractTransformationOnElement) fPapyrusRefactoringTransformation, fModelSet);
// return compositeChange;
} else {
// PapyrusChange change = new PapyrusChange(fPapyrusRefactoringTransformation, fName, fModelSet);
// return change;
}
return change;
} finally {
pm.done();
}
}
/**
* @return The corresponding {@link AbstractPapyrusTransformation}
*/
public AbstractPapyrusTransformation getPapyrusTransformation() {
return fPapyrusRefactoringTransformation;
}
}