Eclipse-PyUML/pyUml/src/pyUML/actions/SyncCodeAction.java

234 lines
7.0 KiB
Java
Executable File

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<EObject, String> modelXmiDict = res.getEObjectToIDMap();
// do the same for the backupModel:
// get model -> xmi-id dictionary
Map<String, EObject> xmiModelDictOld = new HashMap<String, EObject>();
int classCount = 0; // count classes for progression bar
if (diagramRootBackup != null) {
UMLResource resBack = (UMLResource) ((Model)diagramRootBackup).eResource();
Map<EObject, String> 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);
}
}