Initial Commit
This commit is contained in:
parent
13d5ca4906
commit
997f68e0f3
9
pyUml/.classpath
Executable file
9
pyUml/.classpath
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry exported="true" kind="lib" path="bin/"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||||
|
<classpathentry kind="lib" path="lib/refactoring.jar"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
28
pyUml/.project
Executable file
28
pyUml/.project
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>pyUml</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.pde.PluginNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
4
pyUml/.pydevproject
Executable file
4
pyUml/.pydevproject
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<?eclipse-pydev version="1.0"?>
|
||||||
|
|
||||||
|
<pydev_project/>
|
5
pyUml/.settings/org.eclipse.core.resources.prefs
Executable file
5
pyUml/.settings/org.eclipse.core.resources.prefs
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#Tue Jan 08 23:39:24 CET 2008
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
encoding//custom-src/pyUMLProfile.umlprofile_diagram=UTF-8
|
||||||
|
encoding//documents/pythonTree.uml=UTF-8
|
||||||
|
encoding//documents/pythonTree.umlclass_diagram=UTF-8
|
3
pyUml/.settings/org.eclipse.ltk.core.refactoring.prefs
Executable file
3
pyUml/.settings/org.eclipse.ltk.core.refactoring.prefs
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#Tue Nov 13 00:31:02 CET 2007
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
|
37
pyUml/META-INF/MANIFEST.MF
Executable file
37
pyUml/META-INF/MANIFEST.MF
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Bundle-ManifestVersion: 2
|
||||||
|
Bundle-Name: PyUML
|
||||||
|
Bundle-SymbolicName: pyUml;singleton:=true
|
||||||
|
Bundle-Version: 0.9
|
||||||
|
Bundle-Activator: pyUML.plugin.Activator
|
||||||
|
Eclipse-LazyStart: true
|
||||||
|
Bundle-ClassPath: lib/refactoring.jar,
|
||||||
|
.,
|
||||||
|
src/,
|
||||||
|
bin/
|
||||||
|
Bundle-Vendor: Freie University Berlin, Germany, Martin Dittmar
|
||||||
|
Export-Package: pyUML.actions,
|
||||||
|
pyUML.backend,
|
||||||
|
pyUML.exceptions,
|
||||||
|
pyUML.listeners,
|
||||||
|
pyUML.plugin,
|
||||||
|
pyUML.pythonTree,
|
||||||
|
pyUML.refactoring,
|
||||||
|
pyUML.views
|
||||||
|
Require-Bundle: org.eclipse.core.resources,
|
||||||
|
org.eclipse.core.runtime,
|
||||||
|
org.eclipse.jface,
|
||||||
|
org.eclipse.ui,
|
||||||
|
org.eclipse.ui.ide,
|
||||||
|
org.eclipse.emf.common,
|
||||||
|
org.eclipse.emf.ecore,
|
||||||
|
org.eclipse.uml2.uml,
|
||||||
|
org.eclipse.gmf.runtime.common.core,
|
||||||
|
org.eclipse.gmf.runtime.diagram.core,
|
||||||
|
org.eclipse.gmf.runtime.common.ui,
|
||||||
|
org.eclipse.gmf.runtime.diagram.ui,
|
||||||
|
org.eclipse.gmf.runtime.diagram.ui.resources.editor,
|
||||||
|
org.python.pydev,
|
||||||
|
org.python.pydev.core,
|
||||||
|
org.python.pydev.parser,
|
||||||
|
org.eclipse.uml2.diagram.clazz
|
12
pyUml/build.properties
Executable file
12
pyUml/build.properties
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
source.. = src/
|
||||||
|
output.. = bin/
|
||||||
|
bin.includes = META-INF/,\
|
||||||
|
.,\
|
||||||
|
plugin.xml,\
|
||||||
|
lib/refactoring.jar,\
|
||||||
|
images/,\
|
||||||
|
src/,\
|
||||||
|
bin/
|
||||||
|
additional.bundles = org.eclipse.ui.ide
|
||||||
|
src.includes = src/,\
|
||||||
|
.usedDocuments/
|
39
pyUml/custom-src/PyUMLProfile.uml
Executable file
39
pyUml/custom-src/PyUMLProfile.uml
Executable file
@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<uml:Profile xmi:version="2.1" xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:uml="http://www.eclipse.org/uml2/2.1.0/UML" xmi:id="_7Y-UAKi8Edyr_pXRyLU3wA" name="PyUMLProfile " metaclassReference="_ZtOxIKjHEdym48zZ96s2nA" metamodelReference="_bkzWwKjHEdym48zZ96s2nA">
|
||||||
|
<eAnnotations xmi:id="_oyijYKjHEdym48zZ96s2nA" source="http://www.eclipse.org/uml2/2.0.0/UML">
|
||||||
|
<contents xmi:type="ecore:EPackage" xmi:id="_bm4k8KjIEdym48zZ96s2nA" name="PyUMLProfile" nsURI="http:///schemas/PyUMLProfile/_bm06kKjIEdym48zZ96s2nA/1" nsPrefix="PyUMLProfile">
|
||||||
|
<eClassifiers xmi:type="ecore:EClass" xmi:id="_bm4k8ajIEdym48zZ96s2nA" name="BeanClass">
|
||||||
|
<eAnnotations xmi:id="_bm4k8qjIEdym48zZ96s2nA" source="http://www.eclipse.org/uml2/2.0.0/UML" references="_e8aLwKjHEdym48zZ96s2nA"/>
|
||||||
|
<eAnnotations xmi:id="_bm4k86jIEdym48zZ96s2nA" source="duplicates">
|
||||||
|
<contents xmi:type="ecore:EReference" xmi:id="_bm4k9KjIEdym48zZ96s2nA" name="base_Class" ordered="false" lowerBound="1">
|
||||||
|
<eAnnotations xmi:id="_bm4k9ajIEdym48zZ96s2nA" source="redefines" references="_bm4k-ajIEdym48zZ96s2nA"/>
|
||||||
|
<eType xmi:type="ecore:EClass" href="http://www.eclipse.org/uml2/2.1.0/UML#//Class"/>
|
||||||
|
</contents>
|
||||||
|
</eAnnotations>
|
||||||
|
<eStructuralFeatures xmi:type="ecore:EAttribute" xmi:id="_bm4k96jIEdym48zZ96s2nA" name="TestProperty" ordered="false" lowerBound="1">
|
||||||
|
<eType xmi:type="ecore:EDataType" href="http://www.eclipse.org/emf/2002/Ecore#//EString"/>
|
||||||
|
</eStructuralFeatures>
|
||||||
|
<eStructuralFeatures xmi:type="ecore:EReference" xmi:id="_bm4k-ajIEdym48zZ96s2nA" name="base_Class" ordered="false" lowerBound="1">
|
||||||
|
<eType xmi:type="ecore:EClass" href="http://www.eclipse.org/uml2/2.1.0/UML#//Class"/>
|
||||||
|
</eStructuralFeatures>
|
||||||
|
</eClassifiers>
|
||||||
|
</contents>
|
||||||
|
</eAnnotations>
|
||||||
|
<elementImport xmi:id="_ZtOxIKjHEdym48zZ96s2nA">
|
||||||
|
<importedElement xmi:type="uml:Class" href="pathmap://UML_METAMODELS/UML.metamodel.uml#Class"/>
|
||||||
|
</elementImport>
|
||||||
|
<packageImport xmi:id="_bkzWwKjHEdym48zZ96s2nA">
|
||||||
|
<importedPackage xmi:type="uml:Model" href="pathmap://UML_METAMODELS/UML.metamodel.uml#_0"/>
|
||||||
|
</packageImport>
|
||||||
|
<packagedElement xmi:type="uml:Stereotype" xmi:id="_e8aLwKjHEdym48zZ96s2nA" name="BeanClass">
|
||||||
|
<ownedAttribute xmi:id="_OAXE4KjIEdym48zZ96s2nA" name="base_Class">
|
||||||
|
<type xmi:type="uml:Class" href="pathmap://UML_METAMODELS/UML.metamodel.uml#Class"/>
|
||||||
|
</ownedAttribute>
|
||||||
|
<ownedAttribute xmi:id="_S_NkgKjIEdym48zZ96s2nA" name="base_Class" association="_S_MWYKjIEdym48zZ96s2nA">
|
||||||
|
<type xmi:type="uml:Class" href="pathmap://UML_METAMODELS/UML.metamodel.uml#Class"/>
|
||||||
|
</ownedAttribute>
|
||||||
|
</packagedElement>
|
||||||
|
<packagedElement xmi:type="uml:Extension" xmi:id="_S_MWYKjIEdym48zZ96s2nA" name="Class_BeanClass" memberEnd="_S_M9cKjIEdym48zZ96s2nA _S_NkgKjIEdym48zZ96s2nA">
|
||||||
|
<ownedEnd xmi:type="uml:ExtensionEnd" xmi:id="_S_M9cKjIEdym48zZ96s2nA" name="extension_BeanClass" type="_e8aLwKjHEdym48zZ96s2nA" aggregation="composite" association="_S_MWYKjIEdym48zZ96s2nA"/>
|
||||||
|
</packagedElement>
|
||||||
|
</uml:Profile>
|
96
pyUml/custom-src/UMLMarkerNavigationProvider.java
Executable file
96
pyUml/custom-src/UMLMarkerNavigationProvider.java
Executable file
@ -0,0 +1,96 @@
|
|||||||
|
package org.eclipse.uml2.diagram.clazz.providers;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IMarker;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.emf.ecore.EObject;
|
||||||
|
import org.eclipse.gef.EditPart;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor;
|
||||||
|
import org.eclipse.gmf.runtime.emf.ui.providers.marker.AbstractModelMarkerNavigationProvider;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.UMLDiagramEditorPlugin;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.UMLDiagramEditorUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public class UMLMarkerNavigationProvider extends
|
||||||
|
AbstractModelMarkerNavigationProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static final String MARKER_TYPE = UMLDiagramEditorPlugin.ID
|
||||||
|
+ ".diagnostic"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
protected void doGotoMarker(IMarker marker) {
|
||||||
|
String elementId = marker
|
||||||
|
.getAttribute(
|
||||||
|
org.eclipse.gmf.runtime.common.core.resources.IMarker.ELEMENT_ID,
|
||||||
|
null);
|
||||||
|
if (elementId == null || !(getEditor() instanceof DiagramEditor)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DiagramEditor editor = (DiagramEditor) getEditor();
|
||||||
|
Map editPartRegistry = editor.getDiagramGraphicalViewer()
|
||||||
|
.getEditPartRegistry();
|
||||||
|
EObject targetView = editor.getDiagram().eResource().getEObject(
|
||||||
|
elementId);
|
||||||
|
if (targetView == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EditPart targetEditPart = (EditPart) editPartRegistry.get(targetView);
|
||||||
|
if (targetEditPart != null) {
|
||||||
|
UMLDiagramEditorUtil.selectElementsInDiagram(editor, Arrays
|
||||||
|
.asList(new EditPart[] { targetEditPart }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static void deleteMarkers(IResource resource) {
|
||||||
|
try {
|
||||||
|
resource.deleteMarkers(MARKER_TYPE, true, IResource.DEPTH_ZERO);
|
||||||
|
} catch (CoreException e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"Failed to delete validation markers", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static IMarker addMarker(IFile file, String elementId,
|
||||||
|
String location, String message, int statusSeverity) {
|
||||||
|
IMarker marker = null;
|
||||||
|
try {
|
||||||
|
marker = file.createMarker(MARKER_TYPE);
|
||||||
|
marker.setAttribute(IMarker.MESSAGE, message);
|
||||||
|
marker.setAttribute(IMarker.LOCATION, location);
|
||||||
|
marker
|
||||||
|
.setAttribute(
|
||||||
|
org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID,
|
||||||
|
elementId);
|
||||||
|
int markerSeverity = IMarker.SEVERITY_INFO;
|
||||||
|
if (statusSeverity == IStatus.WARNING) {
|
||||||
|
markerSeverity = IMarker.SEVERITY_WARNING;
|
||||||
|
} else if (statusSeverity == IStatus.ERROR
|
||||||
|
|| statusSeverity == IStatus.CANCEL) {
|
||||||
|
markerSeverity = IMarker.SEVERITY_ERROR;
|
||||||
|
}
|
||||||
|
marker.setAttribute(IMarker.SEVERITY, markerSeverity);
|
||||||
|
} catch (CoreException e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"Failed to create validation marker", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
return marker;
|
||||||
|
}
|
||||||
|
}
|
463
pyUml/custom-src/UMLValidationDecoratorProvider.java
Executable file
463
pyUml/custom-src/UMLValidationDecoratorProvider.java
Executable file
@ -0,0 +1,463 @@
|
|||||||
|
package org.eclipse.uml2.diagram.clazz.providers;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IMarker;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.draw2d.FlowLayout;
|
||||||
|
import org.eclipse.draw2d.Label;
|
||||||
|
import org.eclipse.emf.ecore.resource.Resource;
|
||||||
|
import org.eclipse.emf.transaction.TransactionalEditingDomain;
|
||||||
|
import org.eclipse.emf.transaction.util.TransactionUtil;
|
||||||
|
import org.eclipse.emf.workspace.util.WorkspaceSynchronizer;
|
||||||
|
import org.eclipse.gef.EditDomain;
|
||||||
|
import org.eclipse.gef.EditPart;
|
||||||
|
import org.eclipse.gef.editparts.AbstractConnectionEditPart;
|
||||||
|
import org.eclipse.gmf.runtime.common.core.service.AbstractProvider;
|
||||||
|
import org.eclipse.gmf.runtime.common.core.service.IOperation;
|
||||||
|
import org.eclipse.gmf.runtime.common.ui.resources.FileChangeManager;
|
||||||
|
import org.eclipse.gmf.runtime.common.ui.resources.IFileObserver;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditDomain;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.AbstractDecorator;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.CreateDecoratorsOperation;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecorator;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecoratorProvider;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecoratorTarget;
|
||||||
|
import org.eclipse.gmf.runtime.draw2d.ui.mapmode.MapModeUtil;
|
||||||
|
import org.eclipse.gmf.runtime.notation.Diagram;
|
||||||
|
import org.eclipse.gmf.runtime.notation.Edge;
|
||||||
|
import org.eclipse.gmf.runtime.notation.View;
|
||||||
|
import org.eclipse.swt.graphics.Image;
|
||||||
|
import org.eclipse.ui.ISharedImages;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.edit.parts.PackageEditPart;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.UMLDiagramEditor;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.UMLDiagramEditorPlugin;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.UMLVisualIDRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public class UMLValidationDecoratorProvider extends AbstractProvider implements
|
||||||
|
IDecoratorProvider {
|
||||||
|
|
||||||
|
public static Resource usedResource = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static final String KEY = "validationStatus"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static final String MARKER_TYPE = UMLDiagramEditorPlugin.ID
|
||||||
|
+ ".diagnostic"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static MarkerObserver fileObserver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static Map/*<String, List<IDecorator>>*/allDecorators = new HashMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void createDecorators(IDecoratorTarget decoratorTarget) {
|
||||||
|
EditPart editPart = (EditPart) decoratorTarget
|
||||||
|
.getAdapter(EditPart.class);
|
||||||
|
if (editPart instanceof GraphicalEditPart
|
||||||
|
|| editPart instanceof AbstractConnectionEditPart) {
|
||||||
|
Object model = editPart.getModel();
|
||||||
|
if ((model instanceof View)) {
|
||||||
|
View view = (View) model;
|
||||||
|
if (!(view instanceof Edge) && !view.isSetElement()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EditDomain ed = editPart.getViewer().getEditDomain();
|
||||||
|
if (!(ed instanceof DiagramEditDomain)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (((DiagramEditDomain) ed).getEditorPart() instanceof UMLDiagramEditor) {
|
||||||
|
decoratorTarget.installDecorator(KEY, new StatusDecorator(
|
||||||
|
decoratorTarget));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean provides(IOperation operation) {
|
||||||
|
if (!(operation instanceof CreateDecoratorsOperation)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
IDecoratorTarget decoratorTarget = ((CreateDecoratorsOperation) operation)
|
||||||
|
.getDecoratorTarget();
|
||||||
|
View view = (View) decoratorTarget.getAdapter(View.class);
|
||||||
|
return view != null
|
||||||
|
&& PackageEditPart.MODEL_ID.equals(UMLVisualIDRegistry
|
||||||
|
.getModelID(view));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static void refreshDecorators(View view) {
|
||||||
|
refreshDecorators(ViewUtil.getIdStr(view), view.getDiagram());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static void refreshDecorators(String viewId, Diagram diagram) {
|
||||||
|
final List decorators = viewId != null ? (List) allDecorators
|
||||||
|
.get(viewId) : null;
|
||||||
|
if (decorators == null || decorators.isEmpty() || diagram == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final Diagram fdiagram = diagram;
|
||||||
|
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
if (UMLValidationDecoratorProvider.usedResource == null)
|
||||||
|
UMLValidationDecoratorProvider.usedResource = fdiagram.eResource();
|
||||||
|
|
||||||
|
if (UMLValidationDecoratorProvider.usedResource == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TransactionalEditingDomain domain =
|
||||||
|
TransactionalEditingDomain.Factory.INSTANCE.getEditingDomain(
|
||||||
|
UMLValidationDecoratorProvider.usedResource.getResourceSet());
|
||||||
|
domain.runExclusive(
|
||||||
|
new Runnable() {
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
for (Iterator it = decorators.iterator(); it
|
||||||
|
.hasNext();) {
|
||||||
|
IDecorator decorator = (IDecorator) it
|
||||||
|
.next();
|
||||||
|
decorator.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"Decorator refresh failure", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class StatusDecorator extends AbstractDecorator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private String viewId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public StatusDecorator(IDecoratorTarget decoratorTarget) {
|
||||||
|
super(decoratorTarget);
|
||||||
|
try {
|
||||||
|
final View view = (View) getDecoratorTarget().getAdapter(
|
||||||
|
View.class);
|
||||||
|
TransactionUtil.getEditingDomain(view).runExclusive(
|
||||||
|
new Runnable() {
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
StatusDecorator.this.viewId = view != null ? ViewUtil
|
||||||
|
.getIdStr(view)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"ViewID access failure", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void refresh() {
|
||||||
|
removeDecoration();
|
||||||
|
View view = (View) getDecoratorTarget().getAdapter(View.class);
|
||||||
|
if (view == null || view.eResource() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EditPart editPart = (EditPart) getDecoratorTarget().getAdapter(
|
||||||
|
EditPart.class);
|
||||||
|
if (editPart == null || editPart.getViewer() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// query for all the validation markers of the current resource
|
||||||
|
String elementId = ViewUtil.getIdStr(view);
|
||||||
|
if (elementId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int severity = IMarker.SEVERITY_INFO;
|
||||||
|
IMarker foundMarker = null;
|
||||||
|
IResource resource = WorkspaceSynchronizer
|
||||||
|
.getFile(view.eResource());
|
||||||
|
if (resource == null || !resource.exists()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
IMarker[] markers = null;
|
||||||
|
try {
|
||||||
|
markers = resource.findMarkers(MARKER_TYPE, true,
|
||||||
|
IResource.DEPTH_INFINITE);
|
||||||
|
} catch (CoreException e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"Validation markers refresh failure", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
if (markers == null || markers.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Label toolTip = null;
|
||||||
|
for (int i = 0; i < markers.length; i++) {
|
||||||
|
IMarker marker = markers[i];
|
||||||
|
String attribute = marker
|
||||||
|
.getAttribute(
|
||||||
|
org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID,
|
||||||
|
""); //$NON-NLS-1$
|
||||||
|
if (attribute.equals(elementId)) {
|
||||||
|
int nextSeverity = marker.getAttribute(IMarker.SEVERITY,
|
||||||
|
IMarker.SEVERITY_INFO);
|
||||||
|
Image nextImage = getImage(nextSeverity);
|
||||||
|
if (foundMarker == null) {
|
||||||
|
foundMarker = marker;
|
||||||
|
toolTip = new Label(marker.getAttribute(
|
||||||
|
IMarker.MESSAGE, ""), //$NON-NLS-1$
|
||||||
|
nextImage);
|
||||||
|
} else {
|
||||||
|
if (toolTip.getChildren().isEmpty()) {
|
||||||
|
Label comositeLabel = new Label();
|
||||||
|
FlowLayout fl = new FlowLayout(false);
|
||||||
|
fl.setMinorSpacing(0);
|
||||||
|
comositeLabel.setLayoutManager(fl);
|
||||||
|
comositeLabel.add(toolTip);
|
||||||
|
toolTip = comositeLabel;
|
||||||
|
}
|
||||||
|
toolTip.add(new Label(marker.getAttribute(
|
||||||
|
IMarker.MESSAGE, ""), //$NON-NLS-1$
|
||||||
|
nextImage));
|
||||||
|
}
|
||||||
|
severity = (nextSeverity > severity) ? nextSeverity
|
||||||
|
: severity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (foundMarker == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add decoration
|
||||||
|
if (editPart instanceof org.eclipse.gef.GraphicalEditPart) {
|
||||||
|
if (view instanceof Edge) {
|
||||||
|
setDecoration(getDecoratorTarget().addConnectionDecoration(
|
||||||
|
getImage(severity), 50, true));
|
||||||
|
} else {
|
||||||
|
int margin = -1;
|
||||||
|
if (editPart instanceof org.eclipse.gef.GraphicalEditPart) {
|
||||||
|
margin = MapModeUtil.getMapMode(
|
||||||
|
((org.eclipse.gef.GraphicalEditPart) editPart)
|
||||||
|
.getFigure()).DPtoLP(margin);
|
||||||
|
}
|
||||||
|
setDecoration(getDecoratorTarget()
|
||||||
|
.addShapeDecoration(getImage(severity),
|
||||||
|
IDecoratorTarget.Direction.NORTH_EAST,
|
||||||
|
margin, true));
|
||||||
|
}
|
||||||
|
getDecoration().setToolTip(toolTip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private Image getImage(int severity) {
|
||||||
|
String imageName = ISharedImages.IMG_OBJS_ERROR_TSK;
|
||||||
|
switch (severity) {
|
||||||
|
case IMarker.SEVERITY_ERROR:
|
||||||
|
imageName = ISharedImages.IMG_OBJS_ERROR_TSK;
|
||||||
|
break;
|
||||||
|
case IMarker.SEVERITY_WARNING:
|
||||||
|
imageName = ISharedImages.IMG_OBJS_WARN_TSK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
imageName = ISharedImages.IMG_OBJS_INFO_TSK;
|
||||||
|
}
|
||||||
|
return PlatformUI.getWorkbench().getSharedImages().getImage(
|
||||||
|
imageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void activate() {
|
||||||
|
if (viewId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add self to global decorators registry
|
||||||
|
List list = (List) allDecorators.get(viewId);
|
||||||
|
if (list == null) {
|
||||||
|
list = new ArrayList(2);
|
||||||
|
list.add(this);
|
||||||
|
allDecorators.put(viewId, list);
|
||||||
|
} else if (!list.contains(this)) {
|
||||||
|
list.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// start listening to changes in resources
|
||||||
|
View view = (View) getDecoratorTarget().getAdapter(View.class);
|
||||||
|
if (view == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Diagram diagramView = view.getDiagram();
|
||||||
|
if (diagramView == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fileObserver == null) {
|
||||||
|
FileChangeManager.getInstance().addFileObserver(
|
||||||
|
fileObserver = new MarkerObserver(diagramView));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void deactivate() {
|
||||||
|
if (viewId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove self from global decorators registry
|
||||||
|
List list = (List) allDecorators.get(viewId);
|
||||||
|
if (list != null) {
|
||||||
|
list.remove(this);
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
allDecorators.remove(viewId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop listening to changes in resources if there are no more decorators
|
||||||
|
if (fileObserver != null && allDecorators.isEmpty()) {
|
||||||
|
FileChangeManager.getInstance()
|
||||||
|
.removeFileObserver(fileObserver);
|
||||||
|
fileObserver = null;
|
||||||
|
}
|
||||||
|
super.deactivate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
static class MarkerObserver implements IFileObserver {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private Diagram diagram;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private MarkerObserver(Diagram diagram) {
|
||||||
|
this.diagram = diagram;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void handleFileRenamed(IFile oldFile, IFile file) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void handleFileMoved(IFile oldFile, IFile file) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void handleFileDeleted(IFile file) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void handleFileChanged(IFile file) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void handleMarkerAdded(IMarker marker) {
|
||||||
|
if (marker
|
||||||
|
.getAttribute(
|
||||||
|
org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID,
|
||||||
|
null) != null) {
|
||||||
|
handleMarkerChanged(marker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void handleMarkerDeleted(IMarker marker, Map attributes) {
|
||||||
|
String viewId = (String) attributes
|
||||||
|
.get(org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID);
|
||||||
|
refreshDecorators(viewId, diagram);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void handleMarkerChanged(IMarker marker) {
|
||||||
|
if (!MARKER_TYPE.equals(getType(marker))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String viewId = marker
|
||||||
|
.getAttribute(
|
||||||
|
org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID,
|
||||||
|
""); //$NON-NLS-1$
|
||||||
|
refreshDecorators(viewId, diagram);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private String getType(IMarker marker) {
|
||||||
|
try {
|
||||||
|
return marker.getType();
|
||||||
|
} catch (CoreException e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"Validation marker refresh failure", e); //$NON-NLS-1$
|
||||||
|
return ""; //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
406
pyUml/custom-src/UMLValidationProvider.java
Executable file
406
pyUml/custom-src/UMLValidationProvider.java
Executable file
@ -0,0 +1,406 @@
|
|||||||
|
package org.eclipse.uml2.diagram.clazz.providers;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.emf.ecore.EObject;
|
||||||
|
import org.eclipse.emf.transaction.TransactionalEditingDomain;
|
||||||
|
import org.eclipse.emf.transaction.util.TransactionUtil;
|
||||||
|
import org.eclipse.emf.validation.model.IClientSelector;
|
||||||
|
import org.eclipse.emf.validation.service.IBatchValidator;
|
||||||
|
import org.eclipse.emf.validation.service.ITraversalStrategy;
|
||||||
|
import org.eclipse.gmf.runtime.common.ui.services.action.contributionitem.AbstractContributionItemProvider;
|
||||||
|
import org.eclipse.gmf.runtime.common.ui.util.IWorkbenchPartDescriptor;
|
||||||
|
import org.eclipse.gmf.runtime.notation.View;
|
||||||
|
import org.eclipse.jface.action.IAction;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.edit.parts.PackageEditPart;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.UMLDiagramEditorPlugin;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.UMLVisualIDRegistry;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.ValidateAction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public class UMLValidationProvider extends AbstractContributionItemProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static boolean constraintsActive = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static boolean shouldConstraintsBePrivate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
protected IAction createAction(String actionId,
|
||||||
|
IWorkbenchPartDescriptor partDescriptor) {
|
||||||
|
if (ValidateAction.VALIDATE_ACTION_KEY.equals(actionId)) {
|
||||||
|
return new ValidateAction(partDescriptor);
|
||||||
|
}
|
||||||
|
return super.createAction(actionId, partDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static void runWithConstraints(View view, Runnable op) {
|
||||||
|
final Runnable fop = op;
|
||||||
|
Runnable task = new Runnable() {
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
constraintsActive = true;
|
||||||
|
fop.run();
|
||||||
|
} finally {
|
||||||
|
constraintsActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
TransactionalEditingDomain txDomain = TransactionUtil
|
||||||
|
.getEditingDomain(view);
|
||||||
|
if (txDomain != null) {
|
||||||
|
try {
|
||||||
|
txDomain.runExclusive(task);
|
||||||
|
} catch (Exception e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"Validation action failed", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
task.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
static boolean isInDefaultEditorContext(Object object) {
|
||||||
|
if (shouldConstraintsBePrivate() && !constraintsActive) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (object instanceof View) {
|
||||||
|
return constraintsActive
|
||||||
|
&& PackageEditPart.MODEL_ID.equals(UMLVisualIDRegistry
|
||||||
|
.getModelID((View) object));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
static final Map semanticCtxIdMap = new HashMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx1 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx2 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx3 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx4 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx5 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx6 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx7 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx8 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx9 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx10 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx11 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx12 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx13 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx14 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static ITraversalStrategy getNotationTraversalStrategy(
|
||||||
|
IBatchValidator validator) {
|
||||||
|
return new CtxSwitchStrategy(validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static class CtxSwitchStrategy implements ITraversalStrategy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private ITraversalStrategy defaultStrategy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private String currentSemanticCtxId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private boolean ctxChanged = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private EObject currentTarget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private EObject preFetchedNextTarget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
CtxSwitchStrategy(IBatchValidator validator) {
|
||||||
|
this.defaultStrategy = validator.getDefaultTraversalStrategy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void elementValidated(EObject element, IStatus status) {
|
||||||
|
defaultStrategy.elementValidated(element, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean hasNext() {
|
||||||
|
return defaultStrategy.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean isClientContextChanged() {
|
||||||
|
if (preFetchedNextTarget == null) {
|
||||||
|
preFetchedNextTarget = next();
|
||||||
|
prepareNextClientContext(preFetchedNextTarget);
|
||||||
|
}
|
||||||
|
return ctxChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public EObject next() {
|
||||||
|
EObject nextTarget = preFetchedNextTarget;
|
||||||
|
if (nextTarget == null) {
|
||||||
|
nextTarget = defaultStrategy.next();
|
||||||
|
}
|
||||||
|
this.preFetchedNextTarget = null;
|
||||||
|
return this.currentTarget = nextTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void startTraversal(Collection traversalRoots,
|
||||||
|
IProgressMonitor monitor) {
|
||||||
|
defaultStrategy.startTraversal(traversalRoots, monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private void prepareNextClientContext(EObject nextTarget) {
|
||||||
|
if (nextTarget != null && currentTarget != null) {
|
||||||
|
if (nextTarget instanceof View) {
|
||||||
|
String id = ((View) nextTarget).getType();
|
||||||
|
String nextSemanticId = id != null
|
||||||
|
&& semanticCtxIdMap.containsKey(id) ? id : null;
|
||||||
|
if ((currentSemanticCtxId != null && !currentSemanticCtxId
|
||||||
|
.equals(nextSemanticId))
|
||||||
|
|| (nextSemanticId != null && !nextSemanticId
|
||||||
|
.equals(currentSemanticCtxId))) {
|
||||||
|
this.ctxChanged = true;
|
||||||
|
}
|
||||||
|
currentSemanticCtxId = nextSemanticId;
|
||||||
|
} else {
|
||||||
|
// context of domain model
|
||||||
|
this.ctxChanged = currentSemanticCtxId != null;
|
||||||
|
currentSemanticCtxId = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.ctxChanged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
static class JavaAudits {
|
||||||
|
}
|
||||||
|
}
|
297
pyUml/custom-src/ValidateAction.java
Executable file
297
pyUml/custom-src/ValidateAction.java
Executable file
@ -0,0 +1,297 @@
|
|||||||
|
package org.eclipse.uml2.diagram.clazz.part;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||||
|
import org.eclipse.emf.common.util.Diagnostic;
|
||||||
|
import org.eclipse.emf.ecore.EObject;
|
||||||
|
import org.eclipse.emf.ecore.util.Diagnostician;
|
||||||
|
import org.eclipse.emf.validation.model.EvaluationMode;
|
||||||
|
import org.eclipse.emf.validation.model.IConstraintStatus;
|
||||||
|
import org.eclipse.emf.validation.service.IBatchValidator;
|
||||||
|
import org.eclipse.emf.validation.service.ModelValidationService;
|
||||||
|
import org.eclipse.emf.workspace.util.WorkspaceSynchronizer;
|
||||||
|
import org.eclipse.gef.EditPartViewer;
|
||||||
|
import org.eclipse.gmf.runtime.common.ui.util.IWorkbenchPartDescriptor;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.OffscreenEditPartFactory;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramWorkbenchPart;
|
||||||
|
import org.eclipse.gmf.runtime.emf.core.util.EMFCoreUtil;
|
||||||
|
import org.eclipse.gmf.runtime.notation.View;
|
||||||
|
import org.eclipse.jface.action.Action;
|
||||||
|
import org.eclipse.jface.operation.IRunnableWithProgress;
|
||||||
|
import org.eclipse.ui.IEditorPart;
|
||||||
|
import org.eclipse.ui.IWorkbenchPart;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
import org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.providers.UMLMarkerNavigationProvider;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.providers.UMLValidationProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public class ValidateAction extends Action {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static final String VALIDATE_ACTION_KEY = "validateAction"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private IWorkbenchPartDescriptor workbenchPartDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public ValidateAction(IWorkbenchPartDescriptor workbenchPartDescriptor) {
|
||||||
|
setId(VALIDATE_ACTION_KEY);
|
||||||
|
setText(Messages.ValidateActionMessage);
|
||||||
|
this.workbenchPartDescriptor = workbenchPartDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void run() {
|
||||||
|
IWorkbenchPart workbenchPart = workbenchPartDescriptor.getPartPage()
|
||||||
|
.getActivePart();
|
||||||
|
if (workbenchPart instanceof IDiagramWorkbenchPart) {
|
||||||
|
final IDiagramWorkbenchPart part = (IDiagramWorkbenchPart) workbenchPart;
|
||||||
|
try {
|
||||||
|
new WorkspaceModifyDelegatingOperation(
|
||||||
|
new IRunnableWithProgress() {
|
||||||
|
|
||||||
|
public void run(IProgressMonitor monitor)
|
||||||
|
throws InterruptedException,
|
||||||
|
InvocationTargetException {
|
||||||
|
runValidation(part.getDiagramEditPart(), part
|
||||||
|
.getDiagram());
|
||||||
|
}
|
||||||
|
}).run(new NullProgressMonitor());
|
||||||
|
} catch (Exception e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"Validation action failed", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static void runValidation(View view) {
|
||||||
|
try {
|
||||||
|
if (UMLDiagramEditorUtil.openDiagram(view.eResource())) {
|
||||||
|
IEditorPart editorPart = PlatformUI.getWorkbench()
|
||||||
|
.getActiveWorkbenchWindow().getActivePage()
|
||||||
|
.getActiveEditor();
|
||||||
|
if (editorPart instanceof IDiagramWorkbenchPart) {
|
||||||
|
runValidation(((IDiagramWorkbenchPart) editorPart)
|
||||||
|
.getDiagramEditPart(), view);
|
||||||
|
} else {
|
||||||
|
runNonUIValidation(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"Validation action failed", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static void runNonUIValidation(View view) {
|
||||||
|
DiagramEditPart diagramEditPart = OffscreenEditPartFactory
|
||||||
|
.getInstance().createDiagramEditPart(view.getDiagram());
|
||||||
|
runValidation(diagramEditPart, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static void runValidation(DiagramEditPart diagramEditPart, View view) {
|
||||||
|
final DiagramEditPart fpart = diagramEditPart;
|
||||||
|
final View fview = view;
|
||||||
|
UMLValidationProvider.runWithConstraints(view, new Runnable() {
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
validate(fpart, fview);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static Diagnostic runEMFValidator(View target) {
|
||||||
|
if (target.isSetElement() && target.getElement() != null) {
|
||||||
|
return new Diagnostician() {
|
||||||
|
|
||||||
|
public String getObjectLabel(EObject eObject) {
|
||||||
|
return EMFCoreUtil.getQualifiedName(eObject, true);
|
||||||
|
}
|
||||||
|
}.validate(target.getElement());
|
||||||
|
}
|
||||||
|
return Diagnostic.OK_INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static void validate(DiagramEditPart diagramEditPart, View view) {
|
||||||
|
IFile target = view.eResource() != null ? WorkspaceSynchronizer
|
||||||
|
.getFile(view.eResource()) : null;
|
||||||
|
if (target != null) {
|
||||||
|
UMLMarkerNavigationProvider.deleteMarkers(target);
|
||||||
|
}
|
||||||
|
Diagnostic diagnostic = runEMFValidator(view);
|
||||||
|
createMarkers(target, diagnostic, diagramEditPart);
|
||||||
|
IBatchValidator validator = (IBatchValidator) ModelValidationService
|
||||||
|
.getInstance().newValidator(EvaluationMode.BATCH);
|
||||||
|
validator.setIncludeLiveConstraints(true);
|
||||||
|
if (view.isSetElement() && view.getElement() != null) {
|
||||||
|
IStatus status = validator.validate(view.getElement());
|
||||||
|
createMarkers(target, status, diagramEditPart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static void createMarkers(IFile target, IStatus validationStatus,
|
||||||
|
DiagramEditPart diagramEditPart) {
|
||||||
|
if (validationStatus.isOK()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final IStatus rootStatus = validationStatus;
|
||||||
|
List allStatuses = new ArrayList();
|
||||||
|
UMLDiagramEditorUtil.LazyElement2ViewMap element2ViewMap = new UMLDiagramEditorUtil.LazyElement2ViewMap(
|
||||||
|
diagramEditPart.getDiagramView(), collectTargetElements(
|
||||||
|
rootStatus, new HashSet(), allStatuses));
|
||||||
|
for (Iterator it = allStatuses.iterator(); it.hasNext();) {
|
||||||
|
IConstraintStatus nextStatus = (IConstraintStatus) it.next();
|
||||||
|
View view = UMLDiagramEditorUtil.findView(diagramEditPart,
|
||||||
|
nextStatus.getTarget(), element2ViewMap);
|
||||||
|
addMarker(diagramEditPart.getViewer(), target, view.eResource()
|
||||||
|
.getURIFragment(view), EMFCoreUtil.getQualifiedName(
|
||||||
|
nextStatus.getTarget(), true), nextStatus.getMessage(),
|
||||||
|
nextStatus.getSeverity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static void createMarkers(IFile target,
|
||||||
|
Diagnostic emfValidationStatus, DiagramEditPart diagramEditPart) {
|
||||||
|
if (emfValidationStatus.getSeverity() == Diagnostic.OK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final Diagnostic rootStatus = emfValidationStatus;
|
||||||
|
List allDiagnostics = new ArrayList();
|
||||||
|
UMLDiagramEditorUtil.LazyElement2ViewMap element2ViewMap = new UMLDiagramEditorUtil.LazyElement2ViewMap(
|
||||||
|
diagramEditPart.getDiagramView(), collectTargetElements(
|
||||||
|
rootStatus, new HashSet(), allDiagnostics));
|
||||||
|
for (Iterator it = emfValidationStatus.getChildren().iterator(); it
|
||||||
|
.hasNext();) {
|
||||||
|
Diagnostic nextDiagnostic = (Diagnostic) it.next();
|
||||||
|
List data = nextDiagnostic.getData();
|
||||||
|
if (data != null && !data.isEmpty()
|
||||||
|
&& data.get(0) instanceof EObject) {
|
||||||
|
EObject element = (EObject) data.get(0);
|
||||||
|
View view = UMLDiagramEditorUtil.findView(diagramEditPart,
|
||||||
|
element, element2ViewMap);
|
||||||
|
addMarker(
|
||||||
|
diagramEditPart.getViewer(),
|
||||||
|
target,
|
||||||
|
view.eResource().getURIFragment(view),
|
||||||
|
EMFCoreUtil.getQualifiedName(element, true),
|
||||||
|
nextDiagnostic.getMessage(),
|
||||||
|
diagnosticToStatusSeverity(nextDiagnostic.getSeverity()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static void addMarker(EditPartViewer viewer, IFile target,
|
||||||
|
String elementId, String location, String message,
|
||||||
|
int statusSeverity) {
|
||||||
|
if (target == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UMLMarkerNavigationProvider.addMarker(target, elementId, location,
|
||||||
|
message, statusSeverity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static int diagnosticToStatusSeverity(int diagnosticSeverity) {
|
||||||
|
if (diagnosticSeverity == Diagnostic.OK) {
|
||||||
|
return IStatus.OK;
|
||||||
|
} else if (diagnosticSeverity == Diagnostic.INFO) {
|
||||||
|
return IStatus.INFO;
|
||||||
|
} else if (diagnosticSeverity == Diagnostic.WARNING) {
|
||||||
|
return IStatus.WARNING;
|
||||||
|
} else if (diagnosticSeverity == Diagnostic.ERROR
|
||||||
|
|| diagnosticSeverity == Diagnostic.CANCEL) {
|
||||||
|
return IStatus.ERROR;
|
||||||
|
}
|
||||||
|
return IStatus.INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static Set collectTargetElements(IStatus status,
|
||||||
|
Set targetElementCollector, List allConstraintStatuses) {
|
||||||
|
if (status instanceof IConstraintStatus) {
|
||||||
|
targetElementCollector
|
||||||
|
.add(((IConstraintStatus) status).getTarget());
|
||||||
|
allConstraintStatuses.add(status);
|
||||||
|
}
|
||||||
|
if (status.isMultiStatus()) {
|
||||||
|
IStatus[] children = status.getChildren();
|
||||||
|
for (int i = 0; i < children.length; i++) {
|
||||||
|
collectTargetElements(children[i], targetElementCollector,
|
||||||
|
allConstraintStatuses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return targetElementCollector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static Set collectTargetElements(Diagnostic diagnostic,
|
||||||
|
Set targetElementCollector, List allDiagnostics) {
|
||||||
|
List data = diagnostic.getData();
|
||||||
|
EObject target = null;
|
||||||
|
if (data != null && !data.isEmpty() && data.get(0) instanceof EObject) {
|
||||||
|
target = (EObject) data.get(0);
|
||||||
|
targetElementCollector.add(target);
|
||||||
|
allDiagnostics.add(diagnostic);
|
||||||
|
}
|
||||||
|
if (diagnostic.getChildren() != null
|
||||||
|
&& !diagnostic.getChildren().isEmpty()) {
|
||||||
|
for (Iterator it = diagnostic.getChildren().iterator(); it
|
||||||
|
.hasNext();) {
|
||||||
|
collectTargetElements((Diagnostic) it.next(),
|
||||||
|
targetElementCollector, allDiagnostics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return targetElementCollector;
|
||||||
|
}
|
||||||
|
}
|
9215
pyUml/custom-src/classDiagram.gmfgen
Executable file
9215
pyUml/custom-src/classDiagram.gmfgen
Executable file
File diff suppressed because one or more lines are too long
1978
pyUml/custom-src/classDiagram.gmfmap
Executable file
1978
pyUml/custom-src/classDiagram.gmfmap
Executable file
File diff suppressed because it is too large
Load Diff
38
pyUml/custom-src/pyUMLProfile.umlprofile_diagram
Executable file
38
pyUml/custom-src/pyUMLProfile.umlprofile_diagram
Executable file
@ -0,0 +1,38 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<notation:Diagram xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.1/notation" xmlns:uml="http://www.eclipse.org/uml2/2.1.0/UML" xmi:id="_dobnwK1vEdyCurEqUBGZMw" type="UMLProfile" name="pyUMLProfile.umlprofile_diagram" measurementUnit="Pixel">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_rcHaEK1vEdyCurEqUBGZMw" type="2007">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_rcHaE61vEdyCurEqUBGZMw" type="5009"/>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_rcHaFK1vEdyCurEqUBGZMw" type="7005">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_rcHaFa1vEdyCurEqUBGZMw"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_rcHaFq1vEdyCurEqUBGZMw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_rcHaF61vEdyCurEqUBGZMw"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:ShapeStyle" xmi:id="_rcHaEa1vEdyCurEqUBGZMw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Profile" href="PyUMLProfile.uml#_7Y-UAKi8Edyr_pXRyLU3wA"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_rcHaEq1vEdyCurEqUBGZMw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_rcIoMK1vEdyCurEqUBGZMw" type="2001">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_rcJPQK1vEdyCurEqUBGZMw" type="5001"/>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_rcJ2UK1vEdyCurEqUBGZMw" type="7001">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_rcJ2Ua1vEdyCurEqUBGZMw"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_rcJ2Uq1vEdyCurEqUBGZMw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_rcJ2U61vEdyCurEqUBGZMw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_rcKdYK1vEdyCurEqUBGZMw" type="7002">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_rcKdYa1vEdyCurEqUBGZMw"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_rcKdYq1vEdyCurEqUBGZMw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_rcKdY61vEdyCurEqUBGZMw"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:ShapeStyle" xmi:id="_rcIoMa1vEdyCurEqUBGZMw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Stereotype" href="PyUMLProfile.uml#_e8aLwKjHEdym48zZ96s2nA"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_rcIoMq1vEdyCurEqUBGZMw" x="167"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_rcM5oK1vEdyCurEqUBGZMw" type="2006">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_rcNgsK1vEdyCurEqUBGZMw" type="5008"/>
|
||||||
|
<styles xmi:type="notation:ShapeStyle" xmi:id="_rcM5oa1vEdyCurEqUBGZMw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:ElementImport" href="PyUMLProfile.uml#_ZtOxIKjHEdym48zZ96s2nA"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_rcM5oq1vEdyCurEqUBGZMw" x="189" y="117" width="78"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:DiagramStyle" xmi:id="_dobnwa1vEdyCurEqUBGZMw"/>
|
||||||
|
<element xmi:type="uml:Profile" href="PyUMLProfile.uml#_7Y-UAKi8Edyr_pXRyLU3wA"/>
|
||||||
|
</notation:Diagram>
|
1675
pyUml/custom-src/uml2tools_class_plugin.xml
Executable file
1675
pyUml/custom-src/uml2tools_class_plugin.xml
Executable file
File diff suppressed because it is too large
Load Diff
49
pyUml/custom-src/umltools_class_MANIFEST.MF
Executable file
49
pyUml/custom-src/umltools_class_MANIFEST.MF
Executable file
@ -0,0 +1,49 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Bundle-ManifestVersion: 2
|
||||||
|
Bundle-Name: %pluginName
|
||||||
|
Bundle-SymbolicName: org.eclipse.uml2.diagram.clazz; singleton:=true
|
||||||
|
Bundle-Version: 0.7.1.qualifier
|
||||||
|
Bundle-ClassPath: .
|
||||||
|
Bundle-Activator: org.eclipse.uml2.diagram.clazz.part.UMLDiagramEditorPlugin
|
||||||
|
Bundle-Vendor: %providerName
|
||||||
|
Bundle-Localization: plugin
|
||||||
|
Export-Package: org.eclipse.uml2.diagram.clazz.edit.parts,
|
||||||
|
org.eclipse.uml2.diagram.clazz.part,
|
||||||
|
org.eclipse.uml2.diagram.clazz.providers,
|
||||||
|
org.eclipse.uml2.diagram.clazz.navigator
|
||||||
|
Require-Bundle: org.eclipse.core.runtime,
|
||||||
|
org.eclipse.core.resources,
|
||||||
|
org.eclipse.core.expressions,
|
||||||
|
org.eclipse.jface,
|
||||||
|
org.eclipse.ui.ide,
|
||||||
|
org.eclipse.ui.views,
|
||||||
|
org.eclipse.ui.navigator,
|
||||||
|
org.eclipse.emf.ecore,
|
||||||
|
org.eclipse.emf.ecore.xmi,
|
||||||
|
org.eclipse.emf.edit.ui,
|
||||||
|
org.eclipse.gef;visibility:=reexport,
|
||||||
|
org.eclipse.gmf.runtime.emf.core,
|
||||||
|
org.eclipse.gmf.runtime.emf.commands.core,
|
||||||
|
org.eclipse.gmf.runtime.emf.ui.properties,
|
||||||
|
org.eclipse.gmf.runtime.diagram.ui,
|
||||||
|
org.eclipse.gmf.runtime.diagram.ui.properties,
|
||||||
|
org.eclipse.gmf.runtime.diagram.ui.providers,
|
||||||
|
org.eclipse.gmf.runtime.diagram.ui.providers.ide,
|
||||||
|
org.eclipse.gmf.runtime.diagram.ui.resources.editor,
|
||||||
|
org.eclipse.gmf.runtime.diagram.ui.resources.editor.ide,
|
||||||
|
org.eclipse.gmf.runtime.notation.providers,
|
||||||
|
org.eclipse.uml2.uml;visibility:=reexport,
|
||||||
|
org.eclipse.uml2.uml.edit;visibility:=reexport,
|
||||||
|
org.eclipse.emf.ecore;visibility:=reexport,
|
||||||
|
org.eclipse.emf.ecore.edit;visibility:=reexport,
|
||||||
|
org.eclipse.emf.ocl;visibility:=reexport,
|
||||||
|
org.eclipse.emf.query.ocl;visibility:=reexport,
|
||||||
|
org.eclipse.gmf.runtime.draw2d.ui;visibility:=reexport,
|
||||||
|
org.eclipse.uml2.diagram.common;visibility:=reexport,
|
||||||
|
org.eclipse.draw2d;visibility:=reexport,
|
||||||
|
org.eclipse.ocl.ecore;visibility:=reexport,
|
||||||
|
org.eclipse.gmf.runtime.diagram.ui.render,
|
||||||
|
org.eclipse.ui.navigator.resources,
|
||||||
|
org.eclipse.emf.validation;visibility:=reexport
|
||||||
|
Eclipse-LazyStart: true
|
||||||
|
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
107
pyUml/documents/pythonTree.uml
Executable file
107
pyUml/documents/pythonTree.uml
Executable file
@ -0,0 +1,107 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<uml:Package xmi:version="2.1" xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" xmlns:uml="http://www.eclipse.org/uml2/2.1.0/UML" xmi:id="_Mve2kaGbEdy6I6R2I8Pp5Q" name="PythonTree">
|
||||||
|
<packagedElement xmi:type="uml:Class" xmi:id="_RzMBAKGbEdy6I6R2I8Pp5Q" name="PythonTreePackage">
|
||||||
|
<generalization xmi:id="_YFqPMKGcEdyiqaZxdx2orw" general="_V11hoKGcEdyiqaZxdx2orw"/>
|
||||||
|
<ownedAttribute xmi:id="_oCNygKGcEdyiqaZxdx2orw" name="packagedFile" type="_Zg8hcKGcEdyiqaZxdx2orw" association="_oCL9UKGcEdyiqaZxdx2orw">
|
||||||
|
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_pjpTkKGdEdyiqaZxdx2orw" value="*"/>
|
||||||
|
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_pjp6oKGdEdyiqaZxdx2orw" value="1"/>
|
||||||
|
</ownedAttribute>
|
||||||
|
<ownedAttribute xmi:id="_qqgDYqGcEdyiqaZxdx2orw" name="childClass" type="_ar4qkKGcEdyiqaZxdx2orw" association="_qqfcUKGcEdyiqaZxdx2orw">
|
||||||
|
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_v6Qs0KGcEdyiqaZxdx2orw" value="*"/>
|
||||||
|
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_v6RT4KGcEdyiqaZxdx2orw" value="1"/>
|
||||||
|
</ownedAttribute>
|
||||||
|
<ownedAttribute xmi:id="_7HezMKGcEdyiqaZxdx2orw" name="childPackage" type="_RzMBAKGbEdy6I6R2I8Pp5Q" association="_7Hc-AKGcEdyiqaZxdx2orw">
|
||||||
|
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_TcvG0KGdEdyiqaZxdx2orw" value="*"/>
|
||||||
|
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_Tcvt4KGdEdyiqaZxdx2orw" value="1"/>
|
||||||
|
</ownedAttribute>
|
||||||
|
</packagedElement>
|
||||||
|
<packagedElement xmi:type="uml:Class" xmi:id="_ST-Z4KGbEdy6I6R2I8Pp5Q" name="PythonTreeRoot">
|
||||||
|
<generalization xmi:id="_VD-m4KGcEdyiqaZxdx2orw" general="_RzMBAKGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<ownedAttribute xmi:id="_7xOJMKGbEdyiqaZxdx2orw" name="childPackage" type="_RzMBAKGbEdy6I6R2I8Pp5Q" association="_7w9DcKGbEdyiqaZxdx2orw">
|
||||||
|
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_Nq5ggKGcEdyiqaZxdx2orw" value="*"/>
|
||||||
|
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_Nq6HkKGcEdyiqaZxdx2orw" value="1"/>
|
||||||
|
</ownedAttribute>
|
||||||
|
</packagedElement>
|
||||||
|
<packagedElement xmi:type="uml:Association" xmi:id="_7w9DcKGbEdyiqaZxdx2orw" name="contains ->" memberEnd="_7xE_QKGbEdyiqaZxdx2orw _7xOJMKGbEdyiqaZxdx2orw">
|
||||||
|
<ownedEnd xmi:id="_7xE_QKGbEdyiqaZxdx2orw" name="src" type="_ST-Z4KGbEdy6I6R2I8Pp5Q" association="_7w9DcKGbEdyiqaZxdx2orw">
|
||||||
|
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_7xNiIKGbEdyiqaZxdx2orw" value="1"/>
|
||||||
|
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_7xLs8KGbEdyiqaZxdx2orw" value="1"/>
|
||||||
|
</ownedEnd>
|
||||||
|
</packagedElement>
|
||||||
|
<packagedElement xmi:type="uml:Class" xmi:id="_V11hoKGcEdyiqaZxdx2orw" name="PythonTreeNode">
|
||||||
|
<ownedAttribute xmi:id="_1h4nMKGdEdyiqaZxdx2orw" name="parent" type="_V11hoKGcEdyiqaZxdx2orw" aggregation="composite"/>
|
||||||
|
<ownedAttribute xmi:id="_85RrgKGdEdyiqaZxdx2orw" name="associatedModelElement" aggregation="composite"/>
|
||||||
|
<ownedAttribute xmi:id="_sINsoKGeEdyiqaZxdx2orw" name="xmiID" aggregation="composite"/>
|
||||||
|
<ownedAttribute xmi:id="_zgt5UKGgEdyiqaZxdx2orw" name="name" aggregation="composite"/>
|
||||||
|
<ownedOperation xmi:id="_5aDyoKGdEdyiqaZxdx2orw" name="synchonizeCode">
|
||||||
|
<ownedParameter xmi:id="_6QYWoKGdEdyiqaZxdx2orw" direction="return"/>
|
||||||
|
</ownedOperation>
|
||||||
|
<ownedOperation xmi:id="_6rj2wKGdEdyiqaZxdx2orw" name="synchronizeModel">
|
||||||
|
<ownedParameter xmi:id="_7OuOMKGdEdyiqaZxdx2orw" direction="return"/>
|
||||||
|
</ownedOperation>
|
||||||
|
</packagedElement>
|
||||||
|
<packagedElement xmi:type="uml:Class" xmi:id="_Zg8hcKGcEdyiqaZxdx2orw" name="PythonTreeFile">
|
||||||
|
<generalization xmi:id="_gz_RQKGcEdyiqaZxdx2orw" general="_V11hoKGcEdyiqaZxdx2orw"/>
|
||||||
|
<ownedAttribute xmi:id="_tGRFwqGdEdyiqaZxdx2orw" name="containedClass" type="_ar4qkKGcEdyiqaZxdx2orw" association="_tGP3oKGdEdyiqaZxdx2orw">
|
||||||
|
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_v1pdIKGdEdyiqaZxdx2orw" value="*"/>
|
||||||
|
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_v1pdIaGdEdyiqaZxdx2orw" value="1"/>
|
||||||
|
</ownedAttribute>
|
||||||
|
<ownedAttribute xmi:id="_cG6zQKGeEdyiqaZxdx2orw" name="fileAST" aggregation="composite"/>
|
||||||
|
</packagedElement>
|
||||||
|
<packagedElement xmi:type="uml:Class" xmi:id="_ar4qkKGcEdyiqaZxdx2orw" name="PythonTreeClass">
|
||||||
|
<generalization xmi:id="_hmyAIKGcEdyiqaZxdx2orw" general="_V11hoKGcEdyiqaZxdx2orw"/>
|
||||||
|
<ownedAttribute xmi:id="_tazn0KGcEdyiqaZxdx2orw" name="childMethod" type="_bvh44KGcEdyiqaZxdx2orw" association="_taxyoKGcEdyiqaZxdx2orw">
|
||||||
|
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_u2imAKGcEdyiqaZxdx2orw" value="*"/>
|
||||||
|
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_u2jNEKGcEdyiqaZxdx2orw" value="1"/>
|
||||||
|
</ownedAttribute>
|
||||||
|
<ownedOperation xmi:id="_Iva9oKGfEdyiqaZxdx2orw" name="createNewClass">
|
||||||
|
<ownedParameter xmi:id="_JWMCsKGfEdyiqaZxdx2orw" direction="return"/>
|
||||||
|
</ownedOperation>
|
||||||
|
</packagedElement>
|
||||||
|
<packagedElement xmi:type="uml:Class" xmi:id="_bvh44KGcEdyiqaZxdx2orw" name="PythonTreeMethod">
|
||||||
|
<generalization xmi:id="_iB514KGcEdyiqaZxdx2orw" general="_V11hoKGcEdyiqaZxdx2orw"/>
|
||||||
|
<ownedAttribute xmi:id="_wxIqcaGcEdyiqaZxdx2orw" name="childAttribute" type="_dULigKGcEdyiqaZxdx2orw" association="_wxHcUKGcEdyiqaZxdx2orw">
|
||||||
|
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_yniycKGcEdyiqaZxdx2orw" value="*"/>
|
||||||
|
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_ynjZgKGcEdyiqaZxdx2orw" value="1"/>
|
||||||
|
</ownedAttribute>
|
||||||
|
</packagedElement>
|
||||||
|
<packagedElement xmi:type="uml:Class" xmi:id="_dULigKGcEdyiqaZxdx2orw" name="PythonTreeAttribute">
|
||||||
|
<generalization xmi:id="_iXnnMKGcEdyiqaZxdx2orw" general="_V11hoKGcEdyiqaZxdx2orw"/>
|
||||||
|
</packagedElement>
|
||||||
|
<packagedElement xmi:type="uml:Association" xmi:id="_oCL9UKGcEdyiqaZxdx2orw" name="contains ->" memberEnd="_oCMkYKGcEdyiqaZxdx2orw _oCNygKGcEdyiqaZxdx2orw">
|
||||||
|
<ownedEnd xmi:id="_oCMkYKGcEdyiqaZxdx2orw" name="src" type="_RzMBAKGbEdy6I6R2I8Pp5Q" association="_oCL9UKGcEdyiqaZxdx2orw">
|
||||||
|
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_oCNLcaGcEdyiqaZxdx2orw" value="1"/>
|
||||||
|
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_oCNLcKGcEdyiqaZxdx2orw" value="1"/>
|
||||||
|
</ownedEnd>
|
||||||
|
</packagedElement>
|
||||||
|
<packagedElement xmi:type="uml:Association" xmi:id="_qqfcUKGcEdyiqaZxdx2orw" name="contains ->" memberEnd="_qqfcUaGcEdyiqaZxdx2orw _qqgDYqGcEdyiqaZxdx2orw">
|
||||||
|
<ownedEnd xmi:id="_qqfcUaGcEdyiqaZxdx2orw" name="src" type="_RzMBAKGbEdy6I6R2I8Pp5Q" association="_qqfcUKGcEdyiqaZxdx2orw">
|
||||||
|
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_qqgDYaGcEdyiqaZxdx2orw" value="1"/>
|
||||||
|
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_qqgDYKGcEdyiqaZxdx2orw" value="1"/>
|
||||||
|
</ownedEnd>
|
||||||
|
</packagedElement>
|
||||||
|
<packagedElement xmi:type="uml:Association" xmi:id="_taxyoKGcEdyiqaZxdx2orw" name="contains ->" memberEnd="_tayZsKGcEdyiqaZxdx2orw _tazn0KGcEdyiqaZxdx2orw">
|
||||||
|
<ownedEnd xmi:id="_tayZsKGcEdyiqaZxdx2orw" name="src" type="_ar4qkKGcEdyiqaZxdx2orw" association="_taxyoKGcEdyiqaZxdx2orw">
|
||||||
|
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_tazAwaGcEdyiqaZxdx2orw" value="1"/>
|
||||||
|
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_tazAwKGcEdyiqaZxdx2orw" value="1"/>
|
||||||
|
</ownedEnd>
|
||||||
|
</packagedElement>
|
||||||
|
<packagedElement xmi:type="uml:Association" xmi:id="_wxHcUKGcEdyiqaZxdx2orw" name=" contains ^" memberEnd="_wxIDYKGcEdyiqaZxdx2orw _wxIqcaGcEdyiqaZxdx2orw">
|
||||||
|
<ownedEnd xmi:id="_wxIDYKGcEdyiqaZxdx2orw" name="src" type="_bvh44KGcEdyiqaZxdx2orw" association="_wxHcUKGcEdyiqaZxdx2orw">
|
||||||
|
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_wxIqcKGcEdyiqaZxdx2orw" value="1"/>
|
||||||
|
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_wxIDYaGcEdyiqaZxdx2orw" value="1"/>
|
||||||
|
</ownedEnd>
|
||||||
|
</packagedElement>
|
||||||
|
<packagedElement xmi:type="uml:Association" xmi:id="_7Hc-AKGcEdyiqaZxdx2orw" name="contains ->" memberEnd="_7HdlEKGcEdyiqaZxdx2orw _7HezMKGcEdyiqaZxdx2orw">
|
||||||
|
<ownedEnd xmi:id="_7HdlEKGcEdyiqaZxdx2orw" name="src" type="_RzMBAKGbEdy6I6R2I8Pp5Q" association="_7Hc-AKGcEdyiqaZxdx2orw">
|
||||||
|
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_7HeMIaGcEdyiqaZxdx2orw" value="1"/>
|
||||||
|
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_7HeMIKGcEdyiqaZxdx2orw" value="1"/>
|
||||||
|
</ownedEnd>
|
||||||
|
</packagedElement>
|
||||||
|
<packagedElement xmi:type="uml:Association" xmi:id="_tGP3oKGdEdyiqaZxdx2orw" name="conatins ->" memberEnd="_tGQesKGdEdyiqaZxdx2orw _tGRFwqGdEdyiqaZxdx2orw">
|
||||||
|
<ownedEnd xmi:id="_tGQesKGdEdyiqaZxdx2orw" name="src" type="_Zg8hcKGcEdyiqaZxdx2orw" association="_tGP3oKGdEdyiqaZxdx2orw">
|
||||||
|
<upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_tGRFwaGdEdyiqaZxdx2orw" value="1"/>
|
||||||
|
<lowerValue xmi:type="uml:LiteralInteger" xmi:id="_tGRFwKGdEdyiqaZxdx2orw" value="1"/>
|
||||||
|
</ownedEnd>
|
||||||
|
</packagedElement>
|
||||||
|
</uml:Package>
|
492
pyUml/documents/pythonTree.umlclass_diagram
Executable file
492
pyUml/documents/pythonTree.umlclass_diagram
Executable file
@ -0,0 +1,492 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<notation:Diagram xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.1/notation" xmlns:uml="http://www.eclipse.org/uml2/2.1.0/UML" xmi:id="_M8LOwKGbEdy6I6R2I8Pp5Q" type="UMLClass" name="pythonTree.umlclass_diagram" measurementUnit="Pixel">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_N0TJkKGbEdy6I6R2I8Pp5Q" type="2014">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_N0UXsKGbEdy6I6R2I8Pp5Q" type="5020"/>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_N0bFYKGbEdy6I6R2I8Pp5Q" type="7032">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_N0bFYaGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_N0bFYqGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_N0bFY6GbEdy6I6R2I8Pp5Q"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:ShapeStyle" xmi:id="_N0TJkaGbEdy6I6R2I8Pp5Q" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Package" href="pythonTree.uml#_Mve2kaGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_N0TJkqGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_SBmQcKGbEdy6I6R2I8Pp5Q" type="2001">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_SBoFoKGbEdy6I6R2I8Pp5Q" type="5003">
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_SDBz0KGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_SBossKGbEdy6I6R2I8Pp5Q" type="5019"/>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_SBzEwKGbEdy6I6R2I8Pp5Q" type="7001">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_SBzEwaGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_SBzEwqGbEdy6I6R2I8Pp5Q" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_SBzEw6GbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_SBzExKGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_SB39QKGbEdy6I6R2I8Pp5Q" type="7002">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_SB39QaGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_SB39QqGbEdy6I6R2I8Pp5Q" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_SB39Q6GbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_SB39RKGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_SB5ycKGbEdy6I6R2I8Pp5Q" type="7003">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_SB5ycaGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_SB5ycqGbEdy6I6R2I8Pp5Q" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_SB5yc6GbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_SB5ydKGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:ShapeStyle" xmi:id="_SBmQcaGbEdy6I6R2I8Pp5Q" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Class" href="pythonTree.uml#_RzMBAKGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_SBmQcqGbEdy6I6R2I8Pp5Q" x="104" y="195"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_SUL1QKGbEdy6I6R2I8Pp5Q" type="2001">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_SUL1Q6GbEdy6I6R2I8Pp5Q" type="5003">
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_SUPfoKGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_SUMcUKGbEdy6I6R2I8Pp5Q" type="5019"/>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_SUNDYKGbEdy6I6R2I8Pp5Q" type="7001">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_SUNDYaGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_SUNDYqGbEdy6I6R2I8Pp5Q" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_SUNDY6GbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_SUNDZKGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_SUNDZaGbEdy6I6R2I8Pp5Q" type="7002">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_SUNDZqGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_SUNDZ6GbEdy6I6R2I8Pp5Q" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_SUNDaKGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_SUNDaaGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_SUNqcKGbEdy6I6R2I8Pp5Q" type="7003">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_SUNqcaGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_SUNqcqGbEdy6I6R2I8Pp5Q" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_SUNqc6GbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_SUNqdKGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:ShapeStyle" xmi:id="_SUL1QaGbEdy6I6R2I8Pp5Q" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Class" href="pythonTree.uml#_ST-Z4KGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_SUL1QqGbEdy6I6R2I8Pp5Q" x="26" y="416"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_V4DIIKGcEdyiqaZxdx2orw" type="2001">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_V4FkYKGcEdyiqaZxdx2orw" type="5003">
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_V4P8cKGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_V4GLcKGcEdyiqaZxdx2orw" type="5019"/>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_V4IAoKGcEdyiqaZxdx2orw" type="7001">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_1iS24KGdEdyiqaZxdx2orw" type="3001">
|
||||||
|
<element xmi:type="uml:Property" href="pythonTree.uml#_1h4nMKGdEdyiqaZxdx2orw"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_1iS24aGdEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_85lNgKGdEdyiqaZxdx2orw" type="3001">
|
||||||
|
<element xmi:type="uml:Property" href="pythonTree.uml#_85RrgKGdEdyiqaZxdx2orw"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_85lNgaGdEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_sIgnkKGeEdyiqaZxdx2orw" type="3001">
|
||||||
|
<element xmi:type="uml:Property" href="pythonTree.uml#_sINsoKGeEdyiqaZxdx2orw"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_sIgnkaGeEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_zhDQgKGgEdyiqaZxdx2orw" type="3001">
|
||||||
|
<element xmi:type="uml:Property" href="pythonTree.uml#_zgt5UKGgEdyiqaZxdx2orw"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_zhDQgaGgEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_V4IAoaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_V4IAoqGcEdyiqaZxdx2orw" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_V4IAo6GcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_V4IApKGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_V4J10KGcEdyiqaZxdx2orw" type="7002">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_5aWtkKGdEdyiqaZxdx2orw" type="3002">
|
||||||
|
<element xmi:type="uml:Operation" href="pythonTree.uml#_5aDyoKGdEdyiqaZxdx2orw"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_5aWtkaGdEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_6r2KoKGdEdyiqaZxdx2orw" type="3002">
|
||||||
|
<element xmi:type="uml:Operation" href="pythonTree.uml#_6rj2wKGdEdyiqaZxdx2orw"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_6r2KoaGdEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_V4J10aGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_V4J10qGcEdyiqaZxdx2orw" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_V4J106GcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_V4J11KGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_V4LD8KGcEdyiqaZxdx2orw" type="7003">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_V4LrAKGcEdyiqaZxdx2orw" collapsed="true"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_V4LrAaGcEdyiqaZxdx2orw" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_V4LrAqGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_V4LrA6GcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:ShapeStyle" xmi:id="_V4DIIaGcEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Class" href="pythonTree.uml#_V11hoKGcEdyiqaZxdx2orw"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_V4DIIqGcEdyiqaZxdx2orw" x="442" y="-52"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_ZhVjAKGcEdyiqaZxdx2orw" type="2001">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_ZhWxIKGcEdyiqaZxdx2orw" type="5003">
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_ZhbCkKGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_ZhWxIaGcEdyiqaZxdx2orw" type="5019"/>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_ZhWxIqGcEdyiqaZxdx2orw" type="7001">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_tGo5MKGdEdyiqaZxdx2orw" type="3001">
|
||||||
|
<element xmi:type="uml:Property" href="pythonTree.uml#_tGRFwqGdEdyiqaZxdx2orw"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_tGo5MaGdEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_cHOVQKGeEdyiqaZxdx2orw" type="3001">
|
||||||
|
<element xmi:type="uml:Property" href="pythonTree.uml#_cG6zQKGeEdyiqaZxdx2orw"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_cHOVQaGeEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_ZhWxI6GcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_ZhWxJKGcEdyiqaZxdx2orw" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_ZhWxJaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_ZhWxJqGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_ZhXYMKGcEdyiqaZxdx2orw" type="7002">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_ZhXYMaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_ZhXYMqGcEdyiqaZxdx2orw" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_ZhXYM6GcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_ZhXYNKGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_ZhX_QKGcEdyiqaZxdx2orw" type="7003">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_ZhX_QaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_ZhX_QqGcEdyiqaZxdx2orw" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_ZhX_Q6GcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_ZhX_RKGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:ShapeStyle" xmi:id="_ZhVjAaGcEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Class" href="pythonTree.uml#_Zg8hcKGcEdyiqaZxdx2orw"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_ZhWKEKGcEdyiqaZxdx2orw" x="390" y="286"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_asOo0KGcEdyiqaZxdx2orw" type="2001">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_asQeAKGcEdyiqaZxdx2orw" type="5003">
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_asVWgKGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_asRFEKGcEdyiqaZxdx2orw" type="5019"/>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_asRFEaGcEdyiqaZxdx2orw" type="7001">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_asRFEqGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_asRFE6GcEdyiqaZxdx2orw" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_asRFFKGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_asRFFaGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_asRsIKGcEdyiqaZxdx2orw" type="7002">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_IvvGsKGfEdyiqaZxdx2orw" type="3002">
|
||||||
|
<element xmi:type="uml:Operation" href="pythonTree.uml#_Iva9oKGfEdyiqaZxdx2orw"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_IvvGsaGfEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_asRsIaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_asRsIqGcEdyiqaZxdx2orw" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_asRsI6GcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_asRsJKGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_asSTMKGcEdyiqaZxdx2orw" type="7003">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_asSTMaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_asSTMqGcEdyiqaZxdx2orw" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_asSTM6GcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_asSTNKGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:ShapeStyle" xmi:id="_asOo0aGcEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Class" href="pythonTree.uml#_ar4qkKGcEdyiqaZxdx2orw"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_asOo0qGcEdyiqaZxdx2orw" x="598" y="442"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_bwBBEKGcEdyiqaZxdx2orw" type="2001">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_bwBoIKGcEdyiqaZxdx2orw" type="5003">
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_bwF5kKGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_bwBoIaGcEdyiqaZxdx2orw" type="5019"/>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_bwCPMKGcEdyiqaZxdx2orw" type="7001">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_bwCPMaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_bwCPMqGcEdyiqaZxdx2orw" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_bwCPM6GcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_bwCPNKGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_bwCPNaGcEdyiqaZxdx2orw" type="7002">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_bwCPNqGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_bwCPN6GcEdyiqaZxdx2orw" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_bwCPOKGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_bwCPOaGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_bwC2QKGcEdyiqaZxdx2orw" type="7003">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_bwC2QaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_bwC2QqGcEdyiqaZxdx2orw" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_bwC2Q6GcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_bwC2RKGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:ShapeStyle" xmi:id="_bwBBEaGcEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Class" href="pythonTree.uml#_bvh44KGcEdyiqaZxdx2orw"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_bwBBEqGcEdyiqaZxdx2orw" x="663" y="260"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_dUg5sKGcEdyiqaZxdx2orw" type="2001">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_dUhgwKGcEdyiqaZxdx2orw" type="5003">
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_dUlyMKGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_dUiH0KGcEdyiqaZxdx2orw" type="5019"/>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_dUiH0aGcEdyiqaZxdx2orw" type="7001">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_dUiH0qGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_dUiH06GcEdyiqaZxdx2orw" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_dUiH1KGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_dUiH1aGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_dUiu4KGcEdyiqaZxdx2orw" type="7002">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_dUiu4aGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_dUiu4qGcEdyiqaZxdx2orw" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_dUiu46GcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_dUiu5KGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_dUiu5aGcEdyiqaZxdx2orw" type="7003">
|
||||||
|
<styles xmi:type="notation:DrawerStyle" xmi:id="_dUiu5qGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:TitleStyle" xmi:id="_dUiu56GcEdyiqaZxdx2orw" showTitle="true"/>
|
||||||
|
<styles xmi:type="notation:SortingStyle" xmi:id="_dUjV8KGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_dUjV8aGcEdyiqaZxdx2orw"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:ShapeStyle" xmi:id="_dUg5saGcEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Class" href="pythonTree.uml#_dULigKGcEdyiqaZxdx2orw"/>
|
||||||
|
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_dUg5sqGcEdyiqaZxdx2orw" x="715" y="65"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:DiagramStyle" xmi:id="_M8LOwaGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<styles xmi:type="notation:FilteringStyle" xmi:id="_M8LOwqGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<element xmi:type="uml:Package" href="pythonTree.uml#_Mve2kaGbEdy6I6R2I8Pp5Q"/>
|
||||||
|
<edges xmi:type="notation:Edge" xmi:id="_7yYm0KGbEdyiqaZxdx2orw" type="4005" source="_SUL1QKGbEdy6I6R2I8Pp5Q" target="_SBmQcKGbEdy6I6R2I8Pp5Q">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_7ybDEKGbEdyiqaZxdx2orw" type="6003">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_7ybDEaGbEdyiqaZxdx2orw" x="-17" y="6"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_7ycRMKGbEdyiqaZxdx2orw" visible="false" type="6004">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_7ycRMaGbEdyiqaZxdx2orw" y="-15"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_7yetcKGbEdyiqaZxdx2orw" type="6005">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_7yetcaGbEdyiqaZxdx2orw" x="-14" y="-10"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_7yfUgKGbEdyiqaZxdx2orw" type="6006">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_7yfUgaGbEdyiqaZxdx2orw" y="-30"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_7yf7kKGbEdyiqaZxdx2orw" type="6007">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_7yf7kaGbEdyiqaZxdx2orw" y="-30"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_7ygioKGbEdyiqaZxdx2orw" type="6008">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_7yhJsKGbEdyiqaZxdx2orw" y="15"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_7yhwwKGbEdyiqaZxdx2orw" type="6009">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_7yhwwaGbEdyiqaZxdx2orw" x="10" y="13"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:RoutingStyle" xmi:id="_7yYm0aGbEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_7yYm0qGbEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Association" href="pythonTree.uml#_7w9DcKGbEdyiqaZxdx2orw"/>
|
||||||
|
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_7yYm06GbEdyiqaZxdx2orw" points="[0, -2, -44, 104]$[-14, -107, -58, -1]$[41, -107, -3, -1]"/>
|
||||||
|
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_76RXgKGbEdyiqaZxdx2orw" id="(0.07826087,0.01923077)"/>
|
||||||
|
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_HKc10KGdEdyiqaZxdx2orw" id="(0.013043478,0.8787879)"/>
|
||||||
|
</edges>
|
||||||
|
<edges xmi:type="notation:Edge" xmi:id="_VEztUKGcEdyiqaZxdx2orw" type="4001" source="_SUL1QKGbEdy6I6R2I8Pp5Q" target="_SBmQcKGbEdy6I6R2I8Pp5Q">
|
||||||
|
<styles xmi:type="notation:ConnectorStyle" xmi:id="_VEztUaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_VEztUqGcEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Generalization" href="pythonTree.uml#_VD-m4KGcEdyiqaZxdx2orw"/>
|
||||||
|
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_VEztU6GcEdyiqaZxdx2orw" points="[18, -17, -82, 79]$[94, -87, -6, 9]"/>
|
||||||
|
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_VE8QMKGcEdyiqaZxdx2orw" id="(0.83913046,0.16346154)"/>
|
||||||
|
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_VE8QMaGcEdyiqaZxdx2orw" id="(0.32857144,0.9)"/>
|
||||||
|
</edges>
|
||||||
|
<edges xmi:type="notation:Edge" xmi:id="_YFtSgKGcEdyiqaZxdx2orw" type="4001" source="_SBmQcKGbEdy6I6R2I8Pp5Q" target="_V4DIIKGcEdyiqaZxdx2orw">
|
||||||
|
<styles xmi:type="notation:ConnectorStyle" xmi:id="_YFtSgaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_YFtSgqGcEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Generalization" href="pythonTree.uml#_YFqPMKGcEdyiqaZxdx2orw"/>
|
||||||
|
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_YFtSg6GcEdyiqaZxdx2orw" points="[12, -14, -117, 111]$[67, -116, -62, 9]"/>
|
||||||
|
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_YFw84KGcEdyiqaZxdx2orw" id="(0.95,0.1)"/>
|
||||||
|
</edges>
|
||||||
|
<edges xmi:type="notation:Edge" xmi:id="_g0CUkKGcEdyiqaZxdx2orw" type="4001" source="_ZhVjAKGcEdyiqaZxdx2orw" target="_V4DIIKGcEdyiqaZxdx2orw">
|
||||||
|
<styles xmi:type="notation:ConnectorStyle" xmi:id="_g0CUkaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_g0CUkqGcEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Generalization" href="pythonTree.uml#_gz_RQKGcEdyiqaZxdx2orw"/>
|
||||||
|
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_g0CUk6GcEdyiqaZxdx2orw" points="[-12, -45, 40, 131]$[10, -178, 62, -2]"/>
|
||||||
|
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_GNELEKGeEdyiqaZxdx2orw" id="(0.32894737,0.028846154)"/>
|
||||||
|
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_GdcJYKGeEdyiqaZxdx2orw" id="(0.2,0.9794521)"/>
|
||||||
|
</edges>
|
||||||
|
<edges xmi:type="notation:Edge" xmi:id="_hm1DcKGcEdyiqaZxdx2orw" type="4001" source="_asOo0KGcEdyiqaZxdx2orw" target="_V4DIIKGcEdyiqaZxdx2orw">
|
||||||
|
<styles xmi:type="notation:ConnectorStyle" xmi:id="_hm1DcaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_hm1DcqGcEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Generalization" href="pythonTree.uml#_hmyAIKGcEdyiqaZxdx2orw"/>
|
||||||
|
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_hm1Dc6GcEdyiqaZxdx2orw" points="[-2, -18, 22, 215]$[-53, -215, -29, 18]"/>
|
||||||
|
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_hm4t0KGcEdyiqaZxdx2orw" id="(0.31308413,0.025423728)"/>
|
||||||
|
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_hm4t0aGcEdyiqaZxdx2orw" id="(0.97333336,0.9683544)"/>
|
||||||
|
</edges>
|
||||||
|
<edges xmi:type="notation:Edge" xmi:id="_iB8SIKGcEdyiqaZxdx2orw" type="4001" source="_bwBBEKGcEdyiqaZxdx2orw" target="_V4DIIKGcEdyiqaZxdx2orw">
|
||||||
|
<styles xmi:type="notation:ConnectorStyle" xmi:id="_iB8SIaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_iB8SIqGcEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Generalization" href="pythonTree.uml#_iB514KGcEdyiqaZxdx2orw"/>
|
||||||
|
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_iB8SI6GcEdyiqaZxdx2orw" points="[-8, -12, 155, 219]$[-145, -224, 18, 7]"/>
|
||||||
|
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_iB_VcKGcEdyiqaZxdx2orw" id="(0.7810219,0.13333334)"/>
|
||||||
|
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_iB_VcaGcEdyiqaZxdx2orw" id="(0.8548387,0.7)"/>
|
||||||
|
</edges>
|
||||||
|
<edges xmi:type="notation:Edge" xmi:id="_iXqqgKGcEdyiqaZxdx2orw" type="4001" source="_dUg5sKGcEdyiqaZxdx2orw" target="_V4DIIKGcEdyiqaZxdx2orw">
|
||||||
|
<styles xmi:type="notation:ConnectorStyle" xmi:id="_iXqqgaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_iXqqgqGcEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Generalization" href="pythonTree.uml#_iXnnMKGcEdyiqaZxdx2orw"/>
|
||||||
|
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_iXqqg6GcEdyiqaZxdx2orw" points="[-24, -16, 183, 124]$[-181, -139, 26, 1]"/>
|
||||||
|
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_iXtt0KGcEdyiqaZxdx2orw" id="(0.2689655,0.17777778)"/>
|
||||||
|
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_iXtt0aGcEdyiqaZxdx2orw" id="(0.7903226,0.51111114)"/>
|
||||||
|
</edges>
|
||||||
|
<edges xmi:type="notation:Edge" xmi:id="_oCTSEKGcEdyiqaZxdx2orw" type="4005" source="_SBmQcKGbEdy6I6R2I8Pp5Q" target="_ZhVjAKGcEdyiqaZxdx2orw">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_oCT5IKGcEdyiqaZxdx2orw" type="6003">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_oCT5IaGcEdyiqaZxdx2orw" x="-24" y="-9"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_oCT5IqGcEdyiqaZxdx2orw" visible="false" type="6004">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_oCT5I6GcEdyiqaZxdx2orw" y="-15"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_oCUgMKGcEdyiqaZxdx2orw" type="6005">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_oCUgMaGcEdyiqaZxdx2orw" x="10" y="39"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_oCUgMqGcEdyiqaZxdx2orw" type="6006">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_oCUgM6GcEdyiqaZxdx2orw" y="-30"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_oCVHQKGcEdyiqaZxdx2orw" type="6007">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_oCVHQaGcEdyiqaZxdx2orw" y="-30"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_oCVHQqGcEdyiqaZxdx2orw" type="6008">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_oCVHQ6GcEdyiqaZxdx2orw" y="15"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_oCVHRKGcEdyiqaZxdx2orw" type="6009">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_oCVHRaGcEdyiqaZxdx2orw" x="15" y="-18"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:RoutingStyle" xmi:id="_oCTSEaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_oCTSEqGcEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Association" href="pythonTree.uml#_oCL9UKGcEdyiqaZxdx2orw"/>
|
||||||
|
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_oCTSE6GcEdyiqaZxdx2orw" points="[3, -1, -82, -66]$[91, -1, 6, -66]$[91, 65, 6, 0]"/>
|
||||||
|
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_oCam0KGcEdyiqaZxdx2orw" id="(0.98695654,0.1969697)"/>
|
||||||
|
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_oCam0aGcEdyiqaZxdx2orw" id="(0.118421055,0.0)"/>
|
||||||
|
</edges>
|
||||||
|
<edges xmi:type="notation:Edge" xmi:id="_qqifoKGcEdyiqaZxdx2orw" type="4005" source="_SBmQcKGbEdy6I6R2I8Pp5Q" target="_asOo0KGcEdyiqaZxdx2orw">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_qqjGsKGcEdyiqaZxdx2orw" type="6003">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_qqjGsaGcEdyiqaZxdx2orw" x="38" y="9"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_qqjGsqGcEdyiqaZxdx2orw" visible="false" type="6004">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_qqjGs6GcEdyiqaZxdx2orw" y="-15"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_qqjGtKGcEdyiqaZxdx2orw" type="6005">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_qqjGtaGcEdyiqaZxdx2orw" x="39" y="-13"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_qqjGtqGcEdyiqaZxdx2orw" type="6006">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_qqjGt6GcEdyiqaZxdx2orw" y="-30"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_qqjGuKGcEdyiqaZxdx2orw" type="6007">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_qqjGuaGcEdyiqaZxdx2orw" y="-30"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_qqjtwKGcEdyiqaZxdx2orw" type="6008">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_qqjtwaGcEdyiqaZxdx2orw" y="15"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_qqjtwqGcEdyiqaZxdx2orw" type="6009">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_qqjtw6GcEdyiqaZxdx2orw" x="47" y="13"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:RoutingStyle" xmi:id="_qqifoaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_qqifoqGcEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Association" href="pythonTree.uml#_qqfcUKGcEdyiqaZxdx2orw"/>
|
||||||
|
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_qqifo6GcEdyiqaZxdx2orw" points="[-1, 28, -298, -209]$[-1, 230, -298, -7]$[293, 230, -4, -7]"/>
|
||||||
|
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_qqmKAKGcEdyiqaZxdx2orw" id="(0.8742857,0.78846157)"/>
|
||||||
|
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_qqmKAaGcEdyiqaZxdx2orw" id="(0.0,0.7372881)"/>
|
||||||
|
</edges>
|
||||||
|
<edges xmi:type="notation:Edge" xmi:id="_ta5HYKGcEdyiqaZxdx2orw" type="4005" source="_asOo0KGcEdyiqaZxdx2orw" target="_bwBBEKGcEdyiqaZxdx2orw">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_ta5ucKGcEdyiqaZxdx2orw" type="6003">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_ta5ucaGcEdyiqaZxdx2orw" x="-43" y="-22"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_ta5ucqGcEdyiqaZxdx2orw" visible="false" type="6004">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_ta5uc6GcEdyiqaZxdx2orw" y="-15"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_ta6VgKGcEdyiqaZxdx2orw" type="6005">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_ta6VgaGcEdyiqaZxdx2orw" x="11" y="-36"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_ta6VgqGcEdyiqaZxdx2orw" type="6006">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_ta6Vg6GcEdyiqaZxdx2orw" y="-30"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_ta6VhKGcEdyiqaZxdx2orw" type="6007">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_ta6VhaGcEdyiqaZxdx2orw" y="-30"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_ta68kKGcEdyiqaZxdx2orw" type="6008">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_ta68kaGcEdyiqaZxdx2orw" y="15"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_ta68kqGcEdyiqaZxdx2orw" type="6009">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_ta68k6GcEdyiqaZxdx2orw" x="12" y="13"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:RoutingStyle" xmi:id="_ta5HYaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_ta5HYqGcEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Association" href="pythonTree.uml#_taxyoKGcEdyiqaZxdx2orw"/>
|
||||||
|
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_ta5HY6GcEdyiqaZxdx2orw" points="[2, -1, -54, 135]$[63, -1, 7, 135]$[63, -133, 7, 3]"/>
|
||||||
|
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_tbAcIKGcEdyiqaZxdx2orw" id="(0.99065423,0.47115386)"/>
|
||||||
|
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_tbAcIaGcEdyiqaZxdx2orw" id="(0.9099099,0.97115386)"/>
|
||||||
|
</edges>
|
||||||
|
<edges xmi:type="notation:Edge" xmi:id="_wxOKAKGcEdyiqaZxdx2orw" type="4005" source="_bwBBEKGcEdyiqaZxdx2orw" target="_dUg5sKGcEdyiqaZxdx2orw">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_wxOxEKGcEdyiqaZxdx2orw" type="6003">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_wxOxEaGcEdyiqaZxdx2orw" x="-8" y="-6"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_wxOxEqGcEdyiqaZxdx2orw" visible="false" type="6004">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_wxOxE6GcEdyiqaZxdx2orw" y="-15"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_wxPYIKGcEdyiqaZxdx2orw" type="6005">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_wxPYIaGcEdyiqaZxdx2orw" x="2" y="-36"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_wxPYIqGcEdyiqaZxdx2orw" type="6006">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_wxPYI6GcEdyiqaZxdx2orw" y="-30"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_wxPYJKGcEdyiqaZxdx2orw" type="6007">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_wxPYJaGcEdyiqaZxdx2orw" y="-30"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_wxP_MKGcEdyiqaZxdx2orw" type="6008">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_wxP_MaGcEdyiqaZxdx2orw" y="15"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_wxP_MqGcEdyiqaZxdx2orw" type="6009">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_wxP_M6GcEdyiqaZxdx2orw" y="15"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:RoutingStyle" xmi:id="_wxOKAaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_wxOKAqGcEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Association" href="pythonTree.uml#_wxHcUKGcEdyiqaZxdx2orw"/>
|
||||||
|
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_wxOKA6GcEdyiqaZxdx2orw" points="[14, -14, -46, 46]$[63, -46, 3, 14]"/>
|
||||||
|
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_wxVewKGcEdyiqaZxdx2orw" id="(0.7927928,0.009615385)"/>
|
||||||
|
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_wxVewaGcEdyiqaZxdx2orw" id="(0.82758623,0.93333334)"/>
|
||||||
|
</edges>
|
||||||
|
<edges xmi:type="notation:Edge" xmi:id="_7HjrsKGcEdyiqaZxdx2orw" type="4005" source="_SBmQcKGbEdy6I6R2I8Pp5Q" target="_SBmQcKGbEdy6I6R2I8Pp5Q">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_7HkSwKGcEdyiqaZxdx2orw" type="6003">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_7Hk50KGcEdyiqaZxdx2orw" x="48" y="9"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_7Hk50aGcEdyiqaZxdx2orw" visible="false" type="6004">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_7Hk50qGcEdyiqaZxdx2orw" x="-28" y="17"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_7Hk506GcEdyiqaZxdx2orw" type="6005">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_7Hk51KGcEdyiqaZxdx2orw" x="17" y="-44"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_7Hlg4KGcEdyiqaZxdx2orw" type="6006">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_7Hlg4aGcEdyiqaZxdx2orw" y="-30"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_7Hlg4qGcEdyiqaZxdx2orw" type="6007">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_7Hlg46GcEdyiqaZxdx2orw" y="-30"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_7Hlg5KGcEdyiqaZxdx2orw" type="6008">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_7Hlg5aGcEdyiqaZxdx2orw" y="15"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_7HmH8KGcEdyiqaZxdx2orw" type="6009">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_7HmH8aGcEdyiqaZxdx2orw" x="33" y="-21"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:RoutingStyle" xmi:id="_7HjrsaGcEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_7HjrsqGcEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Association" href="pythonTree.uml#_7Hc-AKGcEdyiqaZxdx2orw"/>
|
||||||
|
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_7Hjrs6GcEdyiqaZxdx2orw" points="[0, 6, -97, 48]$[-35, 6, -132, 48]$[-35, -100, -132, -58]$[97, -100, 0, -58]$[97, -46, 0, -4]"/>
|
||||||
|
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_7HrAcKGcEdyiqaZxdx2orw" id="(0.0,0.34848484)"/>
|
||||||
|
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_7HrngKGcEdyiqaZxdx2orw" id="(0.42173913,0.030303031)"/>
|
||||||
|
</edges>
|
||||||
|
<edges xmi:type="notation:Edge" xmi:id="_tGWlUKGdEdyiqaZxdx2orw" type="4005" source="_ZhVjAKGcEdyiqaZxdx2orw" target="_asOo0KGcEdyiqaZxdx2orw">
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_tGXMYKGdEdyiqaZxdx2orw" type="6003">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_tGXMYaGdEdyiqaZxdx2orw" x="-30" y="10"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_tGXMYqGdEdyiqaZxdx2orw" visible="false" type="6004">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_tGXMY6GdEdyiqaZxdx2orw" y="-15"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_tGXMZKGdEdyiqaZxdx2orw" type="6005">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_tGXMZaGdEdyiqaZxdx2orw" x="-20" y="-14"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_tGXzcKGdEdyiqaZxdx2orw" type="6006">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_tGXzcaGdEdyiqaZxdx2orw" y="-30"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_tGXzcqGdEdyiqaZxdx2orw" type="6007">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_tGXzc6GdEdyiqaZxdx2orw" y="-30"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_tGXzdKGdEdyiqaZxdx2orw" type="6008">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_tGYagKGdEdyiqaZxdx2orw" y="15"/>
|
||||||
|
</children>
|
||||||
|
<children xmi:type="notation:Node" xmi:id="_tGYagaGdEdyiqaZxdx2orw" type="6009">
|
||||||
|
<layoutConstraint xmi:type="notation:Location" xmi:id="_tGYagqGdEdyiqaZxdx2orw" y="15"/>
|
||||||
|
</children>
|
||||||
|
<styles xmi:type="notation:RoutingStyle" xmi:id="_tGWlUaGdEdyiqaZxdx2orw"/>
|
||||||
|
<styles xmi:type="notation:FontStyle" xmi:id="_tGWlUqGdEdyiqaZxdx2orw" fontName="Sans Serif"/>
|
||||||
|
<element xmi:type="uml:Association" href="pythonTree.uml#_tGP3oKGdEdyiqaZxdx2orw"/>
|
||||||
|
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_tGWlU6GdEdyiqaZxdx2orw" points="[0, 5, -154, -49]$[0, 54, -154, 0]$[114, 54, -40, 0]"/>
|
||||||
|
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_tGd6EKGdEdyiqaZxdx2orw" id="(0.4122807,0.9576271)"/>
|
||||||
|
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_tGd6EaGdEdyiqaZxdx2orw" id="(0.18691589,0.10576923)"/>
|
||||||
|
</edges>
|
||||||
|
</notation:Diagram>
|
BIN
pyUml/images/class_obj.png
Executable file
BIN
pyUml/images/class_obj.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 774 B |
BIN
pyUml/images/manageViews.png
Executable file
BIN
pyUml/images/manageViews.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 293 B |
BIN
pyUml/images/openuml.png
Executable file
BIN
pyUml/images/openuml.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 259 B |
BIN
pyUml/images/package_obj.png
Executable file
BIN
pyUml/images/package_obj.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 345 B |
BIN
pyUml/images/py2uml.png
Executable file
BIN
pyUml/images/py2uml.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 214 B |
BIN
pyUml/images/pyUML_icons.tgz
Executable file
BIN
pyUml/images/pyUML_icons.tgz
Executable file
Binary file not shown.
BIN
pyUml/images/uml2py.png
Executable file
BIN
pyUml/images/uml2py.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 338 B |
BIN
pyUml/lib/refactoring.jar
Executable file
BIN
pyUml/lib/refactoring.jar
Executable file
Binary file not shown.
319
pyUml/license.html
Executable file
319
pyUml/license.html
Executable file
@ -0,0 +1,319 @@
|
|||||||
|
<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40"><head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||||
|
<meta name="ProgId" content="Word.Document">
|
||||||
|
<meta name="Generator" content="Microsoft Word 9">
|
||||||
|
<meta name="Originator" content="Microsoft Word 9">
|
||||||
|
<link rel="File-List" href="http://www.eclipse.org/org/documents/Eclipse%20EPL%202003_11_10%20Final_files/filelist.xml"><title>Eclipse Public License - Version 1.0</title><!--[if gte mso 9]><xml>
|
||||||
|
<o:DocumentProperties>
|
||||||
|
<o:Revision>2</o:Revision>
|
||||||
|
<o:TotalTime>3</o:TotalTime>
|
||||||
|
<o:Created>2004-03-05T23:03:00Z</o:Created>
|
||||||
|
<o:LastSaved>2004-03-05T23:03:00Z</o:LastSaved>
|
||||||
|
<o:Pages>4</o:Pages>
|
||||||
|
<o:Words>1626</o:Words>
|
||||||
|
<o:Characters>9270</o:Characters>
|
||||||
|
<o:Lines>77</o:Lines>
|
||||||
|
<o:Paragraphs>18</o:Paragraphs>
|
||||||
|
<o:CharactersWithSpaces>11384</o:CharactersWithSpaces>
|
||||||
|
<o:Version>9.4402</o:Version>
|
||||||
|
</o:DocumentProperties>
|
||||||
|
</xml><![endif]--><!--[if gte mso 9]><xml>
|
||||||
|
<w:WordDocument>
|
||||||
|
<w:TrackRevisions/>
|
||||||
|
</w:WordDocument>
|
||||||
|
</xml><![endif]-->
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
<!--
|
||||||
|
/* Font Definitions */
|
||||||
|
@font-face
|
||||||
|
{font-family:Tahoma;
|
||||||
|
panose-1:2 11 6 4 3 5 4 4 2 4;
|
||||||
|
mso-font-charset:0;
|
||||||
|
mso-generic-font-family:swiss;
|
||||||
|
mso-font-pitch:variable;
|
||||||
|
mso-font-signature:553679495 -2147483648 8 0 66047 0;}
|
||||||
|
/* Style Definitions */
|
||||||
|
p.MsoNormal, li.MsoNormal, div.MsoNormal
|
||||||
|
{mso-style-parent:"";
|
||||||
|
margin:0in;
|
||||||
|
margin-bottom:.0001pt;
|
||||||
|
mso-pagination:widow-orphan;
|
||||||
|
font-size:12.0pt;
|
||||||
|
font-family:"Times New Roman";
|
||||||
|
mso-fareast-font-family:"Times New Roman";}
|
||||||
|
p
|
||||||
|
{margin-right:0in;
|
||||||
|
mso-margin-top-alt:auto;
|
||||||
|
mso-margin-bottom-alt:auto;
|
||||||
|
margin-left:0in;
|
||||||
|
mso-pagination:widow-orphan;
|
||||||
|
font-size:12.0pt;
|
||||||
|
font-family:"Times New Roman";
|
||||||
|
mso-fareast-font-family:"Times New Roman";}
|
||||||
|
p.BalloonText, li.BalloonText, div.BalloonText
|
||||||
|
{mso-style-name:"Balloon Text";
|
||||||
|
margin:0in;
|
||||||
|
margin-bottom:.0001pt;
|
||||||
|
mso-pagination:widow-orphan;
|
||||||
|
font-size:8.0pt;
|
||||||
|
font-family:Tahoma;
|
||||||
|
mso-fareast-font-family:"Times New Roman";}
|
||||||
|
@page Section1
|
||||||
|
{size:8.5in 11.0in;
|
||||||
|
margin:1.0in 1.25in 1.0in 1.25in;
|
||||||
|
mso-header-margin:.5in;
|
||||||
|
mso-footer-margin:.5in;
|
||||||
|
mso-paper-source:0;}
|
||||||
|
div.Section1
|
||||||
|
{page:Section1;}
|
||||||
|
-->
|
||||||
|
</style></head>
|
||||||
|
|
||||||
|
<body style="" lang="EN-US">
|
||||||
|
|
||||||
|
<div class="Section1">
|
||||||
|
|
||||||
|
<p style="text-align: center;" align="center"><b>Eclipse Public License - v 1.0</b>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">THE ACCOMPANYING PROGRAM IS PROVIDED UNDER
|
||||||
|
THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE,
|
||||||
|
REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE
|
||||||
|
OF THIS AGREEMENT.</span> </p>
|
||||||
|
|
||||||
|
<p><b><span style="font-size: 10pt;">1. DEFINITIONS</span></b> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">"Contribution" means:</span> </p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">a)
|
||||||
|
in the case of the initial Contributor, the initial code and documentation
|
||||||
|
distributed under this Agreement, and<br clear="left">
|
||||||
|
b) in the case of each subsequent Contributor:</span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">i)
|
||||||
|
changes to the Program, and</span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">ii)
|
||||||
|
additions to the Program;</span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">where
|
||||||
|
such changes and/or additions to the Program originate from and are distributed
|
||||||
|
by that particular Contributor. A Contribution 'originates' from a Contributor
|
||||||
|
if it was added to the Program by such Contributor itself or anyone acting on
|
||||||
|
such Contributor's behalf. Contributions do not include additions to the
|
||||||
|
Program which: (i) are separate modules of software distributed in conjunction
|
||||||
|
with the Program under their own license agreement, and (ii) are not derivative
|
||||||
|
works of the Program. </span></p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">"Contributor" means any person or
|
||||||
|
entity that distributes the Program.</span> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">"Licensed Patents " mean patent
|
||||||
|
claims licensable by a Contributor which are necessarily infringed by the use
|
||||||
|
or sale of its Contribution alone or when combined with the Program. </span></p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">"Program" means the Contributions
|
||||||
|
distributed in accordance with this Agreement.</span> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">"Recipient" means anyone who
|
||||||
|
receives the Program under this Agreement, including all Contributors.</span> </p>
|
||||||
|
|
||||||
|
<p><b><span style="font-size: 10pt;">2. GRANT OF RIGHTS</span></b> </p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">a)
|
||||||
|
Subject to the terms of this Agreement, each Contributor hereby grants Recipient
|
||||||
|
a non-exclusive, worldwide, royalty-free copyright license to<span style="color: red;"> </span>reproduce, prepare derivative works of, publicly
|
||||||
|
display, publicly perform, distribute and sublicense the Contribution of such
|
||||||
|
Contributor, if any, and such derivative works, in source code and object code
|
||||||
|
form.</span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">b)
|
||||||
|
Subject to the terms of this Agreement, each Contributor hereby grants
|
||||||
|
Recipient a non-exclusive, worldwide,<span style="color: green;"> </span>royalty-free
|
||||||
|
patent license under Licensed Patents to make, use, sell, offer to sell, import
|
||||||
|
and otherwise transfer the Contribution of such Contributor, if any, in source
|
||||||
|
code and object code form. This patent license shall apply to the combination
|
||||||
|
of the Contribution and the Program if, at the time the Contribution is added
|
||||||
|
by the Contributor, such addition of the Contribution causes such combination
|
||||||
|
to be covered by the Licensed Patents. The patent license shall not apply to
|
||||||
|
any other combinations which include the Contribution. No hardware per se is
|
||||||
|
licensed hereunder. </span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">c)
|
||||||
|
Recipient understands that although each Contributor grants the licenses to its
|
||||||
|
Contributions set forth herein, no assurances are provided by any Contributor
|
||||||
|
that the Program does not infringe the patent or other intellectual property
|
||||||
|
rights of any other entity. Each Contributor disclaims any liability to Recipient
|
||||||
|
for claims brought by any other entity based on infringement of intellectual
|
||||||
|
property rights or otherwise. As a condition to exercising the rights and
|
||||||
|
licenses granted hereunder, each Recipient hereby assumes sole responsibility
|
||||||
|
to secure any other intellectual property rights needed, if any. For example,
|
||||||
|
if a third party patent license is required to allow Recipient to distribute
|
||||||
|
the Program, it is Recipient's responsibility to acquire that license before
|
||||||
|
distributing the Program.</span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">d)
|
||||||
|
Each Contributor represents that to its knowledge it has sufficient copyright
|
||||||
|
rights in its Contribution, if any, to grant the copyright license set forth in
|
||||||
|
this Agreement. </span></p>
|
||||||
|
|
||||||
|
<p><b><span style="font-size: 10pt;">3. REQUIREMENTS</span></b> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">A Contributor may choose to distribute the
|
||||||
|
Program in object code form under its own license agreement, provided that:</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">a)
|
||||||
|
it complies with the terms and conditions of this Agreement; and</span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">b)
|
||||||
|
its license agreement:</span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">i)
|
||||||
|
effectively disclaims on behalf of all Contributors all warranties and
|
||||||
|
conditions, express and implied, including warranties or conditions of title
|
||||||
|
and non-infringement, and implied warranties or conditions of merchantability
|
||||||
|
and fitness for a particular purpose; </span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">ii)
|
||||||
|
effectively excludes on behalf of all Contributors all liability for damages,
|
||||||
|
including direct, indirect, special, incidental and consequential damages, such
|
||||||
|
as lost profits; </span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">iii)
|
||||||
|
states that any provisions which differ from this Agreement are offered by that
|
||||||
|
Contributor alone and not by any other party; and</span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">iv)
|
||||||
|
states that source code for the Program is available from such Contributor, and
|
||||||
|
informs licensees how to obtain it in a reasonable manner on or through a
|
||||||
|
medium customarily used for software exchange.<span style="color: blue;"> </span></span></p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">When the Program is made available in source
|
||||||
|
code form:</span> </p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">a)
|
||||||
|
it must be made available under this Agreement; and </span></p>
|
||||||
|
|
||||||
|
<p class="MsoNormal" style="margin-left: 0.5in;"><span style="font-size: 10pt;">b) a
|
||||||
|
copy of this Agreement must be included with each copy of the Program. </span></p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">Contributors may not remove or alter any
|
||||||
|
copyright notices contained within the Program. </span></p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">Each Contributor must identify itself as the
|
||||||
|
originator of its Contribution, if any, in a manner that reasonably allows
|
||||||
|
subsequent Recipients to identify the originator of the Contribution. </span></p>
|
||||||
|
|
||||||
|
<p><b><span style="font-size: 10pt;">4. COMMERCIAL DISTRIBUTION</span></b> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">Commercial distributors of software may
|
||||||
|
accept certain responsibilities with respect to end users, business partners
|
||||||
|
and the like. While this license is intended to facilitate the commercial use
|
||||||
|
of the Program, the Contributor who includes the Program in a commercial
|
||||||
|
product offering should do so in a manner which does not create potential
|
||||||
|
liability for other Contributors. Therefore, if a Contributor includes the
|
||||||
|
Program in a commercial product offering, such Contributor ("Commercial
|
||||||
|
Contributor") hereby agrees to defend and indemnify every other
|
||||||
|
Contributor ("Indemnified Contributor") against any losses, damages and
|
||||||
|
costs (collectively "Losses") arising from claims, lawsuits and other
|
||||||
|
legal actions brought by a third party against the Indemnified Contributor to
|
||||||
|
the extent caused by the acts or omissions of such Commercial Contributor in
|
||||||
|
connection with its distribution of the Program in a commercial product
|
||||||
|
offering. The obligations in this section do not apply to any claims or Losses
|
||||||
|
relating to any actual or alleged intellectual property infringement. In order
|
||||||
|
to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
|
||||||
|
Contributor in writing of such claim, and b) allow the Commercial Contributor
|
||||||
|
to control, and cooperate with the Commercial Contributor in, the defense and
|
||||||
|
any related settlement negotiations. The Indemnified Contributor may participate
|
||||||
|
in any such claim at its own expense.</span> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">For example, a Contributor might include the
|
||||||
|
Program in a commercial product offering, Product X. That Contributor is then a
|
||||||
|
Commercial Contributor. If that Commercial Contributor then makes performance
|
||||||
|
claims, or offers warranties related to Product X, those performance claims and
|
||||||
|
warranties are such Commercial Contributor's responsibility alone. Under this
|
||||||
|
section, the Commercial Contributor would have to defend claims against the
|
||||||
|
other Contributors related to those performance claims and warranties, and if a
|
||||||
|
court requires any other Contributor to pay any damages as a result, the
|
||||||
|
Commercial Contributor must pay those damages.</span> </p>
|
||||||
|
|
||||||
|
<p><b><span style="font-size: 10pt;">5. NO WARRANTY</span></b> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">EXCEPT AS EXPRESSLY SET FORTH IN THIS
|
||||||
|
AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT
|
||||||
|
WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
|
||||||
|
WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
|
||||||
|
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
|
||||||
|
responsible for determining the appropriateness of using and distributing the
|
||||||
|
Program and assumes all risks associated with its exercise of rights under this
|
||||||
|
Agreement , including but not limited to the risks and costs of program errors,
|
||||||
|
compliance with applicable laws, damage to or loss of data, programs or
|
||||||
|
equipment, and unavailability or interruption of operations. </span></p>
|
||||||
|
|
||||||
|
<p><b><span style="font-size: 10pt;">6. DISCLAIMER OF LIABILITY</span></b> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">EXCEPT AS EXPRESSLY SET FORTH IN THIS
|
||||||
|
AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY
|
||||||
|
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF
|
||||||
|
THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF
|
||||||
|
THE POSSIBILITY OF SUCH DAMAGES.</span> </p>
|
||||||
|
|
||||||
|
<p><b><span style="font-size: 10pt;">7. GENERAL</span></b> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">If any provision of this Agreement is invalid
|
||||||
|
or unenforceable under applicable law, it shall not affect the validity or
|
||||||
|
enforceability of the remainder of the terms of this Agreement, and without
|
||||||
|
further action by the parties hereto, such provision shall be reformed to the
|
||||||
|
minimum extent necessary to make such provision valid and enforceable.</span> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">If Recipient institutes patent litigation
|
||||||
|
against any entity (including a cross-claim or counterclaim in a lawsuit)
|
||||||
|
alleging that the Program itself (excluding combinations of the Program with
|
||||||
|
other software or hardware) infringes such Recipient's patent(s), then such
|
||||||
|
Recipient's rights granted under Section 2(b) shall terminate as of the date
|
||||||
|
such litigation is filed. </span></p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">All Recipient's rights under this Agreement
|
||||||
|
shall terminate if it fails to comply with any of the material terms or
|
||||||
|
conditions of this Agreement and does not cure such failure in a reasonable
|
||||||
|
period of time after becoming aware of such noncompliance. If all Recipient's
|
||||||
|
rights under this Agreement terminate, Recipient agrees to cease use and
|
||||||
|
distribution of the Program as soon as reasonably practicable. However,
|
||||||
|
Recipient's obligations under this Agreement and any licenses granted by
|
||||||
|
Recipient relating to the Program shall continue and survive. </span></p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">Everyone is permitted to copy and distribute
|
||||||
|
copies of this Agreement, but in order to avoid inconsistency the Agreement is
|
||||||
|
copyrighted and may only be modified in the following manner. The Agreement
|
||||||
|
Steward reserves the right to publish new versions (including revisions) of
|
||||||
|
this Agreement from time to time. No one other than the Agreement Steward has
|
||||||
|
the right to modify this Agreement. The Eclipse Foundation is the initial
|
||||||
|
Agreement Steward. The Eclipse Foundation may assign the responsibility to
|
||||||
|
serve as the Agreement Steward to a suitable separate entity. Each new version
|
||||||
|
of the Agreement will be given a distinguishing version number. The Program
|
||||||
|
(including Contributions) may always be distributed subject to the version of
|
||||||
|
the Agreement under which it was received. In addition, after a new version of
|
||||||
|
the Agreement is published, Contributor may elect to distribute the Program
|
||||||
|
(including its Contributions) under the new version. Except as expressly stated
|
||||||
|
in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to
|
||||||
|
the intellectual property of any Contributor under this Agreement, whether
|
||||||
|
expressly, by implication, estoppel or otherwise. All rights in the Program not
|
||||||
|
expressly granted under this Agreement are reserved.</span> </p>
|
||||||
|
|
||||||
|
<p><span style="font-size: 10pt;">This Agreement is governed by the laws of the
|
||||||
|
State of New York and the intellectual property laws of the United States of
|
||||||
|
America. No party to this Agreement will bring a legal action under this
|
||||||
|
Agreement more than one year after the cause of action arose. Each party waives
|
||||||
|
its rights to a jury trial in any resulting litigation.</span> </p>
|
||||||
|
|
||||||
|
<p class="MsoNormal"><!--[if !supportEmptyParas]--> <!--[endif]--><o:p></o:p></p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body></html>
|
121
pyUml/plugin.xml
Executable file
121
pyUml/plugin.xml
Executable file
@ -0,0 +1,121 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<?eclipse version="3.2"?>
|
||||||
|
<plugin>
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.ui.popupMenus">
|
||||||
|
<objectContribution
|
||||||
|
adaptable="false"
|
||||||
|
id="pyUml.projectMenu"
|
||||||
|
objectClass="org.eclipse.core.internal.resources.Project">
|
||||||
|
<action
|
||||||
|
class="pyUML.actions.SyncCodeAction"
|
||||||
|
definitionId="1"
|
||||||
|
id="pyUML.1-createCode"
|
||||||
|
label="Create/Synchronize Code">
|
||||||
|
</action>
|
||||||
|
<action
|
||||||
|
class="pyUML.actions.SyncModelAction"
|
||||||
|
definitionId="2"
|
||||||
|
id="pyUML.2-testParsingAction"
|
||||||
|
label="Create/Synchronize UML Model">
|
||||||
|
</action>
|
||||||
|
<action
|
||||||
|
class="pyUML.actions.ManageViewsAction"
|
||||||
|
id="pyUML.3-manageViews"
|
||||||
|
label="Manage Views">
|
||||||
|
</action>
|
||||||
|
<action
|
||||||
|
class="pyUML.actions.OpenModelAction"
|
||||||
|
id="pyUML.4-OpenModel"
|
||||||
|
label="Open Model without Sync Run">
|
||||||
|
</action>
|
||||||
|
</objectContribution>
|
||||||
|
<objectContribution
|
||||||
|
id="pyUML.umlModelMenu"
|
||||||
|
nameFilter="*.uml"
|
||||||
|
objectClass="org.eclipse.core.resources.IFile">
|
||||||
|
<action
|
||||||
|
class="pyUML.actions.SyncCodeAction"
|
||||||
|
id="pydev-steering.createCode"
|
||||||
|
label="Create Code from Model">
|
||||||
|
</action>
|
||||||
|
<action
|
||||||
|
class="pyUML.views.SynchronizeModelByView"
|
||||||
|
id="pyUML.snycModelByView"
|
||||||
|
label="Synchronize Model by this View">
|
||||||
|
</action>
|
||||||
|
</objectContribution>
|
||||||
|
</extension>
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.ui.menus">
|
||||||
|
<menuContribution
|
||||||
|
locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
|
||||||
|
<toolbar
|
||||||
|
id="pyUml.mainToolbar">
|
||||||
|
<command
|
||||||
|
commandId="pyUml.syncModelCommand"
|
||||||
|
icon="images/py2uml.png"
|
||||||
|
id="pyuml.toolbars.synchronizeModel"
|
||||||
|
tooltip="This starts a synchronization Run to update the UML model by the Python Code in a project.">
|
||||||
|
</command>
|
||||||
|
<command
|
||||||
|
commandId="pyUml.syncCodeCommand"
|
||||||
|
icon="images/uml2py.png"
|
||||||
|
id="pyuml.toolbars.synchronizeCode"
|
||||||
|
tooltip="This starts a synchronization Run to update the UML code by the UML diagram in a project.">
|
||||||
|
</command>
|
||||||
|
<command
|
||||||
|
commandId="pyUml.manageViewsCommand"
|
||||||
|
icon="images/manageViews.png"
|
||||||
|
id="pyuml.toolbars.manageViews"
|
||||||
|
tooltip="Manage Model Views synchronized with Main model">
|
||||||
|
</command>
|
||||||
|
<command
|
||||||
|
commandId="pyUml.openModelCommand"
|
||||||
|
icon="images/openuml.png"
|
||||||
|
id="pyuml.toolbars.openModel"
|
||||||
|
tooltip="Open the (old) UML model for a project without prior Synchronization run.">
|
||||||
|
</command>
|
||||||
|
</toolbar>
|
||||||
|
</menuContribution>
|
||||||
|
</extension>
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.ui.commands">
|
||||||
|
<command
|
||||||
|
id="pyUml.syncModelCommand"
|
||||||
|
name="Synchronize Model by Code">
|
||||||
|
</command>
|
||||||
|
<command
|
||||||
|
id="pyUml.syncCodeCommand"
|
||||||
|
name="Synchronize Code By Model">
|
||||||
|
</command>
|
||||||
|
<command
|
||||||
|
id="pyUml.manageViewsCommand"
|
||||||
|
name="Manage Views">
|
||||||
|
</command>
|
||||||
|
<command
|
||||||
|
id="pyUml.openModelCommand"
|
||||||
|
name="Open UML Diagram without Synchronization">
|
||||||
|
</command>
|
||||||
|
</extension>
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.ui.handlers">
|
||||||
|
<handler
|
||||||
|
class="pyUML.actions.SyncModelHandler"
|
||||||
|
commandId="pyUml.syncModelCommand">
|
||||||
|
</handler>
|
||||||
|
<handler
|
||||||
|
class="pyUML.actions.SyncCodeHandler"
|
||||||
|
commandId="pyUml.syncCodeCommand">
|
||||||
|
</handler>
|
||||||
|
<handler
|
||||||
|
class="pyUML.actions.ManageViewsHandler"
|
||||||
|
commandId="pyUml.manageViewsCommand">
|
||||||
|
</handler>
|
||||||
|
<handler
|
||||||
|
class="pyUML.actions.OpenModelHandler"
|
||||||
|
commandId="pyUml.openModelCommand">
|
||||||
|
</handler>
|
||||||
|
</extension>
|
||||||
|
|
||||||
|
</plugin>
|
92
pyUml/src/pyUML/actions/ManageViewsAction.java
Executable file
92
pyUml/src/pyUML/actions/ManageViewsAction.java
Executable file
@ -0,0 +1,92 @@
|
|||||||
|
package pyUML.actions;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
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.impl.ResourceSetImpl;
|
||||||
|
import org.eclipse.jface.action.IAction;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.eclipse.jface.viewers.ISelection;
|
||||||
|
import org.eclipse.jface.viewers.TreeSelection;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
import org.eclipse.ui.IObjectActionDelegate;
|
||||||
|
import org.eclipse.ui.IWorkbenchPart;
|
||||||
|
import org.eclipse.uml2.uml.Model;
|
||||||
|
import org.python.pydev.navigator.elements.PythonFile;
|
||||||
|
|
||||||
|
import pyUML.backend.GlobalConstants;
|
||||||
|
import pyUML.views.ManageViewsPage;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class ManageViewsAction implements IObjectActionDelegate{
|
||||||
|
|
||||||
|
IWorkbenchPart part;
|
||||||
|
ISelection selection;
|
||||||
|
IProject project;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
|
||||||
|
*/
|
||||||
|
public void setActivePart(IAction action, IWorkbenchPart part) {
|
||||||
|
this.part = part;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manual way to open a window to manage pyUML.views
|
||||||
|
* A project is needed to open a ManagViews Window
|
||||||
|
* @param project An eclipse project
|
||||||
|
*/
|
||||||
|
public static void run(IProject project) {
|
||||||
|
ManageViewsAction manageViews = new ManageViewsAction();
|
||||||
|
manageViews.project = project;
|
||||||
|
manageViews.run((IAction) null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The run method used when the action is executed
|
||||||
|
* -> a new manage pyUML.views window is opened
|
||||||
|
*/
|
||||||
|
public void run(IAction action) {
|
||||||
|
|
||||||
|
try{
|
||||||
|
String umlFileName=project.getLocation().
|
||||||
|
append(GlobalConstants.getPyUmlDir()).
|
||||||
|
append(project.getName()+".uml").toOSString();
|
||||||
|
|
||||||
|
EObject diagramRoot = null;
|
||||||
|
try {
|
||||||
|
Resource resource = new ResourceSetImpl().getResource(URI.createFileURI(umlFileName), true);
|
||||||
|
diagramRoot = (EObject) resource.getContents().get(0);
|
||||||
|
} catch (WrappedException ex) {
|
||||||
|
MessageDialog.openError(null,"Error opening UML model",
|
||||||
|
"Unable to load model: " + umlFileName + "\n" +
|
||||||
|
"You must create a model before you can create pyUML.views!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Model model = (Model) diagramRoot;
|
||||||
|
|
||||||
|
ManageViewsPage page = new ManageViewsPage((Shell) null, model, project);
|
||||||
|
if (page != null)
|
||||||
|
page.open();
|
||||||
|
|
||||||
|
}catch (Throwable t) {
|
||||||
|
MessageDialog.openError(null,t.getClass().getName(),"Error Managing Views:\n"+t.getClass().getName()+"\n"+t.getMessage());
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void selectionChanged(IAction action, ISelection selection) {
|
||||||
|
if (selection instanceof TreeSelection) {
|
||||||
|
TreeSelection ts = (TreeSelection) selection;
|
||||||
|
Object selectedElement = ts.getFirstElement();
|
||||||
|
this.project = (IProject) selectedElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
pyUml/src/pyUML/actions/ManageViewsHandler.java
Executable file
28
pyUml/src/pyUML/actions/ManageViewsHandler.java
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
package pyUML.actions;
|
||||||
|
|
||||||
|
import org.eclipse.core.commands.AbstractHandler;
|
||||||
|
import org.eclipse.core.commands.ExecutionEvent;
|
||||||
|
import org.eclipse.core.commands.ExecutionException;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
|
||||||
|
import pyUML.backend.EclipseHelperMethods;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An action Handler that calls ManageViewsAction for a user-selected project
|
||||||
|
*/
|
||||||
|
public class ManageViewsHandler extends AbstractHandler{
|
||||||
|
public static IProject selectedProject = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object execute(ExecutionEvent arg0) throws ExecutionException {
|
||||||
|
EclipseHelperMethods.saveAllOpenEditors();
|
||||||
|
IProject project = EclipseHelperMethods.selectProject();
|
||||||
|
|
||||||
|
if (project == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
ManageViewsAction.run(project);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
88
pyUml/src/pyUML/actions/OpenModelAction.java
Executable file
88
pyUml/src/pyUML/actions/OpenModelAction.java
Executable file
@ -0,0 +1,88 @@
|
|||||||
|
package pyUML.actions;
|
||||||
|
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.jface.action.IAction;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.eclipse.jface.viewers.ISelection;
|
||||||
|
import org.eclipse.jface.viewers.TreeSelection;
|
||||||
|
import org.eclipse.ui.IEditorPart;
|
||||||
|
import org.eclipse.ui.IWorkbenchWindow;
|
||||||
|
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
|
||||||
|
|
||||||
|
import pyUML.backend.EclipseHelperMethods;
|
||||||
|
import pyUML.backend.GlobalConstants;
|
||||||
|
import pyUML.backend.UMLToolsHelperMethods;
|
||||||
|
import pyUML.listeners.ModelChangeListener;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class OpenModelAction implements IWorkbenchWindowActionDelegate{
|
||||||
|
|
||||||
|
IProject project = null;
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
// Auto-generated method stub
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(IWorkbenchWindow window) {
|
||||||
|
// Auto-generated method stub
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the UML diagram for the given project
|
||||||
|
* @param project
|
||||||
|
*/
|
||||||
|
public static void runOpenModel(IProject project) {
|
||||||
|
OpenModelAction delegate = new OpenModelAction();
|
||||||
|
delegate.project = project;
|
||||||
|
delegate.run((IAction) null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run(IAction action) {
|
||||||
|
this.openModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the central method -
|
||||||
|
* A UML diagram is opened. The project set
|
||||||
|
* in this object is used
|
||||||
|
*/
|
||||||
|
public void openModel() {
|
||||||
|
|
||||||
|
// Ensure a project was given
|
||||||
|
if (this.project == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save all open editors
|
||||||
|
EclipseHelperMethods.saveAllOpenEditors();
|
||||||
|
|
||||||
|
// open diagram
|
||||||
|
IFile diagramFile = this.project.getWorkspace()
|
||||||
|
.getRoot().getFile(this.project.getFullPath()
|
||||||
|
.append(GlobalConstants.getPyUmlDir())
|
||||||
|
.append(project.getName()+GlobalConstants
|
||||||
|
.getDiagramExtension()));
|
||||||
|
|
||||||
|
if (! diagramFile.exists()) {
|
||||||
|
MessageDialog.openWarning(null, "Opening UML diagram failed",
|
||||||
|
"Failed to open UML diagram, because it does not seem to exist.\n" +
|
||||||
|
"Please use 'synchronize Model' to create a new Diagram!");
|
||||||
|
return;
|
||||||
|
}else {
|
||||||
|
IEditorPart modelEditor = UMLToolsHelperMethods.openDiagram(project, diagramFile, project.getName()+".uml", true);
|
||||||
|
modelEditor.addPropertyListener(new ModelChangeListener(project));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void selectionChanged(IAction action, ISelection selection) {
|
||||||
|
if (selection instanceof TreeSelection) {
|
||||||
|
TreeSelection ts = (TreeSelection) selection;
|
||||||
|
Object selectedElement = ts.getFirstElement();
|
||||||
|
this.project = (IProject) selectedElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
pyUml/src/pyUML/actions/OpenModelHandler.java
Executable file
27
pyUml/src/pyUML/actions/OpenModelHandler.java
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
package pyUML.actions;
|
||||||
|
|
||||||
|
import org.eclipse.core.commands.AbstractHandler;
|
||||||
|
import org.eclipse.core.commands.ExecutionEvent;
|
||||||
|
import org.eclipse.core.commands.ExecutionException;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
|
||||||
|
import pyUML.backend.EclipseHelperMethods;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An action Handler that calls OpenModelAction for a user-selected project
|
||||||
|
*/
|
||||||
|
public class OpenModelHandler extends AbstractHandler{
|
||||||
|
public static IProject selectedProject = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object execute(ExecutionEvent arg0) throws ExecutionException {
|
||||||
|
EclipseHelperMethods.saveAllOpenEditors();
|
||||||
|
IProject project = EclipseHelperMethods.selectProject();
|
||||||
|
|
||||||
|
OpenModelAction.runOpenModel(project);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
233
pyUml/src/pyUML/actions/SyncCodeAction.java
Executable file
233
pyUml/src/pyUML/actions/SyncCodeAction.java
Executable file
@ -0,0 +1,233 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
24
pyUml/src/pyUML/actions/SyncCodeHandler.java
Executable file
24
pyUml/src/pyUML/actions/SyncCodeHandler.java
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
package pyUML.actions;
|
||||||
|
|
||||||
|
import org.eclipse.core.commands.AbstractHandler;
|
||||||
|
import org.eclipse.core.commands.ExecutionEvent;
|
||||||
|
import org.eclipse.core.commands.ExecutionException;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
|
||||||
|
import pyUML.backend.EclipseHelperMethods;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An action Handler that calls SyncCodeAction for a user-selected project
|
||||||
|
*/
|
||||||
|
public class SyncCodeHandler extends AbstractHandler{
|
||||||
|
public static IProject selectedProject = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object execute(ExecutionEvent arg0) throws ExecutionException {
|
||||||
|
EclipseHelperMethods.saveAllOpenEditors();
|
||||||
|
IProject project = EclipseHelperMethods.selectProject();
|
||||||
|
SyncCodeAction.run(project, null, null);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
328
pyUml/src/pyUML/actions/SyncModelAction.java
Executable file
328
pyUml/src/pyUML/actions/SyncModelAction.java
Executable file
@ -0,0 +1,328 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
27
pyUml/src/pyUML/actions/SyncModelHandler.java
Executable file
27
pyUml/src/pyUML/actions/SyncModelHandler.java
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
package pyUML.actions;
|
||||||
|
|
||||||
|
import org.eclipse.core.commands.AbstractHandler;
|
||||||
|
import org.eclipse.core.commands.ExecutionEvent;
|
||||||
|
import org.eclipse.core.commands.ExecutionException;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
|
||||||
|
import pyUML.backend.EclipseHelperMethods;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An action Handler that calls SyncModelAction for a user-selected project
|
||||||
|
*/
|
||||||
|
public class SyncModelHandler extends AbstractHandler{
|
||||||
|
public static IProject selectedProject = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object execute(ExecutionEvent arg0) throws ExecutionException {
|
||||||
|
EclipseHelperMethods.saveAllOpenEditors();
|
||||||
|
IProject project = EclipseHelperMethods.selectProject();
|
||||||
|
|
||||||
|
SyncModelAction.runModelSync(project);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
126
pyUml/src/pyUML/backend/ChooseProjectDialog.java
Executable file
126
pyUml/src/pyUML/backend/ChooseProjectDialog.java
Executable file
@ -0,0 +1,126 @@
|
|||||||
|
package pyUML.backend;
|
||||||
|
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.jface.dialogs.Dialog;
|
||||||
|
import org.eclipse.jface.dialogs.IDialogConstants;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
|
import org.eclipse.swt.layout.GridData;
|
||||||
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Control;
|
||||||
|
import org.eclipse.swt.widgets.Group;
|
||||||
|
import org.eclipse.swt.widgets.List;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a SWT dialog the lets the user choose one of
|
||||||
|
* the given projects.
|
||||||
|
* By the next run, the lately selected project in preselected
|
||||||
|
*/
|
||||||
|
public class ChooseProjectDialog extends Dialog{
|
||||||
|
public static IProject preSelectedProject = null;
|
||||||
|
|
||||||
|
private java.util.List<IProject> projects;
|
||||||
|
private List selectProjectBox;
|
||||||
|
private IProject selectedProject = null;
|
||||||
|
private java.util.List<String> projectsList;
|
||||||
|
|
||||||
|
public ChooseProjectDialog(Shell parent, java.util.List<IProject> projects) {
|
||||||
|
super(parent);
|
||||||
|
this.projects = projects;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a ChooseProjectDialog and lets the user choose
|
||||||
|
* one of the given projects.
|
||||||
|
* After "Use" or "Cancel" is pressed, the selected
|
||||||
|
* Project is returned, or null if cancel was pressed.
|
||||||
|
* @param parent
|
||||||
|
* @param projects
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static IProject runChooseProject(Shell parent, java.util.List<IProject> projects) {
|
||||||
|
if (preSelectedProject != null && (! preSelectedProject.isOpen()))
|
||||||
|
preSelectedProject = null;
|
||||||
|
|
||||||
|
// Create dialog
|
||||||
|
ChooseProjectDialog dialog = new ChooseProjectDialog(parent, projects);
|
||||||
|
dialog.create();
|
||||||
|
|
||||||
|
// Pre-select project that was selected before
|
||||||
|
if (ChooseProjectDialog.preSelectedProject != null) {
|
||||||
|
String preSelectedProjectName = ChooseProjectDialog.preSelectedProject.getName();
|
||||||
|
if (dialog.getProjectsList().contains(preSelectedProjectName)) {
|
||||||
|
int index = dialog.getProjectsList().indexOf(preSelectedProjectName);
|
||||||
|
dialog.selectProjectBox.setSelection(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.open();
|
||||||
|
|
||||||
|
ChooseProjectDialog.preSelectedProject = dialog.selectedProject;
|
||||||
|
|
||||||
|
return dialog.selectedProject;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Control createDialogArea(Composite parent) {
|
||||||
|
Composite composite = (Composite) super.createDialogArea(parent);
|
||||||
|
setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX);
|
||||||
|
createControls(composite);
|
||||||
|
//add controls to composite as necessary
|
||||||
|
return composite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createControls (Composite composite) {
|
||||||
|
// create graphical components
|
||||||
|
Shell shell = composite.getShell();
|
||||||
|
shell.setText("Select Python Project To Use");
|
||||||
|
|
||||||
|
Group selectBoxGroup = new Group(composite, SWT.None);
|
||||||
|
selectBoxGroup.setText("Please select a project to be used by PyUML:");
|
||||||
|
|
||||||
|
selectBoxGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
|
||||||
|
selectBoxGroup.setLayout(new GridLayout(1, true));
|
||||||
|
|
||||||
|
this.selectProjectBox = new List( selectBoxGroup, SWT.BORDER|SWT.SINGLE|SWT.V_SCROLL|SWT.H_SCROLL );
|
||||||
|
selectProjectBox.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||||
|
|
||||||
|
this.projectsList = new Vector<String>();
|
||||||
|
for (IProject project : this.projects) {
|
||||||
|
this.selectProjectBox.add(project.getName());
|
||||||
|
projectsList.add(project.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
selectProjectBox.setSize(300,300);
|
||||||
|
|
||||||
|
//buttonGroup.pack();
|
||||||
|
selectBoxGroup.pack();
|
||||||
|
|
||||||
|
composite.pack();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void widgetDefaultSelected(SelectionEvent e) {
|
||||||
|
// Not needed in this dialog
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void buttonPressed(int buttonId) {
|
||||||
|
if (IDialogConstants.OK_ID == buttonId) {
|
||||||
|
int selectedIndex = this.selectProjectBox.getSelectionIndex();
|
||||||
|
if (selectedIndex < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.selectedProject = this.projects.get(selectedIndex);
|
||||||
|
this.close();
|
||||||
|
} else if (IDialogConstants.CANCEL_ID == buttonId) {
|
||||||
|
cancelPressed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public java.util.List<String> getProjectsList() {
|
||||||
|
return projectsList;
|
||||||
|
}
|
||||||
|
}
|
290
pyUml/src/pyUML/backend/EclipseHelperMethods.java
Executable file
290
pyUml/src/pyUML/backend/EclipseHelperMethods.java
Executable file
@ -0,0 +1,290 @@
|
|||||||
|
package pyUML.backend;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
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.resources.ResourcesPlugin;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.Path;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
import org.eclipse.ui.IEditorReference;
|
||||||
|
import org.eclipse.ui.IWorkbenchPage;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
import org.python.pydev.plugin.nature.PythonNature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some Helper methods for Eclipse-specific tasks
|
||||||
|
*/
|
||||||
|
public class EclipseHelperMethods {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes an open Editor, if it is already opened
|
||||||
|
* @param project the current project
|
||||||
|
* @param editorName the Name of the editor to close (or a REGEX)
|
||||||
|
* @return true, if an editor was closed, false, if nothing was done
|
||||||
|
*/
|
||||||
|
public static boolean closeEditorByName(IProject project, String editorName){
|
||||||
|
IEditorReference editor = firstOpenEditorByName(editorName);
|
||||||
|
if (editor == null)
|
||||||
|
return false;
|
||||||
|
IWorkbenchPage page =
|
||||||
|
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
|
||||||
|
return page.closeEditor(editor.getEditor(true), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks for an open editor with a name that matches the given regex.
|
||||||
|
* Returns a list of matching editors or an empty list, if no such editor is open.
|
||||||
|
* @param editorNameRegex
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static List<IEditorReference> lookForOpenEditorByName(String editorNameRegex) {
|
||||||
|
IWorkbenchPage page =
|
||||||
|
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
|
||||||
|
|
||||||
|
List<IEditorReference> editorList = new Vector<IEditorReference>();
|
||||||
|
for (IEditorReference editor : page.getEditorReferences()) {
|
||||||
|
if (editor.getTitle().matches(editorNameRegex)) {
|
||||||
|
editorList.add(editor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return editorList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks for an open editor with a name that matches the given regex.
|
||||||
|
* Returns the first matching editors or null, if no such editor is open.
|
||||||
|
* @param editorNameRegex
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static IEditorReference firstOpenEditorByName(String editorNameRegex) {
|
||||||
|
List<IEditorReference> editorList = lookForOpenEditorByName(editorNameRegex);
|
||||||
|
if (editorList.size() == 0)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return editorList.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the content of an IFile and returns teh String of the content
|
||||||
|
* @param file the IFile to read
|
||||||
|
* @return The file content String, null on error
|
||||||
|
*/
|
||||||
|
public static String iFileToString(IFile file){
|
||||||
|
String fileContents = "";
|
||||||
|
try{
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(file.getContents()));
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
fileContents+= line+"\n";
|
||||||
|
}
|
||||||
|
return fileContents;
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
MessageDialog.openError(null, "Error Reading File",
|
||||||
|
"Cannot Read file "+file+"\nReason:\n"+e.getMessage());
|
||||||
|
}
|
||||||
|
catch (CoreException e) {
|
||||||
|
MessageDialog.openError(null, "Error Reading File",
|
||||||
|
"Cannot Read file "+file+"\nReason:\n"+e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a string to an IFile. The old file content is replaced completely.
|
||||||
|
*
|
||||||
|
* @param file the IFile to update
|
||||||
|
* @param s the string to write to the file
|
||||||
|
* @return true on success, false otherwise
|
||||||
|
*/
|
||||||
|
public static boolean StringToIFile(IFile file, String s) {
|
||||||
|
try{
|
||||||
|
file.setContents(JavaHelperMethods.stringToStream(s),
|
||||||
|
IResource.FORCE, null);
|
||||||
|
EclipseHelperMethods.updateFile(file);
|
||||||
|
return true;
|
||||||
|
} catch (CoreException err) {
|
||||||
|
MessageDialog.openError(null, "Error writing file", err.getMessage());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* marks the ressource as updated in eclipse
|
||||||
|
* @param file the changed IFile
|
||||||
|
*/
|
||||||
|
public static void updateFile(IFile file) {
|
||||||
|
try {
|
||||||
|
file.refreshLocal(1, null);
|
||||||
|
} catch (CoreException e) {
|
||||||
|
System.out.println("Error updating ressource "+file.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* marks the resource as updated in eclipse
|
||||||
|
* @param path the full path of the changed file
|
||||||
|
*/
|
||||||
|
public static void updateFile(String path, IProject project) {
|
||||||
|
try {
|
||||||
|
IFile file = createFile(path, project);
|
||||||
|
file.refreshLocal(1, null);
|
||||||
|
} catch (CoreException e) {
|
||||||
|
System.out.println("Error updating ressource "+path);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* marks the folder as updated in eclipse
|
||||||
|
* @param path the full path of the changed file
|
||||||
|
*/
|
||||||
|
public static void updateFolder(String path, IProject project) {
|
||||||
|
try {
|
||||||
|
IFolder file = createFolder(path, project);
|
||||||
|
file.refreshLocal(IResource.DEPTH_INFINITE, null);
|
||||||
|
} catch (CoreException e) {
|
||||||
|
System.out.println("Error updating folder "+path);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creates an IFile resource out of an absolute Path and a project
|
||||||
|
* (the file is not created on the file system, only an IFile Object
|
||||||
|
* with appropriate path is created)
|
||||||
|
*/
|
||||||
|
public static IFile createFile(String path, IProject project) {
|
||||||
|
// cut everything in front of project name
|
||||||
|
String localPath = path.replace(project.getLocation().toOSString(), "");
|
||||||
|
IPath relativeFilePath = project.getFullPath().append(localPath);
|
||||||
|
return project.getWorkspace().getRoot().getFile(relativeFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creates an IFolder resource out of an absolute Path and a project
|
||||||
|
* (the folder is not created on the file system, only an IFolder Object
|
||||||
|
* with appropriate path is created)
|
||||||
|
*/
|
||||||
|
public static IFolder createFolder(String path, IProject project) {
|
||||||
|
// cut everything in front of project name
|
||||||
|
String localPath = path.replace(project.getLocation().toOSString(), "");
|
||||||
|
IPath relativeFilePath = project.getFullPath().append(localPath);
|
||||||
|
return project.getWorkspace().getRoot().getFolder(relativeFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves all Editors opened in the Workbench.
|
||||||
|
*/
|
||||||
|
public static void saveAllOpenEditors() {
|
||||||
|
// save all open editors
|
||||||
|
// (this may fail if the process is forked)
|
||||||
|
// (-> catch NullpointerException and do not save, then)
|
||||||
|
try {
|
||||||
|
IWorkbenchPage page =
|
||||||
|
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
|
||||||
|
page.saveAllEditors(false);
|
||||||
|
} catch (NullPointerException e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isPythonProject(IProject project) {
|
||||||
|
PythonNature store = new PythonNature();
|
||||||
|
store.setProject(project);
|
||||||
|
try {
|
||||||
|
store.getPythonPathNature().getProjectSourcePathSet();
|
||||||
|
} catch (CoreException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (NullPointerException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the source folder(s) of this python project.
|
||||||
|
* If an error occurs (e.g. the project is no python
|
||||||
|
* project), the project location is returned.
|
||||||
|
* Source folders contained in other source folders are
|
||||||
|
* removed from list.
|
||||||
|
*
|
||||||
|
* @param project
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Set<IPath> getPythonSrcDirs(IProject project) {
|
||||||
|
PythonNature store = new PythonNature();
|
||||||
|
store.setProject(project);
|
||||||
|
Set<IPath> srcPaths = new HashSet<IPath>();
|
||||||
|
try{
|
||||||
|
Set<String> srcStrings = store.getPythonPathNature().getProjectSourcePathSet();
|
||||||
|
srcDirLoop:
|
||||||
|
for (String dirString : srcStrings) {
|
||||||
|
|
||||||
|
// continue, if this dir is already contained in any other dir
|
||||||
|
for (String dirString2 : srcStrings) {
|
||||||
|
if (dirString != dirString2 && dirString2.startsWith(dirString))
|
||||||
|
continue srcDirLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPath srcPath = new Path(dirString);
|
||||||
|
IPath srcDir = srcPath.removeFirstSegments(1); //remove project dir
|
||||||
|
IPath completeSrcPath = project.getLocation().append(srcDir);
|
||||||
|
srcPaths.add(completeSrcPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return srcPaths;
|
||||||
|
}
|
||||||
|
catch (CoreException e) {
|
||||||
|
srcPaths.add(project.getLocation());
|
||||||
|
return srcPaths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method chooses from the list of available Projects
|
||||||
|
* in the Workspace the project to work with, which is
|
||||||
|
* -> a python project
|
||||||
|
* -> if there are several, the user us asked which one to use
|
||||||
|
* -> if there is no project selected, the user asked to select one
|
||||||
|
*
|
||||||
|
* @return the pyDev project that was selected
|
||||||
|
* null, if no project could be chosen
|
||||||
|
*/
|
||||||
|
public static IProject selectProject() {
|
||||||
|
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
|
||||||
|
List<IProject> pyDevProjects = new Vector<IProject>();
|
||||||
|
// find all pyDev-Projects
|
||||||
|
for (IProject project : projects) {
|
||||||
|
if (project.isOpen() && isPythonProject(project))
|
||||||
|
pyDevProjects.add(project);
|
||||||
|
}
|
||||||
|
if (pyDevProjects.size() == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (pyDevProjects.size() == 1)
|
||||||
|
return (pyDevProjects.get(0));
|
||||||
|
|
||||||
|
// let user choose the project to use
|
||||||
|
return ChooseProjectDialog.runChooseProject((Shell) null, pyDevProjects);
|
||||||
|
}
|
||||||
|
}
|
51
pyUml/src/pyUML/backend/GlobalConstants.java
Executable file
51
pyUml/src/pyUML/backend/GlobalConstants.java
Executable file
@ -0,0 +1,51 @@
|
|||||||
|
package pyUML.backend;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This class holds global parameters used by different classes
|
||||||
|
* of PyUML
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class GlobalConstants {
|
||||||
|
|
||||||
|
private final static String pyUmlDir="PyUML";
|
||||||
|
private final static String viewUmlExtension = ".pyUmlView.uml";
|
||||||
|
private final static String viewConfExtension = ".pyUmlViewConfig";
|
||||||
|
private final static String diagramExtension = ".umlclass_diagram";
|
||||||
|
private final static String unknownExpression = "\"??unknown??\"";
|
||||||
|
private final static String fullDefault = "PyUML:FullDefault:";
|
||||||
|
|
||||||
|
public final static String STEREOTYPE_BEANCLASS = "BeanClass";
|
||||||
|
private final static String[] possibleStereotypes = {GlobalConstants.STEREOTYPE_BEANCLASS};
|
||||||
|
|
||||||
|
public static String getViewUmlExtension() {
|
||||||
|
return viewUmlExtension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getPyUmlDir() {
|
||||||
|
return pyUmlDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getViewConfExtension() {
|
||||||
|
return viewConfExtension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getDiagramExtension() {
|
||||||
|
return diagramExtension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getUnknownExpression() {
|
||||||
|
return unknownExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getFullDefault() {
|
||||||
|
return fullDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> getPossibleStereoTypes() {
|
||||||
|
return Arrays.asList(possibleStereotypes);
|
||||||
|
}
|
||||||
|
}
|
84
pyUml/src/pyUML/backend/JavaHelperMethods.java
Executable file
84
pyUml/src/pyUML/backend/JavaHelperMethods.java
Executable file
@ -0,0 +1,84 @@
|
|||||||
|
package pyUML.backend;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* some helper methods for common java problems, i.e. file copying
|
||||||
|
*/
|
||||||
|
public class JavaHelperMethods {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fast & simple file copy.
|
||||||
|
* copies source file to destination file
|
||||||
|
*/
|
||||||
|
public static void copy(File source, File dest) throws IOException {
|
||||||
|
|
||||||
|
InputStream in = new FileInputStream(source);
|
||||||
|
OutputStream out = new FileOutputStream(dest);
|
||||||
|
final int bufferSize = 4096;
|
||||||
|
try {
|
||||||
|
byte[] buffer = new byte[bufferSize];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = in.read(buffer)) >= 0) {
|
||||||
|
out.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
out.close();
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static InputStream stringToStream(String s) {
|
||||||
|
return new ByteArrayInputStream(s.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Joins an Array of Strings to one big String separated by
|
||||||
|
* a separator
|
||||||
|
* @param array The String array to join
|
||||||
|
* @param separator The separator
|
||||||
|
* @return the joined String
|
||||||
|
*/
|
||||||
|
public static String join(String[] array, String separator) {
|
||||||
|
if (array==null) return "";
|
||||||
|
StringBuffer sb = new StringBuffer(array[0]);
|
||||||
|
for(int i=1; i<array.length; i++) {
|
||||||
|
sb.append(separator + array[i]);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of files present in a directory-tree
|
||||||
|
* matching the given regex.
|
||||||
|
* This can be used to count the packages (__init__.py)
|
||||||
|
* for progress monitoring.
|
||||||
|
* @param parentDir The directory to start with
|
||||||
|
* @param regex The regex to match
|
||||||
|
* @return the Number of occurrence of the file in the dir tree
|
||||||
|
*/
|
||||||
|
public static int getFileCount(File parentDir, String regex)
|
||||||
|
{
|
||||||
|
|
||||||
|
File[] filesAndDirs = parentDir.listFiles();
|
||||||
|
int count=0;
|
||||||
|
|
||||||
|
for( File file: filesAndDirs )
|
||||||
|
{
|
||||||
|
if( file.getName().matches(regex))
|
||||||
|
{
|
||||||
|
count ++;
|
||||||
|
}
|
||||||
|
if (file.isDirectory())
|
||||||
|
{
|
||||||
|
count += getFileCount(file, regex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
194
pyUml/src/pyUML/backend/ParseHelpers.java
Executable file
194
pyUml/src/pyUML/backend/ParseHelpers.java
Executable file
@ -0,0 +1,194 @@
|
|||||||
|
package pyUML.backend;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.eclipse.uml2.uml.Classifier;
|
||||||
|
import org.eclipse.uml2.uml.Model;
|
||||||
|
import org.python.pydev.parser.jython.ast.Name;
|
||||||
|
import org.python.pydev.parser.jython.ast.Num;
|
||||||
|
import org.python.pydev.parser.jython.ast.Str;
|
||||||
|
import org.python.pydev.parser.jython.ast.exprType;
|
||||||
|
|
||||||
|
import pyUML.pythonTree.PythonTreeFile;
|
||||||
|
import pyUML.pythonTree.PythonTreePackage;
|
||||||
|
import pyUML.pythonTree.PythonTreeRoot;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some Helper methods needed for parsing Pything Code
|
||||||
|
* and handling the Python Abstract Syntax Tree
|
||||||
|
*/
|
||||||
|
public class ParseHelpers {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads out a file and returns the file content as a string
|
||||||
|
*
|
||||||
|
* @param file the file to read
|
||||||
|
* @return a String representing the file's content
|
||||||
|
* null on Error
|
||||||
|
*/
|
||||||
|
public static String fileToString(File file, IProject project) {
|
||||||
|
IFile iFile = EclipseHelperMethods.createFile(file.getAbsolutePath(), project);
|
||||||
|
return EclipseHelperMethods.iFileToString(iFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Re-)Writes a string to a file and updates the file in the project,
|
||||||
|
* if the project is != null
|
||||||
|
* @param file the file to write to
|
||||||
|
* @param str the String to write to the File
|
||||||
|
* @param project (optional) the project where the file is located in
|
||||||
|
*/
|
||||||
|
public static void stringToFile(File file, String str, IProject project) {
|
||||||
|
try {
|
||||||
|
file.createNewFile();
|
||||||
|
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
|
||||||
|
writer.write(str);
|
||||||
|
writer.close();
|
||||||
|
EclipseHelperMethods.updateFile(file.getAbsolutePath(), project);
|
||||||
|
}catch (IOException e) {
|
||||||
|
MessageDialog.openError(null, "IOException",
|
||||||
|
"Error writing to file "+ file.getPath());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts a String representation of a python expression,
|
||||||
|
* if the expression is of type String or Num.
|
||||||
|
* The quotes of Strings are preserved
|
||||||
|
*
|
||||||
|
* @param expr The Python AST expression
|
||||||
|
* @param fileContent the content of the file where the expression
|
||||||
|
* is to be read
|
||||||
|
* @param attribute if true, expressions other than Strings or numbers are
|
||||||
|
* read by just reading the pure file content to the end of the line
|
||||||
|
* (or to a # sign). This works ONLY for attributes, not for expressions in
|
||||||
|
* function definitions.
|
||||||
|
* @param abbreviate if true, long values are abbreviated; at the end "(...)"
|
||||||
|
* is appended
|
||||||
|
* @param ONLY if this reads an attribute value: the value of the next line
|
||||||
|
* (needed to read multi-line attributes)
|
||||||
|
* if this is no attribute, this value is ignored.
|
||||||
|
*
|
||||||
|
* @return The String representation of this expression, null if expr is null
|
||||||
|
*/
|
||||||
|
public static String getStringOfExpr(exprType expr, PythonTreeFile pyFile, boolean attribute, boolean abbreviate, int nextLine){
|
||||||
|
if (expr == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
String exprString;
|
||||||
|
if (expr instanceof Str) {
|
||||||
|
Str defaultValStr = (Str) expr;
|
||||||
|
exprString = defaultValStr.s;
|
||||||
|
if (defaultValStr.type == Str.SingleDouble) {
|
||||||
|
exprString = "\"" + exprString + "\"";
|
||||||
|
}
|
||||||
|
else if (defaultValStr.type == Str.SingleSingle) {
|
||||||
|
exprString = "'" + exprString + "'";
|
||||||
|
}
|
||||||
|
} else if (expr instanceof Name) {
|
||||||
|
Name defaultValNum = (Name) expr;
|
||||||
|
exprString = defaultValNum.id;
|
||||||
|
} else if (expr instanceof Num) {
|
||||||
|
Num defaultValNum = (Num) expr;
|
||||||
|
exprString = defaultValNum.num;
|
||||||
|
} else if (attribute){
|
||||||
|
exprString = readExprAsText(expr, pyFile, nextLine);
|
||||||
|
} else {
|
||||||
|
return GlobalConstants.getUnknownExpression();
|
||||||
|
}
|
||||||
|
|
||||||
|
// cut default value, if it is too long
|
||||||
|
if (abbreviate && exprString.length() > 19) {
|
||||||
|
exprString = exprString.substring(0,14) + "(...)";
|
||||||
|
}
|
||||||
|
|
||||||
|
return exprString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for getStringOfExpr()
|
||||||
|
* Can read a multi-line-expression of an attribute
|
||||||
|
*
|
||||||
|
* @param expr
|
||||||
|
* @param pyFile
|
||||||
|
* @param nextLine
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String readExprAsText(exprType expr, PythonTreeFile pyFile, int nextLine) {
|
||||||
|
String[] lines = pyFile.getSplittedFileContent();
|
||||||
|
String exprString = lines[expr.beginLine-1];
|
||||||
|
exprString = exprString.substring(exprString.indexOf("=")+1);
|
||||||
|
exprString = exprString.replaceAll("^[\\s]*","");
|
||||||
|
exprString = exprString.replaceAll(" # created by PyUML.*$", "");
|
||||||
|
|
||||||
|
exprString = exprString.replaceAll("[\\s]*$", "");
|
||||||
|
|
||||||
|
for (int i=expr.beginLine; i < nextLine - 1; i++) {
|
||||||
|
String line = lines[i];
|
||||||
|
|
||||||
|
// docString comments of static attributes have a wrong "beginLine" value
|
||||||
|
// -> manually define here to ignore docStrings!
|
||||||
|
if (line.matches("^[\\s]*\"\"\".*"))
|
||||||
|
break;
|
||||||
|
line = line.replaceAll("# created by PyUML.*$", "");
|
||||||
|
line = " " +line.replaceAll("^[\\s]*", "");
|
||||||
|
exprString += line;
|
||||||
|
exprString = exprString.replaceAll("[\\s]*$", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there are called other classes/packages, the index
|
||||||
|
// is on the value, not on the "a.b.c"-prefix.
|
||||||
|
// if that's the case, add the prefix afterwards:
|
||||||
|
|
||||||
|
return exprString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple method to extract the XMI-ID out of a line
|
||||||
|
* containing the PyUML string "# PyUML: XMI_ID: ..."
|
||||||
|
* @param content
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String extractXmiFromString(String content) {
|
||||||
|
String xmi_id = null;
|
||||||
|
String[] lines = content.split("\n");
|
||||||
|
for (String line : lines) {
|
||||||
|
if (line.matches("\\s*# PyUML:.*")) {
|
||||||
|
String[] splittedLine = line.split("XMI_ID:");
|
||||||
|
if (splittedLine.length == 2) {
|
||||||
|
xmi_id = splittedLine[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return xmi_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This creates a string containing the model package structure as
|
||||||
|
* "/packSup/packSub/" , where the last package contains the
|
||||||
|
* current class.
|
||||||
|
* @param cl The class in the model to find the package structure for
|
||||||
|
* @return a string containing the parent package structure
|
||||||
|
* of this class
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static String getModelPackageStructure(org.eclipse.uml2.uml.Type cl) {
|
||||||
|
org.eclipse.uml2.uml.Package pack = cl.getPackage();
|
||||||
|
String structure = "";
|
||||||
|
while (! (pack instanceof Model))
|
||||||
|
{
|
||||||
|
structure = "/"+pack.getName() + structure ;
|
||||||
|
pack = pack.getNestingPackage();
|
||||||
|
}
|
||||||
|
|
||||||
|
return structure + "/";
|
||||||
|
}
|
||||||
|
}
|
59
pyUml/src/pyUML/backend/PyUMLProfile.java
Executable file
59
pyUml/src/pyUML/backend/PyUMLProfile.java
Executable file
@ -0,0 +1,59 @@
|
|||||||
|
package pyUML.backend;
|
||||||
|
|
||||||
|
public class PyUMLProfile {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the pyUML XMLProfile as a string;
|
||||||
|
* the hard-coded profile String can be replaces by a method
|
||||||
|
* loading a profile UML file
|
||||||
|
*/
|
||||||
|
public static String getProfileString() {
|
||||||
|
return profileString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String profileString =
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||||
|
"<uml:Profile xmi:version=\"2.1\" xmlns:xmi=\"http://schema.omg.org/spec/XMI/2.1\" xmlns:ecore=\"http://www.eclipse.org/emf/2002/Ecore\" xmlns:uml=\"http://www.eclipse.org/uml2/2.1.0/UML\" xmi:id=\"_7Y-UAKi8Edyr_pXRyLU3wA\" name=\"PyUMLProfile\" metaclassReference=\"_ZtOxIKjHEdym48zZ96s2nA\" metamodelReference=\"_bkzWwKjHEdym48zZ96s2nA\">\n" +
|
||||||
|
" <eAnnotations xmi:id=\"_oyijYKjHEdym48zZ96s2nA\" source=\"http://www.eclipse.org/uml2/2.0.0/UML\">\n" +
|
||||||
|
" <contents xmi:type=\"ecore:EPackage\" xmi:id=\"_bm4k8KjIEdym48zZ96s2nA\" name=\"PyUMLProfile\" nsURI=\"http:///schemas/PyUMLProfile/_bm06kKjIEdym48zZ96s2nA/1\" nsPrefix=\"PyUMLProfile\">\n" +
|
||||||
|
" <eClassifiers xmi:type=\"ecore:EClass\" xmi:id=\"_bm4k8ajIEdym48zZ96s2nA\" name=\"BeanClass\">\n" +
|
||||||
|
" <eAnnotations xmi:id=\"_bm4k8qjIEdym48zZ96s2nA\" source=\"http://www.eclipse.org/uml2/2.0.0/UML\" references=\"_e8aLwKjHEdym48zZ96s2nA\"/>\n" +
|
||||||
|
" <eAnnotations xmi:id=\"_bm4k86jIEdym48zZ96s2nA\" source=\"duplicates\">\n" +
|
||||||
|
" <contents xmi:type=\"ecore:EReference\" xmi:id=\"_bm4k9KjIEdym48zZ96s2nA\" name=\"base_Class\" ordered=\"false\" lowerBound=\"1\">\n" +
|
||||||
|
" <eAnnotations xmi:id=\"_bm4k9ajIEdym48zZ96s2nA\" source=\"redefines\" references=\"_bm4k-ajIEdym48zZ96s2nA\"/>\n" +
|
||||||
|
" <eType xmi:type=\"ecore:EClass\" href=\"http://www.eclipse.org/uml2/2.1.0/UML#//Class\"/>\n" +
|
||||||
|
" </contents>\n" +
|
||||||
|
" </eAnnotations>\n" +
|
||||||
|
" <eStructuralFeatures xmi:type=\"ecore:EAttribute\" xmi:id=\"_bm4k96jIEdym48zZ96s2nA\" name=\"TestProperty\" ordered=\"false\" lowerBound=\"1\">\n" +
|
||||||
|
" <eType xmi:type=\"ecore:EDataType\" href=\"http://www.eclipse.org/emf/2002/Ecore#//EString\"/>\n" +
|
||||||
|
" </eStructuralFeatures>\n" +
|
||||||
|
" <eStructuralFeatures xmi:type=\"ecore:EReference\" xmi:id=\"_bm4k-ajIEdym48zZ96s2nA\" name=\"base_Class\" ordered=\"false\" lowerBound=\"1\">\n" +
|
||||||
|
" <eType xmi:type=\"ecore:EClass\" href=\"http://www.eclipse.org/uml2/2.1.0/UML#//Class\"/>\n" +
|
||||||
|
" </eStructuralFeatures>\n" +
|
||||||
|
" </eClassifiers>\n" +
|
||||||
|
" </contents>\n" +
|
||||||
|
" <contents xmi:type=\"ecore:EPackage\" xmi:id=\"_oyjKcKjHEdym48zZ96s2nA\" name=\"PyUMLProfile\" nsURI=\"http:///schemas/PyUMLProfile/_oyfgEKjHEdym48zZ96s2nA/0\" nsPrefix=\"PyUMLProfile\">\n" +
|
||||||
|
" <eClassifiers xmi:type=\"ecore:EClass\" xmi:id=\"_oyjKcajHEdym48zZ96s2nA\" name=\"BeanClass\">\n" +
|
||||||
|
" <eAnnotations xmi:id=\"_oyjKcqjHEdym48zZ96s2nA\" source=\"http://www.eclipse.org/uml2/2.0.0/UML\" references=\"_e8aLwKjHEdym48zZ96s2nA\"/>\n" +
|
||||||
|
" </eClassifiers>\n" +
|
||||||
|
" </contents>\n" +
|
||||||
|
" </eAnnotations>\n" +
|
||||||
|
" <elementImport xmi:id=\"_ZtOxIKjHEdym48zZ96s2nA\">\n" +
|
||||||
|
" <importedElement xmi:type=\"uml:Class\" href=\"pathmap://UML_METAMODELS/UML.metamodel.uml#Class\"/>\n" +
|
||||||
|
" </elementImport>\n" +
|
||||||
|
" <packageImport xmi:id=\"_bkzWwKjHEdym48zZ96s2nA\">\n" +
|
||||||
|
" <importedPackage xmi:type=\"uml:Model\" href=\"pathmap://UML_METAMODELS/UML.metamodel.uml#_0\"/>\n" +
|
||||||
|
" </packageImport>\n" +
|
||||||
|
" <packagedElement xmi:type=\"uml:Stereotype\" xmi:id=\"_e8aLwKjHEdym48zZ96s2nA\" name=\"BeanClass\">\n" +
|
||||||
|
" <ownedAttribute xmi:id=\"_OAXE4KjIEdym48zZ96s2nA\" name=\"base_Class\">\n" +
|
||||||
|
" <type xmi:type=\"uml:Class\" href=\"pathmap://UML_METAMODELS/UML.metamodel.uml#Class\"/>\n" +
|
||||||
|
" </ownedAttribute>\n" +
|
||||||
|
" <ownedAttribute xmi:id=\"_S_NkgKjIEdym48zZ96s2nA\" name=\"base_Class\" association=\"_S_MWYKjIEdym48zZ96s2nA\">\n" +
|
||||||
|
" <type xmi:type=\"uml:Class\" href=\"pathmap://UML_METAMODELS/UML.metamodel.uml#Class\"/>\n" +
|
||||||
|
" </ownedAttribute>\n" +
|
||||||
|
" </packagedElement>\n" +
|
||||||
|
" <packagedElement xmi:type=\"uml:Extension\" xmi:id=\"_S_MWYKjIEdym48zZ96s2nA\" name=\"Class_BeanClass\" memberEnd=\"_S_M9cKjIEdym48zZ96s2nA _S_NkgKjIEdym48zZ96s2nA\">\n" +
|
||||||
|
" <ownedEnd xmi:type=\"uml:ExtensionEnd\" xmi:id=\"_S_M9cKjIEdym48zZ96s2nA\" name=\"extension_BeanClass\" type=\"_e8aLwKjHEdym48zZ96s2nA\" aggregation=\"composite\" association=\"_S_MWYKjIEdym48zZ96s2nA\"/>\n" +
|
||||||
|
" </packagedElement>\n" +
|
||||||
|
"</uml:Profile>\n" ;
|
||||||
|
}
|
311
pyUml/src/pyUML/backend/UMLToolsHelperMethods.java
Executable file
311
pyUml/src/pyUML/backend/UMLToolsHelperMethods.java
Executable file
@ -0,0 +1,311 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
13
pyUml/src/pyUML/exceptions/PyUMLCancelledException.java
Executable file
13
pyUml/src/pyUML/exceptions/PyUMLCancelledException.java
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
package pyUML.exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This exception is thrown when a user puhes the "cancel"
|
||||||
|
* Button in the progress monitor
|
||||||
|
*/
|
||||||
|
public class PyUMLCancelledException extends Exception{
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
}
|
18
pyUml/src/pyUML/exceptions/PyUMLParseException.java
Executable file
18
pyUml/src/pyUML/exceptions/PyUMLParseException.java
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
package pyUML.exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This exception is thrown when the parser returns an error;
|
||||||
|
* When parsing (in python only because of syntax errors),
|
||||||
|
* the user must fix the problem manually before pyUML can continue.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class PyUMLParseException extends Exception {
|
||||||
|
|
||||||
|
public PyUMLParseException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
}
|
19
pyUml/src/pyUML/exceptions/PyUMLSynchronizeCodeException.java
Executable file
19
pyUml/src/pyUML/exceptions/PyUMLSynchronizeCodeException.java
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
package pyUML.exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This exception is thrown when errors occur while snychronizing code
|
||||||
|
* An error message should be given.
|
||||||
|
*/
|
||||||
|
public class PyUMLSynchronizeCodeException extends Exception{
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public PyUMLSynchronizeCodeException (String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PyUMLSynchronizeCodeException () {
|
||||||
|
super("Error synchronizing code!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
144
pyUml/src/pyUML/listeners/LiveValidationListener.java
Executable file
144
pyUml/src/pyUML/listeners/LiveValidationListener.java
Executable file
@ -0,0 +1,144 @@
|
|||||||
|
package pyUML.listeners;
|
||||||
|
|
||||||
|
import org.eclipse.gmf.runtime.common.ui.util.IWorkbenchPartDescriptor;
|
||||||
|
import org.eclipse.gmf.runtime.common.ui.util.WorkbenchPartDescriptor;
|
||||||
|
import org.eclipse.ui.IEditorPart;
|
||||||
|
import org.eclipse.ui.IPropertyListener;
|
||||||
|
import org.eclipse.ui.IWorkbenchWindow;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.UMLDiagramEditor;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.ValidateAction;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.providers.UMLValidationDecoratorProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is a listener that runs a live validation run,
|
||||||
|
* when the listener is called.
|
||||||
|
* Additionally, it provides static functions to run validation as a background
|
||||||
|
* process which call the Validation run every n seconds.
|
||||||
|
*/
|
||||||
|
public class LiveValidationListener implements IPropertyListener{
|
||||||
|
|
||||||
|
private static LiveValidationListener singleton;
|
||||||
|
private static boolean isStarted;
|
||||||
|
private static int intervalSeconds = 3;
|
||||||
|
private static IWorkbenchWindow workbenchWindow;
|
||||||
|
|
||||||
|
private LiveValidationListener() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the singleton instance of this listener
|
||||||
|
*/
|
||||||
|
public static LiveValidationListener getListenerSingleton() {
|
||||||
|
if (LiveValidationListener.singleton == null)
|
||||||
|
LiveValidationListener.singleton = new LiveValidationListener();
|
||||||
|
return LiveValidationListener.singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs a live validation process once. Uses the currently open
|
||||||
|
* document for validation
|
||||||
|
*/
|
||||||
|
public static void startLiveValidation() {
|
||||||
|
LiveValidationListener.getListenerSingleton().propertyChanged(null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener method: On every change: do live validation run
|
||||||
|
*/
|
||||||
|
public void propertyChanged(Object o, int i) {
|
||||||
|
IEditorPart ed;
|
||||||
|
|
||||||
|
if (LiveValidationListener.workbenchWindow == null)
|
||||||
|
LiveValidationListener.workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
|
||||||
|
if (LiveValidationListener.workbenchWindow == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ed = LiveValidationListener.workbenchWindow.getActivePage().getActiveEditor();
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ed instanceof UMLDiagramEditor))
|
||||||
|
return;
|
||||||
|
UMLDiagramEditor umlEditor = (UMLDiagramEditor) ed;
|
||||||
|
|
||||||
|
IWorkbenchPartDescriptor desc = new WorkbenchPartDescriptor(umlEditor.getSite().getId(), umlEditor.getSite().getClass(), umlEditor.getSite().getPage());
|
||||||
|
ValidateAction action = new ValidateAction(desc);
|
||||||
|
UMLValidationDecoratorProvider.usedResource = umlEditor.getDiagram().eResource();
|
||||||
|
|
||||||
|
action.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a live validation Thread in background.
|
||||||
|
* The thread can be stopped with stopLiveValidationInBackground().
|
||||||
|
* Runs validation every getIntervalSeconds() seconds
|
||||||
|
*/
|
||||||
|
public static void startLiveValidationInBackground() {
|
||||||
|
LiveValidationListener.workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
|
||||||
|
|
||||||
|
if (isStarted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
isStarted = true;
|
||||||
|
Runnable runnable = new Runnable() {
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
// do validation run and sleep for a while
|
||||||
|
// to avoid bad performance on slow systems, the time
|
||||||
|
// the run takes is measured; the 2-fold time of the
|
||||||
|
// run is added to the interval time, so that
|
||||||
|
// the overall CPU usage for validation is < 33%
|
||||||
|
while (LiveValidationListener.isStarted()) {
|
||||||
|
long timeBefore = System.currentTimeMillis();
|
||||||
|
|
||||||
|
// run validation
|
||||||
|
LiveValidationListener.startLiveValidation();
|
||||||
|
|
||||||
|
long timeAfter = System.currentTimeMillis();
|
||||||
|
long timeDiff = timeAfter-timeBefore;
|
||||||
|
long timeToSleep = LiveValidationListener.getIntervalSeconds()*1000
|
||||||
|
+ timeDiff * 2;
|
||||||
|
try {
|
||||||
|
Thread.sleep(timeToSleep);
|
||||||
|
} catch (InterruptedException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Thread t = new Thread(runnable);
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the live validation in background.
|
||||||
|
*/
|
||||||
|
public static void stopLiveValidationInBackground() {
|
||||||
|
isStarted = false;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return true, if there is a background thread doing validation
|
||||||
|
*/
|
||||||
|
public static boolean isStarted() {
|
||||||
|
return isStarted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the update interval in seconds
|
||||||
|
*/
|
||||||
|
public static int getIntervalSeconds() {
|
||||||
|
return intervalSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param intervalSeconds the new interval between beackground live
|
||||||
|
* validation runs in seconds
|
||||||
|
*/
|
||||||
|
public static void setIntervalSeconds(int intervalSeconds) {
|
||||||
|
LiveValidationListener.intervalSeconds = intervalSeconds;
|
||||||
|
}
|
||||||
|
}
|
32
pyUml/src/pyUML/listeners/ModelChangeListener.java
Executable file
32
pyUml/src/pyUML/listeners/ModelChangeListener.java
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
package pyUML.listeners;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor;
|
||||||
|
import org.eclipse.ui.IPropertyListener;
|
||||||
|
|
||||||
|
import pyUML.backend.UMLToolsHelperMethods;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is to update all pyUML.views (model and diagram)
|
||||||
|
* On every model change
|
||||||
|
*/
|
||||||
|
public class ModelChangeListener implements IPropertyListener {
|
||||||
|
private IProject project;
|
||||||
|
|
||||||
|
public ModelChangeListener(IProject project) {
|
||||||
|
super();
|
||||||
|
this.project = project;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void propertyChanged(Object source, int propId) {
|
||||||
|
// on model save, update all pyUML.views
|
||||||
|
if (source instanceof DiagramEditor) {
|
||||||
|
DiagramEditor umlEditor = (DiagramEditor) source;
|
||||||
|
|
||||||
|
if (! umlEditor.isDirty()) {
|
||||||
|
UMLToolsHelperMethods.updateModelAndViewPages(this.project);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
74
pyUml/src/pyUML/listeners/ViewChangeListener.java
Executable file
74
pyUml/src/pyUML/listeners/ViewChangeListener.java
Executable file
@ -0,0 +1,74 @@
|
|||||||
|
package pyUML.listeners;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor;
|
||||||
|
import org.eclipse.ui.IEditorPart;
|
||||||
|
import org.eclipse.ui.IPropertyListener;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
|
||||||
|
import pyUML.backend.EclipseHelperMethods;
|
||||||
|
import pyUML.backend.GlobalConstants;
|
||||||
|
import pyUML.backend.UMLToolsHelperMethods;
|
||||||
|
import pyUML.views.SynchronizeModelByView;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This listener synchronizes the global model and
|
||||||
|
* all other pyUML.views whenever a view is saved
|
||||||
|
*/
|
||||||
|
public class ViewChangeListener implements IPropertyListener {
|
||||||
|
private IProject project;
|
||||||
|
|
||||||
|
public ViewChangeListener(IProject project) {
|
||||||
|
super();
|
||||||
|
this.project = project;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void propertyChanged(Object source, int propId) {
|
||||||
|
if (source instanceof DiagramEditor) {
|
||||||
|
DiagramEditor umlEditor = (DiagramEditor) source;
|
||||||
|
if (! umlEditor.isDirty()) {
|
||||||
|
// editor was just saved, otherwise it would be dirty.
|
||||||
|
// -> synchronize model every time the view is saved
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
String openEditorName=umlEditor.getTitle();
|
||||||
|
String viewPath = this.project.getLocation()
|
||||||
|
.append(GlobalConstants.getPyUmlDir())
|
||||||
|
.append(openEditorName.replace(GlobalConstants.getDiagramExtension(), "")
|
||||||
|
+ GlobalConstants.getViewUmlExtension()).toOSString();
|
||||||
|
SynchronizeModelByView.synchronizeGlobalModel(viewPath, this.project);
|
||||||
|
|
||||||
|
|
||||||
|
IFile globalModelDiagramFile = this.project.getWorkspace()
|
||||||
|
.getRoot().getFile(this.project.getFullPath()
|
||||||
|
.append(GlobalConstants.getPyUmlDir())
|
||||||
|
.append(project.getName()+GlobalConstants
|
||||||
|
.getDiagramExtension()));
|
||||||
|
|
||||||
|
// close all sub-package pyUML.views of global model diagram
|
||||||
|
for ( org.eclipse.ui.IEditorReference editor :
|
||||||
|
EclipseHelperMethods.lookForOpenEditorByName(project.getName()+"::.*")) {
|
||||||
|
PlatformUI.getWorkbench().getActiveWorkbenchWindow()
|
||||||
|
.getActivePage().closeEditor(editor.getEditor(true), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// after creating model, be sure the diagram view is reloaded
|
||||||
|
boolean diagramOpened = null != EclipseHelperMethods
|
||||||
|
.lookForOpenEditorByName(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());
|
||||||
|
IEditorPart modelDiagram = UMLToolsHelperMethods.refreshDiagramEditor(project, globalModelDiagramFile, keepFocus);
|
||||||
|
modelDiagram.addPropertyListener(new ModelChangeListener(project));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
pyUml/src/pyUML/plugin/Activator.java
Executable file
50
pyUml/src/pyUML/plugin/Activator.java
Executable file
@ -0,0 +1,50 @@
|
|||||||
|
package pyUML.plugin;
|
||||||
|
|
||||||
|
import org.eclipse.ui.plugin.AbstractUIPlugin;
|
||||||
|
import org.osgi.framework.BundleContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The activator class controls the plug-in life cycle
|
||||||
|
*/
|
||||||
|
public class Activator extends AbstractUIPlugin {
|
||||||
|
|
||||||
|
// The plug-in ID
|
||||||
|
public static final String PLUGIN_ID = "pyUML.plugin";
|
||||||
|
|
||||||
|
// The shared instance
|
||||||
|
private static Activator plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The constructor
|
||||||
|
*/
|
||||||
|
public Activator() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
|
||||||
|
*/
|
||||||
|
public void start(BundleContext context) throws Exception {
|
||||||
|
super.start(context);
|
||||||
|
plugin = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
|
||||||
|
*/
|
||||||
|
public void stop(BundleContext context) throws Exception {
|
||||||
|
plugin = null;
|
||||||
|
super.stop(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the shared instance
|
||||||
|
*
|
||||||
|
* @return the shared instance
|
||||||
|
*/
|
||||||
|
public static Activator getDefault() {
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
193
pyUml/src/pyUML/pythonTree/PythonTreeAttribute.java
Executable file
193
pyUml/src/pyUML/pythonTree/PythonTreeAttribute.java
Executable file
@ -0,0 +1,193 @@
|
|||||||
|
package pyUML.pythonTree;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import org.eclipse.uml2.uml.Comment;
|
||||||
|
import org.eclipse.uml2.uml.NamedElement;
|
||||||
|
import org.eclipse.uml2.uml.Property;
|
||||||
|
import org.eclipse.uml2.uml.VisibilityKind;
|
||||||
|
import org.python.pydev.parser.jython.ast.Assign;
|
||||||
|
import org.python.pydev.parser.jython.ast.Attribute;
|
||||||
|
import org.python.pydev.parser.jython.ast.Call;
|
||||||
|
import org.python.pydev.parser.jython.ast.Name;
|
||||||
|
import org.python.pydev.parser.jython.ast.NameTok;
|
||||||
|
import org.python.pydev.parser.jython.ast.exprType;
|
||||||
|
|
||||||
|
import pyUML.backend.GlobalConstants;
|
||||||
|
import pyUML.backend.ParseHelpers;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This PythonTree member represents a python attribute.
|
||||||
|
* It can represent static attributes (defined outside any method)
|
||||||
|
* or object attributes (defined with "self." inside __init__()
|
||||||
|
*/
|
||||||
|
public class PythonTreeAttribute extends PythonTreeNode {
|
||||||
|
private Assign astNode;
|
||||||
|
private boolean valid;
|
||||||
|
private boolean staticAtt;
|
||||||
|
private String value;
|
||||||
|
private String fullValue;
|
||||||
|
private int line;
|
||||||
|
private int col;
|
||||||
|
private int nextLine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param parent the parent in the PythonTree
|
||||||
|
* @param astNode the corresponding Python AST node
|
||||||
|
* @param staticAtt true, if this is an attribute outside a
|
||||||
|
* function definition
|
||||||
|
* @param nextLine the line of the next Python statement. This
|
||||||
|
* is needed to extract multi-line-attributes
|
||||||
|
*/
|
||||||
|
public PythonTreeAttribute(PythonTreeNode parent, Assign astNode, boolean staticAtt, int nextLine) {
|
||||||
|
super(parent);
|
||||||
|
this.astNode = astNode;
|
||||||
|
this.staticAtt = staticAtt;
|
||||||
|
this.nextLine = nextLine;
|
||||||
|
this.valid = this.initAttribute();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return false, if this is no valid attribute
|
||||||
|
*/
|
||||||
|
private boolean initAttribute(){
|
||||||
|
exprType left = this.astNode.targets[0];
|
||||||
|
exprType right = this.astNode.value;
|
||||||
|
|
||||||
|
// analyze the left side of the assign and see
|
||||||
|
// if this might be a valid attribute
|
||||||
|
try {
|
||||||
|
if (staticAtt) { //static: attr without "self"
|
||||||
|
this.name = ((Name)left).id;
|
||||||
|
this.line = ((Name)left).beginLine;
|
||||||
|
this.col = ((Name)left).beginColumn;
|
||||||
|
}
|
||||||
|
else{ // object attr: begins with "self."
|
||||||
|
Attribute leftAtt = (Attribute)left;
|
||||||
|
if (! ((Name)leftAtt.value).id.equals("self"))
|
||||||
|
return false;
|
||||||
|
this.name =((NameTok)(leftAtt).attr).id;
|
||||||
|
this.line = ((NameTok)(leftAtt).attr).beginLine;
|
||||||
|
this.col = ((NameTok)(leftAtt).attr).beginColumn;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ClassCastException e) {
|
||||||
|
// if anything is not like expected, this is not a
|
||||||
|
// att=value
|
||||||
|
// or self.att=value
|
||||||
|
// attribute -> this is not considered a valid attribute!
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now, look at the right side
|
||||||
|
if (right instanceof Call)
|
||||||
|
return false;
|
||||||
|
this.value = ParseHelpers.getStringOfExpr(right, this.getParent().getInFile(), true, true, this.nextLine);
|
||||||
|
|
||||||
|
// if the value was abbreviated, save full value, also.
|
||||||
|
if (this.value.endsWith("(...)")) {
|
||||||
|
this.fullValue = ParseHelpers.getStringOfExpr(right, this.getParent().getInFile(), true, false, this.nextLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if everything went right, this is considered a valid attribute!
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A PythonTreeAttribute is created always when an Assign
|
||||||
|
* is found in the class body or the constructor.
|
||||||
|
* Sometimes an assign does not declare an attribute; then,
|
||||||
|
* this object should not be added to the PythonTreeClass
|
||||||
|
* attributes and be left for the garbage collector.
|
||||||
|
*
|
||||||
|
* @return if this astNode really represents a python
|
||||||
|
* static/object attribute and shall be saved
|
||||||
|
*/
|
||||||
|
public boolean isValid() {
|
||||||
|
return this.valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStatic() {
|
||||||
|
return staticAtt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return this attribute's (default) value
|
||||||
|
*/
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean synchronizeModel(NamedElement modelElement) {
|
||||||
|
Property modelProperty = (Property) modelElement;
|
||||||
|
|
||||||
|
// set this attribute private in model, if its name starts with "__"
|
||||||
|
// use protected, if class starts with "_" (this is only python convention)
|
||||||
|
if (this.getName().startsWith("__")) {
|
||||||
|
modelProperty.setVisibility(VisibilityKind.PRIVATE_LITERAL);
|
||||||
|
} else if (this.getName().startsWith("_")) {
|
||||||
|
modelProperty.setVisibility(VisibilityKind.PROTECTED_LITERAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
String defVal = this.getValue();
|
||||||
|
if (! "None".equals(defVal))
|
||||||
|
modelProperty.setDefault(this.getValue());
|
||||||
|
// if default value was abbreviated ->
|
||||||
|
// save full default value as comment,
|
||||||
|
// beginning with a PyUML Marker
|
||||||
|
if (this.fullValue != null) {
|
||||||
|
Comment fullValueComment = null;
|
||||||
|
for (Comment comment : modelProperty.getOwnedComments()) {
|
||||||
|
if (comment.getBody().startsWith(GlobalConstants.getFullDefault())) {
|
||||||
|
fullValueComment=comment;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fullValueComment == null)
|
||||||
|
fullValueComment = modelProperty.createOwnedComment();
|
||||||
|
|
||||||
|
fullValueComment.setBody(GlobalConstants.getFullDefault()
|
||||||
|
+ this.fullValue);
|
||||||
|
} else {
|
||||||
|
// there is no "full" value -> delete all comments
|
||||||
|
// that save a full value
|
||||||
|
List<Comment> commentList = new Vector<Comment>();
|
||||||
|
commentList.addAll(modelProperty.getOwnedComments());
|
||||||
|
for (Comment comment : commentList) {
|
||||||
|
if (comment.getBody().startsWith(GlobalConstants.getFullDefault())) {
|
||||||
|
comment.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
modelProperty.setIsStatic(this.isStatic());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLine() {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCol() {
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PythonTreeClass getParent() {
|
||||||
|
return (PythonTreeClass) super.getParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the un-abbreviated attribute (default) value
|
||||||
|
* for this attribute
|
||||||
|
*/
|
||||||
|
public String getFullValue() {
|
||||||
|
return fullValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNextLine() {
|
||||||
|
return nextLine;
|
||||||
|
}
|
||||||
|
}
|
1177
pyUml/src/pyUML/pythonTree/PythonTreeClass.java
Executable file
1177
pyUml/src/pyUML/pythonTree/PythonTreeClass.java
Executable file
File diff suppressed because it is too large
Load Diff
166
pyUml/src/pyUML/pythonTree/PythonTreeFile.java
Executable file
166
pyUml/src/pyUML/pythonTree/PythonTreeFile.java
Executable file
@ -0,0 +1,166 @@
|
|||||||
|
package pyUML.pythonTree;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.python.pydev.parser.jython.SimpleNode;
|
||||||
|
import org.python.pydev.parser.jython.ast.ClassDef;
|
||||||
|
import org.python.pydev.parser.jython.ast.Module;
|
||||||
|
import org.python.pydev.parser.jython.ast.stmtType;
|
||||||
|
import org.python.pydev.refactoring.ast.visitors.VisitorFactory;
|
||||||
|
|
||||||
|
import pyUML.backend.EclipseHelperMethods;
|
||||||
|
import pyUML.backend.ParseHelpers;
|
||||||
|
import pyUML.exceptions.PyUMLCancelledException;
|
||||||
|
import pyUML.exceptions.PyUMLParseException;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents a Python file in the Python
|
||||||
|
* Package structure.
|
||||||
|
* It must have a parent package and contains a
|
||||||
|
* pydev Abstract Syntax Tree (AST)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class PythonTreeFile extends PythonTreeNode{
|
||||||
|
private IPath filePath;
|
||||||
|
private PythonTreePackage parent;
|
||||||
|
private SimpleNode ast;
|
||||||
|
private List<PythonTreeClass> classesInFile;
|
||||||
|
private String fileContent;
|
||||||
|
private String[] splittedFileContent = null;
|
||||||
|
|
||||||
|
|
||||||
|
public PythonTreeFile(IPath filePath, PythonTreePackage parent) throws PyUMLParseException, PyUMLCancelledException{
|
||||||
|
super(parent);
|
||||||
|
this.filePath = filePath;
|
||||||
|
this.parent = parent;
|
||||||
|
this.name = filePath.lastSegment();
|
||||||
|
|
||||||
|
this.classesInFile = new Vector<PythonTreeClass>();
|
||||||
|
this.initAst();
|
||||||
|
this.initClassesWithAST();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the given Python file and saves the ast
|
||||||
|
*/
|
||||||
|
private void initAst() throws PyUMLParseException{
|
||||||
|
// init AST so that it will never be null
|
||||||
|
this.ast=new SimpleNode();
|
||||||
|
// try to get content of python file
|
||||||
|
this.fileContent = ParseHelpers.fileToString(
|
||||||
|
new File(filePath.toOSString()), this.getProject());
|
||||||
|
if (this.fileContent==null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get AST of file
|
||||||
|
try{
|
||||||
|
this.ast = VisitorFactory.getRootNodeFromString(this.fileContent);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
String message = t.getClass().getName()+ " while parsing file "
|
||||||
|
+ this.filePath.toOSString() +"\n\n" +t.getMessage();
|
||||||
|
throw new PyUMLParseException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* extracts all the top level clases (no inner classes)
|
||||||
|
* out of the AST
|
||||||
|
*/
|
||||||
|
private void initClassesWithAST() throws PyUMLParseException, PyUMLCancelledException{
|
||||||
|
if (this.ast instanceof Module) {
|
||||||
|
Module pyModule = (Module) this.ast;
|
||||||
|
stmtType[] statements = pyModule.body;
|
||||||
|
for (int i = 0; i < statements.length; i++) {
|
||||||
|
if (statements[i] instanceof ClassDef) {
|
||||||
|
// get end line of class -> look for following statement
|
||||||
|
int followingLine = 0;
|
||||||
|
if (i +1 < statements.length) {
|
||||||
|
stmtType followingStmt = statements[i+1];
|
||||||
|
followingLine = followingStmt.beginLine;
|
||||||
|
}
|
||||||
|
ClassDef pyClass = (ClassDef) statements[i];
|
||||||
|
PythonTreeClass cl = new PythonTreeClass(this.parent, this, pyClass, followingLine-1);
|
||||||
|
this.classesInFile.add(cl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateFileInEclipse() {
|
||||||
|
EclipseHelperMethods.updateFile(this.getFilePath().toOSString(), this.getProject());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* re-inits a file -> re-parses the content
|
||||||
|
* and adds new classes, if needed.
|
||||||
|
* @throws PyUMLParseException
|
||||||
|
*/
|
||||||
|
public void reInitFile() throws PyUMLParseException, PyUMLCancelledException {
|
||||||
|
for (PythonTreeClass cl : this.getClassesInFile()) {
|
||||||
|
this.getRoot().getClassDict().remove(cl.getPackageStructure()+cl.getName());
|
||||||
|
this.getRoot().getClassNameDict().remove(cl.getPackageStructure()+cl.getName());
|
||||||
|
this.getParent().getChildClasses().remove(cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.splittedFileContent=null;
|
||||||
|
this.classesInFile = new Vector<PythonTreeClass>();
|
||||||
|
this.initAst();
|
||||||
|
this.initClassesWithAST();
|
||||||
|
this.getParent().getChildClasses().addAll(this.getClassesInFile());
|
||||||
|
this.getRoot().getChildClasses().addAll(this.getParent().getChildClasses());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits the file content by "\n", which results in an array of lines.
|
||||||
|
* The result is cached for performance reasons.
|
||||||
|
* @return an Array containing the lines of the file content
|
||||||
|
*/
|
||||||
|
public String[] getSplittedFileContent() {
|
||||||
|
if (splittedFileContent == null)
|
||||||
|
splittedFileContent = fileContent.split("\n");
|
||||||
|
return splittedFileContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPath getFilePath() {
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
public SimpleNode getAst() {
|
||||||
|
return ast;
|
||||||
|
}
|
||||||
|
public PythonTreePackage getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PythonTreeClass> getClassesInFile() {
|
||||||
|
return classesInFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the content of the whole file as a String
|
||||||
|
*/
|
||||||
|
public String getFileContent() {
|
||||||
|
return fileContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this objects "file content" string. This does *not*
|
||||||
|
* update any real file!
|
||||||
|
* @param fileContent the file content as a String
|
||||||
|
*/
|
||||||
|
public void setFileContent(String fileContent) {
|
||||||
|
this.fileContent = fileContent;
|
||||||
|
this.splittedFileContent=null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilePath(IPath filePath) {
|
||||||
|
this.filePath = filePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
627
pyUml/src/pyUML/pythonTree/PythonTreeMethod.java
Executable file
627
pyUml/src/pyUML/pythonTree/PythonTreeMethod.java
Executable file
@ -0,0 +1,627 @@
|
|||||||
|
package pyUML.pythonTree;
|
||||||
|
|
||||||
|
import java.util.Dictionary;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
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.uml2.uml.Class;
|
||||||
|
import org.eclipse.uml2.uml.Classifier;
|
||||||
|
import org.eclipse.uml2.uml.Comment;
|
||||||
|
import org.eclipse.uml2.uml.Interface;
|
||||||
|
import org.eclipse.uml2.uml.NamedElement;
|
||||||
|
import org.eclipse.uml2.uml.Operation;
|
||||||
|
import org.eclipse.uml2.uml.Parameter;
|
||||||
|
import org.eclipse.uml2.uml.Property;
|
||||||
|
import org.eclipse.uml2.uml.VisibilityKind;
|
||||||
|
import org.python.pydev.parser.jython.ast.Expr;
|
||||||
|
import org.python.pydev.parser.jython.ast.FunctionDef;
|
||||||
|
import org.python.pydev.parser.jython.ast.Name;
|
||||||
|
import org.python.pydev.parser.jython.ast.NameTok;
|
||||||
|
import org.python.pydev.parser.jython.ast.Str;
|
||||||
|
import org.python.pydev.parser.jython.ast.exprType;
|
||||||
|
import org.python.pydev.parser.jython.ast.stmtType;
|
||||||
|
|
||||||
|
import pyUML.backend.GlobalConstants;
|
||||||
|
import pyUML.backend.ParseHelpers;
|
||||||
|
import pyUML.exceptions.PyUMLParseException;
|
||||||
|
import pyUML.exceptions.PyUMLSynchronizeCodeException;
|
||||||
|
import pyUML.refactoring.BicycleRefactoring;
|
||||||
|
import pyUML.refactoring.FileRefactoring;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents a Method definition inside a Python Class
|
||||||
|
*/
|
||||||
|
public class PythonTreeMethod extends PythonTreeNode {
|
||||||
|
private FunctionDef astNode;
|
||||||
|
private boolean staticMethod;
|
||||||
|
private List<String> arguments;
|
||||||
|
private String docString;
|
||||||
|
private int docStringLine;
|
||||||
|
private int docStringCol;
|
||||||
|
private int lastLine;
|
||||||
|
private String indent = " ";
|
||||||
|
private Dictionary<String, String> argumentDefaultDict;
|
||||||
|
private Dictionary<String, Integer> argumentLineDict;
|
||||||
|
private Dictionary<String, Integer> argumentColumnDict;
|
||||||
|
|
||||||
|
public PythonTreeMethod(PythonTreeClass parent, FunctionDef astNode, int nextLine) throws PyUMLParseException{
|
||||||
|
super(parent);
|
||||||
|
this.astNode = astNode;
|
||||||
|
this.lastLine = nextLine - 1;
|
||||||
|
// set last non-empty line as last line of this method
|
||||||
|
while (this.lastLine>=0 && parent.inFile.getSplittedFileContent()[lastLine-1].matches("[\\s]*")) {
|
||||||
|
this.lastLine--;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.arguments = new Vector<String>();
|
||||||
|
this.argumentDefaultDict = new Hashtable<String, String>();
|
||||||
|
this.argumentLineDict = new Hashtable<String, Integer>();
|
||||||
|
this.argumentColumnDict = new Hashtable<String, Integer>();
|
||||||
|
this.initMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initMethod() throws PyUMLParseException{
|
||||||
|
this.name = ((NameTok) this.astNode.name).id;
|
||||||
|
|
||||||
|
if (this.name.matches(".*__init__.*") && this.getParent().getName().matches(".*CMCEntryBrows.*")) {
|
||||||
|
}
|
||||||
|
exprType[] argList = this.astNode.args.args;
|
||||||
|
exprType[] defaultList = this.astNode.args.defaults;
|
||||||
|
|
||||||
|
// ### Get Arguments ### //
|
||||||
|
|
||||||
|
// get offset of first argument with default value
|
||||||
|
int argCount = argList.length;
|
||||||
|
int defaultCount = defaultList.length;
|
||||||
|
int defaultOffset = argCount - defaultCount;
|
||||||
|
|
||||||
|
// get arguments with corresponding default values
|
||||||
|
int argNo = 0;
|
||||||
|
for (exprType arg : argList) {
|
||||||
|
// fix indent, if needed
|
||||||
|
String line = this.getParent().getInFile().getSplittedFileContent()[arg.beginLine ];
|
||||||
|
int indentLength=0;
|
||||||
|
if (line.length() > 0)
|
||||||
|
for (; line.charAt(indentLength) == ' ' && line.length() > indentLength +1 ; indentLength++) ;
|
||||||
|
if (this.indent.length() != indentLength && ! line.matches("^[\\s]*\\\"\\\"\\\".*$")) {
|
||||||
|
this.indent = "";
|
||||||
|
for (int i=0; i< indentLength; i++)
|
||||||
|
this.indent += " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// argument name
|
||||||
|
String argName = ((Name) arg).id;
|
||||||
|
if (this.arguments.contains(argName)) {
|
||||||
|
String message = "Argument inconsistency detected!\n"+
|
||||||
|
"The python method '"+this.name+ "' in the class '" +
|
||||||
|
this.getParent().getName() +
|
||||||
|
"'\nhas an argument inconsistency with the argument '" +
|
||||||
|
argName + "'.\n\n" +
|
||||||
|
"The argument exists mor than once!\n\n" +
|
||||||
|
"Please correct this error!";
|
||||||
|
throw new PyUMLParseException(message);
|
||||||
|
}
|
||||||
|
this.arguments.add(argName);
|
||||||
|
this.argumentLineDict.put(argName, arg.beginLine);
|
||||||
|
this.argumentColumnDict.put(argName, arg.beginColumn);
|
||||||
|
|
||||||
|
// argument default value
|
||||||
|
if (defaultCount> 0 && argNo >= defaultOffset && (! argName.equals("self"))) {
|
||||||
|
|
||||||
|
|
||||||
|
exprType defaultVal = defaultList[argNo - defaultOffset];
|
||||||
|
exprType defaultValBefore = null;
|
||||||
|
|
||||||
|
// test if parameter without default follows parameter with default
|
||||||
|
// -> this is not allowed but not caught by pyDev
|
||||||
|
if (argNo - defaultOffset >= 1)
|
||||||
|
defaultValBefore = defaultList[argNo - defaultOffset-1];
|
||||||
|
|
||||||
|
String defValString = ParseHelpers.getStringOfExpr(defaultVal, this.getParent().getInFile(), false, false, 0);
|
||||||
|
|
||||||
|
if (defaultVal == null && defaultValBefore!= null) {
|
||||||
|
String message = "Argument inconsistency detected!\n"+
|
||||||
|
"The python method '"+this.name+ "' in the class '" +
|
||||||
|
this.getParent().getName() +
|
||||||
|
"'\nhas an argument inconsistency with the argument '" +
|
||||||
|
argName + "'.\n\n" +
|
||||||
|
"There are arguments without default values" +
|
||||||
|
"\nfollowing arguments with default values.\n\n" +
|
||||||
|
"Please correct this error!";
|
||||||
|
throw new PyUMLParseException(message);
|
||||||
|
} else if (defaultVal != null){
|
||||||
|
this.argumentDefaultDict.put(argName, defValString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argNo++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set static attribute */
|
||||||
|
if (argList.length == 0 || (! this.arguments.get(0).equals("self")))
|
||||||
|
this.staticMethod = true;
|
||||||
|
|
||||||
|
|
||||||
|
stmtType[] methodBody = this.astNode.body;
|
||||||
|
|
||||||
|
// extract DocString, if it exists
|
||||||
|
if (methodBody.length > 0 && methodBody[0] instanceof Expr) {
|
||||||
|
Expr exp = (Expr) methodBody[0];
|
||||||
|
if (exp.value instanceof Str) {
|
||||||
|
Str stringExp = (Str) exp.value;
|
||||||
|
if (stringExp.type == Str.TripleDouble ||
|
||||||
|
stringExp.type == Str.TripleSingle) {
|
||||||
|
this.docString=stringExp.s;
|
||||||
|
this.docStringLine = stringExp.beginLine;
|
||||||
|
this.docStringCol = stringExp.beginColumn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean synchronizeModel(NamedElement modelElement) {
|
||||||
|
|
||||||
|
super.synchronizeModel(modelElement);
|
||||||
|
Operation modelMethod = (Operation) modelElement;
|
||||||
|
|
||||||
|
// set this method private in model, if its name starts with "__"
|
||||||
|
// use protected, if class starts with "_" (this is only python convention)
|
||||||
|
if (this.getName().startsWith("__")) {
|
||||||
|
modelMethod.setVisibility(VisibilityKind.PRIVATE_LITERAL);
|
||||||
|
} else if (this.getName().startsWith("_")) {
|
||||||
|
modelMethod.setVisibility(VisibilityKind.PROTECTED_LITERAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set/remove static flag
|
||||||
|
if (this.staticMethod != modelMethod.isStatic())
|
||||||
|
modelMethod.setIsStatic(this.staticMethod);
|
||||||
|
|
||||||
|
List<Parameter> parameterList = modelMethod.getOwnedParameters();
|
||||||
|
|
||||||
|
// for all parameters in code -> check if model parameters are the same;
|
||||||
|
/// if not, add them
|
||||||
|
for (int i=0; i< this.getArguments().size(); i++) {
|
||||||
|
String pyArg = this.getArguments().get(i);
|
||||||
|
if (parameterList.size() > i) {
|
||||||
|
Parameter modelParam = parameterList.get(i);
|
||||||
|
// check if parameter name and default value are the same
|
||||||
|
String defautlValue = (this.getArgumentDefaultDict().get(pyArg));
|
||||||
|
if (defautlValue == null)
|
||||||
|
defautlValue = "";
|
||||||
|
if ((! pyArg.equals(modelParam.getName())) ||
|
||||||
|
( ! defautlValue.equals(modelParam.getDefault()))) {
|
||||||
|
|
||||||
|
// this parameter is not the same!
|
||||||
|
// remove all parameters from here and create following parameters!
|
||||||
|
for (int j=i; j< parameterList.size(); j++)
|
||||||
|
parameterList.remove(j);
|
||||||
|
|
||||||
|
// restart loop at the current position (again)
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Parameter at this position does not exist
|
||||||
|
// Append new parameter
|
||||||
|
Parameter newParam = modelMethod.createOwnedParameter(pyArg, null);
|
||||||
|
newParam.setDefault(this.getArgumentDefaultDict().get(pyArg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test, if there are additional model parameters -> remove them!
|
||||||
|
if (parameterList.size() > this.getArguments().size()) {
|
||||||
|
for (int i=this.getArguments().size(); i < parameterList.size(); i++) {
|
||||||
|
parameterList.get(i).destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean synchronizeCode(Operation modelOp) throws PyUMLSynchronizeCodeException{
|
||||||
|
if (this.name.matches("search.*") && this.getParent().getName().startsWith("Group")) {
|
||||||
|
}
|
||||||
|
List<String> modelParameters = new Vector<String>();
|
||||||
|
int line = this.astNode.name.beginLine;
|
||||||
|
|
||||||
|
boolean parametersNeedRewrite = false;
|
||||||
|
|
||||||
|
boolean modelIsStatic = true;
|
||||||
|
|
||||||
|
methodChildLoop:
|
||||||
|
for (Parameter modelParameter : modelOp.getOwnedParameters()) {
|
||||||
|
|
||||||
|
// get all relevant data
|
||||||
|
String modelParName = modelParameter.getName();
|
||||||
|
modelParameters.add(modelParName);
|
||||||
|
|
||||||
|
// stop if this is not a parameter (null)
|
||||||
|
if (modelParName == null)
|
||||||
|
continue methodChildLoop;
|
||||||
|
|
||||||
|
if (modelParName.equals("self")) {
|
||||||
|
modelIsStatic = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String modelParDefault = modelParameter.getDefault();
|
||||||
|
|
||||||
|
if (this.arguments.contains(modelParName)){
|
||||||
|
//found parameter with same name!
|
||||||
|
String codeParDefault = this.getArgumentDefaultDict().get(modelParName);
|
||||||
|
|
||||||
|
if (((modelParDefault == codeParDefault)&&(codeParDefault== null))
|
||||||
|
|| (modelParDefault != null && codeParDefault != null
|
||||||
|
&& (codeParDefault.equals(modelParDefault)
|
||||||
|
|| (modelParDefault.equals(GlobalConstants.getUnknownExpression())))))
|
||||||
|
// parameter exists and has the same default value
|
||||||
|
// everything is fine!
|
||||||
|
continue methodChildLoop;
|
||||||
|
|
||||||
|
|
||||||
|
// parameter exists, but with different default!
|
||||||
|
// fix default value!
|
||||||
|
|
||||||
|
// if default value does not exist in model
|
||||||
|
if (modelParDefault == null) {
|
||||||
|
parametersNeedRewrite = true;
|
||||||
|
continue methodChildLoop;
|
||||||
|
}
|
||||||
|
else if (codeParDefault == null) { //if default value wasn't there
|
||||||
|
//add a default value
|
||||||
|
parametersNeedRewrite = true;
|
||||||
|
continue methodChildLoop;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// default value changed
|
||||||
|
// -> change default value
|
||||||
|
parametersNeedRewrite = true;
|
||||||
|
continue methodChildLoop;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// parameter with this name not found!
|
||||||
|
// look if parameter was renamed (look in old model)
|
||||||
|
// this is done with bicycle repair man, so that
|
||||||
|
// all references will be renamed, too
|
||||||
|
|
||||||
|
String paramXMIId = this.getRoot().getModelXmiDict().get(modelParameter);
|
||||||
|
if (this.getRoot().getXmiModelDictOld().keySet().contains(paramXMIId)) {
|
||||||
|
// parameter found -> try to find old name in code
|
||||||
|
Parameter oldModelParam = (Parameter) this.getRoot().getXmiModelDictOld().get(paramXMIId);
|
||||||
|
String oldParamName = oldModelParam.getName();
|
||||||
|
if (this.arguments.contains(oldParamName)) {
|
||||||
|
// parameter with old name found -> rename it!
|
||||||
|
int col = this.argumentColumnDict.get(oldParamName);
|
||||||
|
BicycleRefactoring.doRenameObject(this.getParent().inFile,
|
||||||
|
modelParName, line, col, this.getRoot().getProject());
|
||||||
|
setChanged(line, modelParName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//parameter does and did not exist in code
|
||||||
|
//create it!
|
||||||
|
parametersNeedRewrite = true;
|
||||||
|
continue methodChildLoop;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if parameters were deleted -> delete them in code!
|
||||||
|
for (String parameter : this.arguments) {
|
||||||
|
if (! modelParameters.contains(parameter)) {
|
||||||
|
//parameter does not exist in model -> delete it
|
||||||
|
parametersNeedRewrite = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if method changed its static property,
|
||||||
|
// ensure the "staticmethod" call is added/removed
|
||||||
|
if (this.fixStaticmethodCall(modelIsStatic))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (parametersNeedRewrite) {
|
||||||
|
// write new parameters definition
|
||||||
|
String parametersDef = "";
|
||||||
|
|
||||||
|
for (Parameter modelParameter: modelOp.getOwnedParameters()) {
|
||||||
|
// get all relevant data
|
||||||
|
String modelParName = modelParameter.getName();
|
||||||
|
|
||||||
|
// stop if this is not a parameter (null)
|
||||||
|
if (modelParName == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
String modelParDefault = modelParameter.getDefault();
|
||||||
|
|
||||||
|
if (parametersDef.length() > 0)
|
||||||
|
parametersDef += ", ";
|
||||||
|
|
||||||
|
parametersDef += modelParName;
|
||||||
|
if (modelParDefault != null)
|
||||||
|
parametersDef += "=" + modelParDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace old definition with help of regex
|
||||||
|
Pattern pattern = Pattern.compile("([\\s]*def[\\s]*[^\\(]+[\\s]*\\()[^\\)]*(\\)[\\s]*:.*)");
|
||||||
|
String defLine = FileRefactoring.getLine(this.getParent().inFile, line);
|
||||||
|
Matcher matcher = pattern.matcher(defLine);
|
||||||
|
if (! matcher.find()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write the new method definition line
|
||||||
|
String newDefLine = matcher.group(1) + parametersDef + matcher.group(2);
|
||||||
|
FileRefactoring.replaceLine(this.getParent().inFile, line, newDefLine, true);
|
||||||
|
|
||||||
|
setChanged(line, newDefLine);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On synchronizing code:
|
||||||
|
* Test the presence of all attributes
|
||||||
|
* - add/rename them, if needed
|
||||||
|
* - check initial value and fix it, if needed
|
||||||
|
*
|
||||||
|
* @param modelClass the class in the model where the attributes are defined
|
||||||
|
* @return true, if something was changed; false otherwise
|
||||||
|
*/
|
||||||
|
public static boolean fixAttributeDefinitions(
|
||||||
|
Classifier modelClass, String initIndent,
|
||||||
|
Map<String, PythonTreeAttribute> presentAttrs,
|
||||||
|
PythonTreeClass pyClass, int lastLine, boolean isStatic)
|
||||||
|
throws PyUMLSynchronizeCodeException{
|
||||||
|
|
||||||
|
// if this is the __init__ method, ensure all non-static attributes are defined here!
|
||||||
|
//Map<String, PythonTreeAttribute> presentAttrs = pyClass.getChildObjectAttrDict();
|
||||||
|
List<Property> neededAttrs = null;
|
||||||
|
if (modelClass instanceof Class)
|
||||||
|
neededAttrs = ((Class) modelClass).getOwnedAttributes();
|
||||||
|
else if (modelClass instanceof Interface)
|
||||||
|
neededAttrs = ((Interface) modelClass).getOwnedAttributes();
|
||||||
|
|
||||||
|
for (Property neededAttr : neededAttrs) {
|
||||||
|
if (isStatic != neededAttr.isStatic())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
String attrName = neededAttr.getName();
|
||||||
|
String initialValue = neededAttr.getDefault();
|
||||||
|
|
||||||
|
// if initial value was abbreviated before, try to get
|
||||||
|
// full value out of model
|
||||||
|
if (initialValue != null && initialValue.endsWith("(...)")) {
|
||||||
|
for (Comment comment :neededAttr.getOwnedComments()) {
|
||||||
|
if (comment.getBody().startsWith(GlobalConstants.getFullDefault())) {
|
||||||
|
initialValue = comment.getBody().substring(GlobalConstants.getFullDefault().length());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! presentAttrs.containsKey(attrName)) {
|
||||||
|
// attribute is not present -> find out, if it was renamed in model
|
||||||
|
String param_xmi = pyClass.getRoot().getModelXmiDict().get(neededAttr);
|
||||||
|
if (pyClass.getRoot().getXmiModelDictOld().containsKey(param_xmi)) {
|
||||||
|
Property oldParameter = (Property) pyClass.getRoot().getXmiModelDictOld().get(param_xmi);
|
||||||
|
String oldParamName = oldParameter.getName();
|
||||||
|
if (presentAttrs.containsKey(oldParamName)) {
|
||||||
|
// attribute was renamed -> rename it in code with Bicycle Repair Man
|
||||||
|
int line = presentAttrs.get(oldParamName).getLine();
|
||||||
|
int col = presentAttrs.get(oldParamName).getCol();
|
||||||
|
boolean success = BicycleRefactoring.doRenameObject(
|
||||||
|
pyClass.inFile,
|
||||||
|
attrName, line, col, pyClass.getRoot().getProject());
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// attribute is and was not present -> create it!
|
||||||
|
String attrDefLine = (isStatic ? pyClass.getIndent() : initIndent+"self.")+ attrName + " = ";
|
||||||
|
if (initialValue != null && (! initialValue.endsWith("(...)")))
|
||||||
|
attrDefLine += initialValue;
|
||||||
|
else
|
||||||
|
attrDefLine += "None";
|
||||||
|
attrDefLine += " # created by PyUML";
|
||||||
|
if (lastLine <=0 )
|
||||||
|
FileRefactoring.appendToFile(pyClass.inFile, attrDefLine);
|
||||||
|
else
|
||||||
|
FileRefactoring.insertAtLine(pyClass.inFile,
|
||||||
|
lastLine, attrDefLine + "\n");
|
||||||
|
pyClass.getRoot().setChangedFileLine(pyClass.inFile.getFilePath().toOSString()+":"+lastLine + attrDefLine + ":");
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// attribute is defined, check initial value
|
||||||
|
// if initial model value ends with (...),
|
||||||
|
// this value was cut when creating the model
|
||||||
|
// -> do not change it in code
|
||||||
|
PythonTreeAttribute pyAttr = presentAttrs.get(attrName);
|
||||||
|
if (pyAttr.getValue() != null && initialValue != null) {
|
||||||
|
}
|
||||||
|
if ((!pyAttr.getValue().equals(initialValue))
|
||||||
|
&& (!(pyAttr.getValue().equals("None") && initialValue==null))
|
||||||
|
&& (! initialValue.endsWith("(...)"))
|
||||||
|
&& (! initialValue.startsWith(pyAttr.getValue().replaceAll("\\(\\.\\.\\.\\)$", ""))) ){
|
||||||
|
// default value changed!
|
||||||
|
int line = pyAttr.getLine();
|
||||||
|
|
||||||
|
Pattern pattern = Pattern.compile("([\\s]*"+(isStatic?"":"self.")+"[^=]*=[\\s]*)([^#]+)(.*)");
|
||||||
|
String defLine = FileRefactoring.getLine(pyClass.getInFile(), line);
|
||||||
|
Matcher matcher = pattern.matcher(defLine);
|
||||||
|
|
||||||
|
if (! matcher.find()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String initString = initialValue;
|
||||||
|
if (initString == null)
|
||||||
|
initString = "None";
|
||||||
|
|
||||||
|
// write the new method definition line
|
||||||
|
String commentGroup = matcher.group(3);
|
||||||
|
if (commentGroup.startsWith("#"))
|
||||||
|
commentGroup = " " + commentGroup;
|
||||||
|
String newDefLine = matcher.group(1) + initString + commentGroup;
|
||||||
|
|
||||||
|
// if this was a multi-line attribute, delete
|
||||||
|
// all following lines and preserver comments
|
||||||
|
for (int i = line ; i < pyAttr.getNextLine() - 1; i++)
|
||||||
|
pyClass.getInFile().setFileContent(FileRefactoring.removeLine(pyClass.inFile, i, false, true));
|
||||||
|
|
||||||
|
// now, just replace the changed line
|
||||||
|
FileRefactoring.replaceLine(pyClass.inFile, line, newDefLine, true);
|
||||||
|
|
||||||
|
pyClass.getRoot().setChangedFileLine(pyClass.inFile.getFilePath().toOSString()+":"+line);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On synchronizing code:
|
||||||
|
* Test staticmethod call of this method and
|
||||||
|
* fix it, if needed
|
||||||
|
*
|
||||||
|
* (python static methods must have the call
|
||||||
|
* <methodname> = staticmethod(<methodname>)
|
||||||
|
* after the method definition)
|
||||||
|
*
|
||||||
|
* @param modelIsStatic true, if this method should be static
|
||||||
|
* in code and vice versa
|
||||||
|
* @return true, if something was changed
|
||||||
|
* false, otherwise
|
||||||
|
*/
|
||||||
|
public boolean fixStaticmethodCall(boolean modelIsStatic) throws PyUMLSynchronizeCodeException{
|
||||||
|
// ensure there is a staticmethod call after the method
|
||||||
|
String fileContent[] = this.getParent().inFile.getFileContent().split("\n");
|
||||||
|
String lineContent = "";
|
||||||
|
int lineNo = this.lastLine;
|
||||||
|
|
||||||
|
if (this.lastLine <= 0)
|
||||||
|
lineNo= fileContent.length -1;
|
||||||
|
|
||||||
|
// if next command is "staticmethod", it is meant to be
|
||||||
|
// part of *this* method
|
||||||
|
if (fileContent.length > lineNo + 1
|
||||||
|
&& fileContent[lineNo+1].matches("^[\\s]*[^=\\(\\s]*[\\s]*=[\\s]*staticmethod[\\s]*\\([\\s]*[^\\)\\s]*[\\s]*\\)[\\s]*.*")) {
|
||||||
|
// the next command is the line to change
|
||||||
|
lineNo++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the last non-empty non-comment line
|
||||||
|
for (; lineNo>=0; lineNo--){
|
||||||
|
lineContent = fileContent[lineNo];
|
||||||
|
if (! (lineContent.matches("^[\\s]*$") || lineContent.matches("^[\\s]*#.*$")) )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lineContent.matches("^[\\s]*[^=\\(\\s]*[\\s]*=[\\s]*staticmethod[\\s]*\\([\\s]*[^\\)\\s]*[\\s]*\\)[\\s]*.*")) {
|
||||||
|
// there is already a staticmethod call
|
||||||
|
if (!modelIsStatic) {
|
||||||
|
// staticmethod call has to be removed
|
||||||
|
FileRefactoring.removeLine(this.getParent().inFile, lineNo, true, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure staticmethod call is OK
|
||||||
|
if (lineContent.matches("[\\s]*"+this.getName()+"[\\s]*=[\\s]*staticmethod[\\s]*\\([^\\)\\s]*\\)[\\s]*.*")){
|
||||||
|
// staticmethod call alright, nothing needs to be changed
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// fix staticmethod call (e.g. when method was renamed)
|
||||||
|
String newContent = this.getParent().getIndent() + this.getName()+" = staticmethod("+this.getName()+")";
|
||||||
|
FileRefactoring.replaceLine(this.getParent().inFile, lineNo+1, newContent, true);
|
||||||
|
setChanged(lineNo, newContent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// there is no staticmethod call at all
|
||||||
|
if (!modelIsStatic) {
|
||||||
|
// all is OK
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
//-> insert it after the end of the method
|
||||||
|
String newContent = this.getParent().getIndent()+this.getName()+" = staticmethod("+this.getName()+")";
|
||||||
|
|
||||||
|
lineNo = this.lastLine;
|
||||||
|
|
||||||
|
if (this.lastLine <= 0)
|
||||||
|
lineNo = fileContent.length -1;
|
||||||
|
|
||||||
|
// from the next method, find the first before line with whitespace
|
||||||
|
for (; lineNo>=0; lineNo--){
|
||||||
|
lineContent = fileContent[lineNo];
|
||||||
|
if (! (lineContent.matches("^[\\s]*$")))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FileRefactoring.insertAtLine(this.getParent().inFile, lineNo + 2, newContent + "\n");
|
||||||
|
|
||||||
|
setChanged(lineNo, newContent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tells the position of current code change to PythonTreeRoot
|
||||||
|
* so that it can decide if the same line is changed again
|
||||||
|
* and again and thus detect an unfinished loop.
|
||||||
|
*
|
||||||
|
* @param line the changed line in the file
|
||||||
|
*/
|
||||||
|
private void setChanged(int line, String pos) throws PyUMLSynchronizeCodeException{
|
||||||
|
if (pos == null)
|
||||||
|
pos = "";
|
||||||
|
else pos = ":position:"+pos;
|
||||||
|
this.getRoot().setChangedFileLine(getParent().inFile.getFilePath().toOSString()+":"+line+pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStatic() {
|
||||||
|
return staticMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PythonTreeClass getParent() {
|
||||||
|
return (PythonTreeClass) super.getParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDocString() {
|
||||||
|
return docString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDocStringLine() {
|
||||||
|
return docStringLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDocStringCol() {
|
||||||
|
return docStringCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FunctionDef getAstNode() {
|
||||||
|
return astNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getArguments() {
|
||||||
|
return arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<String, String> getArgumentDefaultDict() {
|
||||||
|
return argumentDefaultDict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLastLine() {
|
||||||
|
return lastLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIndent() {
|
||||||
|
return indent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
128
pyUml/src/pyUML/pythonTree/PythonTreeNode.java
Executable file
128
pyUml/src/pyUML/pythonTree/PythonTreeNode.java
Executable file
@ -0,0 +1,128 @@
|
|||||||
|
package pyUML.pythonTree;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.uml2.uml.NamedElement;
|
||||||
|
|
||||||
|
import pyUML.exceptions.PyUMLCancelledException;
|
||||||
|
import pyUML.exceptions.PyUMLSynchronizeCodeException;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A generic node of the Python package structure tree
|
||||||
|
* This class is used as abstract super class for all
|
||||||
|
* PythonTree Elements
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class PythonTreeNode {
|
||||||
|
private PythonTreeNode parent;
|
||||||
|
protected String name;
|
||||||
|
protected String xmi_id;
|
||||||
|
private NamedElement associatedModelElement;
|
||||||
|
|
||||||
|
|
||||||
|
public PythonTreeNode(PythonTreeNode parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the parent of this package.
|
||||||
|
* If this is the root, return null.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public PythonTreeNode getParent() {
|
||||||
|
if (! this.isRoot())
|
||||||
|
return parent;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronize the model from the given model element
|
||||||
|
* downwards.
|
||||||
|
* Create, delete and move model elements
|
||||||
|
*
|
||||||
|
* @param modelElement
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean synchronizeModel(NamedElement modelElement) {
|
||||||
|
this.associatedModelElement = modelElement;
|
||||||
|
|
||||||
|
// test if name changed -> update model element name if name changed
|
||||||
|
if (! this.isRoot() && (!this.getName().equals(modelElement.getName()))) {
|
||||||
|
modelElement.setName(this.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opposite of synchronizeModel; Synchronizes the code
|
||||||
|
* with a given model
|
||||||
|
*
|
||||||
|
* @param umlElement
|
||||||
|
* @return true if code was changed (so that the python tree
|
||||||
|
* has to be updated), false if everything went OK
|
||||||
|
*/
|
||||||
|
public boolean synchronizeCode(NamedElement modelElement) throws PyUMLSynchronizeCodeException, PyUMLCancelledException{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* after running synchronizeModel, this method returns the corresponding
|
||||||
|
* UML Model NamedElement of this PythonTreeNode
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public NamedElement getAssociatedModelElement() {
|
||||||
|
return associatedModelElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* method to easily find out if this is the Root
|
||||||
|
* of the Python Package Tree
|
||||||
|
*
|
||||||
|
* @return false, if this is a package,
|
||||||
|
* the subclass PythonTreeRoot returns true
|
||||||
|
*/
|
||||||
|
public boolean isRoot() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the XMI-id of this node,
|
||||||
|
* or null, if no XMI-ID was defined
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getXmi_id() {
|
||||||
|
return xmi_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the root Element of this PythonTree
|
||||||
|
*/
|
||||||
|
public PythonTreeRoot getRoot() {
|
||||||
|
if (this.isRoot())
|
||||||
|
return (PythonTreeRoot) this;
|
||||||
|
else
|
||||||
|
return this.getParent().getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of this node
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Eclipse project that was used while creating this node
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public IProject getProject() {
|
||||||
|
return this.getRoot().getProject();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
531
pyUml/src/pyUML/pythonTree/PythonTreePackage.java
Executable file
531
pyUml/src/pyUML/pythonTree/PythonTreePackage.java
Executable file
@ -0,0 +1,531 @@
|
|||||||
|
package pyUML.pythonTree;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFolder;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.Path;
|
||||||
|
import org.eclipse.emf.ecore.EObject;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.eclipse.uml2.uml.Class;
|
||||||
|
import org.eclipse.uml2.uml.Classifier;
|
||||||
|
import org.eclipse.uml2.uml.Element;
|
||||||
|
import org.eclipse.uml2.uml.Interface;
|
||||||
|
import org.eclipse.uml2.uml.NamedElement;
|
||||||
|
import org.eclipse.uml2.uml.Package;
|
||||||
|
|
||||||
|
import pyUML.backend.EclipseHelperMethods;
|
||||||
|
import pyUML.backend.ParseHelpers;
|
||||||
|
import pyUML.exceptions.PyUMLCancelledException;
|
||||||
|
import pyUML.exceptions.PyUMLParseException;
|
||||||
|
import pyUML.exceptions.PyUMLSynchronizeCodeException;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents a package directory in the python
|
||||||
|
* code structure.
|
||||||
|
* A package can contain child packages or Python files.
|
||||||
|
*/
|
||||||
|
public class PythonTreePackage extends PythonTreeNode{
|
||||||
|
IPath packageDir;
|
||||||
|
private List<PythonTreePackage> childPackages;
|
||||||
|
private List<PythonTreeClass> childClasses;
|
||||||
|
private List<PythonTreeFile> pythonFiles;
|
||||||
|
private PythonTreeFile initPy;
|
||||||
|
static int count = 0;
|
||||||
|
|
||||||
|
// this is used when a class was moved -> a complete restart is needed
|
||||||
|
// instead of re-initializing the changed class
|
||||||
|
static boolean completeNewStart = false;
|
||||||
|
|
||||||
|
public PythonTreePackage(IPath packageDir, PythonTreeNode parent) throws PyUMLParseException, PyUMLCancelledException {
|
||||||
|
super(parent);
|
||||||
|
this.packageDir = packageDir;
|
||||||
|
this.childClasses = new Vector<PythonTreeClass>();
|
||||||
|
this.childPackages = new Vector<PythonTreePackage>();
|
||||||
|
this.pythonFiles = new Vector<PythonTreeFile>();
|
||||||
|
|
||||||
|
if (packageDir != null) {
|
||||||
|
initPackage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initPackage() throws PyUMLParseException, PyUMLCancelledException{
|
||||||
|
File dir = new File(packageDir.toOSString());
|
||||||
|
this.name = dir.getName();
|
||||||
|
// list dir
|
||||||
|
File[] dirList = dir.listFiles();
|
||||||
|
|
||||||
|
for (File entry:dirList) {
|
||||||
|
// if directory found: check if it is package,
|
||||||
|
// if yes, recursively add child packages
|
||||||
|
if (entry.isDirectory()){
|
||||||
|
if (checkForInitPy(entry)){
|
||||||
|
childPackages.add(new PythonTreePackage(
|
||||||
|
new Path(entry.getAbsolutePath()),this));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (entry.getName().endsWith(".py")) {
|
||||||
|
PythonTreeFile f = new PythonTreeFile(
|
||||||
|
new Path(entry.getAbsolutePath()), this);
|
||||||
|
this.pythonFiles.add(f);
|
||||||
|
this.childClasses.addAll(f.getClassesInFile());
|
||||||
|
if (entry.getName().equals("__init__.py")) {
|
||||||
|
this.initPy = f;
|
||||||
|
}
|
||||||
|
this.getRoot().worked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get XMI:ID from __init__.py
|
||||||
|
if (this.initPy != null) {
|
||||||
|
this.xmi_id = ParseHelpers.extractXmiFromString(
|
||||||
|
this.initPy.getFileContent());
|
||||||
|
if (this.xmi_id != null)
|
||||||
|
this.getRoot().getXmiPackDict().put(this.xmi_id, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tests, if the given directory contains a file "__init__.py"
|
||||||
|
* If yes, it can be considered as package.
|
||||||
|
*
|
||||||
|
* @param dir the directory to check
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean checkForInitPy(File dir) {
|
||||||
|
if (! dir.isDirectory())
|
||||||
|
return false;
|
||||||
|
for (File entry: dir.listFiles()) {
|
||||||
|
if (entry.getName().equals("__init__.py"))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a XMI-ID as a comment to this packages's __init__.py file
|
||||||
|
* @param xmiID
|
||||||
|
*/
|
||||||
|
public void writeXmiID(String xmiID) {
|
||||||
|
String initPyContent = this.getInitPy().getFileContent();
|
||||||
|
initPyContent = initPyContent.replaceAll("# PyUML: .*\n", "");
|
||||||
|
initPyContent = "# PyUML: Do not remove this line! # XMI_ID:" + xmiID + "\n" + initPyContent;
|
||||||
|
File f = new File(this.getInitPy().getFilePath().toOSString());
|
||||||
|
ParseHelpers.stringToFile(f, initPyContent, this.getProject());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* synchronize the model by this Package using
|
||||||
|
* the packages/classes XMI-IDs
|
||||||
|
*/
|
||||||
|
public boolean synchronizeModel(NamedElement modelElement){
|
||||||
|
super.synchronizeModel(modelElement);
|
||||||
|
|
||||||
|
Package modelPack = (Package) modelElement;
|
||||||
|
Map<String, EObject> xmiModelDict = this.getRoot().getXmiModelDict();
|
||||||
|
|
||||||
|
List<NamedElement> processedElements = new Vector<NamedElement>();
|
||||||
|
List<PythonTreeNode> childElements = new Vector<PythonTreeNode>();
|
||||||
|
childElements.addAll(this.getChildPackages());
|
||||||
|
childElements.addAll(this.getChildClasses());
|
||||||
|
|
||||||
|
for (PythonTreeNode pyChildNode : childElements) {
|
||||||
|
String xmi_id= pyChildNode.getXmi_id();
|
||||||
|
boolean createNewElement = false;
|
||||||
|
if (xmi_id != null) {
|
||||||
|
if (xmiModelDict.containsKey(xmi_id)) {
|
||||||
|
NamedElement modelChild = (NamedElement) xmiModelDict.get(xmi_id);
|
||||||
|
// if found element is also child of model,
|
||||||
|
// everything is OK, continue with packageSynchonization of children
|
||||||
|
if (modelElement.getOwnedElements().contains(modelChild)) {
|
||||||
|
pyChildNode.synchronizeModel(modelChild);
|
||||||
|
processedElements.add(modelChild);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// element found, but at another place
|
||||||
|
// -> move model element to be child of this model element
|
||||||
|
if (modelChild instanceof Package) {
|
||||||
|
Package childPack = (Package) modelChild;
|
||||||
|
childPack.setNestingPackage(modelPack);
|
||||||
|
}
|
||||||
|
else if (modelChild instanceof Class || modelChild instanceof Interface) {
|
||||||
|
Classifier childClass = (Classifier) modelChild;
|
||||||
|
childClass.setPackage(modelPack);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ## synchronize children ##
|
||||||
|
// now the package has the right place, continue recursively
|
||||||
|
if (! pyChildNode.synchronizeModel(modelChild))
|
||||||
|
return false;
|
||||||
|
processedElements.add(modelChild);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* the xmi_id in the code is not present in model, but
|
||||||
|
* in the code. (Propably it was deleted in the model)
|
||||||
|
* This is not possible, because when this method is called
|
||||||
|
* the code was supposed to change, not the model.
|
||||||
|
* -> This is an inconsistency that cannot be resolved.
|
||||||
|
* -> Because a Model element with a special xmi_id cannot
|
||||||
|
* be created.
|
||||||
|
* -> Show an Error message
|
||||||
|
*/
|
||||||
|
if (! this.getRoot().isCreateNewModel()) {
|
||||||
|
boolean ignore = false;
|
||||||
|
if (this.getRoot().getXmiModelDict().size() == 0) {
|
||||||
|
ignore = MessageDialog.openQuestion(null, "Deleted Model",
|
||||||
|
"The current python code was synchronized \n" +
|
||||||
|
"with a UML model earlier.\n" +
|
||||||
|
"Now, the UML model cannot be found.\n\n" +
|
||||||
|
"Do you want to create a new UML model?");
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ignore = MessageDialog.openQuestion(null, "Model Synchronization error found",
|
||||||
|
"The model is missing an element it formerly had\n" +
|
||||||
|
"and which is still present in the code.\n" +
|
||||||
|
"Obviously, the model was edited outside PyUml!\n\n" +
|
||||||
|
"Please manually resolve the situation by removing\n" +
|
||||||
|
"the XMI_ID comment in the __init__.py file of the\n" +
|
||||||
|
"package or in the DocString comment of the class.\n\n" +
|
||||||
|
"Element name: "+ pyChildNode.getName() +"\n\n"+
|
||||||
|
"Do you want to ignore this and create new model elements?");
|
||||||
|
}
|
||||||
|
if (! ignore)
|
||||||
|
return false;
|
||||||
|
else {
|
||||||
|
this.getRoot().setCreateNewModel(true);
|
||||||
|
createNewElement=true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// the warning was disabled by user;
|
||||||
|
createNewElement=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xmi_id==null || createNewElement) {
|
||||||
|
// no xmi_id is present in the code -> this is a manually
|
||||||
|
// created package! It must be created in the model, too.
|
||||||
|
NamedElement modelNewChild = null;
|
||||||
|
if (pyChildNode instanceof PythonTreePackage) {
|
||||||
|
modelNewChild = modelPack.createNestedPackage(pyChildNode.getName());
|
||||||
|
} else if (pyChildNode instanceof PythonTreeClass) {
|
||||||
|
modelNewChild = modelPack.createOwnedClass(pyChildNode.getName(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ## synchronize children ##
|
||||||
|
if (modelNewChild != null) {
|
||||||
|
// now the package is created, we can recursively edit it
|
||||||
|
// by the pyPack synchronization method
|
||||||
|
if (! pyChildNode.synchronizeModel(modelNewChild))
|
||||||
|
return false;
|
||||||
|
processedElements.add(modelNewChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test if all elements of model were processed
|
||||||
|
for (Element modelChild : modelElement.getOwnedElements()) {
|
||||||
|
if ((modelChild instanceof Class || modelChild instanceof Package)
|
||||||
|
&& (! processedElements.contains(modelChild)))
|
||||||
|
// if this model element was not touched until now,
|
||||||
|
// it obviously was deleted in code and must be deleted
|
||||||
|
// also in model
|
||||||
|
this.getRoot().getModelElementsToDestroy().add((NamedElement)modelChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean synchronizeCode(NamedElement modelElement) throws PyUMLSynchronizeCodeException, PyUMLCancelledException {
|
||||||
|
Map<EObject, String> modelXmiDict = this.getRoot().getModelXmiDict();
|
||||||
|
Map<String, PythonTreePackage> xmiPackDict = this.getRoot().getXmiPackDict();
|
||||||
|
Map<String, PythonTreeClass> xmiClassDict = this.getRoot().getXmiClassDict();
|
||||||
|
|
||||||
|
Package modelPack = (Package) modelElement;
|
||||||
|
|
||||||
|
// if package is to be renamed
|
||||||
|
if (! modelPack.getName().equals(this.getName())) {
|
||||||
|
// rename package;
|
||||||
|
boolean success = this.renamePackage(modelPack.getName());
|
||||||
|
if (! success)
|
||||||
|
throw new PyUMLSynchronizeCodeException();
|
||||||
|
// folder has changed -> return "true" to start from beginning
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate over child elements of model
|
||||||
|
globalLoop:
|
||||||
|
for (Element modelChild:modelElement.getOwnedElements()) {
|
||||||
|
//child package found
|
||||||
|
if (modelChild instanceof Package) {
|
||||||
|
Package modelChildPack = (Package) modelChild;
|
||||||
|
// get xmi_id of model element
|
||||||
|
String xmi_id = modelXmiDict.get(modelChildPack);
|
||||||
|
if (xmiPackDict.containsKey(xmi_id)) {
|
||||||
|
// this package is present in model
|
||||||
|
// now we have to check it is also child of this package and
|
||||||
|
// recurse over child elements.
|
||||||
|
PythonTreePackage pyPack = xmiPackDict.get(xmi_id);
|
||||||
|
if (this.getChildPackages().contains(pyPack)) {
|
||||||
|
|
||||||
|
// child is Okay!
|
||||||
|
boolean startNew = pyPack.synchronizeCode(modelChildPack);
|
||||||
|
if (startNew) return true;
|
||||||
|
} else {
|
||||||
|
// move package to this package
|
||||||
|
IPath newPath = EclipseHelperMethods.createFolder(this.getPackageDir().append(pyPack.name).toOSString(), this.getProject()).getFullPath();
|
||||||
|
|
||||||
|
boolean success = pyPack.movePackage(newPath);
|
||||||
|
if (success)
|
||||||
|
// now the package is moved, start from the beginning
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
throw new PyUMLSynchronizeCodeException();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// xmi_id not found -> look for package with same name!
|
||||||
|
boolean packageFound = false;
|
||||||
|
for (PythonTreePackage pySubPack : this.getChildPackages()) {
|
||||||
|
if (pySubPack.getName().equals(modelChildPack.getName())){
|
||||||
|
// write xmi_id to code (only needed once)
|
||||||
|
pySubPack.writeXmiID(xmi_id);
|
||||||
|
boolean startNew = pySubPack.synchronizeCode(modelChildPack);
|
||||||
|
if (startNew) return true;
|
||||||
|
packageFound=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if this package was not found, create it (recursively)!
|
||||||
|
if (! packageFound) {
|
||||||
|
// create package
|
||||||
|
IPath newPackPath = getPackageDir().append(modelChildPack.getName());
|
||||||
|
File newPackDir = new File(newPackPath.toOSString());
|
||||||
|
newPackDir.mkdir();
|
||||||
|
EclipseHelperMethods.updateFolder(newPackDir.getAbsolutePath(), this.getProject());
|
||||||
|
File initPy = new File(newPackPath.append("__init__.py").toOSString());
|
||||||
|
try{
|
||||||
|
initPy.createNewFile();
|
||||||
|
EclipseHelperMethods.updateFile(initPy.getAbsolutePath(), this.getProject());
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
MessageDialog.openError(null, "IOException", "Error writing to file "+ initPy.getPath());
|
||||||
|
throw new PyUMLSynchronizeCodeException();
|
||||||
|
}
|
||||||
|
PythonTreePackage newPyPack=null;
|
||||||
|
try{
|
||||||
|
newPyPack = new PythonTreePackage(newPackPath, this);
|
||||||
|
}
|
||||||
|
catch (PyUMLParseException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
newPyPack.writeXmiID(xmi_id);
|
||||||
|
this.childPackages.add(newPyPack);
|
||||||
|
boolean startNew = newPyPack.synchronizeCode(modelChildPack);
|
||||||
|
if (startNew) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// handle child classes in model
|
||||||
|
else if (modelChild instanceof Class || modelChild instanceof Interface) {
|
||||||
|
Classifier modelChildClass = (Classifier) modelChild;
|
||||||
|
this.getRoot().worked(this.getName() + "/" + modelChildClass.getName());
|
||||||
|
this.getRoot().setSubTaskName(this.getName() + "/" + modelChildClass.getName());
|
||||||
|
String xmi_id = modelXmiDict.get(modelChildClass);
|
||||||
|
// look for class with this xmi_id
|
||||||
|
if (xmiClassDict.containsKey(xmi_id)) {
|
||||||
|
PythonTreeClass pyClass = xmiClassDict.get(xmi_id);
|
||||||
|
// if the class is already child of this package
|
||||||
|
if (this.getChildClasses().contains(pyClass)) {
|
||||||
|
|
||||||
|
// continue with children in model+code
|
||||||
|
boolean startNew = pyClass.synchronizeCode(modelChildClass);
|
||||||
|
while (startNew) {
|
||||||
|
try {
|
||||||
|
pyClass.getInFile().reInitFile();
|
||||||
|
startNew = this.synchronizeCode(modelElement);
|
||||||
|
if (PythonTreePackage.completeNewStart) {
|
||||||
|
PythonTreePackage.completeNewStart = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (PyUMLParseException e) {
|
||||||
|
String message = "After changing the code parsing the " +
|
||||||
|
"changed code failed!\n" +
|
||||||
|
"Error was:\n" +
|
||||||
|
e.getMessage();
|
||||||
|
e.printStackTrace();
|
||||||
|
|
||||||
|
throw new PyUMLSynchronizeCodeException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// move class to this package;
|
||||||
|
IPath newPath = this.getPackageDir().append(pyClass.name);
|
||||||
|
|
||||||
|
boolean success = pyClass.moveClass(newPath);
|
||||||
|
if (success)
|
||||||
|
// now the class is moved, start from the beginning
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
throw new PyUMLSynchronizeCodeException("Class could not be moved.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// no class with this xmi_id found!
|
||||||
|
// look for python child class with same name
|
||||||
|
// and write the right xmi_id
|
||||||
|
boolean classFound = false;
|
||||||
|
for (PythonTreeClass pySubClass : this.getChildClasses()) {
|
||||||
|
if (pySubClass.getName().equals(modelChildClass.getName())){
|
||||||
|
classFound = true;
|
||||||
|
// write xmi_id to code (only needed once)
|
||||||
|
pySubClass.writeXmiID(xmi_id);
|
||||||
|
// restart hole process
|
||||||
|
setChanged(pySubClass.astNode.beginLine);
|
||||||
|
|
||||||
|
try {
|
||||||
|
pySubClass.getInFile().reInitFile();
|
||||||
|
this.synchronizeCode(modelElement);
|
||||||
|
|
||||||
|
} catch (PyUMLParseException e) {
|
||||||
|
String message = "After changing the code parsing the " +
|
||||||
|
"changed code failed!\n" +
|
||||||
|
"Error was:\n" +
|
||||||
|
e.getMessage();
|
||||||
|
e.printStackTrace();
|
||||||
|
|
||||||
|
throw new PyUMLSynchronizeCodeException(message);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! classFound) {
|
||||||
|
// if this class was not found, create it (recursively)!
|
||||||
|
boolean success = PythonTreeClass.createNewClass(modelChildClass, this);
|
||||||
|
if (success) {
|
||||||
|
File newClassFile = new File(this.getPackageDir().append(modelChildClass.getName()).toOSString() + ".py");
|
||||||
|
try {
|
||||||
|
PythonTreeFile newPyFile = new PythonTreeFile(Path.fromOSString(newClassFile.toString()), this);
|
||||||
|
this.childClasses.addAll(newPyFile.getClassesInFile());
|
||||||
|
this.synchronizeCode(modelElement);
|
||||||
|
break globalLoop;
|
||||||
|
|
||||||
|
} catch (PyUMLParseException e) {
|
||||||
|
throw new PyUMLSynchronizeCodeException(
|
||||||
|
"Error: The newly created class" + newClassFile +
|
||||||
|
"\ncannot be parsed!\n" +
|
||||||
|
"Synchronizing Code cannot continue!\n" +
|
||||||
|
"Message was:\n" +
|
||||||
|
e.getClass().getName()+"\n"+e.getMessage());
|
||||||
|
}
|
||||||
|
//OK, class was created!
|
||||||
|
} else {
|
||||||
|
throw new PyUMLSynchronizeCodeException("Error creating class: "+modelChildClass.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move this package in the python code to another package/folder
|
||||||
|
* * Rename the package directory
|
||||||
|
* * TODO: Update references
|
||||||
|
*
|
||||||
|
* @param newPath the IPath where the package is to be moved
|
||||||
|
* @return true on success, false if package already exists
|
||||||
|
*/
|
||||||
|
public boolean movePackage(IPath newPath) {
|
||||||
|
IFolder packDir = EclipseHelperMethods.createFolder(this.getPackageDir().toOSString(), this.getProject());
|
||||||
|
if (! packDir.exists()) {
|
||||||
|
MessageDialog.openError(null, "Error moving package", "Package " + this.name + " cannot " +
|
||||||
|
"be renamed\n because it does not seem to exist!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
packDir.move(newPath, true, null);
|
||||||
|
} catch (CoreException e) {
|
||||||
|
MessageDialog.openError(null, "Error moving package", "The package " +this.name+ " cannot" +
|
||||||
|
" be moved to "+ newPath +".\n Propably a package with the new name already exists!" +
|
||||||
|
"\n\nReason:\n" +e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rename this package in the python code
|
||||||
|
* * Rename the package directory
|
||||||
|
* * TODO: Update references
|
||||||
|
*
|
||||||
|
* @param newName the new name of the package in the same directory
|
||||||
|
* @return true on success, false if package already exists
|
||||||
|
*/
|
||||||
|
public boolean renamePackage(String newName) {
|
||||||
|
IFolder packDir = EclipseHelperMethods.createFolder(this.getPackageDir().toOSString(), this.getProject());
|
||||||
|
IPath newPath = packDir.getFullPath().removeLastSegments(1).append(newName);
|
||||||
|
return this.movePackage(newPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submits the position of current code change to PythonTreeRoot
|
||||||
|
* so that it can decide if the same line is changed again
|
||||||
|
* and again and thus detect an unfinished loop.
|
||||||
|
*
|
||||||
|
* @param line the changed line in the file
|
||||||
|
*/
|
||||||
|
private void setChanged(int line) throws PyUMLSynchronizeCodeException{
|
||||||
|
this.getRoot().setChangedFileLine(this.packageDir+":"+line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts a new Package as a child beneath this package.
|
||||||
|
* @param pack
|
||||||
|
*/
|
||||||
|
public void addChildPackage(PythonTreePackage pack) {
|
||||||
|
childPackages.add(pack);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns all child Packages
|
||||||
|
*/
|
||||||
|
public List<PythonTreePackage> getChildPackages() {
|
||||||
|
return this.childPackages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns all child classes (as PythonTreeClass)
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<PythonTreeClass> getChildClasses() {
|
||||||
|
return childClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return __init__.py file of this package
|
||||||
|
*/
|
||||||
|
public PythonTreeFile getInitPy() {
|
||||||
|
return initPy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPath getPackageDir() {
|
||||||
|
return packageDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the parent package of this package,
|
||||||
|
* null if the parent package is root
|
||||||
|
*/
|
||||||
|
public PythonTreePackage getParent() {
|
||||||
|
return (PythonTreePackage) super.getParent();
|
||||||
|
}
|
||||||
|
}
|
529
pyUml/src/pyUML/pythonTree/PythonTreeRoot.java
Executable file
529
pyUml/src/pyUML/pythonTree/PythonTreeRoot.java
Executable file
@ -0,0 +1,529 @@
|
|||||||
|
package pyUML.pythonTree;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.Path;
|
||||||
|
import org.eclipse.emf.ecore.EObject;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
import org.eclipse.uml2.uml.Classifier;
|
||||||
|
import org.eclipse.uml2.uml.Generalization;
|
||||||
|
import org.eclipse.uml2.uml.Model;
|
||||||
|
import org.eclipse.uml2.uml.NamedElement;
|
||||||
|
import org.eclipse.uml2.uml.Package;
|
||||||
|
import org.eclipse.uml2.uml.Relationship;
|
||||||
|
|
||||||
|
import pyUML.backend.EclipseHelperMethods;
|
||||||
|
import pyUML.backend.JavaHelperMethods;
|
||||||
|
import pyUML.exceptions.PyUMLCancelledException;
|
||||||
|
import pyUML.exceptions.PyUMLParseException;
|
||||||
|
import pyUML.exceptions.PyUMLSynchronizeCodeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is the root of the Python Syntax Tree
|
||||||
|
* it represents the parent directory of the uppermost
|
||||||
|
* package in the python package structure.
|
||||||
|
*
|
||||||
|
* If the Project directory is already a package
|
||||||
|
* (contains __init__.py), then this class will
|
||||||
|
* contain a Package representing the own directory
|
||||||
|
* as child.
|
||||||
|
*
|
||||||
|
* Typically, this represents the "src" directory
|
||||||
|
* of the eclipse project.
|
||||||
|
*
|
||||||
|
* The root node corresponds with the "model" node of the UML diagram.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class PythonTreeRoot extends PythonTreePackage{
|
||||||
|
private IProject project;
|
||||||
|
private Set<IPath> srcPaths;
|
||||||
|
private Map<String, PythonTreePackage> xmiPackDict;
|
||||||
|
private Map<String, PythonTreeClass> xmiClassDict;
|
||||||
|
private Map<String, PythonTreeClass> classDict;
|
||||||
|
private Map<String, String> classNameDict;
|
||||||
|
private List<String> renamedClasses;
|
||||||
|
|
||||||
|
// Attributes needed for model synchronization
|
||||||
|
private Map<String, EObject> xmiModelDict;
|
||||||
|
private Map<EObject, String> modelXmiDict;
|
||||||
|
private Map<String, EObject> xmiModelDictOld;
|
||||||
|
private List<NamedElement> modelElementsToDestroy;
|
||||||
|
|
||||||
|
private List<String> changedFileLines;
|
||||||
|
private boolean createNewModel = false;
|
||||||
|
private boolean showWarnings = true;
|
||||||
|
private IProgressMonitor monitor;
|
||||||
|
private List<String> progressFinishedItems;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* createNewModel is true, if a user decided to create a new model,
|
||||||
|
* even though a model former existed and was obviously deleted
|
||||||
|
* or edited outside PyUML
|
||||||
|
* initially, createNewModel is false, and if a former model is detected,
|
||||||
|
* the user is asked
|
||||||
|
* @return the current value of is CreateNewModel
|
||||||
|
*/
|
||||||
|
public boolean isCreateNewModel() {
|
||||||
|
return createNewModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if a user decided to create a new model,
|
||||||
|
* even though a model former existed and was obviously deleted
|
||||||
|
* or edited outside PyUML, this decision can be saved here so that
|
||||||
|
* the user is asked only once
|
||||||
|
|
||||||
|
* @param createNewModel -> true, if the user decided to re-create the model
|
||||||
|
*/
|
||||||
|
public void setCreateNewModel(boolean createNewModel) {
|
||||||
|
this.createNewModel = createNewModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sets the last changed line on synchronizing code.
|
||||||
|
*
|
||||||
|
* Background:
|
||||||
|
* on synchronizing code, after every change the whole code is re-read
|
||||||
|
* an synchronizing started from beginning, until there are no more changes.
|
||||||
|
* The danger is that the program runs in an endless loop, e.g. if changes
|
||||||
|
* are not sufficient (this should NOT happen normally)
|
||||||
|
* To detect this situation, the line of the last change in code is saved;
|
||||||
|
* if this line does not change for many times, we detect a dead loop
|
||||||
|
* and break it with an error message
|
||||||
|
*
|
||||||
|
* @param changedFileLine a line, typically representing the changed line
|
||||||
|
* in code. It can also hold a package/file path etc.
|
||||||
|
* It must always be the same for the same operation!
|
||||||
|
*/
|
||||||
|
public void setChangedFileLine(String changedFileLine) throws PyUMLSynchronizeCodeException{
|
||||||
|
if (this.changedFileLines.size() == 0){
|
||||||
|
this.changedFileLines.add(changedFileLine);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.changedFileLines.get(this.changedFileLines.size()-1).equals(changedFileLine)) {
|
||||||
|
this.changedFileLines.add(changedFileLine);
|
||||||
|
} else {
|
||||||
|
this.changedFileLines.clear();
|
||||||
|
this.changedFileLines.add(changedFileLine);
|
||||||
|
}
|
||||||
|
if (this.changedFileLines.size() > 20) {
|
||||||
|
String message = "Error: Synchronize Code runs in an unfinished loop!\n\n" +
|
||||||
|
"The loop is in the File/Line\n" + changedFileLine;
|
||||||
|
throw new PyUMLSynchronizeCodeException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param project the eclipse IProject
|
||||||
|
* @param showWarnings if true, warnings (e.g. duplicate classes) are shown
|
||||||
|
* this is typically done only on the first run, if there are several runs
|
||||||
|
*/
|
||||||
|
public PythonTreeRoot(IProject project, boolean showWarnings, IProgressMonitor monitor) throws PyUMLParseException, PyUMLCancelledException{
|
||||||
|
super(null, null);
|
||||||
|
this.project = project;
|
||||||
|
this.showWarnings = showWarnings;
|
||||||
|
this.monitor = monitor;
|
||||||
|
this.srcPaths = EclipseHelperMethods.getPythonSrcDirs(project);
|
||||||
|
|
||||||
|
// first Source dir is standard dir -> all new packages will be
|
||||||
|
// created here!
|
||||||
|
this.packageDir = this.srcPaths.iterator().next();
|
||||||
|
int numPackages=JavaHelperMethods.getFileCount(this.packageDir.toFile(), "^.*.py$");
|
||||||
|
this.beginTask("Analyze Python Code", numPackages);
|
||||||
|
|
||||||
|
initRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On object Creation, this initializes the root of the python
|
||||||
|
* code representationS
|
||||||
|
* @throws PyUMLParseException
|
||||||
|
*/
|
||||||
|
private void initRoot() throws PyUMLParseException, PyUMLCancelledException{
|
||||||
|
// initialize name and xmi_id dictionaries
|
||||||
|
this.xmiPackDict = new Hashtable<String, PythonTreePackage>();
|
||||||
|
this.xmiClassDict = new Hashtable<String, PythonTreeClass>();
|
||||||
|
this.classDict = new Hashtable<String, PythonTreeClass>();
|
||||||
|
this.classNameDict = new Hashtable<String, String>();
|
||||||
|
|
||||||
|
|
||||||
|
// set the Tree name (= project name = model name)
|
||||||
|
this.name = this.project.getName();
|
||||||
|
|
||||||
|
// iterate over all source paths: find uppermost package(s)
|
||||||
|
// and append it to this root node.
|
||||||
|
for (IPath path : this.srcPaths) {
|
||||||
|
|
||||||
|
File srcDir = new File(path.toOSString());
|
||||||
|
if (! srcDir.isDirectory())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// check if dir is already package.
|
||||||
|
// if yes, add it
|
||||||
|
// if no, check all child dirs (until packages were found)
|
||||||
|
|
||||||
|
List<File> checkPackDirs = new Vector<File>();
|
||||||
|
checkPackDirs.add(srcDir);
|
||||||
|
|
||||||
|
while(checkPackDirs.size() > 0) { //take the next subdir
|
||||||
|
File dir = checkPackDirs.get(0);
|
||||||
|
checkPackDirs.remove(dir);
|
||||||
|
|
||||||
|
// list dir
|
||||||
|
File[] dirList = dir.listFiles();
|
||||||
|
boolean isPackage=false;
|
||||||
|
List<File> childDirList =new Vector<File>();
|
||||||
|
|
||||||
|
// look for child directories or "__init__.py"
|
||||||
|
for (File entry:dirList) {
|
||||||
|
if (entry.isDirectory())
|
||||||
|
childDirList.add(entry);
|
||||||
|
else if (entry.getName().equals("__init__.py"))
|
||||||
|
isPackage=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this dir is a package, initialize a new PythonTreePackage
|
||||||
|
if (isPackage)
|
||||||
|
this.addChildPackage(
|
||||||
|
new PythonTreePackage(
|
||||||
|
new Path(dir.getAbsolutePath()), this));
|
||||||
|
else
|
||||||
|
checkPackDirs.addAll(childDirList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For a given model (it can be empty), synchronize the Model
|
||||||
|
* with the code represented by this PythonTreeNode
|
||||||
|
* use xmi_id for identifying moved Packages
|
||||||
|
*
|
||||||
|
* @param model
|
||||||
|
* @param xmiModelDict
|
||||||
|
* @return true on success, false on Errors (Model must not be saved)
|
||||||
|
*/
|
||||||
|
public boolean synchronizeModel(Model model, Map<String, EObject> xmiModelDict) throws PyUMLCancelledException{
|
||||||
|
// set name of model (e.g. when newly created
|
||||||
|
if (! model.getName().equals(this.name))
|
||||||
|
model.setName(this.name);
|
||||||
|
|
||||||
|
this.xmiModelDict = xmiModelDict;
|
||||||
|
this.modelElementsToDestroy = new Vector<NamedElement>();
|
||||||
|
boolean success = super.synchronizeModel(model);
|
||||||
|
if (! success)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// create Generalizations
|
||||||
|
this.createModelGeneralizations(model);
|
||||||
|
|
||||||
|
// delete elements not present in model any more
|
||||||
|
for (NamedElement elementToDestroy : this.modelElementsToDestroy) {
|
||||||
|
// destroy all relationships
|
||||||
|
Vector<Relationship> rels = new Vector<Relationship>();
|
||||||
|
for (Relationship rel : elementToDestroy.getRelationships())
|
||||||
|
rels.add(rel);
|
||||||
|
for (Relationship rel : rels)
|
||||||
|
rel.destroy();
|
||||||
|
|
||||||
|
elementToDestroy.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* after synchronizeModel was run, this method creates all generals
|
||||||
|
* in the model. That can be done only *after* the model synchronized,
|
||||||
|
* to ensure all classes are present in the model.
|
||||||
|
* @param model
|
||||||
|
*/
|
||||||
|
public void createModelGeneralizations(Model model) {
|
||||||
|
for (PythonTreeClass pyClass : classDict.values()) {
|
||||||
|
// get model class of this class
|
||||||
|
Classifier modelClass = (Classifier) pyClass.getAssociatedModelElement();
|
||||||
|
|
||||||
|
// get all model superclasses for this class
|
||||||
|
List<Generalization> modelGenerals = modelClass.getGeneralizations();
|
||||||
|
Map<Classifier, Generalization> modelSuperClasses =
|
||||||
|
new Hashtable<Classifier, Generalization>();
|
||||||
|
for (Generalization gen : modelGenerals) {
|
||||||
|
if (gen.getGeneral() != null)
|
||||||
|
modelSuperClasses.put(gen.getGeneral(), gen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get list of superclasses in python code
|
||||||
|
Set<PythonTreeClass> pySuperClasses = pyClass.getGeneralizationsInProject();
|
||||||
|
|
||||||
|
// ensure all python superclasses are in model
|
||||||
|
for (PythonTreeClass pySuperClass : pySuperClasses) {
|
||||||
|
if (! modelSuperClasses.containsKey((Classifier)pySuperClass.getAssociatedModelElement())) {
|
||||||
|
modelClass.createGeneralization(
|
||||||
|
(Classifier)pySuperClass.getAssociatedModelElement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure all model superclasses are present in python.
|
||||||
|
// if not, delete model superclass
|
||||||
|
List<Generalization> modelGeneralList = new Vector<Generalization>();
|
||||||
|
modelGeneralList.addAll(modelGenerals);
|
||||||
|
for (Generalization modelGen : modelGeneralList) {
|
||||||
|
Classifier modelSuperClass = modelGen.getGeneral();
|
||||||
|
if (modelSuperClass == null) {
|
||||||
|
modelGen.destroy();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no class with the Generalization exists
|
||||||
|
if (! this.getClassDict().containsKey(this.getModelPackageStructure(modelSuperClass) + modelSuperClass.getName())) {
|
||||||
|
// destroy generalization
|
||||||
|
modelGen.destroy();
|
||||||
|
} else {
|
||||||
|
PythonTreeClass pySuperClass = this.getClassDict().get(this.getModelPackageStructure(modelSuperClass) + modelSuperClass.getName());
|
||||||
|
// if Superclass exists, but is no superclass
|
||||||
|
if (! pySuperClasses.contains(pySuperClass)) {
|
||||||
|
// destroy all relationships
|
||||||
|
Vector<Relationship> rels = new Vector<Relationship>();
|
||||||
|
for (Relationship rel : modelSuperClasses.get(modelSuperClass).getRelationships())
|
||||||
|
rels.add(rel);
|
||||||
|
for (Relationship rel : rels)
|
||||||
|
rel.destroy();
|
||||||
|
// destroy superclass
|
||||||
|
modelSuperClasses.get(modelSuperClass).destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//otherwise: everything is OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param modelElement
|
||||||
|
* @param modelXmiDict
|
||||||
|
* @param xmiModelDictOld
|
||||||
|
* @param monitor
|
||||||
|
* @param classCount the number of classes in model - optional parameter for progress bar
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean synchronizeCode(NamedElement modelElement, Map<EObject,
|
||||||
|
String> modelXmiDict, Map<String, EObject> xmiModelDictOld,
|
||||||
|
IProgressMonitor monitor, int classCount)
|
||||||
|
throws PyUMLCancelledException{
|
||||||
|
this.monitor = monitor;
|
||||||
|
this.modelXmiDict = modelXmiDict;
|
||||||
|
this.xmiModelDictOld = xmiModelDictOld;
|
||||||
|
this.renamedClasses = new Vector<String>();
|
||||||
|
this.showWarnings = false;
|
||||||
|
this.changedFileLines = new Vector<String>();
|
||||||
|
this.progressFinishedItems = new Vector<String>();
|
||||||
|
|
||||||
|
this.beginTask("Synchronize Code by Model", classCount);
|
||||||
|
|
||||||
|
// synchronize until no more changes were found (synchronize returns false)
|
||||||
|
try {
|
||||||
|
while(super.synchronizeCode(modelElement)) {
|
||||||
|
// if synchronizeCode returned true, it just changed the code!
|
||||||
|
// -> Re-read the code and start from the beginning
|
||||||
|
this.initRoot();
|
||||||
|
this.beginTask("Synchronize Code by Model", classCount*2);
|
||||||
|
}
|
||||||
|
// finally, do a second sync run to ensure all newly
|
||||||
|
// created classes can be used in import statements
|
||||||
|
super.synchronizeCode(modelElement);
|
||||||
|
} catch (PyUMLSynchronizeCodeException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
MessageDialog.openError(null, "An Exception happened while synchronizing code",
|
||||||
|
"An Exception happened while synchronizing code.\n" +
|
||||||
|
"Message was: \n\n" + e.getMessage());
|
||||||
|
return false;
|
||||||
|
} catch (PyUMLParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
MessageDialog.openError(null, "An Exception happened while synchronizing code",
|
||||||
|
"Obviously, while synchronizing code a python syntax error was\n" +
|
||||||
|
"created. This should not happen!\n" +
|
||||||
|
"Please resolve the problem manually!\n\n" +
|
||||||
|
"Message was: \n" + e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isRoot() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns a dictionary of all class names with their corresponding
|
||||||
|
* PythonTreeClass
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Map<String, PythonTreeClass> getClassDict() {
|
||||||
|
return classDict;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the XMI-ID <-> PythonTreePackage dictionary with XMI-IDs as keys
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
|
||||||
|
public Map<String, PythonTreePackage> getXmiPackDict() {
|
||||||
|
return xmiPackDict;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the XMI-ID <-> PythonTreeClass dictionary with XMI-IDs as keys
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Map<String, PythonTreeClass> getXmiClassDict() {
|
||||||
|
return xmiClassDict;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the XMI-ID <-> model dictionary with XMI-IDs as keys
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Map<String, EObject> getXmiModelDict() {
|
||||||
|
return xmiModelDict;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the XMI-ID <-> model dictionary with model elements as keys
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Map<EObject, String> getModelXmiDict() {
|
||||||
|
return modelXmiDict;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like PythonTreeClass.getPackageStructure(), this
|
||||||
|
* generates a string with the Package structure containing
|
||||||
|
* a class, like "/supPack/subPack/"
|
||||||
|
* @param c The model class to use
|
||||||
|
* @return the parent package structure as a String
|
||||||
|
*/
|
||||||
|
public String getModelPackageStructure(Classifier c) {
|
||||||
|
|
||||||
|
Package parent = c.getPackage();
|
||||||
|
String structure = "";
|
||||||
|
do {
|
||||||
|
structure = "/"+parent.getName() + structure;
|
||||||
|
parent = parent.getNestingPackage();
|
||||||
|
} while (! (parent instanceof Model));
|
||||||
|
|
||||||
|
return structure + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy method. Runs beginTask, if there is a monitor,
|
||||||
|
* does nothing, otherwise
|
||||||
|
* @param name The name of the task to start
|
||||||
|
* @param totalWork The number of task steps to display
|
||||||
|
*/
|
||||||
|
public void beginTask(String name, int totalWork) {
|
||||||
|
if (this.monitor != null)
|
||||||
|
this.monitor.beginTask(name, totalWork);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Completes a sub-step in the progress monitor,
|
||||||
|
* if any.
|
||||||
|
*/
|
||||||
|
public void worked() throws PyUMLCancelledException {
|
||||||
|
if (this.monitor.isCanceled())
|
||||||
|
throw new PyUMLCancelledException();
|
||||||
|
if (this.monitor != null) {
|
||||||
|
monitor.worked(1);
|
||||||
|
}
|
||||||
|
// update UI
|
||||||
|
while (Display.getCurrent().readAndDispatch())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the name of the current task in the progress monitor
|
||||||
|
* @param name
|
||||||
|
* @throws PyUMLCancelledException
|
||||||
|
*/
|
||||||
|
public void setSubTaskName(String name) throws PyUMLCancelledException{
|
||||||
|
if (this.monitor.isCanceled())
|
||||||
|
throw new PyUMLCancelledException();
|
||||||
|
if (this.monitor != null) {
|
||||||
|
monitor.subTask(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update UI
|
||||||
|
while (Display.getCurrent().readAndDispatch())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* like worked(), this additionally has the possibility to
|
||||||
|
* put an item name of the finished item, so that
|
||||||
|
* the progress bar will only be updated the first time an item is
|
||||||
|
* finished.
|
||||||
|
* This is useful for a progress bar with recursive sync calls
|
||||||
|
* @param itemName the name of the finished item
|
||||||
|
*/
|
||||||
|
public void worked(String itemName) throws PyUMLCancelledException{
|
||||||
|
if (! this.progressFinishedItems.contains(itemName)) {
|
||||||
|
this.progressFinishedItems.add(itemName);
|
||||||
|
this.worked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMonitor(IProgressMonitor monitor) {
|
||||||
|
this.monitor = monitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the list of model elements that are to be removed from
|
||||||
|
* the model after synchronizing.
|
||||||
|
* This has to be done as the last step of the sync process
|
||||||
|
* so that no concurrent modification is done on the model.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<NamedElement> getModelElementsToDestroy() {
|
||||||
|
return modelElementsToDestroy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overwrites the method fromPythonTreePackage
|
||||||
|
* -> On a renaming of the model root nothing is to be done!
|
||||||
|
* @param newName
|
||||||
|
*/
|
||||||
|
public boolean renamePackage(String newName) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, EObject> getXmiModelDictOld() {
|
||||||
|
return xmiModelDictOld;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IProject getProject() {
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getRenamedClasses() {
|
||||||
|
return renamedClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isShowWarnings() {
|
||||||
|
return showWarnings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getClassNameDict() {
|
||||||
|
return classNameDict;
|
||||||
|
}
|
||||||
|
}
|
120
pyUml/src/pyUML/refactoring/BicycleRefactoring.java
Executable file
120
pyUml/src/pyUML/refactoring/BicycleRefactoring.java
Executable file
@ -0,0 +1,120 @@
|
|||||||
|
package pyUML.refactoring;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.python.pydev.core.IPythonNature;
|
||||||
|
import org.python.pydev.core.REF;
|
||||||
|
import org.python.pydev.editor.codecompletion.shell.AbstractShell;
|
||||||
|
import org.python.pydev.editor.refactoring.AbstractPyRefactoring;
|
||||||
|
import org.python.pydev.editor.refactoring.IPyRefactoring;
|
||||||
|
import org.python.pydev.plugin.nature.PythonNature;
|
||||||
|
|
||||||
|
|
||||||
|
import pyUML.exceptions.PyUMLSynchronizeCodeException;
|
||||||
|
import pyUML.pythonTree.PythonTreeFile;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to use the Python pyUML.refactoring functionality
|
||||||
|
* provided by "Bicycle Repair Man", written in Python
|
||||||
|
* as used by PyDev
|
||||||
|
*/
|
||||||
|
public class BicycleRefactoring {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the generic refactor command using bicycle pyUML.refactoring.
|
||||||
|
* Is is used by specializes pyUML.refactoring methods
|
||||||
|
*
|
||||||
|
* @param refactorCommand - the String with the pyUML.refactoring to be done
|
||||||
|
* @param conditionalMethod - the name of the pyUML.refactoring method
|
||||||
|
* @param project - the current project
|
||||||
|
* @return true on success, false on error
|
||||||
|
*/
|
||||||
|
public static boolean doGenericBikeRefactoring(String refactorCommand, String conditionalMethod, IProject project) throws PyUMLSynchronizeCodeException{
|
||||||
|
IPyRefactoring pyRefactoring = AbstractPyRefactoring.getPyRefactoring();
|
||||||
|
IPythonNature pythonNature = PythonNature.getPythonNature(project);
|
||||||
|
try {
|
||||||
|
if ((Boolean) REF.invoke(pyRefactoring, conditionalMethod, new Object[0])) {
|
||||||
|
AbstractShell pytonShell = AbstractShell.getServerShell(pythonNature, AbstractShell.OTHERS_SHELL);
|
||||||
|
String output = "";
|
||||||
|
try{
|
||||||
|
pytonShell.changePythonPath(pythonNature.getPythonPathNature().getCompleteProjectPythonPath(null)); //default
|
||||||
|
pytonShell.write(refactorCommand);
|
||||||
|
output = URLDecoder.decode(pytonShell.read((IProgressMonitor)null), "UTF-8");
|
||||||
|
} catch (Exception e) {
|
||||||
|
output = "ERROR: "+e.getClass().getName()+"\n";
|
||||||
|
e.printStackTrace();
|
||||||
|
pytonShell.restartShell();
|
||||||
|
}
|
||||||
|
if (output.startsWith("ERROR:")) {
|
||||||
|
String errmsg = output.substring(0, output.indexOf('\n'));
|
||||||
|
pytonShell.restartShell();
|
||||||
|
MessageDialog.openError(null, "Error on pyUML.refactoring using Bike!" ,
|
||||||
|
"There was a pyUML.refactoring error using the Bicycle Repair Man Browser\n" +
|
||||||
|
"The command was: "+refactorCommand
|
||||||
|
+"\nThe error was: "+errmsg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new PyUMLSynchronizeCodeException("Error on pyUML.refactoring using Bike!\n\n" +
|
||||||
|
"pyRefactoring is not available!");
|
||||||
|
}
|
||||||
|
}catch (CoreException e) {
|
||||||
|
throw new PyUMLSynchronizeCodeException("CoreException on pyUML.refactoring using Bike!\n\n" +
|
||||||
|
e.getMessage());
|
||||||
|
}catch (IOException e) {
|
||||||
|
throw new PyUMLSynchronizeCodeException("IOException on pyUML.refactoring using Bike!\n\n" +
|
||||||
|
e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DO a 'rename' Refactoring. This is for class / method renaming
|
||||||
|
*
|
||||||
|
* @param filePath the Path of the file to edit
|
||||||
|
* (other files may be affected as well)
|
||||||
|
* (use File.toOSString() to get this Path string)
|
||||||
|
* @param newName the new Name of the object
|
||||||
|
* @param line the line of the object
|
||||||
|
* @param col the column of the object
|
||||||
|
* @param project the current project
|
||||||
|
* @return true on success, false otherwise.
|
||||||
|
*/
|
||||||
|
public static boolean doRenameObject(PythonTreeFile file, String newName, int line, int col, IProject project) throws PyUMLSynchronizeCodeException{
|
||||||
|
|
||||||
|
String filePath = file.getFilePath().toOSString();
|
||||||
|
|
||||||
|
// make sure the line to change is not the last line in file
|
||||||
|
// -> then bike will fail!
|
||||||
|
if (line == file.getFileContent().split("\n").length ) {
|
||||||
|
// insert line and start again
|
||||||
|
FileRefactoring.appendToFile(file, " ");
|
||||||
|
file.getRoot().setChangedFileLine(filePath+":"+line);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String command = "@@BIKE";
|
||||||
|
command+= "renameByCoordinates";
|
||||||
|
command+= "|"+filePath;
|
||||||
|
command+= "|"+line;
|
||||||
|
command+= "|"+(col-1);
|
||||||
|
command+= "|"+newName;
|
||||||
|
command+= "END@@";
|
||||||
|
|
||||||
|
String conditionalMethod = "canRename";
|
||||||
|
|
||||||
|
boolean success = doGenericBikeRefactoring(command, conditionalMethod, project);
|
||||||
|
file.updateFileInEclipse();
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
}
|
161
pyUml/src/pyUML/refactoring/FileRefactoring.java
Executable file
161
pyUml/src/pyUML/refactoring/FileRefactoring.java
Executable file
@ -0,0 +1,161 @@
|
|||||||
|
package pyUML.refactoring;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
|
||||||
|
import pyUML.backend.ParseHelpers;
|
||||||
|
import pyUML.pythonTree.PythonTreeFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some convenience methods for modifying/writing files
|
||||||
|
*/
|
||||||
|
public class FileRefactoring {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* replaces a string in a file from a given line/col
|
||||||
|
* deletes the file from that position unto
|
||||||
|
*
|
||||||
|
* @param pyFile the python file to edit
|
||||||
|
* @param startLine the line, from which the replace should begin
|
||||||
|
* @param startCol the column, from which the replace should begin
|
||||||
|
* @param newString the new String to replace the deleted with
|
||||||
|
* @param endMarker the char/string, unto the file content is replaces
|
||||||
|
* @param reInit if true, a reInit() is called on the python file after finishing
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean replaceFromCoordinate(PythonTreeFile pyFile, int startLine, int startCol, String newString, String endMarker, boolean reInit){
|
||||||
|
String content = pyFile.getFileContent();
|
||||||
|
int lineIndex = 0;
|
||||||
|
for (int i=1; i<startLine; i++) {
|
||||||
|
lineIndex = content.indexOf('\n' ,lineIndex)+1;
|
||||||
|
}
|
||||||
|
int startIndex = lineIndex + startCol -1;
|
||||||
|
int endIndex = content.indexOf(endMarker, startIndex);
|
||||||
|
String newContent = content.substring(0, startIndex) + newString + content.substring(endIndex);
|
||||||
|
ParseHelpers.stringToFile(new File(pyFile.getFilePath().toOSString()), newContent, pyFile.getProject());
|
||||||
|
pyFile.setFileContent(newContent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* inserts the given string at the beginning of the given line
|
||||||
|
*
|
||||||
|
* @param pyFile
|
||||||
|
* @param insertLine
|
||||||
|
* @param newString
|
||||||
|
* @return success
|
||||||
|
*/
|
||||||
|
public static boolean insertAtLine(PythonTreeFile pyFile, int insertLine, String newString){
|
||||||
|
String content = pyFile.getFileContent();
|
||||||
|
int lineIndex = 0;
|
||||||
|
for (int i=1; i<insertLine; i++) {
|
||||||
|
lineIndex = content.indexOf('\n' ,lineIndex)+1;
|
||||||
|
}
|
||||||
|
String newContent = content.substring(0, lineIndex) + newString + content.substring(lineIndex);
|
||||||
|
ParseHelpers.stringToFile(new File(pyFile.getFilePath().toOSString()), newContent, pyFile.getProject());
|
||||||
|
pyFile.setFileContent(newContent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* completely replace a given line in a python file
|
||||||
|
* @param pyFile
|
||||||
|
* @param lineNo
|
||||||
|
* @param newString
|
||||||
|
* @param writeToFile if true, the changes are directly written to the python file
|
||||||
|
* @return the String with the replaced line
|
||||||
|
*/
|
||||||
|
public static String replaceLine(PythonTreeFile pyFile, int lineNo, String newString, boolean writeToFile) {
|
||||||
|
String content = pyFile.getFileContent();
|
||||||
|
int lineIndex = 0;
|
||||||
|
for (int i=1; i<lineNo; i++) {
|
||||||
|
lineIndex = content.indexOf('\n' ,lineIndex)+1;
|
||||||
|
}
|
||||||
|
int lineIndexAfter = content.indexOf('\n' ,lineIndex);
|
||||||
|
|
||||||
|
String contentBefore = content.substring(0, lineIndex);
|
||||||
|
String newContent = contentBefore + newString;
|
||||||
|
if (lineIndexAfter > lineIndex) {
|
||||||
|
String contentAfter = content.substring(lineIndexAfter);
|
||||||
|
newContent += contentAfter;
|
||||||
|
}
|
||||||
|
if (writeToFile) {
|
||||||
|
ParseHelpers.stringToFile(new File(pyFile.getFilePath().toOSString()), newContent, pyFile.getProject());
|
||||||
|
pyFile.updateFileInEclipse();
|
||||||
|
}
|
||||||
|
pyFile.setFileContent(newContent);
|
||||||
|
|
||||||
|
return newContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* completely removes a given line in a python file
|
||||||
|
* @param pyFile
|
||||||
|
* @param lineNo The lineNo to deletes
|
||||||
|
* @param writeToFile if true, the changes are directly written to the python file
|
||||||
|
* @param onlyIfNotEmpty if true, only a non-empty-line is deleted (to preserve file design)
|
||||||
|
* @return the String with the replaced line
|
||||||
|
*/
|
||||||
|
public static String removeLine(PythonTreeFile pyFile, int lineNo, boolean writeToFile, boolean onlyIfNotEmpty) {
|
||||||
|
String content = pyFile.getFileContent();
|
||||||
|
int lineIndex = 0;
|
||||||
|
for (int i=1; i<lineNo+1; i++) {
|
||||||
|
lineIndex = content.indexOf('\n' ,lineIndex)+1;
|
||||||
|
}
|
||||||
|
int lineIndexAfter = content.indexOf('\n' ,lineIndex)+1;
|
||||||
|
|
||||||
|
String contentBefore = content.substring(0, lineIndex);
|
||||||
|
String newContent = contentBefore;
|
||||||
|
if (lineIndexAfter > lineIndex) {
|
||||||
|
String contentAfter = content.substring(lineIndexAfter);
|
||||||
|
newContent += contentAfter;
|
||||||
|
}
|
||||||
|
if (onlyIfNotEmpty) {
|
||||||
|
String lineToDelete = content.substring(lineIndex+1, lineIndexAfter );
|
||||||
|
if (lineToDelete.matches("[\\s]*"))
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writeToFile) {
|
||||||
|
ParseHelpers.stringToFile(new File(pyFile.getFilePath().toOSString()), newContent, pyFile.getProject());
|
||||||
|
pyFile.updateFileInEclipse();
|
||||||
|
}
|
||||||
|
|
||||||
|
pyFile.setFileContent(newContent);
|
||||||
|
return newContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends a String to a PythonTreeFile and saves the file on disk
|
||||||
|
* @param pyFile
|
||||||
|
* @param stringToAppend
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean appendToFile(PythonTreeFile pyFile, String stringToAppend) {
|
||||||
|
String content = pyFile.getFileContent();
|
||||||
|
String newContent = content + stringToAppend;
|
||||||
|
ParseHelpers.stringToFile(new File(pyFile.getFilePath().toOSString()), newContent, pyFile.getProject());
|
||||||
|
pyFile.updateFileInEclipse();
|
||||||
|
pyFile.setFileContent(newContent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the line with the given line number
|
||||||
|
* for this file. Line numbers start with 1, not with 0
|
||||||
|
* @param pyFile the PythonTreeFile which represents the file
|
||||||
|
* @param lineNo the lineNumber
|
||||||
|
* @return The searched line as a string, null if lineNo is
|
||||||
|
* not in index.
|
||||||
|
*/
|
||||||
|
public static String getLine(PythonTreeFile pyFile, int lineNo) {
|
||||||
|
String[] splittedFileContent = pyFile.getSplittedFileContent();
|
||||||
|
if (lineNo <= 0)
|
||||||
|
return null;
|
||||||
|
if (lineNo > splittedFileContent.length)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return splittedFileContent[lineNo - 1];
|
||||||
|
}
|
||||||
|
}
|
63
pyUml/src/pyUML/views/EditView.java
Executable file
63
pyUml/src/pyUML/views/EditView.java
Executable file
@ -0,0 +1,63 @@
|
|||||||
|
package pyUML.views;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
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.impl.ResourceSetImpl;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.eclipse.jface.wizard.WizardDialog;
|
||||||
|
import org.eclipse.uml2.uml.Model;
|
||||||
|
import org.eclipse.uml2.uml.resource.UMLResource;
|
||||||
|
|
||||||
|
import pyUML.backend.GlobalConstants;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This edits a given view for a project.
|
||||||
|
* It loads the view configuration and calls EditViewWizard
|
||||||
|
*/
|
||||||
|
public class EditView{
|
||||||
|
private EditViewWizard editViewWizard;
|
||||||
|
|
||||||
|
public EditView(IProject project, IFile confFile, String viewName, boolean open) {
|
||||||
|
|
||||||
|
try{
|
||||||
|
String umlModelFileName=project.getLocation().
|
||||||
|
append(GlobalConstants.getPyUmlDir()).
|
||||||
|
append(project.getName()+".uml").toOSString();
|
||||||
|
|
||||||
|
EObject diagramRoot = null;
|
||||||
|
try {
|
||||||
|
Resource resource = new ResourceSetImpl().getResource(URI.createFileURI(umlModelFileName), true);
|
||||||
|
diagramRoot = (EObject) resource.getContents().get(0);
|
||||||
|
} catch (WrappedException ex) {
|
||||||
|
MessageDialog.openError(null,ex.getMessage(),"Unable to load model: " + umlModelFileName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UMLResource res = (UMLResource) diagramRoot.eResource();
|
||||||
|
Map<EObject, String> modelXmiDict = res.getEObjectToIDMap();
|
||||||
|
Model model = (Model) diagramRoot;
|
||||||
|
|
||||||
|
editViewWizard = new EditViewWizard(null, model, res, project, confFile, viewName, modelXmiDict);
|
||||||
|
WizardDialog dialog = new WizardDialog(null, editViewWizard);
|
||||||
|
if (open)
|
||||||
|
dialog.open();
|
||||||
|
else
|
||||||
|
dialog.create();
|
||||||
|
|
||||||
|
}catch (Throwable t) {
|
||||||
|
MessageDialog.openError(null,t.getMessage(),"Error Managing Views:"+t.getMessage());
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public EditViewWizard getEditViewWizard() {
|
||||||
|
return editViewWizard;
|
||||||
|
}
|
||||||
|
}
|
437
pyUml/src/pyUML/views/EditViewWizard.java
Executable file
437
pyUml/src/pyUML/views/EditViewWizard.java
Executable file
@ -0,0 +1,437 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
307
pyUml/src/pyUML/views/ManageViewsPage.java
Executable file
307
pyUml/src/pyUML/views/ManageViewsPage.java
Executable file
@ -0,0 +1,307 @@
|
|||||||
|
package pyUML.views;
|
||||||
|
|
||||||
|
|
||||||
|
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.jface.dialogs.Dialog;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
|
import org.eclipse.swt.events.SelectionListener;
|
||||||
|
import org.eclipse.swt.layout.GridData;
|
||||||
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
|
import org.eclipse.swt.widgets.Button;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Control;
|
||||||
|
import org.eclipse.swt.widgets.Group;
|
||||||
|
import org.eclipse.swt.widgets.List;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
import org.eclipse.ui.IEditorPart;
|
||||||
|
import org.eclipse.uml2.uml.Model;
|
||||||
|
|
||||||
|
import pyUML.actions.ManageViewsAction;
|
||||||
|
import pyUML.backend.GlobalConstants;
|
||||||
|
import pyUML.backend.JavaHelperMethods;
|
||||||
|
import pyUML.backend.UMLToolsHelperMethods;
|
||||||
|
import pyUML.listeners.ViewChangeListener;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the dialog for managing pyUML.views.
|
||||||
|
* Views can be selected, deleted, edited and created.
|
||||||
|
* A listener is implemented with this class, so here
|
||||||
|
* is defined what happens when you press buttons in the dialog.
|
||||||
|
*/
|
||||||
|
public class ManageViewsPage extends Dialog implements SelectionListener{
|
||||||
|
Composite composite = null;
|
||||||
|
Group viewsBoxGroup = null;
|
||||||
|
List viewsBox = null;
|
||||||
|
Button openButton = null;
|
||||||
|
Button editButton = null;
|
||||||
|
Button deleteButton = null;
|
||||||
|
Button createNewButton = null;
|
||||||
|
Model model;
|
||||||
|
IProject project;
|
||||||
|
|
||||||
|
Shell shell=null;
|
||||||
|
|
||||||
|
public ManageViewsPage(Shell parent, Model model, IProject project){
|
||||||
|
super(parent);
|
||||||
|
this.model= model;
|
||||||
|
this.project=project;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Control createDialogArea(Composite parent) {
|
||||||
|
this.composite = (Composite) super.createDialogArea(parent);
|
||||||
|
setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX);
|
||||||
|
createControls(composite);
|
||||||
|
initializeDialog();
|
||||||
|
//add controls to composite as necessary
|
||||||
|
return composite;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void createControls (Composite composite) {
|
||||||
|
// create graphical components
|
||||||
|
shell = composite.getShell();
|
||||||
|
shell.setText("Manage UML Views");
|
||||||
|
|
||||||
|
viewsBoxGroup = new Group(composite, SWT.None);
|
||||||
|
viewsBoxGroup.setText("Available Views");
|
||||||
|
|
||||||
|
viewsBoxGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
|
||||||
|
viewsBoxGroup.setLayout(new GridLayout(1, true));
|
||||||
|
|
||||||
|
|
||||||
|
viewsBox = new List( viewsBoxGroup, SWT.BORDER|SWT.SINGLE|SWT.V_SCROLL|SWT.H_SCROLL );
|
||||||
|
viewsBox.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||||
|
|
||||||
|
Composite buttonGroup = new Composite(viewsBoxGroup, SWT.NONE);
|
||||||
|
buttonGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
|
||||||
|
buttonGroup.setLayout(new GridLayout(3, true));
|
||||||
|
|
||||||
|
viewsBox.setSize(300,300);
|
||||||
|
|
||||||
|
openButton = new Button(buttonGroup, SWT.PUSH);
|
||||||
|
openButton.setText("Open View");
|
||||||
|
openButton.addSelectionListener(this);
|
||||||
|
|
||||||
|
editButton = new Button(buttonGroup, SWT.PUSH);
|
||||||
|
editButton.setText("Edit View");
|
||||||
|
editButton.addSelectionListener(this);
|
||||||
|
|
||||||
|
deleteButton = new Button(buttonGroup, SWT.PUSH);
|
||||||
|
deleteButton.setText("Delete View");
|
||||||
|
deleteButton.addSelectionListener(this);
|
||||||
|
|
||||||
|
|
||||||
|
buttonGroup.pack();
|
||||||
|
viewsBoxGroup.pack();
|
||||||
|
setElementEnabled(false, viewsBoxGroup);
|
||||||
|
|
||||||
|
createNewButton = new Button(composite, SWT.PUSH);
|
||||||
|
createNewButton.setText("Create New View");
|
||||||
|
createNewButton.setLayoutData(new GridData(GridData.FILL_BOTH));
|
||||||
|
createNewButton.addSelectionListener(this);
|
||||||
|
|
||||||
|
composite.pack();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a composite element and all children enabled/disabled
|
||||||
|
* @param enabled
|
||||||
|
* @param element
|
||||||
|
*/
|
||||||
|
public static void setElementEnabled(boolean enabled, Control element) {
|
||||||
|
element.setEnabled(enabled);
|
||||||
|
if (element instanceof Composite) {
|
||||||
|
Composite comp = (Composite) element;
|
||||||
|
for (Control child : comp.getChildren()) {
|
||||||
|
setElementEnabled(enabled, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void widgetDefaultSelected(SelectionEvent e) {
|
||||||
|
// Auto-generated method stub
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles pressed-button events and runs appropriate pyUML.actions
|
||||||
|
*/
|
||||||
|
public void widgetSelected(SelectionEvent e) {
|
||||||
|
// "CREATE NEW" BUTTON
|
||||||
|
if (e.getSource() == this.createNewButton) {
|
||||||
|
this.createDialog();
|
||||||
|
|
||||||
|
// re-open View management window
|
||||||
|
this.cancelPressed();
|
||||||
|
}
|
||||||
|
//DELETE BUTTON
|
||||||
|
else if (e.getSource() == this.deleteButton) {
|
||||||
|
|
||||||
|
// return if nothing was selected
|
||||||
|
if (this.viewsBox.getSelection().length <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// warn before deletion
|
||||||
|
if (MessageDialog.openConfirm(null, "Confirm deletion of view",
|
||||||
|
"Do you really want to delete this view?") == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// delete view configuration, UML model and diagram
|
||||||
|
String selectedElement = this.viewsBox.getSelection()[0];
|
||||||
|
IPath conFilePath = project.getFullPath().append(GlobalConstants.getPyUmlDir())
|
||||||
|
.append(selectedElement+GlobalConstants.getViewConfExtension());
|
||||||
|
IFile confFile = this.project.getWorkspace().getRoot().getFile(conFilePath);
|
||||||
|
IPath umlFilePath = project.getFullPath().append(GlobalConstants.getPyUmlDir())
|
||||||
|
.append(selectedElement+GlobalConstants.getViewUmlExtension());
|
||||||
|
IFile umlFile = this.project.getWorkspace().getRoot().getFile(umlFilePath);
|
||||||
|
IPath diagramFilePath = project.getFullPath().append(GlobalConstants.getPyUmlDir())
|
||||||
|
.append(selectedElement+GlobalConstants.getDiagramExtension());
|
||||||
|
IFile diagramFile = this.project.getWorkspace().getRoot().getFile(diagramFilePath);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (confFile.exists())
|
||||||
|
confFile.delete(false, null);
|
||||||
|
if (umlFile.exists())
|
||||||
|
umlFile.delete(false, null);
|
||||||
|
if (diagramFile.exists())
|
||||||
|
diagramFile.delete(false, null);
|
||||||
|
} catch (CoreException err) {
|
||||||
|
MessageDialog.openError(null, "Error deleting element",
|
||||||
|
"Could not delete view. Reason:\n"+err.getMessage());
|
||||||
|
}
|
||||||
|
this.cancelPressed();
|
||||||
|
ManageViewsAction.run(project);
|
||||||
|
|
||||||
|
// OPEN BUTTON
|
||||||
|
} else if (e.getSource() == this.openButton) {
|
||||||
|
if (this.viewsBox.getSelection().length <= 0)
|
||||||
|
return;
|
||||||
|
String ViewUmlFileName = this.viewsBox.getSelection()[0]+GlobalConstants.getViewUmlExtension();
|
||||||
|
String ViewConfFileName = this.viewsBox.getSelection()[0]+GlobalConstants.getViewConfExtension();
|
||||||
|
String selectedElement = this.viewsBox.getSelection()[0]+GlobalConstants.getDiagramExtension();
|
||||||
|
IFile viewDiagramFile = this.project.getWorkspace().getRoot().
|
||||||
|
getFile(project.getFullPath().append(GlobalConstants.getPyUmlDir()).
|
||||||
|
append(selectedElement));
|
||||||
|
IFile viewConfFile = this.project.getWorkspace().getRoot().
|
||||||
|
getFile(project.getFullPath().append(GlobalConstants.getPyUmlDir()).
|
||||||
|
append(ViewConfFileName));
|
||||||
|
|
||||||
|
if (! viewDiagramFile.exists()) {
|
||||||
|
MessageDialog.openError(null, "Error opening view", "The selected view could not be opened;\n" +
|
||||||
|
"The UML diagram does not seem to exist!");
|
||||||
|
} else {
|
||||||
|
UMLToolsHelperMethods.updateViewModel(project, viewConfFile);
|
||||||
|
IEditorPart newPage = null;
|
||||||
|
try {
|
||||||
|
newPage = UMLToolsHelperMethods.refreshDiagramEditor(this.project, viewDiagramFile, false);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
if (newPage == null)
|
||||||
|
newPage = UMLToolsHelperMethods.openDiagram(this.project, viewDiagramFile, ViewUmlFileName, true);
|
||||||
|
|
||||||
|
|
||||||
|
if ( newPage == null) {
|
||||||
|
MessageDialog.openError(null, "Error opening view", "The selected view could not be opened!");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newPage.addPropertyListener(new ViewChangeListener(this.project));
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // EDIT BUTTON
|
||||||
|
else if (e.getSource() == this.editButton) {
|
||||||
|
|
||||||
|
String selectedViewName = this.viewsBox.getSelection()[0];
|
||||||
|
|
||||||
|
IFile confFile = this.project.getWorkspace().getRoot().getFile(project.getFullPath().append(GlobalConstants.getPyUmlDir()).append(selectedViewName + GlobalConstants.getViewConfExtension()));
|
||||||
|
IFile viewDiagramFile = this.project.getWorkspace().getRoot().getFile(project.getFullPath().append(GlobalConstants.getPyUmlDir()).append(selectedViewName + GlobalConstants.getDiagramExtension()));
|
||||||
|
|
||||||
|
|
||||||
|
// open view editor
|
||||||
|
new EditView(this.project, confFile, selectedViewName, true);
|
||||||
|
|
||||||
|
// reload View, if it is already opened
|
||||||
|
UMLToolsHelperMethods.refreshDiagramEditor(project, viewDiagramFile, true);
|
||||||
|
|
||||||
|
// re-open View management window
|
||||||
|
this.cancelPressed();
|
||||||
|
ManageViewsAction.run(project);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creates a "new View" dialog
|
||||||
|
* creates an empty view config file and runs "edit" on this file
|
||||||
|
*/
|
||||||
|
public void createDialog() {
|
||||||
|
String viewName = "newView";
|
||||||
|
String newViewName = viewName;
|
||||||
|
IPath filePath=this.project.getLocation().append(GlobalConstants.getPyUmlDir());
|
||||||
|
|
||||||
|
// find initial filename that is not already used
|
||||||
|
int i=0;
|
||||||
|
java.io.File f;
|
||||||
|
do {
|
||||||
|
newViewName = viewName+(i==0?"":i);
|
||||||
|
String fileName=filePath.append(newViewName +GlobalConstants.getViewConfExtension()).toOSString();
|
||||||
|
f= new java.io.File(fileName);
|
||||||
|
i++;
|
||||||
|
} while (f.exists());
|
||||||
|
|
||||||
|
// create initial config file
|
||||||
|
try{
|
||||||
|
IFile confFile = this.project.getWorkspace().getRoot().getFile(project.getFullPath().append(GlobalConstants.getPyUmlDir()).append(newViewName + GlobalConstants.getViewConfExtension()));
|
||||||
|
confFile.create(JavaHelperMethods.stringToStream(""), false, null);
|
||||||
|
|
||||||
|
//open "edit view" editor
|
||||||
|
new EditView(this.project, confFile, newViewName, true);
|
||||||
|
this.close();
|
||||||
|
|
||||||
|
} catch (CoreException err) {
|
||||||
|
MessageDialog.openError(null, "Cannot create View", "View could not be created.\n" +
|
||||||
|
"Reason:\n"+err.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* re-reads available pyUML.views from hard disk
|
||||||
|
*/
|
||||||
|
protected void initializeDialog() {
|
||||||
|
boolean viewFound = false;
|
||||||
|
String pyUmlDir = project.getLocation().append(GlobalConstants.getPyUmlDir()).toOSString();
|
||||||
|
java.io.File umlDir = new java.io.File(pyUmlDir);
|
||||||
|
if (umlDir.list() == null) {
|
||||||
|
MessageDialog.openError(null, "Error Managing Views",
|
||||||
|
"No UML Model was found.\n" +
|
||||||
|
"Please create a Model before creating a View!");
|
||||||
|
this.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String file : umlDir.list()) {
|
||||||
|
if (file.matches(".*.pyUmlView.uml$")) {
|
||||||
|
viewFound=true;
|
||||||
|
this.viewsBox.add(file.replace(".pyUmlView.uml", ""));
|
||||||
|
this.viewsBox.add("a");
|
||||||
|
this.viewsBox.remove(this.viewsBox.getItemCount()-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (viewFound)
|
||||||
|
setElementEnabled(true, viewsBoxGroup);
|
||||||
|
else
|
||||||
|
setElementEnabled(false, viewsBoxGroup);
|
||||||
|
}
|
||||||
|
}
|
235
pyUml/src/pyUML/views/SelectViewElementsPage.java
Executable file
235
pyUml/src/pyUML/views/SelectViewElementsPage.java
Executable file
@ -0,0 +1,235 @@
|
|||||||
|
package pyUML.views;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Dictionary;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import org.eclipse.emf.ecore.EObject;
|
||||||
|
import org.eclipse.jface.wizard.WizardPage;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
|
import org.eclipse.swt.events.SelectionListener;
|
||||||
|
import org.eclipse.swt.layout.GridData;
|
||||||
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
|
import org.eclipse.swt.widgets.Button;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Label;
|
||||||
|
import org.eclipse.swt.widgets.Text;
|
||||||
|
import org.eclipse.swt.widgets.Tree;
|
||||||
|
import org.eclipse.swt.widgets.TreeItem;
|
||||||
|
import org.eclipse.uml2.uml.Classifier;
|
||||||
|
import org.eclipse.uml2.uml.Element;
|
||||||
|
import org.eclipse.uml2.uml.Interface;
|
||||||
|
import org.eclipse.uml2.uml.Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Wizard page contains a tree view where
|
||||||
|
* the user can select packages/classes used in the view.
|
||||||
|
*/
|
||||||
|
public class SelectViewElementsPage extends WizardPage implements SelectionListener{
|
||||||
|
|
||||||
|
private Model model;
|
||||||
|
private List<String> usedXmiIds;
|
||||||
|
protected Dictionary<Element, TreeItem> nodeCheckboxDict;
|
||||||
|
protected Text viewNameField;
|
||||||
|
protected Button buttInclSuperClasses;
|
||||||
|
protected Button buttInclSubClasses;
|
||||||
|
private Map<EObject, String> modelXmiDict;
|
||||||
|
private boolean initialIncludeSuperclasses;
|
||||||
|
private boolean initialIncludeSubclasses;
|
||||||
|
private String initialViewName;
|
||||||
|
|
||||||
|
public Text getViewNameField() {
|
||||||
|
return viewNameField;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SelectViewElementsPage(String pageName, Model model, List<String> usedXmiIds,
|
||||||
|
Map<EObject, String> modelXmiDict, String initialViewName,
|
||||||
|
boolean initialIncludSuperclasses, boolean initialIncludSubclasses) {
|
||||||
|
super(pageName);
|
||||||
|
this.setTitle(pageName);
|
||||||
|
this.model=model;
|
||||||
|
this.nodeCheckboxDict = new Hashtable<Element, TreeItem>();
|
||||||
|
this.usedXmiIds = usedXmiIds;
|
||||||
|
this.modelXmiDict = modelXmiDict;
|
||||||
|
this.initialIncludeSuperclasses = initialIncludSuperclasses;
|
||||||
|
this.initialIncludeSubclasses = initialIncludSubclasses;
|
||||||
|
this.initialViewName = initialViewName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createControl(Composite parent) {
|
||||||
|
// create the composite to hold the widgets
|
||||||
|
GridData gd;
|
||||||
|
Composite composite = new Composite(parent, SWT.NULL);
|
||||||
|
|
||||||
|
// create the desired layout for this wizard page
|
||||||
|
GridLayout gl = new GridLayout();
|
||||||
|
int ncol = 1;
|
||||||
|
gl.numColumns = ncol;
|
||||||
|
gl.makeColumnsEqualWidth=true;
|
||||||
|
composite.setLayout(gl);
|
||||||
|
|
||||||
|
Composite viewNameComp= new Composite(composite, composite.getStyle());
|
||||||
|
GridLayout ViewNameLayout = new GridLayout();
|
||||||
|
ViewNameLayout.numColumns=2;
|
||||||
|
ViewNameLayout.makeColumnsEqualWidth=false;
|
||||||
|
viewNameComp.setLayout(ViewNameLayout);
|
||||||
|
|
||||||
|
Label viewNameLabel = new Label(viewNameComp, SWT.HORIZONTAL);
|
||||||
|
viewNameLabel.setText("View name: ");
|
||||||
|
viewNameField = new Text(viewNameComp, SWT.SINGLE);
|
||||||
|
viewNameField.setText(this.initialViewName);
|
||||||
|
viewNameField.setSize(200, 25);
|
||||||
|
|
||||||
|
Tree tree = new Tree(composite, SWT.CHECK);
|
||||||
|
gd = new GridData(GridData.FILL_BOTH);
|
||||||
|
|
||||||
|
tree.setLayoutData(gd);
|
||||||
|
|
||||||
|
TreeItem item = new TreeItem(tree, tree.getStyle());
|
||||||
|
item.setText(this.model.getName());
|
||||||
|
|
||||||
|
nodeCheckboxDict.put(model, item);
|
||||||
|
if (usedXmiIds.contains(modelXmiDict.get(model)))
|
||||||
|
item.setChecked(true);
|
||||||
|
|
||||||
|
for (Element child : model.getOwnedElements()) {
|
||||||
|
recurseModelElements(child, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usedXmiIds.contains(modelXmiDict.get(model)))
|
||||||
|
item.setChecked(true);
|
||||||
|
|
||||||
|
|
||||||
|
this.buttInclSuperClasses = new Button(composite, SWT.CHECK);
|
||||||
|
this.buttInclSuperClasses.setText("Include superclasses of selected classes");
|
||||||
|
this.buttInclSuperClasses.setSelection(this.initialIncludeSuperclasses);
|
||||||
|
|
||||||
|
this.buttInclSubClasses = new Button(composite, SWT.CHECK);
|
||||||
|
this.buttInclSubClasses.setText("Include child classes of selected classes");
|
||||||
|
this.buttInclSubClasses.setSelection(this.initialIncludeSubclasses);
|
||||||
|
|
||||||
|
|
||||||
|
// set the composite as the control for this page
|
||||||
|
setControl(composite);
|
||||||
|
tree.addSelectionListener(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This adds all sub-elements of checked packages
|
||||||
|
* to the list of used XMI-IDs. This is needed for a non-interactive
|
||||||
|
* View update to ensure all newly created sub-classes/-packages
|
||||||
|
* are added to a checked package.
|
||||||
|
*/
|
||||||
|
public void addPackagedXmiIds() {
|
||||||
|
this.recurseModelElements(this.model, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the TreeView by iterationg the Model
|
||||||
|
* -> Package and class nodes are created in the tree
|
||||||
|
* @param node
|
||||||
|
* @param parentItem if null, the XMI-ID will be added to used IDs
|
||||||
|
* insead of checking the box (used non-interactive mode)
|
||||||
|
*/
|
||||||
|
protected void recurseModelElements(Element node, TreeItem parentItem) {
|
||||||
|
if (node instanceof org.eclipse.uml2.uml.Package) {
|
||||||
|
org.eclipse.uml2.uml.Package pack = (org.eclipse.uml2.uml.Package) node;
|
||||||
|
if (parentItem == null) {
|
||||||
|
if (this.usedXmiIds.contains(this.modelXmiDict.get(pack)))
|
||||||
|
for (Element childNode : pack.getOwnedElements()) {
|
||||||
|
this.usedXmiIds.add(this.modelXmiDict.get(childNode));
|
||||||
|
recurseModelElements(childNode, null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TreeItem item = new TreeItem(parentItem, parentItem.getStyle());
|
||||||
|
item.setText("Package " + pack.getName());
|
||||||
|
nodeCheckboxDict.put(pack, item);
|
||||||
|
|
||||||
|
for (Element childNode : pack.getOwnedElements())
|
||||||
|
recurseModelElements(childNode, item);
|
||||||
|
|
||||||
|
if(this.usedXmiIds.contains(this.modelXmiDict.get(pack)))
|
||||||
|
setWidgetChecked(item, true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (node instanceof Classifier && parentItem != null) {
|
||||||
|
Classifier cl = (Classifier) node;
|
||||||
|
TreeItem item = new TreeItem(parentItem, parentItem.getStyle());
|
||||||
|
if (cl instanceof org.eclipse.uml2.uml.Class)
|
||||||
|
item.setText("Class " + cl.getName());
|
||||||
|
else if (cl instanceof Interface)
|
||||||
|
item.setText("Interface " + cl.getName());
|
||||||
|
else
|
||||||
|
item.setText("Element " + cl.getName());
|
||||||
|
|
||||||
|
nodeCheckboxDict.put(cl, item);
|
||||||
|
if(this.usedXmiIds.contains(this.modelXmiDict.get(cl)))
|
||||||
|
item.setChecked(true);
|
||||||
|
|
||||||
|
for (Element childNode : cl.getOwnedElements())
|
||||||
|
recurseModelElements(childNode, item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void widgetDefaultSelected(SelectionEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check/uncheck a Class/Package in the Tree View
|
||||||
|
* and *all* subpackages/classes of a view
|
||||||
|
* This can be called by the listener or
|
||||||
|
* automatically when updating a view
|
||||||
|
* -> all new Child-Elements of a selected package
|
||||||
|
* should be automatically added to a view.
|
||||||
|
* @param item
|
||||||
|
* @param checked
|
||||||
|
*/
|
||||||
|
public void setWidgetChecked(TreeItem item, boolean checked) {
|
||||||
|
item.setChecked(checked);
|
||||||
|
List<TreeItem> children = new Vector<TreeItem>();
|
||||||
|
children.addAll(Arrays.asList(item.getItems()));
|
||||||
|
while(! children.isEmpty()) {
|
||||||
|
TreeItem child = children.get(0);
|
||||||
|
children.remove(child);
|
||||||
|
children.addAll(Arrays.asList(child.getItems()));
|
||||||
|
child.setChecked(checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void widgetSelected(SelectionEvent e) {
|
||||||
|
// mark or unmark all children check boxes
|
||||||
|
// of a marked/unmarked box
|
||||||
|
if (e.item instanceof TreeItem) {
|
||||||
|
TreeItem item = (TreeItem) e.item;
|
||||||
|
boolean checked = item.getChecked();
|
||||||
|
this.setWidgetChecked(item, checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<Element, TreeItem> getNodeCheckboxDict() {
|
||||||
|
return nodeCheckboxDict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Button getButtInclSuperClasses() {
|
||||||
|
return buttInclSuperClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInitialIncludeSuperclasses() {
|
||||||
|
return initialIncludeSuperclasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInitialIncludeSuperclasses(boolean initialIncludeSuperclasses) {
|
||||||
|
this.initialIncludeSuperclasses = initialIncludeSuperclasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Button getButtInclSubClasses() {
|
||||||
|
return buttInclSubClasses;
|
||||||
|
}
|
||||||
|
}
|
512
pyUml/src/pyUML/views/SynchronizeModelByView.java
Executable file
512
pyUml/src/pyUML/views/SynchronizeModelByView.java
Executable file
@ -0,0 +1,512 @@
|
|||||||
|
package pyUML.views;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.runtime.Path;
|
||||||
|
import org.eclipse.emf.common.util.EList;
|
||||||
|
import org.eclipse.emf.common.util.URI;
|
||||||
|
import org.eclipse.emf.ecore.EClass;
|
||||||
|
import org.eclipse.emf.ecore.EObject;
|
||||||
|
import org.eclipse.emf.ecore.impl.EClassImpl;
|
||||||
|
import org.eclipse.emf.ecore.resource.Resource;
|
||||||
|
import org.eclipse.jface.action.IAction;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.eclipse.jface.viewers.ISelection;
|
||||||
|
import org.eclipse.jface.viewers.TreeSelection;
|
||||||
|
import org.eclipse.ui.IObjectActionDelegate;
|
||||||
|
import org.eclipse.ui.IWorkbenchPage;
|
||||||
|
import org.eclipse.ui.IWorkbenchPart;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
import org.eclipse.uml2.uml.Association;
|
||||||
|
import org.eclipse.uml2.uml.BehavioredClassifier;
|
||||||
|
import org.eclipse.uml2.uml.Class;
|
||||||
|
import org.eclipse.uml2.uml.Classifier;
|
||||||
|
import org.eclipse.uml2.uml.Element;
|
||||||
|
import org.eclipse.uml2.uml.Generalization;
|
||||||
|
import org.eclipse.uml2.uml.Interface;
|
||||||
|
import org.eclipse.uml2.uml.Model;
|
||||||
|
import org.eclipse.uml2.uml.Package;
|
||||||
|
import org.eclipse.uml2.uml.PackageableElement;
|
||||||
|
import org.eclipse.uml2.uml.ParameterableElement;
|
||||||
|
import org.eclipse.uml2.uml.Property;
|
||||||
|
import org.eclipse.uml2.uml.Realization;
|
||||||
|
import org.eclipse.uml2.uml.Relationship;
|
||||||
|
import org.eclipse.uml2.uml.TemplateParameter;
|
||||||
|
import org.eclipse.uml2.uml.Type;
|
||||||
|
import org.eclipse.uml2.uml.resource.UMLResource;
|
||||||
|
|
||||||
|
import pyUML.backend.GlobalConstants;
|
||||||
|
import pyUML.backend.UMLToolsHelperMethods;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is an action class where the global UML model
|
||||||
|
* is to be updated by a view.
|
||||||
|
* Classes cannot be copied, because this would destroy all
|
||||||
|
* model relationships of the class.
|
||||||
|
* New classes in a view are ignored, because it is not known where
|
||||||
|
* they are to be inserted in the model.
|
||||||
|
*
|
||||||
|
* At the moment, class attributes and methods are *not* synchronized
|
||||||
|
* with the mail model.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SynchronizeModelByView implements IObjectActionDelegate{
|
||||||
|
private String pathToModel;;
|
||||||
|
private String pathToView;
|
||||||
|
private Model model;
|
||||||
|
private Model viewModel;
|
||||||
|
private Resource[] viewResource = {null};
|
||||||
|
private Map<String, EObject> xmiModelDict;
|
||||||
|
private Map<EObject, String> modelXmiDict;
|
||||||
|
private Map<String, EObject> xmiViewDict;
|
||||||
|
private Map<EObject, String> viewXmiDict;
|
||||||
|
private IProject project;
|
||||||
|
|
||||||
|
|
||||||
|
public static void synchronizeGlobalModel(String pathToView, IProject project) {
|
||||||
|
SynchronizeModelByView sv = new SynchronizeModelByView();
|
||||||
|
sv.project = project;
|
||||||
|
sv.synchronizeGlobalModel(pathToView);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the global model by changes made by the given view.
|
||||||
|
* Class deletions are removed from the view, not from the model.
|
||||||
|
*
|
||||||
|
* New classes/packages are ignored, because it is not known
|
||||||
|
* where they should be inserted.
|
||||||
|
*
|
||||||
|
* Other changes are updated in the global model.
|
||||||
|
*
|
||||||
|
* @param pathToModel
|
||||||
|
* @param pathToView
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean synchronizeGlobalModel(String pathToView) {
|
||||||
|
String pathToModel = this.project.getLocation()
|
||||||
|
.append(GlobalConstants.getPyUmlDir())
|
||||||
|
.append(this.project.getName()+".uml").toOSString();
|
||||||
|
|
||||||
|
//init models
|
||||||
|
this.pathToModel = pathToModel;
|
||||||
|
this.pathToView = pathToView;
|
||||||
|
initModels();
|
||||||
|
|
||||||
|
|
||||||
|
String viewName = new Path(pathToView).lastSegment().replaceAll(GlobalConstants.getViewUmlExtension(), "");
|
||||||
|
|
||||||
|
Package viewPackage = null;
|
||||||
|
|
||||||
|
viewPackage = this.viewModel.getNestedPackage("View_"+viewName);
|
||||||
|
|
||||||
|
if (viewPackage == null) {
|
||||||
|
MessageDialog.openError(null, "Error synchronizing View",
|
||||||
|
"The Model could not be synchronized by the view, because\n" +
|
||||||
|
"The View package View_"+viewName+" could not\n" +
|
||||||
|
"be found.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
List<PackageableElement> elList = new Vector<PackageableElement>();
|
||||||
|
elList.addAll(viewPackage.getPackagedElements());
|
||||||
|
for (PackageableElement el : elList) {
|
||||||
|
// find parent package in model
|
||||||
|
if (el instanceof Type) {
|
||||||
|
Type packagedType = (Type) el;
|
||||||
|
|
||||||
|
Type includingType = packagedType;
|
||||||
|
|
||||||
|
if (packagedType instanceof Association) {
|
||||||
|
Association as = (Association) packagedType;
|
||||||
|
includingType = as.getEndTypes().get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
String xmi_id = this.viewXmiDict.get(includingType);
|
||||||
|
if (xmi_id == null || (! this.xmiModelDict.containsKey(xmi_id)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Type modelType = (Type) this.xmiModelDict.get(xmi_id);
|
||||||
|
Package parentPackage = modelType.getPackage();
|
||||||
|
String modelPackageXmiId= this.modelXmiDict.get(parentPackage);
|
||||||
|
if (modelPackageXmiId == null)
|
||||||
|
continue;
|
||||||
|
Package newViewPackage = (Package) this.xmiViewDict.get(modelPackageXmiId);
|
||||||
|
if (newViewPackage == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
packagedType.setPackage(newViewPackage);
|
||||||
|
|
||||||
|
} else if (el instanceof ParameterableElement) {
|
||||||
|
ParameterableElement parEl = (ParameterableElement) el;
|
||||||
|
String xmi_id = this.viewXmiDict.get(el);
|
||||||
|
ParameterableElement modelParEl = (ParameterableElement) this.xmiModelDict.get(xmi_id);
|
||||||
|
Realization r;
|
||||||
|
TemplateParameter parentParEl = modelParEl.getOwningTemplateParameter();
|
||||||
|
String modelParElXmiId=this.modelXmiDict.get(parentParEl);
|
||||||
|
if (modelParElXmiId == null)
|
||||||
|
continue;
|
||||||
|
TemplateParameter newViewParEl = (TemplateParameter) this.xmiViewDict.get(modelParElXmiId);
|
||||||
|
if (newViewParEl == null)
|
||||||
|
continue;
|
||||||
|
parEl.setOwningTemplateParameter(newViewParEl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewPackage.destroy();
|
||||||
|
|
||||||
|
/*
|
||||||
|
// synchronize by all child classes
|
||||||
|
try{
|
||||||
|
List<Element> elementCopy = new Vector<Element>();
|
||||||
|
elementCopy.addAll(this.viewModel.getOwnedElements());
|
||||||
|
for (Element child : elementCopy) {
|
||||||
|
if (child instanceof Class)
|
||||||
|
synchronizeClass((Class)child);
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// save model
|
||||||
|
this.viewResource[0].setURI(URI.createFileURI(project.getLocation().append(GlobalConstants.getPyUmlDir()).append(project.getName()+".uml").toOSString()));
|
||||||
|
try {
|
||||||
|
this.viewResource[0].save(null);
|
||||||
|
}catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
//return saveModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initializes the Model of the view and the main model
|
||||||
|
*/
|
||||||
|
private void initModels() {
|
||||||
|
// save all open editors
|
||||||
|
IWorkbenchPage page =
|
||||||
|
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
|
||||||
|
page.saveAllEditors(false);
|
||||||
|
|
||||||
|
// initialize XMI dictionaries as empty -> they are filled, if a
|
||||||
|
// model already exists
|
||||||
|
this.modelXmiDict = new HashMap<EObject, String>();
|
||||||
|
this.xmiModelDict = new HashMap<String, EObject>();
|
||||||
|
this.viewXmiDict = new HashMap<EObject, String>();
|
||||||
|
this.xmiViewDict = new HashMap<String, EObject>();
|
||||||
|
|
||||||
|
// load view and model
|
||||||
|
// this.model =
|
||||||
|
this.model= initModel(this.pathToModel, this.xmiModelDict, this.modelXmiDict, null);
|
||||||
|
if (this.model == null)
|
||||||
|
return;
|
||||||
|
this.viewModel = initModel(this.pathToView, this.xmiViewDict, this.viewXmiDict, this.viewResource);
|
||||||
|
if (this.viewModel == null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* loads a .uml model (main model or view)
|
||||||
|
* and fills the given dictionaries
|
||||||
|
* @param pathToModel
|
||||||
|
* @param xmiModelDict
|
||||||
|
* @param modelXmiDict
|
||||||
|
* @param modelResource
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Model initModel(String pathToModel, Map<String, EObject> xmiModelDict,
|
||||||
|
Map<EObject, String> modelXmiDict, Resource[] modelResource) {
|
||||||
|
|
||||||
|
// look for model file
|
||||||
|
Model model;
|
||||||
|
Resource resource;
|
||||||
|
File modelFile = new File(pathToModel);
|
||||||
|
if (! modelFile.exists()) {
|
||||||
|
MessageDialog.openError(null, "Error synchronizing Model by View",
|
||||||
|
"Model can not be found: "+pathToModel);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// read Model
|
||||||
|
EObject diagramRoot = UMLToolsHelperMethods.loadUMLDiagram(pathToModel);
|
||||||
|
model = (Model) diagramRoot;
|
||||||
|
resource = model.eResource();
|
||||||
|
|
||||||
|
// get model -> xmi-id dictionary
|
||||||
|
UMLResource r = (UMLResource) resource;
|
||||||
|
modelXmiDict.putAll(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);
|
||||||
|
}
|
||||||
|
if (modelResource != null)
|
||||||
|
modelResource[0] = resource;
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronizes a model class by a view class
|
||||||
|
* @param viewClass
|
||||||
|
*/
|
||||||
|
private void synchronizeClass(Class viewClass) {
|
||||||
|
String classXmiId = this.viewXmiDict.get(viewClass);
|
||||||
|
if (! xmiModelDict.containsKey(classXmiId)) {
|
||||||
|
MessageDialog.openWarning(null, "Error saving View",
|
||||||
|
"You created a new class \""+ viewClass.getName() +
|
||||||
|
"\" in the view.\n" +
|
||||||
|
"This is not supported, because it is not " +
|
||||||
|
"known \nwhere to put the class in the original " +
|
||||||
|
"model.\n" +
|
||||||
|
"The inserted class will be ignored.");
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Class modelClass = (Class) xmiModelDict.get(classXmiId);
|
||||||
|
Package parentPackage = (Package) modelClass.getOwner();
|
||||||
|
|
||||||
|
// destroy all generalizations and associations in model,
|
||||||
|
// if both ends are present in view and association is no more
|
||||||
|
// present in view
|
||||||
|
|
||||||
|
for (Relationship rel : modelClass.getRelationships()) {
|
||||||
|
if (rel instanceof Association) {
|
||||||
|
String modelRelationXmiID = this.modelXmiDict.get(rel);
|
||||||
|
if (modelRelationXmiID != null && ! this.xmiViewDict.containsKey(modelRelationXmiID)) {
|
||||||
|
rel.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now, copy all changes from
|
||||||
|
// View to Model.
|
||||||
|
// Also, we have to make sure to delete Attributes/methods in
|
||||||
|
// the model if they were deleted in the code.
|
||||||
|
|
||||||
|
List<Relationship> relList = new Vector<Relationship>();
|
||||||
|
relList.addAll(viewClass.getRelationships());
|
||||||
|
System.out.println(viewClass.getRelationships());
|
||||||
|
System.out.println(viewClass.getSourceDirectedRelationships());
|
||||||
|
|
||||||
|
for (Relationship rel : relList) {
|
||||||
|
if (rel instanceof Association) {
|
||||||
|
Association assoc = (Association) rel;
|
||||||
|
|
||||||
|
EList<Element> elList = rel.getRelatedElements();
|
||||||
|
|
||||||
|
Type connectedElement = (Type) elList.get(0);
|
||||||
|
|
||||||
|
Property end1 = (Property) rel.getOwnedElements().get(0);
|
||||||
|
Property end2 = (Property) (rel.getOwnedElements().size() > 1 ? rel.getOwnedElements().get(1) : end1);
|
||||||
|
|
||||||
|
Type secondElement = (Type) connectedElement;
|
||||||
|
if (elList.size() > 1) {
|
||||||
|
secondElement = (Type) elList.get(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if source (first) element is not current class,
|
||||||
|
// switch first and second element
|
||||||
|
// to be sure element to be connected by this class is second.
|
||||||
|
if (! (connectedElement == viewClass)) {
|
||||||
|
Type tmpElement = secondElement;
|
||||||
|
secondElement = connectedElement;
|
||||||
|
connectedElement = tmpElement;
|
||||||
|
|
||||||
|
Property tmpProp = end1;
|
||||||
|
end1=end2;
|
||||||
|
end2=tmpProp;
|
||||||
|
}
|
||||||
|
|
||||||
|
String secondElXmiID = this.viewXmiDict.get(secondElement);
|
||||||
|
// continue if connected element is not present in model
|
||||||
|
// -> this relationship can not be handled!
|
||||||
|
if (! this.xmiModelDict.containsKey(secondElXmiID)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type connectedElementInModel = (Type) this.xmiModelDict.get(secondElXmiID);
|
||||||
|
|
||||||
|
if (rel.getOwnedElements().size() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get old association, if possible
|
||||||
|
Relationship modelRelationship = null;
|
||||||
|
if (this.xmiModelDict.containsKey(this.viewXmiDict.get(rel))) {
|
||||||
|
modelRelationship = (Relationship) this.xmiModelDict.get(this.viewXmiDict.get(rel));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
boolean changed = true;
|
||||||
|
if (modelRelationship != null) {
|
||||||
|
changed = false;
|
||||||
|
Property modelEnd2 = (Property) modelRelationship.getOwnedElements().get(0);
|
||||||
|
Property modelEnd1 = (Property) (modelRelationship.getOwnedElements().size() > 1 ? modelRelationship.getOwnedElements().get(1) : modelEnd2);
|
||||||
|
|
||||||
|
// update classes that take part in this association
|
||||||
|
modelEnd1.setType(modelClass);
|
||||||
|
modelEnd2.setType(connectedElementInModel);
|
||||||
|
|
||||||
|
// look if anything changed in association; if yes, move view association
|
||||||
|
// to model
|
||||||
|
if ( modelEnd1.isNavigable() != end1.isNavigable()
|
||||||
|
|| modelEnd1.isNavigable() != end1.isNavigable()
|
||||||
|
|| modelEnd2.isNavigable() != end2.isNavigable()
|
||||||
|
|| ! modelEnd1.getAggregation().equals(end1.getAggregation())
|
||||||
|
|| ! modelEnd2.getAggregation().equals(end2.getAggregation())
|
||||||
|
|| ! modelEnd1.getName().equals(end1.getName())
|
||||||
|
|| ! modelEnd2.getName().equals(end2.getName())
|
||||||
|
|| modelEnd1.getLower() != end1.getLower()
|
||||||
|
|| modelEnd2.getLower() != end2.getLower()
|
||||||
|
|| modelEnd1.getUpper() != end1.getUpper()
|
||||||
|
|| modelEnd2.getUpper() != end2.getUpper()
|
||||||
|
|| ! this.modelXmiDict.get(modelEnd1.getType()).equals(this.viewXmiDict.get(end1.getType()))
|
||||||
|
|| ! this.modelXmiDict.get(modelEnd2.getType()).equals(this.viewXmiDict.get(end2.getType())))
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
assoc.setPackage(parentPackage);
|
||||||
|
|
||||||
|
end1.setType(modelClass);
|
||||||
|
end2.setType(connectedElementInModel);
|
||||||
|
//modelClass.createAssociation(end1.isNavigable(), end1.getAggregation(), end1.getName(), end1.getLower(), end1.getUpper(), connectedElementInModel, end2.isNavigable(), end2.getAggregation(), end2.getName(), end2.getLower(), end2.getUpper());
|
||||||
|
|
||||||
|
if (modelRelationship != null)
|
||||||
|
modelRelationship.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Directed Associations are hidden in attributes
|
||||||
|
propertyLoop:
|
||||||
|
for (Property att : viewClass.getAllAttributes()) {
|
||||||
|
if (att.getAssociation() != null) {
|
||||||
|
Association as = att.getAssociation();
|
||||||
|
String asXmiId = this.viewXmiDict.get(as);
|
||||||
|
Type modelType = null;
|
||||||
|
String typeXmiId = this.viewXmiDict.get(att.getType());
|
||||||
|
if (this.xmiModelDict.containsKey(typeXmiId))
|
||||||
|
modelType = (Type) this.xmiModelDict.get(typeXmiId);
|
||||||
|
else
|
||||||
|
continue propertyLoop;
|
||||||
|
|
||||||
|
Property modelProp = null;
|
||||||
|
|
||||||
|
|
||||||
|
// try to find model property -> property with same association
|
||||||
|
for (Property prop : modelClass.getAllAttributes()) {
|
||||||
|
if (prop.getAssociation()!= null &&
|
||||||
|
this.xmiModelDict.get(prop.getAssociation()).equals(asXmiId))
|
||||||
|
modelProp = prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modelProp != null){
|
||||||
|
// Property is present, check if everything is correct;
|
||||||
|
modelProp = (Property) this.xmiModelDict.get(asXmiId);
|
||||||
|
modelProp.setName(att.getName());
|
||||||
|
} else {
|
||||||
|
//create this Property
|
||||||
|
modelProp = modelClass.createOwnedAttribute(att.getName(), modelType);
|
||||||
|
}
|
||||||
|
|
||||||
|
as.setPackage(parentPackage);
|
||||||
|
//for (Element e : as.getOwnedElements();
|
||||||
|
modelProp.setOwningAssociation(as);
|
||||||
|
modelProp.setType(modelType);
|
||||||
|
modelProp.setLower(att.getLower());
|
||||||
|
modelProp.setUpper(att.getUpper());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// delete all generalizations in model not present in view
|
||||||
|
List<Generalization> tmpGens= new Vector<Generalization>();
|
||||||
|
tmpGens.addAll(modelClass.getGeneralizations());
|
||||||
|
for (Generalization general: tmpGens) {
|
||||||
|
String modelSupXmiID = this.modelXmiDict.get(general.getGeneral());
|
||||||
|
Classifier viewSuperClass = (Classifier) this.xmiViewDict.get(modelSupXmiID);
|
||||||
|
|
||||||
|
boolean generalIsPresentInView = false;
|
||||||
|
for (Generalization viewSuper : viewClass.getGeneralizations()) {
|
||||||
|
if (viewSuper.getGeneral() == viewSuperClass) {
|
||||||
|
generalIsPresentInView = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! generalIsPresentInView) {
|
||||||
|
general.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy all generalizations of classes
|
||||||
|
for (Generalization general: viewClass.getGeneralizations()) {
|
||||||
|
String superClassXmiID = viewXmiDict.get(general.getGeneral());
|
||||||
|
Classifier modelSuperClass = (Classifier) xmiModelDict.get(superClassXmiID);
|
||||||
|
|
||||||
|
boolean generalIsPresentInModel = false;
|
||||||
|
for (Generalization modelSuper : modelClass.getGeneralizations()) {
|
||||||
|
if (modelSuper.getGeneral() == modelSuperClass) {
|
||||||
|
generalIsPresentInModel = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! xmiViewDict.containsKey(superClassXmiID))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (! generalIsPresentInModel) {
|
||||||
|
modelClass.createGeneralization(modelSuperClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the edited model .uml file
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean saveModel() {
|
||||||
|
/*try {
|
||||||
|
this.modelResource[0].save(null);
|
||||||
|
EclipseHelperMethods.updateFile(pathToModel, project);
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
MessageDialog.openError(null, "Error saving model",
|
||||||
|
"The model cannot be saved. Reason:\n" + e.getMessage());
|
||||||
|
return false;
|
||||||
|
}*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActivePart(IAction action, IWorkbenchPart targetPart) {
|
||||||
|
// Auto-generated method stub
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run(IAction action) {
|
||||||
|
this.synchronizeGlobalModel(this.pathToView);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void selectionChanged(IAction action, ISelection selection) {
|
||||||
|
// save selected uml view
|
||||||
|
if (selection instanceof TreeSelection) {
|
||||||
|
TreeSelection ts = (TreeSelection) selection;
|
||||||
|
if (ts.getFirstElement() instanceof org.eclipse.core.internal.resources.File) {
|
||||||
|
org.eclipse.core.internal.resources.File selectedFile = (org.eclipse.core.internal.resources.File) ts.getFirstElement();
|
||||||
|
this.pathToView = selectedFile.getLocation().toOSString();
|
||||||
|
this.project = selectedFile.getProject();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
384
pyUml/src/pyUML/views/SynchronizeViews.java
Executable file
384
pyUml/src/pyUML/views/SynchronizeViews.java
Executable file
@ -0,0 +1,384 @@
|
|||||||
|
package pyUML.views;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.emf.common.util.EList;
|
||||||
|
import org.eclipse.emf.ecore.EObject;
|
||||||
|
import org.eclipse.emf.ecore.resource.Resource;
|
||||||
|
import org.eclipse.jface.action.IAction;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.eclipse.jface.viewers.ISelection;
|
||||||
|
import org.eclipse.jface.viewers.TreeSelection;
|
||||||
|
import org.eclipse.ui.IObjectActionDelegate;
|
||||||
|
import org.eclipse.ui.IWorkbenchPage;
|
||||||
|
import org.eclipse.ui.IWorkbenchPart;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
import org.eclipse.uml2.uml.Association;
|
||||||
|
import org.eclipse.uml2.uml.Class;
|
||||||
|
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.ParameterableElement;
|
||||||
|
import org.eclipse.uml2.uml.Property;
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is an action class where the global UML model
|
||||||
|
* is to be updated by a view.
|
||||||
|
* Classes cannot be copied, because this would destroy all
|
||||||
|
* model relationships of the class.
|
||||||
|
* New classes in a view are ignored, because it is not known where
|
||||||
|
* they are to be inserted in the model.
|
||||||
|
*
|
||||||
|
* At the moment, class attributes and methods are *not* synchronized
|
||||||
|
* with the mail model.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SynchronizeViews implements IObjectActionDelegate{
|
||||||
|
private String pathToModel;;
|
||||||
|
private String pathToView;
|
||||||
|
//private Model model;
|
||||||
|
private Model viewModel;
|
||||||
|
private Resource[] modelResource = {null};
|
||||||
|
private Map<String, EObject> xmiModelDict;
|
||||||
|
private Map<EObject, String> modelXmiDict;
|
||||||
|
private Map<String, EObject> xmiViewDict;
|
||||||
|
private Map<EObject, String> viewXmiDict;
|
||||||
|
private IProject project;
|
||||||
|
|
||||||
|
|
||||||
|
public static void synchronizeGlobalModel(String pathToView, IProject project) {
|
||||||
|
SynchronizeViews sv = new SynchronizeViews();
|
||||||
|
sv.project = project;
|
||||||
|
sv.synchronizeGlobalModel(pathToView);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the global model by changes made by the given view.
|
||||||
|
* Class deletions are removed from the view, not from the model.
|
||||||
|
*
|
||||||
|
* New classes/packages are ignored, because it is not known
|
||||||
|
* where they should be inserted.
|
||||||
|
*
|
||||||
|
* Other changes are updated in the global model.
|
||||||
|
*
|
||||||
|
* @param pathToModel
|
||||||
|
* @param pathToView
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean synchronizeGlobalModel(String pathToView) {
|
||||||
|
String pathToModel = this.project.getLocation()
|
||||||
|
.append(GlobalConstants.getPyUmlDir())
|
||||||
|
.append(this.project.getName()+".uml").toOSString();
|
||||||
|
|
||||||
|
//init models
|
||||||
|
this.pathToModel = pathToModel;
|
||||||
|
this.pathToView = pathToView;
|
||||||
|
initModels();
|
||||||
|
|
||||||
|
// synchronize by all child classes
|
||||||
|
try{
|
||||||
|
List<Element> elementCopy = new Vector<Element>();
|
||||||
|
elementCopy.addAll(this.viewModel.getOwnedElements());
|
||||||
|
for (Element child : elementCopy) {
|
||||||
|
if (child instanceof Class)
|
||||||
|
synchronizeClass((Class)child);
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
// save model
|
||||||
|
return saveModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initializes the Model of the view and the main model
|
||||||
|
*/
|
||||||
|
private void initModels() {
|
||||||
|
// save all open editors
|
||||||
|
IWorkbenchPage page =
|
||||||
|
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
|
||||||
|
page.saveAllEditors(false);
|
||||||
|
|
||||||
|
// initialize XMI dictionaries as empty -> they are filled, if a
|
||||||
|
// model already exists
|
||||||
|
this.modelXmiDict = new HashMap<EObject, String>();
|
||||||
|
this.xmiModelDict = new HashMap<String, EObject>();
|
||||||
|
this.viewXmiDict = new HashMap<EObject, String>();
|
||||||
|
this.xmiViewDict = new HashMap<String, EObject>();
|
||||||
|
|
||||||
|
// load view and model
|
||||||
|
// this.model =
|
||||||
|
initModel(this.pathToModel, this.xmiModelDict, this.modelXmiDict, this.modelResource);
|
||||||
|
this.viewModel = initModel(this.pathToView, this.xmiViewDict, this.viewXmiDict, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* loads a .uml model (main model or view)
|
||||||
|
* and fills the given dictionaries
|
||||||
|
* @param pathToModel
|
||||||
|
* @param xmiModelDict
|
||||||
|
* @param modelXmiDict
|
||||||
|
* @param modelResource
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Model initModel(String pathToModel, Map<String, EObject> xmiModelDict,
|
||||||
|
Map<EObject, String> modelXmiDict, Resource[] modelResource) {
|
||||||
|
|
||||||
|
// look for model file
|
||||||
|
Model model;
|
||||||
|
Resource resource;
|
||||||
|
File modelFile = new File(pathToModel);
|
||||||
|
if (! modelFile.exists()) {
|
||||||
|
MessageDialog.openError(null, "Error synchronizing Model by View",
|
||||||
|
"Model can not be found: "+pathToModel);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// read Model
|
||||||
|
EObject diagramRoot = UMLToolsHelperMethods.loadUMLDiagram(pathToModel);
|
||||||
|
model = (Model) diagramRoot;
|
||||||
|
resource = model.eResource();
|
||||||
|
|
||||||
|
// get model -> xmi-id dictionary
|
||||||
|
UMLResource r = (UMLResource) resource;
|
||||||
|
modelXmiDict.putAll(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);
|
||||||
|
}
|
||||||
|
if (modelResource != null)
|
||||||
|
modelResource[0] = resource;
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronizes a model class by a view class
|
||||||
|
* @param viewClass
|
||||||
|
*/
|
||||||
|
private void synchronizeClass(Class viewClass) {
|
||||||
|
String classXmiId = this.viewXmiDict.get(viewClass);
|
||||||
|
if (! xmiModelDict.containsKey(classXmiId)) {
|
||||||
|
MessageDialog.openWarning(null, "Error saving View",
|
||||||
|
"You created a new class \""+ viewClass.getName() +
|
||||||
|
"\" in the view.\n" +
|
||||||
|
"This is not supported, because it is not " +
|
||||||
|
"known \nwhere to put the class in the original " +
|
||||||
|
"model.\n" +
|
||||||
|
"The inserted class will be ignored.");
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Class modelClass = (Class) xmiModelDict.get(classXmiId);
|
||||||
|
Package parentPackage = (Package) modelClass.getOwner();
|
||||||
|
|
||||||
|
// destroy all generalizations and associations in model,
|
||||||
|
// if both ends are present in view and association is no more
|
||||||
|
// present in view
|
||||||
|
|
||||||
|
for (Relationship rel : modelClass.getRelationships()) {
|
||||||
|
if (rel instanceof Association) {
|
||||||
|
String modelRelationXmiID = this.modelXmiDict.get(rel);
|
||||||
|
if (modelRelationXmiID != null && ! this.xmiViewDict.containsKey(modelRelationXmiID)) {
|
||||||
|
rel.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now, copy all associations / attributes/methods from
|
||||||
|
// View to Model.
|
||||||
|
// We cannot just copy the whole class, because this would
|
||||||
|
// destroy the associations/generalizations etc.
|
||||||
|
// Also, we have to make sure to delete Attributes/methods in
|
||||||
|
// the model if they were deleted in the code.
|
||||||
|
|
||||||
|
for (Relationship rel : viewClass.getRelationships()) {
|
||||||
|
if (rel instanceof Association) {
|
||||||
|
Association assoc = (Association) rel;
|
||||||
|
|
||||||
|
EList<Element> elList = rel.getRelatedElements();
|
||||||
|
|
||||||
|
Type connectedElement = (Type) elList.get(0);
|
||||||
|
|
||||||
|
Property end1 = (Property) rel.getOwnedElements().get(0);
|
||||||
|
Property end2 = (Property) (rel.getOwnedElements().size() > 1 ? rel.getOwnedElements().get(1) : end1);
|
||||||
|
|
||||||
|
Type secondElement = (Type) connectedElement;
|
||||||
|
if (elList.size() > 1) {
|
||||||
|
secondElement = (Type) elList.get(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if source (first) element is not current class,
|
||||||
|
// switch first and second element
|
||||||
|
// to be sure element to be connected by this class is second.
|
||||||
|
if (! (connectedElement == viewClass)) {
|
||||||
|
Type tmpElement = secondElement;
|
||||||
|
secondElement = connectedElement;
|
||||||
|
connectedElement = tmpElement;
|
||||||
|
|
||||||
|
Property tmpProp = end1;
|
||||||
|
end1=end2;
|
||||||
|
end2=tmpProp;
|
||||||
|
}
|
||||||
|
|
||||||
|
String secondElXmiID = this.viewXmiDict.get(secondElement);
|
||||||
|
// continue if connected element is not present in model
|
||||||
|
// -> this relationship can not be handled!
|
||||||
|
if (! this.xmiModelDict.containsKey(secondElXmiID)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type connectedElementInModel = (Type) this.xmiModelDict.get(secondElXmiID);
|
||||||
|
|
||||||
|
if (rel.getOwnedElements().size() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get old association, if possible
|
||||||
|
Relationship modelRelationship = null;
|
||||||
|
if (this.xmiModelDict.containsKey(this.viewXmiDict.get(rel))) {
|
||||||
|
modelRelationship = (Relationship) this.xmiModelDict.get(this.viewXmiDict.get(rel));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
boolean changed = true;
|
||||||
|
if (modelRelationship != null) {
|
||||||
|
changed = false;
|
||||||
|
Property modelEnd2 = (Property) modelRelationship.getOwnedElements().get(0);
|
||||||
|
Property modelEnd1 = (Property) (modelRelationship.getOwnedElements().size() > 1 ? modelRelationship.getOwnedElements().get(1) : modelEnd2);
|
||||||
|
|
||||||
|
// update classes that take part in this association
|
||||||
|
modelEnd1.setType(modelClass);
|
||||||
|
modelEnd2.setType(connectedElementInModel);
|
||||||
|
|
||||||
|
// look if anything changed in association; if yes, move view association
|
||||||
|
// to model
|
||||||
|
if ( modelEnd1.isNavigable() != end1.isNavigable()
|
||||||
|
|| modelEnd1.isNavigable() != end1.isNavigable()
|
||||||
|
|| modelEnd2.isNavigable() != end2.isNavigable()
|
||||||
|
|| ! modelEnd1.getAggregation().equals(end1.getAggregation())
|
||||||
|
|| ! modelEnd2.getAggregation().equals(end2.getAggregation())
|
||||||
|
|| ! modelEnd1.getName().equals(end1.getName())
|
||||||
|
|| ! modelEnd2.getName().equals(end2.getName())
|
||||||
|
|| modelEnd1.getLower() != end1.getLower()
|
||||||
|
|| modelEnd2.getLower() != end2.getLower()
|
||||||
|
|| modelEnd1.getUpper() != end1.getUpper()
|
||||||
|
|| modelEnd2.getUpper() != end2.getUpper()
|
||||||
|
|| ! this.modelXmiDict.get(modelEnd1.getType()).equals(this.viewXmiDict.get(end1.getType()))
|
||||||
|
|| ! this.modelXmiDict.get(modelEnd2.getType()).equals(this.viewXmiDict.get(end2.getType())))
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
assoc.setPackage(parentPackage);
|
||||||
|
|
||||||
|
end1.setType(modelClass);
|
||||||
|
end2.setType(connectedElementInModel);
|
||||||
|
//modelClass.createAssociation(end1.isNavigable(), end1.getAggregation(), end1.getName(), end1.getLower(), end1.getUpper(), connectedElementInModel, end2.isNavigable(), end2.getAggregation(), end2.getName(), end2.getLower(), end2.getUpper());
|
||||||
|
|
||||||
|
if (modelRelationship != null)
|
||||||
|
modelRelationship.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete all generalizations in model not present in view
|
||||||
|
List<Generalization> tmpGens= new Vector<Generalization>();
|
||||||
|
tmpGens.addAll(modelClass.getGeneralizations());
|
||||||
|
for (Generalization general: tmpGens) {
|
||||||
|
String modelSupXmiID = this.modelXmiDict.get(general.getGeneral());
|
||||||
|
Classifier viewSuperClass = (Classifier) this.xmiViewDict.get(modelSupXmiID);
|
||||||
|
|
||||||
|
boolean generalIsPresentInView = false;
|
||||||
|
for (Generalization viewSuper : viewClass.getGeneralizations()) {
|
||||||
|
if (viewSuper.getGeneral() == viewSuperClass) {
|
||||||
|
generalIsPresentInView = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! generalIsPresentInView) {
|
||||||
|
general.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy all generalizations of classes
|
||||||
|
for (Generalization general: viewClass.getGeneralizations()) {
|
||||||
|
String superClassXmiID = viewXmiDict.get(general.getGeneral());
|
||||||
|
Classifier modelSuperClass = (Classifier) xmiModelDict.get(superClassXmiID);
|
||||||
|
|
||||||
|
boolean generalIsPresentInModel = false;
|
||||||
|
for (Generalization modelSuper : modelClass.getGeneralizations()) {
|
||||||
|
if (modelSuper.getGeneral() == modelSuperClass) {
|
||||||
|
generalIsPresentInModel = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! xmiViewDict.containsKey(superClassXmiID))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (! generalIsPresentInModel) {
|
||||||
|
modelClass.createGeneralization(modelSuperClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the edited model .uml file
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean saveModel() {
|
||||||
|
try {
|
||||||
|
this.modelResource[0].save(null);
|
||||||
|
EclipseHelperMethods.updateFile(pathToModel, project);
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
MessageDialog.openError(null, "Error saving model",
|
||||||
|
"The model cannot be saved. Reason:\n" + e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActivePart(IAction action, IWorkbenchPart targetPart) {
|
||||||
|
// Auto-generated method stub
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run(IAction action) {
|
||||||
|
this.synchronizeGlobalModel(this.pathToView);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void selectionChanged(IAction action, ISelection selection) {
|
||||||
|
// save selected uml view
|
||||||
|
if (selection instanceof TreeSelection) {
|
||||||
|
TreeSelection ts = (TreeSelection) selection;
|
||||||
|
if (ts.getFirstElement() instanceof org.eclipse.core.internal.resources.File) {
|
||||||
|
org.eclipse.core.internal.resources.File selectedFile = (org.eclipse.core.internal.resources.File) ts.getFirstElement();
|
||||||
|
this.pathToView = selectedFile.getLocation().toOSString();
|
||||||
|
this.project = selectedFile.getProject();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
133
pyUml/trash/CodeFromModelCreator.java
Executable file
133
pyUml/trash/CodeFromModelCreator.java
Executable file
@ -0,0 +1,133 @@
|
|||||||
|
package parser;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.emf.ecore.EObject;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.eclipse.uml2.uml.Class;
|
||||||
|
import org.eclipse.uml2.uml.Element;
|
||||||
|
import org.eclipse.uml2.uml.Package;
|
||||||
|
|
||||||
|
import parser.pythonTree.PythonTreeClass;
|
||||||
|
import parser.pythonTree.PythonTreeNode;
|
||||||
|
import parser.pythonTree.PythonTreePackage;
|
||||||
|
|
||||||
|
public class CodeFromModelCreator {
|
||||||
|
/**
|
||||||
|
* synchronizes the code with the model.
|
||||||
|
* if any python file is changed, false is returned
|
||||||
|
* to rebuild the tree and start from beginning
|
||||||
|
*
|
||||||
|
* @param pythonNode
|
||||||
|
* @param umlElement
|
||||||
|
* @param xmiModelDict
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean synchronizeCodeFromModel(PythonTreeNode pythonNode, Element umlElement, Map<EObject, String> xmiModelDict) {
|
||||||
|
for (Element modelElement:umlElement.getOwnedElements()) {
|
||||||
|
if (modelElement instanceof Package) {
|
||||||
|
Package modelPack = (Package) modelElement;
|
||||||
|
PythonTreePackage pyPack = (PythonTreePackage) pythonNode;
|
||||||
|
if (xmiModelDict.containsKey(modelPack)) {
|
||||||
|
String xmi_id = xmiModelDict.get(modelPack);
|
||||||
|
if (pythonNode.getRoot().getXmiPackDict().containsKey(xmi_id)) {
|
||||||
|
PythonTreeNode node = pythonNode.getRoot().getXmiPackDict().get(xmi_id);
|
||||||
|
if (pyPack.getChildPackages().contains(node)) {
|
||||||
|
boolean startNew = synchronizeCodeFromModel(node, modelElement, xmiModelDict);
|
||||||
|
if (startNew) return true;
|
||||||
|
PythonTreePackage subPack = (PythonTreePackage) node;
|
||||||
|
// TODO: umhaengen des Pakets an die richtige Stelle
|
||||||
|
// im FS und im Python Tree
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// look for python node with same name
|
||||||
|
boolean packageFound = false;
|
||||||
|
for (PythonTreePackage pySubPack : pyPack.getChildPackages()) {
|
||||||
|
if (pySubPack.getName().equals(modelPack.getName())){
|
||||||
|
// write xmi_id to code (only needed once)
|
||||||
|
pySubPack.writeXmiID(xmi_id);
|
||||||
|
packageFound=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if this package was not found, create it (recursively)!
|
||||||
|
if (! packageFound) {
|
||||||
|
// create package
|
||||||
|
IPath newPackPath = pyPack.getPackageDir().append(modelPack.getName());
|
||||||
|
File newPackDir = new File(newPackPath.toOSString());
|
||||||
|
newPackDir.mkdir();
|
||||||
|
File initPy = new File(newPackPath.append("__init__.py").toOSString());
|
||||||
|
try{
|
||||||
|
initPy.createNewFile();
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
MessageDialog.openError(null, "IOException", "Error writing to file "+ initPy.getPath());
|
||||||
|
}
|
||||||
|
PythonTreePackage newPyPack = new PythonTreePackage(newPackPath, pyPack);
|
||||||
|
newPyPack.writeXmiID(xmi_id);
|
||||||
|
boolean startNew = synchronizeCodeFromModel(newPyPack, modelPack, xmiModelDict);
|
||||||
|
if (startNew) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MessageDialog.openError(null,"Error synchronizing","There was an inconsistency in the Python Package Tree");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (modelElement instanceof Class) {
|
||||||
|
Class modelClass = (Class) modelElement;
|
||||||
|
PythonTreePackage pyPack = (PythonTreePackage) pythonNode;
|
||||||
|
if (xmiModelDict.containsKey(modelClass)) {
|
||||||
|
String xmi_id = xmiModelDict.get(modelClass);
|
||||||
|
if (pythonNode.getRoot().getXmiClassDict().containsKey(xmi_id)) {
|
||||||
|
PythonTreeNode node = pythonNode.getRoot().getXmiClassDict().get(xmi_id);
|
||||||
|
if (pyPack.getChildClasses().contains(node)) {
|
||||||
|
boolean startNew = synchronizeCodeFromModel(node, modelElement, xmiModelDict);
|
||||||
|
if (startNew) return true;
|
||||||
|
PythonTreeClass subPack = (PythonTreeClass) node;
|
||||||
|
// TODO: umhaengen der Klasse an die richtige Stelle
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// look for python child class with same name
|
||||||
|
// and write the right xmi_id
|
||||||
|
boolean classFound = false;
|
||||||
|
for (PythonTreeClass pySubClass : pyPack.getChildClasses()) {
|
||||||
|
if (pySubClass.getName().equals(modelClass.getName())){
|
||||||
|
// write xmi_id to code (only needed once)
|
||||||
|
pySubClass.writeXmiID(xmi_id);
|
||||||
|
classFound=true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if this class was not found, create it (recursively)!
|
||||||
|
/* if (! classFound) {
|
||||||
|
// create package
|
||||||
|
IPath newPackPath = treePack.getPackageDir().append(modelPack.getName());
|
||||||
|
File newPackDir = new File(newPackPath.toOSString());
|
||||||
|
newPackDir.mkdir();
|
||||||
|
File initPy = new File(newPackPath.append("__init__.py").toOSString());
|
||||||
|
try{
|
||||||
|
initPy.createNewFile();
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
MessageDialog.openError(null, "IOException", "Error writing to file "+ initPy.getPath());
|
||||||
|
}
|
||||||
|
PythonTreePackage newPyPack = new PythonTreePackage(newPackPath, treePack);
|
||||||
|
newPyPack.writeXmiID(xmi_id);
|
||||||
|
generateCodeFromModel(newPyPack, modelPack, xmiModelDict);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
MessageDialog.openError(null,"Error synchronizing","There was an inconsistency in the Python Package Tree");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
211
pyUml/trash/Py2UMLCreator.java
Executable file
211
pyUml/trash/Py2UMLCreator.java
Executable file
@ -0,0 +1,211 @@
|
|||||||
|
package synchronize;
|
||||||
|
|
||||||
|
import java.util.Dictionary;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import org.eclipse.emf.common.util.BasicEList;
|
||||||
|
import org.eclipse.emf.common.util.EList;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
|
import org.eclipse.uml2.uml.Class;
|
||||||
|
import org.eclipse.uml2.uml.Generalization;
|
||||||
|
import org.eclipse.uml2.uml.Operation;
|
||||||
|
import org.eclipse.uml2.uml.Package;
|
||||||
|
import org.eclipse.uml2.uml.Property;
|
||||||
|
import org.eclipse.uml2.uml.Type;
|
||||||
|
import org.python.pydev.parser.jython.SimpleNode;
|
||||||
|
import org.python.pydev.parser.jython.ast.Assign;
|
||||||
|
import org.python.pydev.parser.jython.ast.Attribute;
|
||||||
|
import org.python.pydev.parser.jython.ast.Call;
|
||||||
|
import org.python.pydev.parser.jython.ast.ClassDef;
|
||||||
|
import org.python.pydev.parser.jython.ast.FunctionDef;
|
||||||
|
import org.python.pydev.parser.jython.ast.Import;
|
||||||
|
import org.python.pydev.parser.jython.ast.ImportFrom;
|
||||||
|
import org.python.pydev.parser.jython.ast.Module;
|
||||||
|
import org.python.pydev.parser.jython.ast.Name;
|
||||||
|
import org.python.pydev.parser.jython.ast.NameTok;
|
||||||
|
import org.python.pydev.parser.jython.ast.Num;
|
||||||
|
import org.python.pydev.parser.jython.ast.Str;
|
||||||
|
import org.python.pydev.parser.jython.ast.exprType;
|
||||||
|
import org.python.pydev.parser.jython.ast.stmtType;
|
||||||
|
|
||||||
|
import parser.ParseHelpers;
|
||||||
|
|
||||||
|
public class Py2UMLCreator {
|
||||||
|
|
||||||
|
// dictionary of all created classes for later access
|
||||||
|
private Dictionary<String, Class> classDict;
|
||||||
|
|
||||||
|
// list of generalizations to add to model
|
||||||
|
// after adding all classes
|
||||||
|
private List<Tuple<Class, String>> generalizations;
|
||||||
|
|
||||||
|
|
||||||
|
public Py2UMLCreator() {
|
||||||
|
this.classDict = new Hashtable<String, Class>();
|
||||||
|
this.generalizations = new Vector<Tuple<Class, String>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createModelFromAST(SimpleNode root, Package rootPack) {
|
||||||
|
parsePackage(root, rootPack);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parsePackage(SimpleNode node, Package pack) {
|
||||||
|
if (node instanceof Module) {
|
||||||
|
Module pyModule = (Module) node;
|
||||||
|
stmtType[] statements = pyModule.body;
|
||||||
|
for (int i = 0; i < statements.length; i++) {
|
||||||
|
parsePackage(statements[i], pack);
|
||||||
|
if (statements[i] instanceof ClassDef) {
|
||||||
|
ClassDef pyClass = (ClassDef) statements[i];
|
||||||
|
parseClass(pyClass, pack);
|
||||||
|
}
|
||||||
|
if (statements[i] instanceof ImportFrom) {
|
||||||
|
ImportFrom importFrom = (ImportFrom) statements[i];
|
||||||
|
//System.out.println("---import---");
|
||||||
|
//System.out.println(((NameTok)importFrom.names[0].name).id);
|
||||||
|
}
|
||||||
|
if (statements[i] instanceof Import) {
|
||||||
|
Import importFrom = (Import) statements[i];
|
||||||
|
//System.out.println("---import---");
|
||||||
|
//System.out.println(((NameTok)importFrom.names[0].name).id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add generalizations to model
|
||||||
|
*/
|
||||||
|
public void createGeneralizations() {
|
||||||
|
System.out.println("creating Gens");
|
||||||
|
System.out.println(this.generalizations);
|
||||||
|
for (Tuple<Class, String> tup : this.generalizations) {
|
||||||
|
Class subClass = tup.a;
|
||||||
|
String superClassStr = tup.b;
|
||||||
|
System.out.println("create gen for " + subClass.getName());
|
||||||
|
System.out.println(superClassStr);
|
||||||
|
if ((classDict.get(superClassStr)) == null) {
|
||||||
|
System.out.println("...failed");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Class superclass = classDict.get(superClassStr);
|
||||||
|
Generalization gen = subClass.createGeneralization(superclass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get basic class information
|
||||||
|
|
||||||
|
private void parseClass(ClassDef pyClass, Package pack) {
|
||||||
|
String className=((NameTok) pyClass.name).id;
|
||||||
|
Class cl = pack.createOwnedClass(className, false);
|
||||||
|
if (classDict.get(className) != null)
|
||||||
|
MessageDialog.openError(null, "Duplicate Class detected",
|
||||||
|
"The class '"+className+ "' exists more than 1 time!");
|
||||||
|
this.classDict.put(className, cl);
|
||||||
|
|
||||||
|
System.out.println("class "+className);
|
||||||
|
exprType[] baseClasses=pyClass.bases;
|
||||||
|
for (exprType baseClass : baseClasses) {
|
||||||
|
if (baseClass instanceof Name) {
|
||||||
|
String baseName = ((Name)baseClass).id;
|
||||||
|
System.out.println("found base class " + baseName);
|
||||||
|
// add generalization
|
||||||
|
generalizations.add(new Tuple<Class,String>(cl, baseName));
|
||||||
|
}else if (baseClass instanceof Attribute){
|
||||||
|
Attribute att = (Attribute) baseClass;
|
||||||
|
String baseName=att.attr.toString();
|
||||||
|
System.out.println("found base class " + baseName);
|
||||||
|
// add generalization
|
||||||
|
generalizations.add(new Tuple<Class,String>(cl, baseName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse class body
|
||||||
|
|
||||||
|
stmtType[] statements = pyClass.body;
|
||||||
|
parseBody: for (int i = 0; i < statements.length; i++) {
|
||||||
|
System.out.println("stmt at line " + statements[i].beginLine);
|
||||||
|
System.out.println(statements[i].getClass().getName());
|
||||||
|
|
||||||
|
// look for static attributes (=assertions inside class body)
|
||||||
|
if (statements[i] instanceof Assign) {
|
||||||
|
Assign assign = (Assign) statements[i];
|
||||||
|
exprType left = assign.targets[0];
|
||||||
|
exprType right = assign.value;
|
||||||
|
|
||||||
|
String assignTo = ((Name)left).id;
|
||||||
|
String assignVal = "";
|
||||||
|
|
||||||
|
assignVal = ParseHelpers.getStringOfExpr(right);
|
||||||
|
System.out.println("attrs:");
|
||||||
|
System.out.println(right.getClass().getName());
|
||||||
|
System.out.println(assignVal);
|
||||||
|
if (right instanceof Call) {
|
||||||
|
Call call = (Call) right;
|
||||||
|
String callName =(((Name)call.func).id);
|
||||||
|
if (callName.equals("staticmethod"))
|
||||||
|
continue parseBody;
|
||||||
|
}
|
||||||
|
Property classAttr = cl.createOwnedAttribute(assignTo, null);
|
||||||
|
classAttr.setIsStatic(true);
|
||||||
|
classAttr.setDefault(assignVal);
|
||||||
|
}
|
||||||
|
// get method definitions
|
||||||
|
if (statements[i] instanceof FunctionDef) {
|
||||||
|
FunctionDef func = (FunctionDef) statements[i];
|
||||||
|
String funcName=((NameTok)func.name).id;
|
||||||
|
exprType[] argList = func.args.args;
|
||||||
|
EList<String> paramNameList = new BasicEList<String>();
|
||||||
|
EList<Type> paramTypeList = new BasicEList<Type>();
|
||||||
|
|
||||||
|
// get arguments
|
||||||
|
for (exprType arg : argList) {
|
||||||
|
Name n = (Name) arg;
|
||||||
|
paramNameList.add(n.id);
|
||||||
|
paramTypeList.add(null);
|
||||||
|
System.out.println(n.id);
|
||||||
|
}
|
||||||
|
// create model element
|
||||||
|
Operation op = cl.createOwnedOperation(funcName, paramNameList, null);
|
||||||
|
// set static method (if so)
|
||||||
|
if (argList.length == 0 || (! ((Name) argList[0]).id.equals("self")))
|
||||||
|
op.setIsStatic(true);
|
||||||
|
|
||||||
|
// get object variables, if this is the __init__ method
|
||||||
|
if (funcName.equals("__init__")){
|
||||||
|
stmtType[] initStmts = func.body;
|
||||||
|
for (stmtType initStmt: initStmts) {
|
||||||
|
if (initStmt instanceof Assign) {
|
||||||
|
Assign assign = (Assign) initStmt;
|
||||||
|
exprType left = assign.targets[0];
|
||||||
|
exprType right = assign.value;
|
||||||
|
if (left instanceof Attribute) {
|
||||||
|
Attribute attrLeft = (Attribute) left;
|
||||||
|
String attrName = ((NameTok)attrLeft.attr).id;
|
||||||
|
String attrVal = ParseHelpers.getStringOfExpr(right);
|
||||||
|
Property att = cl.createOwnedAttribute(attrName, null);
|
||||||
|
att.setDefault(attrVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Tuple<A,B>{
|
||||||
|
A a;
|
||||||
|
B b;
|
||||||
|
public Tuple(A a, B b) {
|
||||||
|
this.a=a;
|
||||||
|
this.b=b;
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
return "(<"+this.a+">,<"+this.b+">)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
134
pyUml/trash/ViewChangeListener2.java
Executable file
134
pyUml/trash/ViewChangeListener2.java
Executable file
@ -0,0 +1,134 @@
|
|||||||
|
package pyUML.listeners;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor;
|
||||||
|
import org.eclipse.ui.IEditorPart;
|
||||||
|
import org.eclipse.ui.IPropertyListener;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
|
||||||
|
import pyUML.backend.EclipseHelperMethods;
|
||||||
|
import pyUML.backend.GlobalConstants;
|
||||||
|
import pyUML.backend.UMLToolsHelperMethods;
|
||||||
|
import pyUML.views.SynchronizeModelByView;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This listener synchronizes the global model and
|
||||||
|
* all other pyUML.views whenever a view is saved
|
||||||
|
*/
|
||||||
|
public abstract class ViewChangeListener2 implements IPropertyListener {
|
||||||
|
private IProject project;
|
||||||
|
private static boolean listenerEnabled = true;
|
||||||
|
|
||||||
|
|
||||||
|
public ViewChangeListener2(IProject project) {
|
||||||
|
super();
|
||||||
|
this.project = project;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disables all Listeners; this can be
|
||||||
|
* useful to avoid circular listener calls
|
||||||
|
* (model, view...) on a document change
|
||||||
|
* @param enabled
|
||||||
|
*/
|
||||||
|
public static void setListenersEnabled(boolean enabled) {
|
||||||
|
listenerEnabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@return true, if the View listeners are currently enabled, false otehrwise.
|
||||||
|
*/
|
||||||
|
public static boolean getListenersEnabled() {
|
||||||
|
return listenerEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void propertyChanged(Object source, int propId) {
|
||||||
|
if (! ViewChangeListener2.listenerEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (source instanceof DiagramEditor) {
|
||||||
|
// Wait until the Model is saved in file system
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
}catch (Exception e) {}
|
||||||
|
|
||||||
|
DiagramEditor umlEditor = (DiagramEditor) source;
|
||||||
|
if (! umlEditor.isDirty()) {
|
||||||
|
try {
|
||||||
|
umlEditor.getDiagram().eResource().save(null);
|
||||||
|
} catch (Exception e){e.printStackTrace();}
|
||||||
|
|
||||||
|
ViewChangeListener2.listenerEnabled = false;
|
||||||
|
ModelChangeListener.setEnabled(false);
|
||||||
|
|
||||||
|
// editor was just saved, otherwise it would be dirty.
|
||||||
|
// -> synchronize model every time the view is saved
|
||||||
|
|
||||||
|
|
||||||
|
String openEditorName=umlEditor.getTitle();
|
||||||
|
String viewPath = this.project.getLocation()
|
||||||
|
.append(GlobalConstants.getPyUmlDir())
|
||||||
|
.append(openEditorName.replace(GlobalConstants.getDiagramExtension(), "")
|
||||||
|
+ GlobalConstants.getViewUmlExtension()).toOSString();
|
||||||
|
SynchronizeModelByView.synchronizeGlobalModel(viewPath, this.project);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
IFile globalModelDiagramFile = this.project.getWorkspace()
|
||||||
|
.getRoot().getFile(this.project.getFullPath()
|
||||||
|
.append(GlobalConstants.getPyUmlDir())
|
||||||
|
.append(project.getName()+GlobalConstants
|
||||||
|
.getDiagramExtension()));
|
||||||
|
|
||||||
|
// close all sub-package pyUML.views of global model diagram
|
||||||
|
for ( org.eclipse.ui.IEditorReference editor :
|
||||||
|
EclipseHelperMethods.lookForOpenEditorByName(project.getName()+"::.*")) {
|
||||||
|
PlatformUI.getWorkbench().getActiveWorkbenchWindow()
|
||||||
|
.getActivePage().closeEditor(editor.getEditor(true), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// after creating model, be sure the diagram view is reloaded
|
||||||
|
/*boolean diagramOpened = null != EclipseHelperMethods
|
||||||
|
.lookForOpenEditorByName(project.getName()+GlobalConstants.getDiagramExtension());
|
||||||
|
if (diagramOpened) {
|
||||||
|
// set focus to updated diagram only if no diagram is currently active
|
||||||
|
boolean keepFocus = false;
|
||||||
|
try {
|
||||||
|
keepFocus = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
|
||||||
|
.getActivePage().getActiveEditor().getTitle()
|
||||||
|
.matches(".*"+GlobalConstants.getDiagramExtension());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
IEditorPart newPage = UMLToolsHelperMethods.refreshDiagramEditor(project, globalModelDiagramFile, keepFocus);
|
||||||
|
if (newPage != null)
|
||||||
|
newPage.addPropertyListener(new ViewChangeListener2(this.project));
|
||||||
|
}*/
|
||||||
|
|
||||||
|
UMLToolsHelperMethods.updateModelAndViewPages(this.project, openEditorName.replace(GlobalConstants.getDiagramExtension(), ""), false);
|
||||||
|
// enable Listeners only after 4 seconds, when all diagrams are reloaded
|
||||||
|
Thread t = new Thread(
|
||||||
|
new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Thread.sleep(4000);
|
||||||
|
System.out.println("finish");
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
ViewChangeListener2.listenerEnabled = true;
|
||||||
|
ModelChangeListener.setEnabled(true);
|
||||||
|
System.out.println(ViewChangeListener2.listenerEnabled);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15558
pyUml/usedDocuments/UML.ecore
Executable file
15558
pyUml/usedDocuments/UML.ecore
Executable file
File diff suppressed because it is too large
Load Diff
1947
pyUml/usedDocuments/UML.uml
Executable file
1947
pyUml/usedDocuments/UML.uml
Executable file
File diff suppressed because it is too large
Load Diff
96
pyUml/usedDocuments/UMLMarkerNavigationProvider.java
Executable file
96
pyUml/usedDocuments/UMLMarkerNavigationProvider.java
Executable file
@ -0,0 +1,96 @@
|
|||||||
|
package org.eclipse.uml2.diagram.clazz.providers;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IMarker;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.emf.ecore.EObject;
|
||||||
|
import org.eclipse.gef.EditPart;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor;
|
||||||
|
import org.eclipse.gmf.runtime.emf.ui.providers.marker.AbstractModelMarkerNavigationProvider;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.UMLDiagramEditorPlugin;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.UMLDiagramEditorUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public class UMLMarkerNavigationProvider extends
|
||||||
|
AbstractModelMarkerNavigationProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static final String MARKER_TYPE = UMLDiagramEditorPlugin.ID
|
||||||
|
+ ".diagnostic"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
protected void doGotoMarker(IMarker marker) {
|
||||||
|
String elementId = marker
|
||||||
|
.getAttribute(
|
||||||
|
org.eclipse.gmf.runtime.common.core.resources.IMarker.ELEMENT_ID,
|
||||||
|
null);
|
||||||
|
if (elementId == null || !(getEditor() instanceof DiagramEditor)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DiagramEditor editor = (DiagramEditor) getEditor();
|
||||||
|
Map editPartRegistry = editor.getDiagramGraphicalViewer()
|
||||||
|
.getEditPartRegistry();
|
||||||
|
EObject targetView = editor.getDiagram().eResource().getEObject(
|
||||||
|
elementId);
|
||||||
|
if (targetView == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EditPart targetEditPart = (EditPart) editPartRegistry.get(targetView);
|
||||||
|
if (targetEditPart != null) {
|
||||||
|
UMLDiagramEditorUtil.selectElementsInDiagram(editor, Arrays
|
||||||
|
.asList(new EditPart[] { targetEditPart }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static void deleteMarkers(IResource resource) {
|
||||||
|
try {
|
||||||
|
resource.deleteMarkers(MARKER_TYPE, true, IResource.DEPTH_ZERO);
|
||||||
|
} catch (CoreException e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"Failed to delete validation markers", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static IMarker addMarker(IFile file, String elementId,
|
||||||
|
String location, String message, int statusSeverity) {
|
||||||
|
IMarker marker = null;
|
||||||
|
try {
|
||||||
|
marker = file.createMarker(MARKER_TYPE);
|
||||||
|
marker.setAttribute(IMarker.MESSAGE, message);
|
||||||
|
marker.setAttribute(IMarker.LOCATION, location);
|
||||||
|
marker
|
||||||
|
.setAttribute(
|
||||||
|
org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID,
|
||||||
|
elementId);
|
||||||
|
int markerSeverity = IMarker.SEVERITY_INFO;
|
||||||
|
if (statusSeverity == IStatus.WARNING) {
|
||||||
|
markerSeverity = IMarker.SEVERITY_WARNING;
|
||||||
|
} else if (statusSeverity == IStatus.ERROR
|
||||||
|
|| statusSeverity == IStatus.CANCEL) {
|
||||||
|
markerSeverity = IMarker.SEVERITY_ERROR;
|
||||||
|
}
|
||||||
|
marker.setAttribute(IMarker.SEVERITY, markerSeverity);
|
||||||
|
} catch (CoreException e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"Failed to create validation marker", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
return marker;
|
||||||
|
}
|
||||||
|
}
|
463
pyUml/usedDocuments/UMLValidationDecoratorProvider.java
Executable file
463
pyUml/usedDocuments/UMLValidationDecoratorProvider.java
Executable file
@ -0,0 +1,463 @@
|
|||||||
|
package org.eclipse.uml2.diagram.clazz.providers;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IMarker;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.draw2d.FlowLayout;
|
||||||
|
import org.eclipse.draw2d.Label;
|
||||||
|
import org.eclipse.emf.ecore.resource.Resource;
|
||||||
|
import org.eclipse.emf.transaction.TransactionalEditingDomain;
|
||||||
|
import org.eclipse.emf.transaction.util.TransactionUtil;
|
||||||
|
import org.eclipse.emf.workspace.util.WorkspaceSynchronizer;
|
||||||
|
import org.eclipse.gef.EditDomain;
|
||||||
|
import org.eclipse.gef.EditPart;
|
||||||
|
import org.eclipse.gef.editparts.AbstractConnectionEditPart;
|
||||||
|
import org.eclipse.gmf.runtime.common.core.service.AbstractProvider;
|
||||||
|
import org.eclipse.gmf.runtime.common.core.service.IOperation;
|
||||||
|
import org.eclipse.gmf.runtime.common.ui.resources.FileChangeManager;
|
||||||
|
import org.eclipse.gmf.runtime.common.ui.resources.IFileObserver;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditDomain;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.AbstractDecorator;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.CreateDecoratorsOperation;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecorator;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecoratorProvider;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecoratorTarget;
|
||||||
|
import org.eclipse.gmf.runtime.draw2d.ui.mapmode.MapModeUtil;
|
||||||
|
import org.eclipse.gmf.runtime.notation.Diagram;
|
||||||
|
import org.eclipse.gmf.runtime.notation.Edge;
|
||||||
|
import org.eclipse.gmf.runtime.notation.View;
|
||||||
|
import org.eclipse.swt.graphics.Image;
|
||||||
|
import org.eclipse.ui.ISharedImages;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.edit.parts.PackageEditPart;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.UMLDiagramEditor;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.UMLDiagramEditorPlugin;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.UMLVisualIDRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public class UMLValidationDecoratorProvider extends AbstractProvider implements
|
||||||
|
IDecoratorProvider {
|
||||||
|
|
||||||
|
public static Resource usedResource = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static final String KEY = "validationStatus"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static final String MARKER_TYPE = UMLDiagramEditorPlugin.ID
|
||||||
|
+ ".diagnostic"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static MarkerObserver fileObserver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static Map/*<String, List<IDecorator>>*/allDecorators = new HashMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void createDecorators(IDecoratorTarget decoratorTarget) {
|
||||||
|
EditPart editPart = (EditPart) decoratorTarget
|
||||||
|
.getAdapter(EditPart.class);
|
||||||
|
if (editPart instanceof GraphicalEditPart
|
||||||
|
|| editPart instanceof AbstractConnectionEditPart) {
|
||||||
|
Object model = editPart.getModel();
|
||||||
|
if ((model instanceof View)) {
|
||||||
|
View view = (View) model;
|
||||||
|
if (!(view instanceof Edge) && !view.isSetElement()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EditDomain ed = editPart.getViewer().getEditDomain();
|
||||||
|
if (!(ed instanceof DiagramEditDomain)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (((DiagramEditDomain) ed).getEditorPart() instanceof UMLDiagramEditor) {
|
||||||
|
decoratorTarget.installDecorator(KEY, new StatusDecorator(
|
||||||
|
decoratorTarget));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean provides(IOperation operation) {
|
||||||
|
if (!(operation instanceof CreateDecoratorsOperation)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
IDecoratorTarget decoratorTarget = ((CreateDecoratorsOperation) operation)
|
||||||
|
.getDecoratorTarget();
|
||||||
|
View view = (View) decoratorTarget.getAdapter(View.class);
|
||||||
|
return view != null
|
||||||
|
&& PackageEditPart.MODEL_ID.equals(UMLVisualIDRegistry
|
||||||
|
.getModelID(view));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static void refreshDecorators(View view) {
|
||||||
|
refreshDecorators(ViewUtil.getIdStr(view), view.getDiagram());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static void refreshDecorators(String viewId, Diagram diagram) {
|
||||||
|
final List decorators = viewId != null ? (List) allDecorators
|
||||||
|
.get(viewId) : null;
|
||||||
|
if (decorators == null || decorators.isEmpty() || diagram == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final Diagram fdiagram = diagram;
|
||||||
|
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
if (UMLValidationDecoratorProvider.usedResource == null)
|
||||||
|
UMLValidationDecoratorProvider.usedResource = fdiagram.eResource();
|
||||||
|
|
||||||
|
if (UMLValidationDecoratorProvider.usedResource == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TransactionalEditingDomain domain =
|
||||||
|
TransactionalEditingDomain.Factory.INSTANCE.getEditingDomain(
|
||||||
|
UMLValidationDecoratorProvider.usedResource.getResourceSet());
|
||||||
|
domain.runExclusive(
|
||||||
|
new Runnable() {
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
for (Iterator it = decorators.iterator(); it
|
||||||
|
.hasNext();) {
|
||||||
|
IDecorator decorator = (IDecorator) it
|
||||||
|
.next();
|
||||||
|
decorator.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"Decorator refresh failure", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class StatusDecorator extends AbstractDecorator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private String viewId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public StatusDecorator(IDecoratorTarget decoratorTarget) {
|
||||||
|
super(decoratorTarget);
|
||||||
|
try {
|
||||||
|
final View view = (View) getDecoratorTarget().getAdapter(
|
||||||
|
View.class);
|
||||||
|
TransactionUtil.getEditingDomain(view).runExclusive(
|
||||||
|
new Runnable() {
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
StatusDecorator.this.viewId = view != null ? ViewUtil
|
||||||
|
.getIdStr(view)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"ViewID access failure", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void refresh() {
|
||||||
|
removeDecoration();
|
||||||
|
View view = (View) getDecoratorTarget().getAdapter(View.class);
|
||||||
|
if (view == null || view.eResource() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EditPart editPart = (EditPart) getDecoratorTarget().getAdapter(
|
||||||
|
EditPart.class);
|
||||||
|
if (editPart == null || editPart.getViewer() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// query for all the validation markers of the current resource
|
||||||
|
String elementId = ViewUtil.getIdStr(view);
|
||||||
|
if (elementId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int severity = IMarker.SEVERITY_INFO;
|
||||||
|
IMarker foundMarker = null;
|
||||||
|
IResource resource = WorkspaceSynchronizer
|
||||||
|
.getFile(view.eResource());
|
||||||
|
if (resource == null || !resource.exists()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
IMarker[] markers = null;
|
||||||
|
try {
|
||||||
|
markers = resource.findMarkers(MARKER_TYPE, true,
|
||||||
|
IResource.DEPTH_INFINITE);
|
||||||
|
} catch (CoreException e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"Validation markers refresh failure", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
if (markers == null || markers.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Label toolTip = null;
|
||||||
|
for (int i = 0; i < markers.length; i++) {
|
||||||
|
IMarker marker = markers[i];
|
||||||
|
String attribute = marker
|
||||||
|
.getAttribute(
|
||||||
|
org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID,
|
||||||
|
""); //$NON-NLS-1$
|
||||||
|
if (attribute.equals(elementId)) {
|
||||||
|
int nextSeverity = marker.getAttribute(IMarker.SEVERITY,
|
||||||
|
IMarker.SEVERITY_INFO);
|
||||||
|
Image nextImage = getImage(nextSeverity);
|
||||||
|
if (foundMarker == null) {
|
||||||
|
foundMarker = marker;
|
||||||
|
toolTip = new Label(marker.getAttribute(
|
||||||
|
IMarker.MESSAGE, ""), //$NON-NLS-1$
|
||||||
|
nextImage);
|
||||||
|
} else {
|
||||||
|
if (toolTip.getChildren().isEmpty()) {
|
||||||
|
Label comositeLabel = new Label();
|
||||||
|
FlowLayout fl = new FlowLayout(false);
|
||||||
|
fl.setMinorSpacing(0);
|
||||||
|
comositeLabel.setLayoutManager(fl);
|
||||||
|
comositeLabel.add(toolTip);
|
||||||
|
toolTip = comositeLabel;
|
||||||
|
}
|
||||||
|
toolTip.add(new Label(marker.getAttribute(
|
||||||
|
IMarker.MESSAGE, ""), //$NON-NLS-1$
|
||||||
|
nextImage));
|
||||||
|
}
|
||||||
|
severity = (nextSeverity > severity) ? nextSeverity
|
||||||
|
: severity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (foundMarker == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add decoration
|
||||||
|
if (editPart instanceof org.eclipse.gef.GraphicalEditPart) {
|
||||||
|
if (view instanceof Edge) {
|
||||||
|
setDecoration(getDecoratorTarget().addConnectionDecoration(
|
||||||
|
getImage(severity), 50, true));
|
||||||
|
} else {
|
||||||
|
int margin = -1;
|
||||||
|
if (editPart instanceof org.eclipse.gef.GraphicalEditPart) {
|
||||||
|
margin = MapModeUtil.getMapMode(
|
||||||
|
((org.eclipse.gef.GraphicalEditPart) editPart)
|
||||||
|
.getFigure()).DPtoLP(margin);
|
||||||
|
}
|
||||||
|
setDecoration(getDecoratorTarget()
|
||||||
|
.addShapeDecoration(getImage(severity),
|
||||||
|
IDecoratorTarget.Direction.NORTH_EAST,
|
||||||
|
margin, true));
|
||||||
|
}
|
||||||
|
getDecoration().setToolTip(toolTip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private Image getImage(int severity) {
|
||||||
|
String imageName = ISharedImages.IMG_OBJS_ERROR_TSK;
|
||||||
|
switch (severity) {
|
||||||
|
case IMarker.SEVERITY_ERROR:
|
||||||
|
imageName = ISharedImages.IMG_OBJS_ERROR_TSK;
|
||||||
|
break;
|
||||||
|
case IMarker.SEVERITY_WARNING:
|
||||||
|
imageName = ISharedImages.IMG_OBJS_WARN_TSK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
imageName = ISharedImages.IMG_OBJS_INFO_TSK;
|
||||||
|
}
|
||||||
|
return PlatformUI.getWorkbench().getSharedImages().getImage(
|
||||||
|
imageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void activate() {
|
||||||
|
if (viewId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add self to global decorators registry
|
||||||
|
List list = (List) allDecorators.get(viewId);
|
||||||
|
if (list == null) {
|
||||||
|
list = new ArrayList(2);
|
||||||
|
list.add(this);
|
||||||
|
allDecorators.put(viewId, list);
|
||||||
|
} else if (!list.contains(this)) {
|
||||||
|
list.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// start listening to changes in resources
|
||||||
|
View view = (View) getDecoratorTarget().getAdapter(View.class);
|
||||||
|
if (view == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Diagram diagramView = view.getDiagram();
|
||||||
|
if (diagramView == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fileObserver == null) {
|
||||||
|
FileChangeManager.getInstance().addFileObserver(
|
||||||
|
fileObserver = new MarkerObserver(diagramView));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void deactivate() {
|
||||||
|
if (viewId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove self from global decorators registry
|
||||||
|
List list = (List) allDecorators.get(viewId);
|
||||||
|
if (list != null) {
|
||||||
|
list.remove(this);
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
allDecorators.remove(viewId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop listening to changes in resources if there are no more decorators
|
||||||
|
if (fileObserver != null && allDecorators.isEmpty()) {
|
||||||
|
FileChangeManager.getInstance()
|
||||||
|
.removeFileObserver(fileObserver);
|
||||||
|
fileObserver = null;
|
||||||
|
}
|
||||||
|
super.deactivate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
static class MarkerObserver implements IFileObserver {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private Diagram diagram;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private MarkerObserver(Diagram diagram) {
|
||||||
|
this.diagram = diagram;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void handleFileRenamed(IFile oldFile, IFile file) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void handleFileMoved(IFile oldFile, IFile file) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void handleFileDeleted(IFile file) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void handleFileChanged(IFile file) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void handleMarkerAdded(IMarker marker) {
|
||||||
|
if (marker
|
||||||
|
.getAttribute(
|
||||||
|
org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID,
|
||||||
|
null) != null) {
|
||||||
|
handleMarkerChanged(marker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void handleMarkerDeleted(IMarker marker, Map attributes) {
|
||||||
|
String viewId = (String) attributes
|
||||||
|
.get(org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID);
|
||||||
|
refreshDecorators(viewId, diagram);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void handleMarkerChanged(IMarker marker) {
|
||||||
|
if (!MARKER_TYPE.equals(getType(marker))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String viewId = marker
|
||||||
|
.getAttribute(
|
||||||
|
org.eclipse.gmf.runtime.common.ui.resources.IMarker.ELEMENT_ID,
|
||||||
|
""); //$NON-NLS-1$
|
||||||
|
refreshDecorators(viewId, diagram);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private String getType(IMarker marker) {
|
||||||
|
try {
|
||||||
|
return marker.getType();
|
||||||
|
} catch (CoreException e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"Validation marker refresh failure", e); //$NON-NLS-1$
|
||||||
|
return ""; //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
367
pyUml/usedDocuments/UMLValidationProvider.java
Executable file
367
pyUml/usedDocuments/UMLValidationProvider.java
Executable file
@ -0,0 +1,367 @@
|
|||||||
|
package org.eclipse.uml2.diagram.clazz.providers;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.emf.ecore.EObject;
|
||||||
|
import org.eclipse.emf.transaction.TransactionalEditingDomain;
|
||||||
|
import org.eclipse.emf.transaction.util.TransactionUtil;
|
||||||
|
import org.eclipse.emf.validation.model.IClientSelector;
|
||||||
|
import org.eclipse.emf.validation.service.IBatchValidator;
|
||||||
|
import org.eclipse.emf.validation.service.ITraversalStrategy;
|
||||||
|
import org.eclipse.gmf.runtime.common.ui.services.action.contributionitem.AbstractContributionItemProvider;
|
||||||
|
import org.eclipse.gmf.runtime.common.ui.util.IWorkbenchPartDescriptor;
|
||||||
|
import org.eclipse.gmf.runtime.notation.View;
|
||||||
|
import org.eclipse.jface.action.IAction;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.edit.parts.PackageEditPart;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.UMLDiagramEditorPlugin;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.UMLVisualIDRegistry;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.part.ValidateAction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public class UMLValidationProvider extends AbstractContributionItemProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static boolean constraintsActive = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static boolean shouldConstraintsBePrivate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
protected IAction createAction(String actionId,
|
||||||
|
IWorkbenchPartDescriptor partDescriptor) {
|
||||||
|
if (ValidateAction.VALIDATE_ACTION_KEY.equals(actionId)) {
|
||||||
|
return new ValidateAction(partDescriptor);
|
||||||
|
}
|
||||||
|
return super.createAction(actionId, partDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static void runWithConstraints(View view, Runnable op) {
|
||||||
|
final Runnable fop = op;
|
||||||
|
Runnable task = new Runnable() {
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
constraintsActive = true;
|
||||||
|
fop.run();
|
||||||
|
} finally {
|
||||||
|
constraintsActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
TransactionalEditingDomain txDomain = TransactionUtil
|
||||||
|
.getEditingDomain(view);
|
||||||
|
if (txDomain != null) {
|
||||||
|
try {
|
||||||
|
txDomain.runExclusive(task);
|
||||||
|
} catch (Exception e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"Validation action failed", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
task.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
static boolean isInDefaultEditorContext(Object object) {
|
||||||
|
if (shouldConstraintsBePrivate() && !constraintsActive) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (object instanceof View) {
|
||||||
|
return constraintsActive
|
||||||
|
&& PackageEditPart.MODEL_ID.equals(UMLVisualIDRegistry
|
||||||
|
.getModelID((View) object));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
static final Map semanticCtxIdMap = new HashMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx1 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx2 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx3 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx4 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx5 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx6 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx7 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx8 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx9 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx10 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static class DefaultCtx11 implements IClientSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean selects(Object object) {
|
||||||
|
return isInDefaultEditorContext(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static ITraversalStrategy getNotationTraversalStrategy(
|
||||||
|
IBatchValidator validator) {
|
||||||
|
return new CtxSwitchStrategy(validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static class CtxSwitchStrategy implements ITraversalStrategy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private ITraversalStrategy defaultStrategy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private String currentSemanticCtxId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private boolean ctxChanged = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private EObject currentTarget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private EObject preFetchedNextTarget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
CtxSwitchStrategy(IBatchValidator validator) {
|
||||||
|
this.defaultStrategy = validator.getDefaultTraversalStrategy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void elementValidated(EObject element, IStatus status) {
|
||||||
|
defaultStrategy.elementValidated(element, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean hasNext() {
|
||||||
|
return defaultStrategy.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public boolean isClientContextChanged() {
|
||||||
|
if (preFetchedNextTarget == null) {
|
||||||
|
preFetchedNextTarget = next();
|
||||||
|
prepareNextClientContext(preFetchedNextTarget);
|
||||||
|
}
|
||||||
|
return ctxChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public EObject next() {
|
||||||
|
EObject nextTarget = preFetchedNextTarget;
|
||||||
|
if (nextTarget == null) {
|
||||||
|
nextTarget = defaultStrategy.next();
|
||||||
|
}
|
||||||
|
this.preFetchedNextTarget = null;
|
||||||
|
return this.currentTarget = nextTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void startTraversal(Collection traversalRoots,
|
||||||
|
IProgressMonitor monitor) {
|
||||||
|
defaultStrategy.startTraversal(traversalRoots, monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private void prepareNextClientContext(EObject nextTarget) {
|
||||||
|
if (nextTarget != null && currentTarget != null) {
|
||||||
|
if (nextTarget instanceof View) {
|
||||||
|
String id = ((View) nextTarget).getType();
|
||||||
|
String nextSemanticId = id != null
|
||||||
|
&& semanticCtxIdMap.containsKey(id) ? id : null;
|
||||||
|
if ((currentSemanticCtxId != null && !currentSemanticCtxId
|
||||||
|
.equals(nextSemanticId))
|
||||||
|
|| (nextSemanticId != null && !nextSemanticId
|
||||||
|
.equals(currentSemanticCtxId))) {
|
||||||
|
this.ctxChanged = true;
|
||||||
|
}
|
||||||
|
currentSemanticCtxId = nextSemanticId;
|
||||||
|
} else {
|
||||||
|
// context of domain model
|
||||||
|
this.ctxChanged = currentSemanticCtxId != null;
|
||||||
|
currentSemanticCtxId = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.ctxChanged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
static class JavaAudits {
|
||||||
|
}
|
||||||
|
}
|
297
pyUml/usedDocuments/ValidateAction.java
Executable file
297
pyUml/usedDocuments/ValidateAction.java
Executable file
@ -0,0 +1,297 @@
|
|||||||
|
package org.eclipse.uml2.diagram.clazz.part;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||||
|
import org.eclipse.emf.common.util.Diagnostic;
|
||||||
|
import org.eclipse.emf.ecore.EObject;
|
||||||
|
import org.eclipse.emf.ecore.util.Diagnostician;
|
||||||
|
import org.eclipse.emf.validation.model.EvaluationMode;
|
||||||
|
import org.eclipse.emf.validation.model.IConstraintStatus;
|
||||||
|
import org.eclipse.emf.validation.service.IBatchValidator;
|
||||||
|
import org.eclipse.emf.validation.service.ModelValidationService;
|
||||||
|
import org.eclipse.emf.workspace.util.WorkspaceSynchronizer;
|
||||||
|
import org.eclipse.gef.EditPartViewer;
|
||||||
|
import org.eclipse.gmf.runtime.common.ui.util.IWorkbenchPartDescriptor;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.OffscreenEditPartFactory;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
|
||||||
|
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramWorkbenchPart;
|
||||||
|
import org.eclipse.gmf.runtime.emf.core.util.EMFCoreUtil;
|
||||||
|
import org.eclipse.gmf.runtime.notation.View;
|
||||||
|
import org.eclipse.jface.action.Action;
|
||||||
|
import org.eclipse.jface.operation.IRunnableWithProgress;
|
||||||
|
import org.eclipse.ui.IEditorPart;
|
||||||
|
import org.eclipse.ui.IWorkbenchPart;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
import org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.providers.UMLMarkerNavigationProvider;
|
||||||
|
import org.eclipse.uml2.diagram.clazz.providers.UMLValidationProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public class ValidateAction extends Action {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static final String VALIDATE_ACTION_KEY = "validateAction"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private IWorkbenchPartDescriptor workbenchPartDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public ValidateAction(IWorkbenchPartDescriptor workbenchPartDescriptor) {
|
||||||
|
setId(VALIDATE_ACTION_KEY);
|
||||||
|
setText(Messages.ValidateActionMessage);
|
||||||
|
this.workbenchPartDescriptor = workbenchPartDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public void run() {
|
||||||
|
IWorkbenchPart workbenchPart = workbenchPartDescriptor.getPartPage()
|
||||||
|
.getActivePart();
|
||||||
|
if (workbenchPart instanceof IDiagramWorkbenchPart) {
|
||||||
|
final IDiagramWorkbenchPart part = (IDiagramWorkbenchPart) workbenchPart;
|
||||||
|
try {
|
||||||
|
new WorkspaceModifyDelegatingOperation(
|
||||||
|
new IRunnableWithProgress() {
|
||||||
|
|
||||||
|
public void run(IProgressMonitor monitor)
|
||||||
|
throws InterruptedException,
|
||||||
|
InvocationTargetException {
|
||||||
|
runValidation(part.getDiagramEditPart(), part
|
||||||
|
.getDiagram());
|
||||||
|
}
|
||||||
|
}).run(new NullProgressMonitor());
|
||||||
|
} catch (Exception e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"Validation action failed", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static void runValidation(View view) {
|
||||||
|
try {
|
||||||
|
if (UMLDiagramEditorUtil.openDiagram(view.eResource())) {
|
||||||
|
IEditorPart editorPart = PlatformUI.getWorkbench()
|
||||||
|
.getActiveWorkbenchWindow().getActivePage()
|
||||||
|
.getActiveEditor();
|
||||||
|
if (editorPart instanceof IDiagramWorkbenchPart) {
|
||||||
|
runValidation(((IDiagramWorkbenchPart) editorPart)
|
||||||
|
.getDiagramEditPart(), view);
|
||||||
|
} else {
|
||||||
|
runNonUIValidation(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
UMLDiagramEditorPlugin.getInstance().logError(
|
||||||
|
"Validation action failed", e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static void runNonUIValidation(View view) {
|
||||||
|
DiagramEditPart diagramEditPart = OffscreenEditPartFactory
|
||||||
|
.getInstance().createDiagramEditPart(view.getDiagram());
|
||||||
|
runValidation(diagramEditPart, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
public static void runValidation(DiagramEditPart diagramEditPart, View view) {
|
||||||
|
final DiagramEditPart fpart = diagramEditPart;
|
||||||
|
final View fview = view;
|
||||||
|
UMLValidationProvider.runWithConstraints(view, new Runnable() {
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
validate(fpart, fview);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static Diagnostic runEMFValidator(View target) {
|
||||||
|
if (target.isSetElement() && target.getElement() != null) {
|
||||||
|
return new Diagnostician() {
|
||||||
|
|
||||||
|
public String getObjectLabel(EObject eObject) {
|
||||||
|
return EMFCoreUtil.getQualifiedName(eObject, true);
|
||||||
|
}
|
||||||
|
}.validate(target.getElement());
|
||||||
|
}
|
||||||
|
return Diagnostic.OK_INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static void validate(DiagramEditPart diagramEditPart, View view) {
|
||||||
|
IFile target = view.eResource() != null ? WorkspaceSynchronizer
|
||||||
|
.getFile(view.eResource()) : null;
|
||||||
|
if (target != null) {
|
||||||
|
UMLMarkerNavigationProvider.deleteMarkers(target);
|
||||||
|
}
|
||||||
|
Diagnostic diagnostic = runEMFValidator(view);
|
||||||
|
createMarkers(target, diagnostic, diagramEditPart);
|
||||||
|
IBatchValidator validator = (IBatchValidator) ModelValidationService
|
||||||
|
.getInstance().newValidator(EvaluationMode.BATCH);
|
||||||
|
validator.setIncludeLiveConstraints(true);
|
||||||
|
if (view.isSetElement() && view.getElement() != null) {
|
||||||
|
IStatus status = validator.validate(view.getElement());
|
||||||
|
createMarkers(target, status, diagramEditPart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static void createMarkers(IFile target, IStatus validationStatus,
|
||||||
|
DiagramEditPart diagramEditPart) {
|
||||||
|
if (validationStatus.isOK()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final IStatus rootStatus = validationStatus;
|
||||||
|
List allStatuses = new ArrayList();
|
||||||
|
UMLDiagramEditorUtil.LazyElement2ViewMap element2ViewMap = new UMLDiagramEditorUtil.LazyElement2ViewMap(
|
||||||
|
diagramEditPart.getDiagramView(), collectTargetElements(
|
||||||
|
rootStatus, new HashSet(), allStatuses));
|
||||||
|
for (Iterator it = allStatuses.iterator(); it.hasNext();) {
|
||||||
|
IConstraintStatus nextStatus = (IConstraintStatus) it.next();
|
||||||
|
View view = UMLDiagramEditorUtil.findView(diagramEditPart,
|
||||||
|
nextStatus.getTarget(), element2ViewMap);
|
||||||
|
addMarker(diagramEditPart.getViewer(), target, view.eResource()
|
||||||
|
.getURIFragment(view), EMFCoreUtil.getQualifiedName(
|
||||||
|
nextStatus.getTarget(), true), nextStatus.getMessage(),
|
||||||
|
nextStatus.getSeverity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static void createMarkers(IFile target,
|
||||||
|
Diagnostic emfValidationStatus, DiagramEditPart diagramEditPart) {
|
||||||
|
if (emfValidationStatus.getSeverity() == Diagnostic.OK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final Diagnostic rootStatus = emfValidationStatus;
|
||||||
|
List allDiagnostics = new ArrayList();
|
||||||
|
UMLDiagramEditorUtil.LazyElement2ViewMap element2ViewMap = new UMLDiagramEditorUtil.LazyElement2ViewMap(
|
||||||
|
diagramEditPart.getDiagramView(), collectTargetElements(
|
||||||
|
rootStatus, new HashSet(), allDiagnostics));
|
||||||
|
for (Iterator it = emfValidationStatus.getChildren().iterator(); it
|
||||||
|
.hasNext();) {
|
||||||
|
Diagnostic nextDiagnostic = (Diagnostic) it.next();
|
||||||
|
List data = nextDiagnostic.getData();
|
||||||
|
if (data != null && !data.isEmpty()
|
||||||
|
&& data.get(0) instanceof EObject) {
|
||||||
|
EObject element = (EObject) data.get(0);
|
||||||
|
View view = UMLDiagramEditorUtil.findView(diagramEditPart,
|
||||||
|
element, element2ViewMap);
|
||||||
|
addMarker(
|
||||||
|
diagramEditPart.getViewer(),
|
||||||
|
target,
|
||||||
|
view.eResource().getURIFragment(view),
|
||||||
|
EMFCoreUtil.getQualifiedName(element, true),
|
||||||
|
nextDiagnostic.getMessage(),
|
||||||
|
diagnosticToStatusSeverity(nextDiagnostic.getSeverity()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static void addMarker(EditPartViewer viewer, IFile target,
|
||||||
|
String elementId, String location, String message,
|
||||||
|
int statusSeverity) {
|
||||||
|
if (target == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UMLMarkerNavigationProvider.addMarker(target, elementId, location,
|
||||||
|
message, statusSeverity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static int diagnosticToStatusSeverity(int diagnosticSeverity) {
|
||||||
|
if (diagnosticSeverity == Diagnostic.OK) {
|
||||||
|
return IStatus.OK;
|
||||||
|
} else if (diagnosticSeverity == Diagnostic.INFO) {
|
||||||
|
return IStatus.INFO;
|
||||||
|
} else if (diagnosticSeverity == Diagnostic.WARNING) {
|
||||||
|
return IStatus.WARNING;
|
||||||
|
} else if (diagnosticSeverity == Diagnostic.ERROR
|
||||||
|
|| diagnosticSeverity == Diagnostic.CANCEL) {
|
||||||
|
return IStatus.ERROR;
|
||||||
|
}
|
||||||
|
return IStatus.INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static Set collectTargetElements(IStatus status,
|
||||||
|
Set targetElementCollector, List allConstraintStatuses) {
|
||||||
|
if (status instanceof IConstraintStatus) {
|
||||||
|
targetElementCollector
|
||||||
|
.add(((IConstraintStatus) status).getTarget());
|
||||||
|
allConstraintStatuses.add(status);
|
||||||
|
}
|
||||||
|
if (status.isMultiStatus()) {
|
||||||
|
IStatus[] children = status.getChildren();
|
||||||
|
for (int i = 0; i < children.length; i++) {
|
||||||
|
collectTargetElements(children[i], targetElementCollector,
|
||||||
|
allConstraintStatuses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return targetElementCollector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
private static Set collectTargetElements(Diagnostic diagnostic,
|
||||||
|
Set targetElementCollector, List allDiagnostics) {
|
||||||
|
List data = diagnostic.getData();
|
||||||
|
EObject target = null;
|
||||||
|
if (data != null && !data.isEmpty() && data.get(0) instanceof EObject) {
|
||||||
|
target = (EObject) data.get(0);
|
||||||
|
targetElementCollector.add(target);
|
||||||
|
allDiagnostics.add(diagnostic);
|
||||||
|
}
|
||||||
|
if (diagnostic.getChildren() != null
|
||||||
|
&& !diagnostic.getChildren().isEmpty()) {
|
||||||
|
for (Iterator it = diagnostic.getChildren().iterator(); it
|
||||||
|
.hasNext();) {
|
||||||
|
collectTargetElements((Diagnostic) it.next(),
|
||||||
|
targetElementCollector, allDiagnostics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return targetElementCollector;
|
||||||
|
}
|
||||||
|
}
|
11451
pyUml/usedDocuments/classDiagram.gmfgen
Executable file
11451
pyUml/usedDocuments/classDiagram.gmfgen
Executable file
File diff suppressed because one or more lines are too long
1978
pyUml/usedDocuments/classDiagram.gmfmap
Executable file
1978
pyUml/usedDocuments/classDiagram.gmfmap
Executable file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user