package pyUML.actions; import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.ui.IObjectActionDelegate; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.uml2.uml.Classifier; import org.eclipse.uml2.uml.Model; import org.eclipse.uml2.uml.resource.UMLResource; import pyUML.backend.EclipseHelperMethods; import pyUML.backend.GlobalConstants; import pyUML.backend.JavaHelperMethods; import pyUML.backend.UMLToolsHelperMethods; import pyUML.exceptions.PyUMLCancelledException; import pyUML.exceptions.PyUMLParseException; import pyUML.pythonTree.PythonTreeRoot; public class SyncCodeAction implements IObjectActionDelegate, IRunnableWithProgress{ private IProject project; private PythonTreeRoot pythonRoot = null; public void setActivePart(IAction action, IWorkbenchPart targetPart) { // Auto-generated method stub } /** * Run this action manually with a Progress Monitor. * If the monitor is null, it will be created * A PythonTreeRoot object can be given so that * The code will not be re-analyzed for better performance. * @param project The synchronized project * @param root The PythonTreeRoot created before (optional) * @param monitor A progress monitor */ public static void run(IProject project, PythonTreeRoot root, IProgressMonitor monitor) { SyncCodeAction createCode = new SyncCodeAction(); createCode.setProject(project); createCode.setRoot(root); if (monitor == null) { ProgressMonitorDialog dialog = new ProgressMonitorDialog(null); try { dialog.run(false, true, createCode); } catch (InterruptedException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} } else { createCode.doSync(monitor); } } /** * run this action ( */ public void run(IAction action) { ProgressMonitorDialog monitor = new ProgressMonitorDialog(null); try { monitor.run(false, true, this); } catch (Exception e) { e.printStackTrace(); } } /** * Do a synchronize run. This is the central method. * It is called in automatic or manual mode * @param monitor a ProgressMonitor */ public void doSync(IProgressMonitor monitor) { // read project IPath projectPath = project.getLocation(); String umlFileName=projectPath. append(GlobalConstants.getPyUmlDir()). append(project.getName()+".uml").toOSString(); String umlSavedFileName=projectPath. append(GlobalConstants.getPyUmlDir()). append(project.getName()+"-backup.uml").toOSString(); File savedModel = new File(umlSavedFileName); File modelToCopy = new File(umlFileName); // read newest Model EObject diagramRoot = UMLToolsHelperMethods.loadUMLDiagram(umlFileName); // read backuped Model if it exists // to be able to see what changed between models EObject diagramRootBackup = null; if (savedModel.exists()) diagramRootBackup = UMLToolsHelperMethods.loadUMLDiagram(umlSavedFileName); Model model = (Model) diagramRoot; // get model -> xmi-id dictionary UMLResource res = (UMLResource) model.eResource(); Map modelXmiDict = res.getEObjectToIDMap(); // do the same for the backupModel: // get model -> xmi-id dictionary Map xmiModelDictOld = new HashMap(); int classCount = 0; // count classes for progression bar if (diagramRootBackup != null) { UMLResource resBack = (UMLResource) ((Model)diagramRootBackup).eResource(); Map modelXmiDictOld = resBack.getEObjectToIDMap(); // create reverse dict, so that xmi_id can be the key for (EObject modelObject : modelXmiDictOld.keySet()) { String xmi_id = modelXmiDictOld.get(modelObject); xmiModelDictOld.put(xmi_id, modelObject); if (modelObject instanceof Classifier) classCount++; } } // create PythonTree from PythonCode if (this.pythonRoot == null) try { this.pythonRoot = new PythonTreeRoot(this.project, true, monitor); } catch (PyUMLCancelledException e) { MessageDialog.openWarning(null, "Operation cancelled", "The Operation was cancelled by the user"); return; } catch (PyUMLParseException e) { MessageDialog.openError(null, "Error parsing project code", "There was an error parsing the python code of the current\n" + "project.\n" + "PyUML can not work as long as there are errors in the project code!\n" + "Please resolve the error and try again!\n\n" + "Error message was:\n\n"+ e.getMessage()); return; } // ######## Synchronize the Code ############################ monitor.beginTask("Synchronize the Python Code", IProgressMonitor.UNKNOWN); try { pythonRoot.synchronizeCode(model, modelXmiDict, xmiModelDictOld, monitor, classCount); } catch (PyUMLCancelledException e) { MessageDialog.openWarning(null, "Operation cancelled", "The Operation was cancelled by the user"); return; } catch (Throwable t) { t.printStackTrace(); MessageDialog.openError(null,"Error synchronizing Code!", t.getClass().getName() + " while synchronizing Code!: \n\n" + t.getMessage()); } // ########################################################## // backup model -> copy new current model over old one try{ JavaHelperMethods.copy(modelToCopy, savedModel); EclipseHelperMethods.updateFile(savedModel.getAbsolutePath(), this.project); } catch (IOException ex) { MessageDialog.openError(null,ex.getMessage(),"Unable to copy model file to: " + umlSavedFileName +"\nCode creation may not work properly!"); } monitor.done(); } /** * Called by Eclipse. If a project is selected, it is saved */ public void selectionChanged(IAction action, ISelection selection) { if (selection instanceof TreeSelection) { TreeSelection ts = (TreeSelection) selection; Object selectedElement = ts.getFirstElement(); if (selectedElement instanceof IProject) { IProject project = (IProject) selectedElement; this.project = project; } } } /** * Get the used project * @return */ public IProject getProject() { return project; } /** * Manually set the project to use * @param project */ public void setProject(IProject project) { this.project = project; } /** * Manually set a PythonTreeRoot to use (if given, * it will not be created again) * @param root */ public void setRoot(PythonTreeRoot root) { this.pythonRoot = root; } public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { doSync(monitor); } }