/*******************************************************************************
* Copyright (c) 2015 Bruno Medeiros and other Contributors.
* 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:
* Bruno Medeiros - initial API and implementation
*******************************************************************************/
package melnorme.lang.ide.ui.dialogs;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue;
import java.util.ArrayList;
import java.util.Collections;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.swt.widgets.Display;
import melnorme.lang.ide.core.LangNature;
import melnorme.lang.ide.core.utils.EclipseUtils;
import melnorme.lang.ide.core.utils.ResourceUtils;
import melnorme.lang.ide.core.utils.ResourceUtils.CoreOperation;
import melnorme.lang.ide.ui.utils.UIOperationsStatusHandler;
import melnorme.lang.ide.ui.utils.operations.RunnableContextUtils;
import melnorme.utilbox.collections.ArrayList2;
import melnorme.utilbox.concurrency.OperationCancellation;
import melnorme.utilbox.core.CommonException;
/**
* Component to create (and removed) new Lang projects, usually used by New Project wizards.
*/
public abstract class ProjectCreationOperation {
public static interface IRevertAction {
public void run(IProgressMonitor monitor) throws CoreException;
}
protected final IRunnableContext context;
protected final ArrayList2<IRevertAction> revertActions = new ArrayList2<>();
protected final ArrayList2<Runnable> finishActions = new ArrayList2<>();
protected IProject createdProject;
public ProjectCreationOperation(IRunnableContext context) {
this.context = context;
}
protected IRunnableContext getRunnableContext() {
return context;
}
public IProject getCreatedProject() {
return createdProject;
}
public abstract IProject getProject() throws CoreException;
public abstract IPath getProjectLocation2();
protected boolean runOperation(boolean isCancellabe, String errorTitle, CoreOperation operation) {
try {
RunnableContextUtils.runOperationInWorkspace(getRunnableContext(), isCancellabe, operation);
return true;
} catch(OperationCancellation e) {
return false;
} catch(CommonException e) {
UIOperationsStatusHandler.handleStatus(true, errorTitle, e);
}
return false;
}
public boolean performCreateProject() {
boolean success = runOperation(true,
WizardMessages.LangNewProject_createProjectError_title, this::doCreateProject);
if(!success) {
revertProjectCreation();
}
return success;
}
protected void doCreateProject(IProgressMonitor monitor)
throws CoreException, CommonException, OperationCancellation {
createdProject = null;
if(getProject() == null) {
throw new CommonException("No project name specified.");
}
if(!getProject().exists()) {
String projectName = getProject().getName();
ResourceUtils.createAndOpenProject(projectName, getProjectLocation2(), false, monitor);
revertActions.add(new IRevertAction() {
@Override
public void run(IProgressMonitor pm) throws CoreException {
getProject().delete(true, pm);
}
});
}
if(!getProject().hasNature(LangNature.NATURE_ID)) {
EclipseUtils.addNature(getProject(), LangNature.NATURE_ID);
revertActions.add(new IRevertAction() {
@Override
public void run(IProgressMonitor pm) throws CoreException {
EclipseUtils.removeNature(getProject(), LangNature.NATURE_ID);
}
});
}
createdProject = getProject();
configureCreatedProject(monitor);
ResourceUtils.refresh(getProject(), EclipseUtils.om(monitor));
}
/**
* Configure created Lang project. Don't forget to add revert actions.
*/
protected abstract void configureCreatedProject(IProgressMonitor monitor)
throws CommonException, OperationCancellation, CoreException;
public boolean revertProjectCreation() {
return runOperation(true, WizardMessages.LangNewProject_removeProjectError_title,
this::doRevertProjectCreation);
}
protected void doRevertProjectCreation(IProgressMonitor monitor) throws CoreException {
ArrayList<IRevertAction> revertActionsToRun = new ArrayList<>(revertActions);
revertActions.clear(); // Clear this before running any code that can throw exceptions.
Collections.reverse(revertActionsToRun); // Run in reverse order.
for(IRevertAction revertAction : revertActionsToRun) {
revertAction.run(monitor);
}
}
public void performFinishActions() {
assertTrue(Display.getCurrent() != null);
// Runs in UI thread.
for(Runnable runnable : finishActions) {
runnable.run();
}
finishActions.clear();
}
}