package org.jactr.eclipse.ui.wizards.model; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.PrintStream; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import org.antlr.runtime.tree.CommonTree; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.ISelection; 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.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWizard; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.IDE; import org.jactr.eclipse.core.CorePlugin; import org.jactr.eclipse.core.bundles.descriptors.ModuleDescriptor; import org.jactr.eclipse.core.parser.ProjectSensitiveParserImportDelegate; import org.jactr.io.IOUtilities; import org.jactr.io.antlr3.builder.JACTRBuilder; import org.jactr.io.antlr3.compiler.CompilationError; import org.jactr.io.antlr3.compiler.CompilationWarning; import org.jactr.io.antlr3.misc.ASTSupport; import org.jactr.io.generator.CodeGeneratorFactory; import org.jactr.io.generator.ICodeGenerator; /** * This is a sample new wizard. Its role is to create a new file resource in the * provided container. If the container resource (a folder or a project) is * selected in the workspace when the wizard is opened, it will accept it as the * target container. The wizard creates one file with the extension "mpe". If a * sample multi-page editor (also available as a template) is registered for the * same extension, it will be able to open it. */ public class NewModelWizard extends Wizard implements INewWizard { /** * Logger definition */ static private final transient Log LOGGER = LogFactory .getLog(NewModelWizard.class); static public final String ID = NewModelWizard.class.getName(); private NewModelWizardPage1 page; private ISelection selection; /** * Constructor for SampleNewWizard. */ public NewModelWizard() { super(); setNeedsProgressMonitor(true); } /** * Adding the page to the wizard. */ @Override public void addPages() { page = new NewModelWizardPage1(selection); addPage(page); } /** * This method is called when 'Finish' button is pressed in the wizard. We * will create an operation and run it using wizard as execution context. */ @Override public boolean performFinish() { final String projectName = page.getProjectName(); final String fileName = page.getFileName(); final Collection<ModuleDescriptor> extensions = page.getSelectedModules(); IRunnableWithProgress op = new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException { // ClassLoader cl = UIPlugin.changeClassLoader(); try { doFinish(projectName, fileName, extensions, monitor); } catch (CoreException e) { throw new InvocationTargetException(e); } finally { monitor.done(); // UIPlugin.restoreClassLoader(cl); } } }; try { getContainer().run(true, false, op); } catch (InterruptedException e) { return false; } catch (InvocationTargetException e) { Throwable realException = e.getTargetException(); MessageDialog.openError(getShell(), "Error", realException.getMessage()); return false; } return true; } /** * The worker method. It will find the container, create the file if missing * or just replace its contents, and open the editor on the newly created * file. */ private void doFinish(final String projectName, final String fileName, final Collection<ModuleDescriptor> modules, IProgressMonitor monitor) throws CoreException { // create a sample file monitor.beginTask("Creating " + fileName, 2); IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IProject project = root.getProject(projectName); if (!project.exists()) throwCoreException("Project \"" + projectName + "\" does not exist."); /* * make sure we have the model directory */ IFolder folder = project.getFolder("models"); if (!folder.exists()) folder.create(true, true, null); final IFile file = folder.getFile(new Path(fileName)); try { InputStream stream = openContentStream(project, fileName, modules); if (file.exists()) file.setContents(stream, true, true, monitor); else file.create(stream, true, monitor); stream.close(); } catch (Exception e) { CorePlugin.error("Could not find code generator for " + fileName, e); } monitor.worked(1); monitor.setTaskName("Opening file for editing..."); getShell().getDisplay().asyncExec(new Runnable() { public void run() { IWorkbenchPage page = PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getActivePage(); try { if (file.exists()) IDE.openEditor(page, file, true); } catch (PartInitException e) { } } }); monitor.worked(1); monitor.done(); } /** * We will initialize file contents with a sample text. */ @SuppressWarnings("unchecked") private InputStream openContentStream(IProject project, String modelName, Collection<ModuleDescriptor> modules) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); BufferedOutputStream bos = new BufferedOutputStream(baos); try { CommonTree modelTree = IOUtilities.createModelDescriptor(modelName .substring( 0, modelName.lastIndexOf("."))); ProjectSensitiveParserImportDelegate delegate = new ProjectSensitiveParserImportDelegate(); delegate.setProject(project); CommonTree modulesRoot = ASTSupport.getFirstDescendantWithType(modelTree, JACTRBuilder.MODULES); for (ModuleDescriptor moduleExt : modules) try { String moduleClass = moduleExt.getClassName(); if (LOGGER.isDebugEnabled()) LOGGER.debug("Installing module into new model " + moduleClass); /* * and do the actual import of content */ CommonTree node = delegate.importModuleInto(modelTree, moduleClass, true); modulesRoot.addChild(node); } catch (CompilationWarning warning) { // this would come up if we can't get the code generator CorePlugin.warn("Problems get module code for " + moduleExt.getName() + " in " + modelName, warning); } catch (CompilationError error) { CorePlugin.warn("Problems get module code for " + moduleExt.getName() + " in " + modelName, error); } String extension = modelName.substring(modelName.lastIndexOf(".") + 1, modelName.length()).toLowerCase(); ICodeGenerator codeGen = CodeGeneratorFactory.getCodeGenerator(extension); if (codeGen != null) { PrintStream ps = new PrintStream(bos); Collection<StringBuilder> text = codeGen.generate(modelTree, true); for (StringBuilder line : text) ps.println(line.toString()); } else CorePlugin.error("Could not find code generator for " + modelName + " based on " + extension); bos.flush(); bos.close(); } catch (Exception e) { CorePlugin.error("Could not create model code for " + modelName, e); } return new ByteArrayInputStream(baos.toByteArray()); } private void throwCoreException(String message) throws CoreException { IStatus status = new Status(IStatus.ERROR, "org.jactr.eclipse.ui", IStatus.OK, message, null); throw new CoreException(status); } /** * We will accept the selection in the workbench to see if we can initialize * from it. * * @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection) */ public void init(IWorkbench workbench, IStructuredSelection selection) { this.selection = selection; } }