312 lines
12 KiB
Java
312 lines
12 KiB
Java
|
package pyUML.backend;
|
||
|
|
||
|
import java.io.IOException;
|
||
|
import java.util.List;
|
||
|
import java.util.Vector;
|
||
|
import java.util.regex.Matcher;
|
||
|
import java.util.regex.Pattern;
|
||
|
|
||
|
import org.eclipse.core.commands.operations.OperationHistoryFactory;
|
||
|
import org.eclipse.core.resources.IFile;
|
||
|
import org.eclipse.core.resources.IFolder;
|
||
|
import org.eclipse.core.resources.IProject;
|
||
|
import org.eclipse.core.resources.IResource;
|
||
|
import org.eclipse.core.runtime.CoreException;
|
||
|
import org.eclipse.core.runtime.IAdaptable;
|
||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||
|
import org.eclipse.core.runtime.NullProgressMonitor;
|
||
|
import org.eclipse.emf.common.util.URI;
|
||
|
import org.eclipse.emf.common.util.WrappedException;
|
||
|
import org.eclipse.emf.ecore.EObject;
|
||
|
import org.eclipse.emf.ecore.resource.Resource;
|
||
|
import org.eclipse.emf.ecore.resource.ResourceSet;
|
||
|
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
|
||
|
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
|
||
|
import org.eclipse.gmf.runtime.diagram.core.services.ViewService;
|
||
|
import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
|
||
|
import org.eclipse.gmf.runtime.emf.core.GMFEditingDomainFactory;
|
||
|
import org.eclipse.gmf.runtime.notation.Diagram;
|
||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||
|
import org.eclipse.ui.IEditorPart;
|
||
|
import org.eclipse.ui.IEditorReference;
|
||
|
import org.eclipse.ui.IWorkbenchPage;
|
||
|
import org.eclipse.ui.PartInitException;
|
||
|
import org.eclipse.ui.PlatformUI;
|
||
|
import org.eclipse.ui.ide.IDE;
|
||
|
import org.eclipse.uml2.diagram.clazz.edit.parts.PackageEditPart;
|
||
|
import org.eclipse.uml2.diagram.clazz.part.Messages;
|
||
|
import org.eclipse.uml2.diagram.clazz.part.UMLDiagramEditor;
|
||
|
import org.eclipse.uml2.diagram.clazz.part.UMLDiagramEditorPlugin;
|
||
|
import org.eclipse.uml2.diagram.clazz.part.UMLDiagramEditorUtil;
|
||
|
import org.eclipse.uml2.diagram.clazz.part.UMLVisualIDRegistry;
|
||
|
|
||
|
import pyUML.listeners.LiveValidationListener;
|
||
|
import pyUML.listeners.ViewChangeListener;
|
||
|
import pyUML.views.EditView;
|
||
|
import pyUML.views.EditViewWizard;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* This class contains methods for reading and writing eclipse
|
||
|
* UML models and for model handling
|
||
|
*/
|
||
|
public class UMLToolsHelperMethods {
|
||
|
|
||
|
/**
|
||
|
* Loads an eclipse UML2 model
|
||
|
*
|
||
|
* @param umlFileName a String containing the filename of the eclipse uml2 diagram
|
||
|
* @return the model root as EObject, null if an exception occured
|
||
|
*/
|
||
|
public static EObject loadUMLDiagram(String umlFileName) {
|
||
|
try {
|
||
|
Resource resource = new ResourceSetImpl().getResource(URI.createFileURI(umlFileName), true);
|
||
|
return resource.getContents().get(0);
|
||
|
/*for (EObject content : resource.getContents()) {
|
||
|
if (content instanceof Model)
|
||
|
return content;
|
||
|
}*/
|
||
|
//return null;
|
||
|
|
||
|
} catch (WrappedException ex) {
|
||
|
MessageDialog.openError(null,ex.getMessage(),"Unable to load model: " + umlFileName+"\n"+ex.getMessage());
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* opens a eclipse uml2tools UML diagram in the editor
|
||
|
* Will edit the diagram file, if a wrong path to a UML model is set
|
||
|
* (Unfortunately, UML diagrams save absolute paths of the corresponding
|
||
|
* UML file)
|
||
|
* @param project the current project
|
||
|
* @param diagramFile the fileName in the pyUml directory
|
||
|
* @param putToFront if the editor is already opened, with putToFront==true
|
||
|
* the editor is given the focus, with putToFront==false nothing is done
|
||
|
* @param umlModelName The name of the corresponding UML model to this model
|
||
|
* This is needed to ensure the diagram has a correct UML file path set
|
||
|
* @return the IEitorPat of the newly opened Diagram, null on Error
|
||
|
* @throws PartInitException
|
||
|
*/
|
||
|
public static IEditorPart openDiagram(IProject project, IFile diagramFile, String umlModelFileName, boolean putToFront) {
|
||
|
// see, if UML model path is set correctly
|
||
|
String absoluteUmlPath = project.getLocation().append(GlobalConstants.getPyUmlDir())
|
||
|
.append(umlModelFileName).toOSString();
|
||
|
String[] diagramFileContent = EclipseHelperMethods.iFileToString(diagramFile).split("\n");
|
||
|
|
||
|
for (int i =0; i< diagramFileContent.length; i++) {
|
||
|
String line = diagramFileContent[i];
|
||
|
Pattern pattern = Pattern.compile("(\\s*<element\\s*xmi:type=\"uml:Model\" href=\"file:)([^#]*)(#.*)");
|
||
|
Matcher matcher = pattern.matcher(line);
|
||
|
if (matcher.find()) {
|
||
|
line = matcher.group(1) + absoluteUmlPath + matcher.group(3);
|
||
|
if (! diagramFileContent[i].equals(line)) {
|
||
|
diagramFileContent[i] = line;
|
||
|
EclipseHelperMethods.StringToIFile(diagramFile,
|
||
|
JavaHelperMethods.join(diagramFileContent, "\n"));
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
IWorkbenchPage page =
|
||
|
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
|
||
|
|
||
|
// if putToFront == false, return if editor is already opened
|
||
|
if (putToFront == false)
|
||
|
for (IEditorReference editor : page.getEditorReferences())
|
||
|
if (editor.getTitle().equals(diagramFile.getName()))
|
||
|
return editor.getEditor(false);
|
||
|
|
||
|
try{
|
||
|
IEditorPart ed = IDE.openEditor(page, diagramFile, UMLDiagramEditor.ID, false);
|
||
|
if (! diagramFile.toString().matches(".*"+project.getName()+GlobalConstants.getDiagramExtension())) {
|
||
|
ed.addPropertyListener(new ViewChangeListener(project));
|
||
|
}
|
||
|
ed.addPropertyListener(LiveValidationListener.getListenerSingleton());
|
||
|
LiveValidationListener.startLiveValidationInBackground();
|
||
|
/*
|
||
|
UMLDiagramEditor umlEd = (UMLDiagramEditor) ed;
|
||
|
umlEd.getDiagram().eResource().load(JavaHelperMethods.stringToStream(PyUMLProfile.getProfileString()), null);
|
||
|
umlEd.refresh();*/
|
||
|
|
||
|
return ed;
|
||
|
} catch (PartInitException e) {
|
||
|
e.printStackTrace();
|
||
|
} catch (Throwable t) {
|
||
|
t.printStackTrace();
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Updates an opened Diagram, if it is already opened
|
||
|
* @param project the current project
|
||
|
* @param diagramFile the IFile of the diagram to refresh
|
||
|
* @param keepFocus if true, workbench focus (currently opened document) is kept open.
|
||
|
* @return true, if a diagram was found and updated
|
||
|
*/
|
||
|
public static IEditorPart refreshDiagramEditor(IProject project, IFile diagramFile, boolean keepFocus){
|
||
|
IWorkbenchPage page =
|
||
|
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
|
||
|
|
||
|
// save active Editor to keep focus
|
||
|
IEditorPart activeEditor = page.getActiveEditor();
|
||
|
//activeEditor.getEditorSite().getId();
|
||
|
String activeEditorName = null;
|
||
|
if (activeEditor != null)
|
||
|
activeEditorName = activeEditor.getTitle();
|
||
|
// look for editor to update
|
||
|
IEditorReference editor = EclipseHelperMethods.firstOpenEditorByName(diagramFile.getName());
|
||
|
if (editor == null)
|
||
|
return null;
|
||
|
|
||
|
// close and open editor again
|
||
|
page.closeEditor(editor.getEditor(true), true);
|
||
|
try{
|
||
|
|
||
|
IEditorPart newEditor = IDE.openEditor(page, diagramFile, UMLDiagramEditor.ID, true);
|
||
|
if (! diagramFile.toString().matches(".*"+project.getName()+GlobalConstants.getDiagramExtension())) {
|
||
|
newEditor.addPropertyListener(new ViewChangeListener(project));
|
||
|
}
|
||
|
|
||
|
EclipseHelperMethods.saveAllOpenEditors();
|
||
|
|
||
|
// activate old active editor
|
||
|
if (keepFocus && activeEditor != null && (! newEditor.getTitle().equals(activeEditorName)))
|
||
|
page.activate(activeEditor);
|
||
|
return newEditor;
|
||
|
} catch (PartInitException e) {
|
||
|
e.printStackTrace();
|
||
|
return null;
|
||
|
}
|
||
|
catch (Throwable t) {
|
||
|
t.printStackTrace();
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
/**
|
||
|
* creates a graphical eclipse UML2TOOLS UML model diagram out of
|
||
|
* a Eclipse UML2 File.
|
||
|
*/
|
||
|
public static void createModelDiagram(EObject modelObject, IFile newDiagramFile) {
|
||
|
org.eclipse.emf.transaction.TransactionalEditingDomain editingDomain =
|
||
|
GMFEditingDomainFactory.INSTANCE.createEditingDomain();
|
||
|
List<IFile> affectedFiles = new Vector<IFile>();
|
||
|
final org.eclipse.uml2.uml.Package model
|
||
|
= (org.eclipse.uml2.uml.Package) modelObject;
|
||
|
URI diagramModelURI = URI.createPlatformResourceURI(newDiagramFile.getFullPath().toString(), true);
|
||
|
ResourceSet resourceSet = editingDomain.getResourceSet();
|
||
|
final Resource diagramResource = resourceSet.createResource(diagramModelURI);
|
||
|
affectedFiles.add(newDiagramFile);
|
||
|
|
||
|
// create diagram from model
|
||
|
AbstractTransactionalCommand command = new AbstractTransactionalCommand(editingDomain, Messages.UMLNewDiagramFileWizard_InitDiagramCommand, affectedFiles) {
|
||
|
public CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) {
|
||
|
int diagramVID = UMLVisualIDRegistry.getDiagramVisualID(model);
|
||
|
if (diagramVID != PackageEditPart.VISUAL_ID) {
|
||
|
return CommandResult.newErrorCommandResult(Messages.UMLNewDiagramFileWizard_IncorrectRootError);
|
||
|
}
|
||
|
Diagram diagram = ViewService.createDiagram(model, PackageEditPart.MODEL_ID, UMLDiagramEditorPlugin.DIAGRAM_PREFERENCES_HINT);
|
||
|
diagramResource.getContents().add(diagram);
|
||
|
return CommandResult.newOKCommandResult();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// save the created diagram file
|
||
|
try {
|
||
|
OperationHistoryFactory.getOperationHistory().execute(command, new NullProgressMonitor(), null);
|
||
|
diagramResource.save(UMLDiagramEditorUtil.getSaveOptions());
|
||
|
} catch (org.eclipse.core.commands.ExecutionException e) {
|
||
|
e.printStackTrace();
|
||
|
}
|
||
|
catch (IOException e) {
|
||
|
e.printStackTrace();
|
||
|
}
|
||
|
// change full path file name to relative path
|
||
|
String diagramFileContent = EclipseHelperMethods.iFileToString(newDiagramFile);//.split("\n");
|
||
|
|
||
|
Pattern pattern = Pattern.compile( "(.*<element xmi:type=\"uml:Model\" href=\")file:([^#]*)(.*)");
|
||
|
Matcher matcher = pattern.matcher(diagramFileContent);
|
||
|
if (! matcher.find()){
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
// write the new method definition line
|
||
|
String newDiagramLine = matcher.group(1) + model.getName()+".uml" + matcher.group(3);
|
||
|
|
||
|
// replace line
|
||
|
String newDiagramFileContent = "";
|
||
|
String[] fileContentLines = diagramFileContent.split("\n");
|
||
|
for (int i=0; i<fileContentLines.length; i++) {
|
||
|
if (fileContentLines[i].equals(matcher.group(0)))
|
||
|
newDiagramFileContent += newDiagramLine + "\n";
|
||
|
else
|
||
|
newDiagramFileContent += fileContentLines[i] + "\n";
|
||
|
}
|
||
|
|
||
|
EclipseHelperMethods.StringToIFile(newDiagramFile, newDiagramFileContent);
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* As a UML diagram is not updated automatically, when .uml file changed,
|
||
|
* we need to manually reload the diagram
|
||
|
* @param project
|
||
|
* @param exceptViewName A name of a view to be excluded from refresh.
|
||
|
* This is useful if a view change is the source of the refreshes.
|
||
|
* Can be null.
|
||
|
* @param onlyIfViewsNotLocked if false, the update will be done any time.
|
||
|
* if false, it will be only done if views are not locked.
|
||
|
*/
|
||
|
public static void updateModelAndViewPages(IProject project) {
|
||
|
|
||
|
// refresh all pyUML.views
|
||
|
IFolder pyUmlDir = project.getFolder(GlobalConstants.getPyUmlDir());
|
||
|
// keep active editor name to activate it afterwards
|
||
|
String activeEditorName = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
|
||
|
.getActivePage().getActiveEditor().getTitle();
|
||
|
|
||
|
try {
|
||
|
for (IResource entry :pyUmlDir.members()) {
|
||
|
if (entry instanceof IFile) {
|
||
|
IFile file = (IFile) entry;
|
||
|
|
||
|
if (file.getName().matches("^.*"+GlobalConstants.getViewConfExtension()+"$")) {
|
||
|
String viewDiagramName = updateViewModel(project, file);
|
||
|
|
||
|
refreshDiagramEditor(project,
|
||
|
project.getFile(new org.eclipse.core.runtime.Path(GlobalConstants.getPyUmlDir()).append(viewDiagramName).toOSString())
|
||
|
, true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// set focus to formerly opened editor page
|
||
|
IEditorReference formerlyOpenedEditor = EclipseHelperMethods.firstOpenEditorByName(activeEditorName);
|
||
|
if (formerlyOpenedEditor != null)
|
||
|
formerlyOpenedEditor.getEditor(true).setFocus();
|
||
|
} catch (CoreException e) {e.printStackTrace();}
|
||
|
//ViewChangeListener.setListenersEnabled(lockBeforeExecution);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Updates the model underlying model of a view by the main model
|
||
|
* @param project The current project
|
||
|
* @param file The View conf file
|
||
|
* @return
|
||
|
*/
|
||
|
public static String updateViewModel(IProject project, IFile file) {
|
||
|
String viewName = file.getName().replace(GlobalConstants.getViewConfExtension(), "");
|
||
|
EditView view = new EditView(project, file, viewName, false);
|
||
|
EditViewWizard wiz = view.getEditViewWizard();
|
||
|
wiz.addPages();
|
||
|
wiz.getPartsPage().addPackagedXmiIds();
|
||
|
wiz.performFinish(false);
|
||
|
String viewDiagramName = viewName+GlobalConstants.getDiagramExtension();
|
||
|
return viewDiagramName;
|
||
|
}
|
||
|
}
|