Eclipse-PyUML/pyUml/src/pyUML/views/EditViewWizard.java

437 lines
13 KiB
Java
Executable File

package pyUML.views;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
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.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.wizard.IWizard;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IEditorPart;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Generalization;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Relationship;
import org.eclipse.uml2.uml.Type;
import org.eclipse.uml2.uml.resource.UMLResource;
import pyUML.backend.EclipseHelperMethods;
import pyUML.backend.GlobalConstants;
import pyUML.backend.UMLToolsHelperMethods;
import pyUML.listeners.ViewChangeListener;
/**
* This wizard lets the user edit a view. Classes
* and Packages can be selected; super- or child classes
* can be used creating a view.
*/
public class EditViewWizard extends Wizard implements IWizard{
private Model model;
private UMLResource resource;
private IProject project;
private IFile confFile;
private String viewName;
private SelectViewElementsPage partsPage;
private List<String> usedXmiIds;
private boolean includeSuperClasses=false;
private boolean includeSubClasses=false;
private Map<EObject, String> modelXmiDict;
private List<Element> nodeToDeleteList;
private List<Element> usedModelElements;
public EditViewWizard(Shell parentShell, Model model, UMLResource resource, IProject project, IFile confFile, String viewName, Map<EObject, String>modelXmiDict) {
super();
this.model = model;
this.resource = resource;
this.project = project;
this.confFile = confFile;
this.viewName = viewName;
this.modelXmiDict = modelXmiDict;
this.usedModelElements = new Vector<Element>();
this.setWindowTitle("Create UML View");
this.readConfFile();
}
@Override
public void addPages() {
this.partsPage = new SelectViewElementsPage("Select Model Elements for this View",
this.model, this.usedXmiIds, this.modelXmiDict, this.viewName,
this.includeSuperClasses, this.includeSubClasses);
addPage(partsPage);
}
/**
* Reads the CONF file of this view (e.g. used classes+packages)
*/
public void readConfFile(){
this.usedXmiIds = new Vector<String>();
String[] confContent = EclipseHelperMethods.iFileToString(confFile).split("\n");
boolean xmiSectionFound=false;
for (String line:confContent) {
if(xmiSectionFound) {
this.usedXmiIds.add(line);
}
if (line.matches("CONF_INCLUDE_SUPERCLASSES:.*")) {
this.includeSuperClasses=
line.replaceAll("CONF_INCLUDE_SUPERCLASSES:", "")
.equals("TRUE");
}
if (line.matches("CONF_INCLUDE_SUBCLASSES:.*")) {
this.includeSubClasses=
line.replaceAll("CONF_INCLUDE_SUBCLASSES:", "")
.equals("TRUE");
}
if (line.matches("XMI_SECTION"))
xmiSectionFound=true;
}
}
@Override
public boolean performFinish() {
return performFinish(true);
}
/**
*
* @param openAfterFinish if true, the created view will be
* opened immediately
* @return true on success
*/
public boolean performFinish(boolean openAfterFinish) {
//generate new model as part of old one
String oldViewName = viewName;
String viewName = this.viewName;
if (this.partsPage.viewNameField != null)
viewName = this.partsPage.getViewNameField().getText();
IFile umlFile = this.project.getWorkspace().getRoot()
.getFile(this.project.getFullPath()
.append(GlobalConstants.getPyUmlDir())
.append(oldViewName+GlobalConstants.getViewUmlExtension()));
IFile diagramFile = this.project.getWorkspace().getRoot()
.getFile(this.project.getFullPath()
.append(GlobalConstants.getPyUmlDir())
.append(oldViewName+GlobalConstants.getDiagramExtension()));
boolean editorChangedNameAndWasOpen =true;
// if view name changed, move all files to new name
if (!viewName.equals(oldViewName)) {
// compute new file names with changed view name
IPath newConfFilePath = this.project.getFullPath()
.append(GlobalConstants.getPyUmlDir())
.append(viewName+GlobalConstants.getViewConfExtension());
IPath newViewUmlPath = this.project.getFullPath()
.append(GlobalConstants.getPyUmlDir())
.append(viewName+GlobalConstants.getViewUmlExtension());
IPath newDiagramFilePath = this.project.getFullPath()
.append(GlobalConstants.getPyUmlDir())
.append(viewName+GlobalConstants.getDiagramExtension());
// close editor, if it is open
EclipseHelperMethods.closeEditorByName(project, diagramFile.getName());
editorChangedNameAndWasOpen = true;
try {
// now really move view files
this.confFile.move(newConfFilePath, true, null);
if (umlFile.exists())
umlFile.move(newViewUmlPath, true, null);
if (diagramFile.exists())
diagramFile.move(newDiagramFilePath, true, null);
this.confFile = project.getFile(newConfFilePath.removeFirstSegments(1));
umlFile = project.getFile(newViewUmlPath.removeFirstSegments(1));
diagramFile = project.getFile(newDiagramFilePath.removeFirstSegments(1));
} catch (CoreException e) {
System.out.println("error moving view file to new view name!");
}
}
//model.setName(viewName);
this.nodeToDeleteList = new Vector<Element>();
if (partsPage.viewNameField != null)
this.usedXmiIds= new Vector<String>();
removeUnmarkedNodes(this.model);
List<Classifier> classList;
classList = getClassListFromModel(this.model);
// if "include superclasses" was checked:
// remove all superclasses of selected items from 'classes to remove' list
if (this.partsPage.getButtInclSuperClasses() != null)
this.includeSuperClasses = this.partsPage.getButtInclSuperClasses().getSelection();
if (this.partsPage.getButtInclSubClasses() != null)
this.includeSubClasses = this.partsPage.getButtInclSubClasses().getSelection();
if (includeSuperClasses) {
boolean superClassFound;
do {
superClassFound = false;
for (Classifier cl:classList) {
EList<Generalization> gens = cl.getGeneralizations();
for (Generalization gen : gens) {
if (nodeToDeleteList.contains(gen.getGeneral())
&& (! nodeToDeleteList.contains(cl))) {
nodeToDeleteList.remove(gen.getGeneral());
superClassFound = true;
}
}
}
}
while (superClassFound);
}
// exclude subclasses from nodeToDeleteList for every class in list
// if includeSubClasses was set in gui
if (includeSubClasses) {
boolean subClassFound;
do {
subClassFound = false;
for (Classifier cl:classList) {
for (Relationship rel : cl.getRelationships()) {
if (rel instanceof Generalization) {
Generalization gen = (Generalization) rel;
if (gen.getOwner() == cl)
continue;
if (nodeToDeleteList.contains(gen.getOwner())
&& (! nodeToDeleteList.contains(cl))) {
nodeToDeleteList.remove(gen.getOwner());
subClassFound = true;
}
}
}
}
}
while (subClassFound);
}
List<Type> elList = getPackagedElementsFromModel(this.model);
Package viewPack = model.createNestedPackage("View_"+viewName);
// make model "flat", setting parent of all classes to model root
for(Type el : elList) {
if (! this.nodeToDeleteList.contains(el))
el.setPackage(viewPack);
}
// remove elements in nodeToDeleteList
/*for (Element e:this.nodeToDeleteList) {
e.destroy();
}
*/
/*
//remove all package entries of model
List<Element> packageList = new Vector<Element>();
for (Element e: model.getOwnedElements()) {
if (e instanceof Package) {
packageList.add(e);
}
}
for (Element e: packageList) {
//e.destroy();
}*/
//save new "view"-model
try {
// if model was renamed, rename old model
String umlFileName=project.getLocation().
append(GlobalConstants.getPyUmlDir()).
append(viewName + GlobalConstants.getViewUmlExtension()).toOSString();
resource.setURI(URI.createFileURI(umlFileName));
resource.save(null);
EclipseHelperMethods.updateFile(umlFile);
System.out.println(("Saving view file "+umlFileName+" done."));
} catch (IOException ioe) {
MessageDialog.openError(null,"IOException",
"Error saving uml file: \n" + ioe.getMessage());
}
//save configuration
String confFileContents="CONF_INCLUDE_SUPERCLASSES:"
+( includeSuperClasses ? "TRUE" : "FALSE" ) + "\n";
confFileContents+="CONF_INCLUDE_SUBCLASSES:"
+( includeSubClasses ? "TRUE" : "FALSE" ) + "\n";
confFileContents += "XMI_SECTION\n";
for (String id: this.usedXmiIds) {
confFileContents += id + "\n";
}
EclipseHelperMethods.StringToIFile(confFile, confFileContents);
// create graphical diagram, if it does not already exist
// create diagram, if it does not exist; after creation, open it
// (diagram should not be opened when "edit" was pressed)
if (! diagramFile.exists() || editorChangedNameAndWasOpen) {
// create and open diagram, if it was created as new
if (! diagramFile.exists())
UMLToolsHelperMethods.createModelDiagram(viewPack, diagramFile);
else {
String oldDiagramContent = EclipseHelperMethods.iFileToString(diagramFile);
Pattern pattern = Pattern.compile("(.*<element xmi:type=\"uml:Package\" href=\"file:[^#]*#)([^\"]*)(\"/>.*)");
String viewId = resource.getID(viewPack);
// get old view package id
Matcher matcher = pattern.matcher(oldDiagramContent);
String oldViewId = null;
if (matcher.find()) {
oldViewId = matcher.group(2);
} else
return false;
// replace all old IDs to the new ID
oldDiagramContent = oldDiagramContent.replace(oldViewId, viewId);
EclipseHelperMethods.StringToIFile(diagramFile, oldDiagramContent);
}
if (openAfterFinish)
UMLToolsHelperMethods.openDiagram(project, diagramFile, umlFile.getName() ,true);
} else {
// refresh editor, if it was open
if (null != EclipseHelperMethods.lookForOpenEditorByName(diagramFile.getName())) {
IEditorPart newPage = UMLToolsHelperMethods.refreshDiagramEditor(project, diagramFile, false);
newPage.addPropertyListener(new ViewChangeListener(this.project));
}
}
EclipseHelperMethods.updateFile(diagramFile);
return true;
}
/**
* Recursive Helper method to add the nodes that were not
* selected to the nodeToDeletelist
* If a package node is selected, all children will be selected, implicitely.
* If a package node is not selected, a recursion on the children is started.
* @param node
*/
private void removeUnmarkedNodes(Element node) {
TreeItem assignedItem =this.partsPage.getNodeCheckboxDict().get(node);
if (assignedItem != null && (assignedItem.getChecked()))
this.usedXmiIds.add(this.modelXmiDict.get(node));
if (node instanceof Relationship) {
return;
}
if (node instanceof org.eclipse.uml2.uml.Classifier) {
assignedItem =this.partsPage.getNodeCheckboxDict().get(node);
if (assignedItem == null) {
if (this.usedXmiIds.contains(modelXmiDict.get(node))) {
this.usedModelElements.add(node);
} else {
this.nodeToDeleteList.add(node);
}
}else if (! assignedItem.getChecked()) {
// add node to remove list if it is not marked.
this.nodeToDeleteList.add(node);
return;
} else {
this.usedModelElements.add(node);
this.usedXmiIds.add(this.modelXmiDict.get(node));
}
}
else if (node instanceof Package) {
for (Element childNode : node.getOwnedElements()) {
assignedItem =this.partsPage.getNodeCheckboxDict().get(node);
if (assignedItem == null) {
}
else if (assignedItem.getChecked())
this.usedXmiIds.add(this.modelXmiDict.get(node));
removeUnmarkedNodes(childNode);
}
}
}
/**
* return all classes in model
* @param node
*/
private Vector<Classifier> getClassListFromModel(Element node) {
Vector<Classifier> classList = new Vector<Classifier>();
if (node instanceof Classifier) {
Classifier cl = (Classifier) node;
classList.add(cl);
} else {
EList<Element> children = node.getOwnedElements();
for (Element child : children) {
classList.addAll(getClassListFromModel(child));
}
}
return classList;
}
/**
* get all child elements of a package
* that are Types (direct successors of packages)
*
* @param node The node where the search is to be started
* @return the list of Types
*/
private Vector<Type> getPackagedElementsFromModel(Element node) {
Vector<Type> elList = new Vector<Type>();
if (node instanceof Classifier) {
Classifier cl = (Classifier) node;
elList.add(cl);
elList.addAll(cl.getAssociations());
} else {
EList<Element> children = node.getOwnedElements();
for (Element child : children) {
elList.addAll(getPackagedElementsFromModel(child));
}
}
return elList;
}
public SelectViewElementsPage getPartsPage() {
return partsPage;
}
}