329 lines
10 KiB
Java
Executable File
329 lines
10 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.IFile;
|
|
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.emf.common.util.URI;
|
|
import org.eclipse.emf.ecore.EAnnotation;
|
|
import org.eclipse.emf.ecore.EObject;
|
|
import org.eclipse.emf.ecore.resource.Resource;
|
|
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
|
|
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.IEditorPart;
|
|
import org.eclipse.ui.IEditorReference;
|
|
import org.eclipse.ui.IWorkbenchWindow;
|
|
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
|
|
import org.eclipse.ui.PlatformUI;
|
|
import org.eclipse.uml2.uml.Model;
|
|
import org.eclipse.uml2.uml.Profile;
|
|
import org.eclipse.uml2.uml.ProfileApplication;
|
|
import org.eclipse.uml2.uml.internal.impl.UMLFactoryImpl;
|
|
import org.eclipse.uml2.uml.resource.UMLResource;
|
|
|
|
import pyUML.backend.EclipseHelperMethods;
|
|
import pyUML.backend.GlobalConstants;
|
|
import pyUML.backend.PyUMLProfile;
|
|
import pyUML.backend.UMLToolsHelperMethods;
|
|
import pyUML.exceptions.PyUMLCancelledException;
|
|
import pyUML.exceptions.PyUMLParseException;
|
|
import pyUML.listeners.ModelChangeListener;
|
|
import pyUML.pythonTree.PythonTreeRoot;
|
|
|
|
|
|
public class SyncModelAction implements IWorkbenchWindowActionDelegate, IRunnableWithProgress{
|
|
|
|
IProject project = null;
|
|
|
|
public void dispose() {
|
|
// Auto-generated method stub
|
|
}
|
|
|
|
public void init(IWorkbenchWindow window) {
|
|
// Auto-generated method stub
|
|
}
|
|
|
|
/**
|
|
* Static method to manually run a Model synchronization
|
|
* @param project The model to use
|
|
*/
|
|
public static void runModelSync(IProject project) {
|
|
SyncModelAction delegate = new SyncModelAction();
|
|
delegate.project = project;
|
|
delegate.run((IAction) null);
|
|
}
|
|
|
|
public void run(IAction action) {
|
|
|
|
ProgressMonitorDialog monitor = new ProgressMonitorDialog(null);
|
|
|
|
try {
|
|
monitor.run(false, true, this);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The central method - synchronizes the model by the python code
|
|
* @param monitor a ProgressMonitor
|
|
*/
|
|
public void doSync(IProgressMonitor monitor) {
|
|
// Ensure a project was given
|
|
if (this.project == null) {
|
|
return;
|
|
}
|
|
|
|
if (monitor != null) {
|
|
monitor.beginTask("Look for existing Model", IProgressMonitor.UNKNOWN);
|
|
}
|
|
|
|
// save all open editors
|
|
EclipseHelperMethods.saveAllOpenEditors();
|
|
|
|
// initialize XMI dictionaries as empty -> they are filled, if a
|
|
// model already exists
|
|
Map<EObject, String> modelXmiDict = new HashMap<EObject, String>();
|
|
Map<String, EObject> xmiModelDict = new HashMap<String, EObject>();
|
|
|
|
// read project
|
|
IPath projectPath = project.getLocation();
|
|
|
|
// define uml file name
|
|
String umlFileName=projectPath.
|
|
append(GlobalConstants.getPyUmlDir()).
|
|
append(project.getName()+".uml").toOSString();
|
|
|
|
// look for model file
|
|
Model model;
|
|
Resource resource;
|
|
File modelFile = new File(umlFileName);
|
|
if (modelFile.exists()) {
|
|
// read Model
|
|
EObject diagramRoot = UMLToolsHelperMethods.loadUMLDiagram(umlFileName);
|
|
model = (Model) diagramRoot;
|
|
resource = model.eResource();
|
|
|
|
// get model -> xmi-id dictionary
|
|
UMLResource r = (UMLResource) resource;
|
|
modelXmiDict = r.getEObjectToIDMap();
|
|
|
|
// create reverse dict, so that xmi_id can be the key
|
|
for (EObject modelObject : modelXmiDict.keySet()) {
|
|
String xmi_id = modelXmiDict.get(modelObject);
|
|
xmiModelDict.put(xmi_id, modelObject);
|
|
}
|
|
} else {
|
|
// Model file does *not* exist ->
|
|
// A model has to be created
|
|
resource = new ResourceSetImpl().createResource(
|
|
URI.createFileURI(umlFileName));
|
|
|
|
model = UMLFactoryImpl.eINSTANCE.createModel();
|
|
model.setName(project.getName());
|
|
|
|
resource.getContents().add(model);
|
|
|
|
try {
|
|
resource.save(null);
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
// update model in eclipse
|
|
EclipseHelperMethods.updateFile(resource.getURI().toFileString(), project);
|
|
}
|
|
|
|
|
|
// define profile file name
|
|
String profileFileName=projectPath.
|
|
append(GlobalConstants.getPyUmlDir()).
|
|
append("PyUMLProfile.uml").toOSString();
|
|
|
|
// look for UML profile file
|
|
Profile profile;
|
|
Resource profileResource;
|
|
File profileFile = new File(profileFileName);
|
|
if (! profileFile.exists()) {
|
|
IFile profileIFile = EclipseHelperMethods.createFile(profileFile.getPath(), project);
|
|
try {
|
|
profileIFile.create(null, true, null);
|
|
}catch (CoreException e) {
|
|
e.printStackTrace();
|
|
}
|
|
EclipseHelperMethods.StringToIFile(profileIFile, PyUMLProfile.getProfileString());
|
|
}
|
|
|
|
// read and add Profile
|
|
EObject profileRoot = UMLToolsHelperMethods.loadUMLDiagram(profileFileName);
|
|
profile = (Profile) profileRoot;
|
|
|
|
if (model.getProfileApplication(profile) == null) {
|
|
|
|
ProfileApplication profApplication = model.createProfileApplication();
|
|
profApplication.setAppliedProfile(profile);
|
|
EAnnotation eannot = profApplication.createEAnnotation("http://www.eclipse.org/uml2/2.0.0/UML");
|
|
}
|
|
|
|
|
|
// generate PythonTree out of PythonCode
|
|
|
|
PythonTreeRoot pythonRoot = null;
|
|
try {
|
|
pythonRoot = new PythonTreeRoot(this.project, true, monitor);
|
|
}
|
|
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;
|
|
}
|
|
catch (PyUMLCancelledException e) {
|
|
MessageDialog.openWarning(null, "Operation cancelled",
|
|
"The Operation was cancelled by the user");
|
|
return;
|
|
}
|
|
catch (Exception e) {
|
|
e.printStackTrace();
|
|
MessageDialog.openError(null, "Error parsing project code",
|
|
"There was an error parsing the python code of the current\n" +
|
|
"project.\n" +"Error message was:\n\n"+
|
|
e.getMessage());
|
|
return;
|
|
}
|
|
|
|
if (monitor != null)
|
|
monitor.beginTask("Synchronize the Model with the given Code", IProgressMonitor.UNKNOWN);
|
|
// ### Synchronize model with code ###
|
|
boolean syncSuccess = false;
|
|
|
|
String errMsg = null;
|
|
boolean normalRun = false;
|
|
try {
|
|
syncSuccess = pythonRoot.synchronizeModel(model, xmiModelDict);
|
|
normalRun=true;
|
|
}catch(Exception e) {
|
|
e.printStackTrace();
|
|
errMsg = e.getClass().getName() + "\n" +e.getMessage();
|
|
}
|
|
|
|
if (!syncSuccess) {
|
|
if (! normalRun) {
|
|
// if no error happened, but model was not synchronized,
|
|
// we assume there already was an adequate message and leave.
|
|
// otherwise, we print a generic message and leave afterwards
|
|
String message = "There was an error synchronizing the Model.\n";
|
|
if (errMsg != null)
|
|
message += "The error message was:\n"+errMsg;
|
|
MessageDialog.openError(null, "Synchronizing Model Failed", message);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// save new or changed model to .uml file,
|
|
// if synchronization was successful
|
|
if (syncSuccess) try {
|
|
resource.save(null);
|
|
// update model in eclipse
|
|
EclipseHelperMethods.updateFile(resource.getURI().toFileString(), project);
|
|
System.out.println(("Saving model file done."));
|
|
} catch (IOException ioe) {
|
|
MessageDialog.openError(null,"IOException",
|
|
"Error saving uml file: \n" + ioe.getMessage());
|
|
}
|
|
|
|
// Synchronize Code
|
|
|
|
if (syncSuccess) {
|
|
try{
|
|
// after creating the model, synchronize the code
|
|
// so that all model xmi_ids will be part of the code
|
|
// re-use existing pythonRoot, so that code will not have
|
|
// to be read-in again.
|
|
SyncCodeAction.run(project, pythonRoot, monitor);
|
|
}catch (Throwable t) {
|
|
MessageDialog.openError(null,"Error synchronizing Code!",
|
|
t.getClass().getName() + " while synchronizing Code!: \n\n"
|
|
+ t.getMessage());
|
|
t.printStackTrace();
|
|
}
|
|
}
|
|
|
|
monitor.beginTask("Update UML diagram", IProgressMonitor.UNKNOWN);
|
|
|
|
// if model diagram does not exist, create it!
|
|
// create graphical diagram, if it does not already exist
|
|
// after creation, open it; if it is opened, refresh view.
|
|
IFile diagramFile = this.project.getWorkspace()
|
|
.getRoot().getFile(this.project.getFullPath()
|
|
.append(GlobalConstants.getPyUmlDir())
|
|
.append(project.getName()+GlobalConstants
|
|
.getDiagramExtension()));
|
|
|
|
if (! diagramFile.exists()) {
|
|
UMLToolsHelperMethods.createModelDiagram(model, diagramFile);
|
|
}else {
|
|
}
|
|
|
|
monitor.beginTask("Open UML diagram", IProgressMonitor.UNKNOWN);
|
|
|
|
// after creating model, be sure the diagram view is reloaded
|
|
boolean diagramOpened = null != EclipseHelperMethods
|
|
.firstOpenEditorByName(project.getName()+GlobalConstants.getDiagramExtension());
|
|
if (diagramOpened) {
|
|
// set focus to updated diagram only if no diagram is currently active
|
|
boolean keepFocus = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
|
|
.getActivePage().getActiveEditor().getTitle()
|
|
.matches(".*"+GlobalConstants.getDiagramExtension());
|
|
|
|
// close all sub-package pyUML.views of global model diagram
|
|
for ( IEditorReference editor :
|
|
EclipseHelperMethods.lookForOpenEditorByName(project.getName()+"::.*")) {
|
|
PlatformUI.getWorkbench().getActiveWorkbenchWindow()
|
|
.getActivePage().closeEditor(editor.getEditor(true), true);
|
|
}
|
|
IEditorPart modelEditor = UMLToolsHelperMethods.refreshDiagramEditor(project, diagramFile, keepFocus);
|
|
modelEditor.addPropertyListener(new ModelChangeListener(project));
|
|
}
|
|
else {
|
|
IEditorPart modelEditor = UMLToolsHelperMethods.openDiagram(project, diagramFile, project.getName()+".uml", true);
|
|
modelEditor.addPropertyListener(new ModelChangeListener(project));
|
|
}
|
|
|
|
UMLToolsHelperMethods.updateModelAndViewPages(this.project);
|
|
|
|
monitor.done();
|
|
}
|
|
|
|
|
|
|
|
public void selectionChanged(IAction action, ISelection selection) {
|
|
if (selection instanceof TreeSelection) {
|
|
TreeSelection ts = (TreeSelection) selection;
|
|
Object selectedElement = ts.getFirstElement();
|
|
this.project = (IProject) selectedElement;
|
|
}
|
|
}
|
|
|
|
public void run(IProgressMonitor monitor) throws InvocationTargetException,
|
|
InterruptedException {
|
|
monitor.setTaskName("Starting Model Synchronization");
|
|
this.doSync(monitor);
|
|
}
|
|
}
|