package com.redhat.ceylon.eclipse.code.wizard;
import static com.redhat.ceylon.eclipse.code.editor.Navigation.gotoLocation;
import static com.redhat.ceylon.eclipse.code.imports.ModuleImportUtil.appendImportStatement;
import static com.redhat.ceylon.eclipse.code.preferences.ModuleImportSelectionDialog.selectModules;
import static com.redhat.ceylon.eclipse.code.refactor.MoveUtil.escapePackageName;
import static com.redhat.ceylon.eclipse.code.wizard.WizardUtil.runOperation;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getProjectTypeChecker;
import static com.redhat.ceylon.eclipse.util.ModuleQueries.getModuleSearchResults;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.AbstractOperation;
import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;
import com.redhat.ceylon.cmr.api.ModuleSearchResult;
import com.redhat.ceylon.eclipse.code.preferences.ModuleImportContentProvider;
import com.redhat.ceylon.eclipse.code.preferences.ModuleImportSelectionDialog;
import com.redhat.ceylon.eclipse.core.builder.CeylonBuilder;
import com.redhat.ceylon.eclipse.ui.CeylonPlugin;
import com.redhat.ceylon.ide.common.modulesearch.ModuleVersionNode;
public class NewModuleWizard extends Wizard implements INewWizard {
private final class CreateModuleOperation extends AbstractOperation {
private IFile result;
private List<IUndoableOperation> ops =
new ArrayList<IUndoableOperation>(3);
private Map<String, String> imports;
private Set<String> sharedImports;
public IFile getResult() {
return result;
}
public CreateModuleOperation(Map<String,String> imports,
Set<String> sharedImports) {
super("New Ceylon Module");
this.imports = imports;
this.sharedImports = sharedImports;
}
@Override
public IStatus execute(IProgressMonitor monitor, IAdaptable info)
throws ExecutionException {
IPackageFragment pf = page.getPackageFragment();
CreateSourceFileOperation op = runFunctionOp(pf);
ops.add(op);
IStatus status = op.execute(monitor, info);
if (!status.isOK()) {
return status;
}
result = op.getFile();
op = moduleDescriptorOp(pf);
status = op.execute(monitor, info);
ops.add(op);
if (!status.isOK()) {
return status;
}
op = packageDescriptorOp(pf);
status = op.execute(monitor, info);
ops.add(op);
if (!status.isOK()) {
return status;
}
return Status.OK_STATUS;
}
private CreateSourceFileOperation packageDescriptorOp(
IPackageFragment pf) {
String moduleName =
escapePackageName(pf.getElementName());
boolean preamble = page.isIncludePreamble();
String newline = System.lineSeparator();
StringBuilder packageDescriptor =
new StringBuilder();
if (page.isShared()) {
packageDescriptor
.append("shared ");
}
packageDescriptor
.append("package ")
.append(moduleName)
.append(";")
.append(newline);
return new CreateSourceFileOperation(page.getSourceDir(),
pf, "package", preamble,
packageDescriptor.toString());
}
private CreateSourceFileOperation moduleDescriptorOp(
IPackageFragment pf) {
String moduleName =
escapePackageName(pf.getElementName());
boolean preamble = page.isIncludePreamble();
String newline = System.lineSeparator();
StringBuilder moduleDescriptor =
new StringBuilder();
IProject project =
pf.getResource()
.getProject();
boolean compileToJava =
CeylonBuilder.compileToJava(project);
boolean compileToJs =
CeylonBuilder.compileToJs(project);
if (compileToJava==compileToJs) {
//no native annotation
}
else if (!compileToJs) {
moduleDescriptor
.append("native(\"jvm\")")
.append(newline);
}
else if (!compileToJava) {
moduleDescriptor
.append("native(\"js\")")
.append(newline);
}
moduleDescriptor
.append("module ")
.append(moduleName)
.append(" \"")
.append(page.getVersion())
.append("\"")
.append(" {");
for (Map.Entry<String,String> entry:
imports.entrySet()) {
String name = entry.getKey();
String version = entry.getValue();
boolean shared = sharedImports.contains(name);
appendImportStatement(moduleDescriptor,
shared, null, name, version, newline);
}
if (!imports.isEmpty()) {
moduleDescriptor.append(newline);
}
moduleDescriptor.append("}").append(newline);
return new CreateSourceFileOperation(page.getSourceDir(),
pf, "module", preamble,
moduleDescriptor.toString());
}
private CreateSourceFileOperation runFunctionOp(
IPackageFragment pf) {
String moduleName = pf.getElementName();
boolean preamble = page.isIncludePreamble();
String newline = System.lineSeparator();
String runFunction =
new StringBuilder()
.append("\"Run the module `")
.append(moduleName)
.append("`.\"")
.append(newline)
.append("shared void run() {")
.append(newline)
.append(" ")
.append(newline)
.append("}")
.toString();
return new CreateSourceFileOperation(
page.getSourceDir(),
pf, page.getUnitName(),
preamble, runFunction);
}
@Override
public IStatus redo(IProgressMonitor monitor,
IAdaptable info)
throws ExecutionException {
return execute(monitor, info);
}
@Override
public IStatus undo(IProgressMonitor monitor,
IAdaptable info)
throws ExecutionException {
for (IUndoableOperation op: ops) {
op.undo(monitor, info);
}
return Status.OK_STATUS;
}
}
private IStructuredSelection selection;
private NewModuleWizardPage page;
private ImportModulesWizardPage importsPage;
private IWorkbench workbench;
public NewModuleWizard() {
setDialogSettings(CeylonPlugin.getInstance()
.getDialogSettings());
setWindowTitle("New Ceylon Module");
}
@Override
public void init(IWorkbench workbench,
IStructuredSelection selection) {
this.selection = selection;
this.workbench = workbench;
}
@Override
public boolean performFinish() {
CreateModuleOperation op =
new CreateModuleOperation(
importsPage.getImports(),
importsPage.getSharedImports());
if (runOperation(op, getContainer())) {
BasicNewResourceWizard.selectAndReveal(
op.getResult(),
workbench.getActiveWorkbenchWindow());
gotoLocation(op.getResult().getFullPath(), 0);
return true;
}
else {
return false;
}
}
@Override
public void addPages() {
super.addPages();
if (page == null) {
page = new NewModuleWizardPage();
page.init(workbench, selection);
}
if (importsPage == null) {
importsPage = new ImportModulesWizardPage() {
IProject getProject() {
IPackageFragmentRoot sourceDir =
page.getSourceDir();
return sourceDir==null ? null :
sourceDir.getResource()
.getProject();
}
@Override
Map<String, ModuleVersionNode> getModules() {
return selectModules(new ModuleImportSelectionDialog(
getShell(),
new ModuleImportContentProvider(null, getProject()) {
@Override
public ModuleSearchResult getModules(String prefix) {
IProject project =
page.getSourceDir()
.getJavaProject()
.getProject();
return getModuleSearchResults(prefix, null,
getProjectTypeChecker(project),
project);
}
}), getProject());
}
};
}
addPage(page);
addPage(importsPage);
}
}