From dd8886f5c40fc871e9d6ea074fd1c86a9cc88e32 Mon Sep 17 00:00:00 2001 From: Rafael Chaves <> Date: Mon, 14 Jan 2008 07:45:24 +0000 Subject: [PATCH] first cut of UML2-based dot rendering (yet to adopt UMLGraph rendering code) --- .../org.umlgraph.engine.tests/.classpath | 1 + .../META-INF/MANIFEST.MF | 4 +- .../org/umlgraph/engine/tests/AllTests.java | 2 + .../tests/ClassDiagramRendererTest.java | 32 ++++++ .../umlgraph/engine/tests/TestStandalone.java | 27 +++++ .../org/umlgraph/engine/tests/TestUtils.java | 23 +++++ .../test-resources/test-models/payment.uml | 10 ++ .../test-resources/test-models/sample.uml | 4 + .../org.umlgraph.engine/META-INF/MANIFEST.MF | 11 ++- .../engine/AbstractDiagramRenderer.java | 22 +++++ .../src/org/umlgraph/engine/Activator.java | 34 +++++++ .../umlgraph/engine/DOTRenderingUtils.java | 17 ++++ .../src/org/umlgraph/engine/Diagram.java | 43 ++++++++ .../org/umlgraph/engine/DiagramOptions.java | 14 +-- .../org/umlgraph/engine/DiagramRenderer.java | 7 ++ .../src/org/umlgraph/engine/EdgeOptions.java | 16 +-- .../src/org/umlgraph/engine/NodeOptions.java | 12 +-- .../src/org/umlgraph/engine/RelationType.java | 11 +++ .../src/org/umlgraph/engine/Util.java | 52 ++++++++++ .../src/org/umlgraph/engine/Visibility.java | 31 ++++++ .../engine/classdiagram/ClassDiagram.java | 25 +++++ .../ClassDiagramOptions.java | 64 +++++++----- .../{ => classdiagram}/ClassOptions.java | 43 ++++---- .../engine/classdiagram/ElementRenderer.java | 13 +++ .../classdiagram/ElementRendererSelector.java | 46 +++++++++ .../{ => classdiagram}/PackageOptions.java | 3 +- .../engine/classdiagram/RenderingSession.java | 44 +++++++++ .../classdiagram/UMLRenderingUtils.java | 55 +++++++++++ .../classdiagram/dot/AssociationRenderer.java | 68 +++++++++++++ .../dot/ClassDiagramRenderer.java | 67 +++++++++++++ .../classdiagram/dot/ClassRenderer.java | 49 ++++++++++ .../dot/EnumerationLiteralRenderer.java | 15 +++ .../classdiagram/dot/EnumerationRenderer.java | 43 ++++++++ .../classdiagram/dot/ExtensionRenderer.java | 29 ++++++ .../dot/GeneralizationRenderer.java | 43 ++++++++ .../classdiagram/dot/IndentedPrintWriter.java | 98 +++++++++++++++++++ .../dot/InterfaceRealizationRenderer.java | 26 +++++ .../classdiagram/dot/InterfaceRenderer.java | 40 ++++++++ .../classdiagram/dot/OperationRenderer.java | 45 +++++++++ .../classdiagram/dot/PackageRenderer.java | 17 ++++ .../classdiagram/dot/ParameterRenderer.java | 21 ++++ .../classdiagram/dot/PropertyRenderer.java | 20 ++++ .../engine/classdiagram/dot/package.html | 4 + .../umlgraph/engine/classdiagram/package.html | 4 + .../umlgraph/engine/matching/AndMatcher.java | 23 +++++ .../umlgraph/engine/matching/AnyMatcher.java | 10 ++ .../engine/matching/ElementMatcher.java | 10 ++ .../matching/GeneralizationTreeMatcher.java | 29 ++++++ .../engine/matching/MatchingHelper.java | 9 ++ .../engine/matching/MetaClassMatcher.java | 21 ++++ .../umlgraph/engine/matching/NameMatcher.java | 25 +++++ .../umlgraph/engine/matching/NotMatcher.java | 21 ++++ .../umlgraph/engine/matching/OrMatcher.java | 25 +++++ .../engine/matching/PatternMatcher.java | 49 ++++++++++ .../org/umlgraph/engine/matching/package.html | 3 + 55 files changed, 1408 insertions(+), 72 deletions(-) create mode 100644 umlgraph_ng/org.umlgraph.engine.tests/src/org/umlgraph/engine/tests/ClassDiagramRendererTest.java create mode 100644 umlgraph_ng/org.umlgraph.engine.tests/src/org/umlgraph/engine/tests/TestStandalone.java create mode 100644 umlgraph_ng/org.umlgraph.engine.tests/src/org/umlgraph/engine/tests/TestUtils.java create mode 100644 umlgraph_ng/org.umlgraph.engine.tests/test-resources/test-models/payment.uml create mode 100644 umlgraph_ng/org.umlgraph.engine.tests/test-resources/test-models/sample.uml create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/AbstractDiagramRenderer.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/Activator.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/DOTRenderingUtils.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/Diagram.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/DiagramRenderer.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/RelationType.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/Util.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/Visibility.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ClassDiagram.java rename umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/{ => classdiagram}/ClassDiagramOptions.java (60%) rename umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/{ => classdiagram}/ClassOptions.java (93%) create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ElementRenderer.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ElementRendererSelector.java rename umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/{ => classdiagram}/PackageOptions.java (93%) create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/RenderingSession.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/UMLRenderingUtils.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/AssociationRenderer.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/ClassDiagramRenderer.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/ClassRenderer.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/EnumerationLiteralRenderer.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/EnumerationRenderer.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/ExtensionRenderer.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/GeneralizationRenderer.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/IndentedPrintWriter.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/InterfaceRealizationRenderer.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/InterfaceRenderer.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/OperationRenderer.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/PackageRenderer.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/ParameterRenderer.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/PropertyRenderer.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/package.html create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/package.html create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/AndMatcher.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/AnyMatcher.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/ElementMatcher.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/GeneralizationTreeMatcher.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/MatchingHelper.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/MetaClassMatcher.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/NameMatcher.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/NotMatcher.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/OrMatcher.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/PatternMatcher.java create mode 100644 umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/package.html diff --git a/umlgraph_ng/org.umlgraph.engine.tests/.classpath b/umlgraph_ng/org.umlgraph.engine.tests/.classpath index 751c8f2..660b948 100644 --- a/umlgraph_ng/org.umlgraph.engine.tests/.classpath +++ b/umlgraph_ng/org.umlgraph.engine.tests/.classpath @@ -1,6 +1,7 @@ + diff --git a/umlgraph_ng/org.umlgraph.engine.tests/META-INF/MANIFEST.MF b/umlgraph_ng/org.umlgraph.engine.tests/META-INF/MANIFEST.MF index 801157a..7132ef2 100644 --- a/umlgraph_ng/org.umlgraph.engine.tests/META-INF/MANIFEST.MF +++ b/umlgraph_ng/org.umlgraph.engine.tests/META-INF/MANIFEST.MF @@ -4,5 +4,7 @@ Bundle-Name: Tests Plug-in Bundle-SymbolicName: org.umlgraph.engine.tests Bundle-Version: 1.0.0 Require-Bundle: org.junit, - org.umlgraph.engine + org.umlgraph.engine, + org.eclipse.uml2.uml, + org.eclipse.uml2.uml.resources Export-Package: org.umlgraph.engine.tests diff --git a/umlgraph_ng/org.umlgraph.engine.tests/src/org/umlgraph/engine/tests/AllTests.java b/umlgraph_ng/org.umlgraph.engine.tests/src/org/umlgraph/engine/tests/AllTests.java index c442c08..6a0da50 100644 --- a/umlgraph_ng/org.umlgraph.engine.tests/src/org/umlgraph/engine/tests/AllTests.java +++ b/umlgraph_ng/org.umlgraph.engine.tests/src/org/umlgraph/engine/tests/AllTests.java @@ -8,6 +8,8 @@ public class AllTests { TestSuite allTests = new TestSuite(AllTests.class.getName()); allTests.addTest(SettingKeyTests.suite()); allTests.addTest(SettingTests.suite()); + allTests.addTest(TestStandalone.suite()); + allTests.addTest(ClassDiagramRendererTest.suite()); return allTests; } } diff --git a/umlgraph_ng/org.umlgraph.engine.tests/src/org/umlgraph/engine/tests/ClassDiagramRendererTest.java b/umlgraph_ng/org.umlgraph.engine.tests/src/org/umlgraph/engine/tests/ClassDiagramRendererTest.java new file mode 100644 index 0000000..b828882 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine.tests/src/org/umlgraph/engine/tests/ClassDiagramRendererTest.java @@ -0,0 +1,32 @@ +package org.umlgraph.engine.tests; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.umlgraph.engine.classdiagram.ClassDiagram; +import org.umlgraph.engine.classdiagram.dot.ClassDiagramRenderer; + +public class ClassDiagramRendererTest extends TestCase { + + public ClassDiagramRendererTest(String name) { + super(name); + } + + public void testBasic() throws IOException { + ResourceSet resourceSet = TestUtils.assemble("payment.uml"); + ClassDiagram diagram = new ClassDiagram("payment", null); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + new ClassDiagramRenderer().render(resourceSet, diagram, output); + //TODO adopt dot comparison utilities from UMLGraph + System.out.println(new String(output.toByteArray())); + } + + public static Test suite() { + return new TestSuite(ClassDiagramRendererTest.class); + } +} diff --git a/umlgraph_ng/org.umlgraph.engine.tests/src/org/umlgraph/engine/tests/TestStandalone.java b/umlgraph_ng/org.umlgraph.engine.tests/src/org/umlgraph/engine/tests/TestStandalone.java new file mode 100644 index 0000000..98fef5a --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine.tests/src/org/umlgraph/engine/tests/TestStandalone.java @@ -0,0 +1,27 @@ +package org.umlgraph.engine.tests; + +import java.io.IOException; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.uml2.uml.util.UMLUtil; + +public class TestStandalone extends TestCase { + + public TestStandalone(String name) { + super(name); + } + + public void testStandalone() throws IOException { + ResourceSet resourceSet = TestUtils.assemble("sample.uml"); + assertNotNull(UMLUtil.findNamedElements(resourceSet, "sample")); + assertNotNull(UMLUtil.findNamedElements(resourceSet, "sample::SampleClass")); + } + + public static Test suite() { + return new TestSuite(TestStandalone.class); + } +} diff --git a/umlgraph_ng/org.umlgraph.engine.tests/src/org/umlgraph/engine/tests/TestUtils.java b/umlgraph_ng/org.umlgraph.engine.tests/src/org/umlgraph/engine/tests/TestUtils.java new file mode 100644 index 0000000..b0fe190 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine.tests/src/org/umlgraph/engine/tests/TestUtils.java @@ -0,0 +1,23 @@ +package org.umlgraph.engine.tests; + +import java.io.IOException; +import java.net.URL; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.umlgraph.engine.Util; + +public class TestUtils { + private static final String BASE_PATH = "/test-models/"; + + public static ResourceSet assemble(String... paths) throws IOException { + ResourceSet resourceSet = Util.createResourceSet(); + for (int i = 0; i < paths.length; i++) { + URL resourceURL = TestUtils.class.getResource(BASE_PATH + paths[i]); + Resource resource = resourceSet.getResource(URI.createURI(resourceURL.toString()), true); + resource.load(null); + } + return resourceSet; + } +} diff --git a/umlgraph_ng/org.umlgraph.engine.tests/test-resources/test-models/payment.uml b/umlgraph_ng/org.umlgraph.engine.tests/test-resources/test-models/payment.uml new file mode 100644 index 0000000..223110a --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine.tests/test-resources/test-models/payment.uml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/umlgraph_ng/org.umlgraph.engine.tests/test-resources/test-models/sample.uml b/umlgraph_ng/org.umlgraph.engine.tests/test-resources/test-models/sample.uml new file mode 100644 index 0000000..34b7e16 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine.tests/test-resources/test-models/sample.uml @@ -0,0 +1,4 @@ + + + + diff --git a/umlgraph_ng/org.umlgraph.engine/META-INF/MANIFEST.MF b/umlgraph_ng/org.umlgraph.engine/META-INF/MANIFEST.MF index a96e010..9050502 100644 --- a/umlgraph_ng/org.umlgraph.engine/META-INF/MANIFEST.MF +++ b/umlgraph_ng/org.umlgraph.engine/META-INF/MANIFEST.MF @@ -4,5 +4,12 @@ Bundle-Name: UMLGraph Bundle-SymbolicName: org.umlgraph.engine Bundle-Version: 5.0.0.qualifier Bundle-Vendor: umlgraph.org -Require-Bundle: org.umlgraph.settings;visibility:=reexport -Export-Package: org.umlgraph.engine +Require-Bundle: org.umlgraph.settings;visibility:=reexport, + org.eclipse.uml2.uml +Export-Package: org.umlgraph.engine, + org.umlgraph.engine.classdiagram, + org.umlgraph.engine.classdiagram.dot, + org.umlgraph.engine.matching +Import-Package: org.osgi.framework;version="1.4.0" +Bundle-Activator: org.umlgraph.engine.Activator +Eclipse-LazyStart: true diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/AbstractDiagramRenderer.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/AbstractDiagramRenderer.java new file mode 100644 index 0000000..7fc076e --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/AbstractDiagramRenderer.java @@ -0,0 +1,22 @@ +package org.umlgraph.engine; + +import org.eclipse.emf.ecore.resource.ResourceSet; + +/** + * This abstract class establishes the protocol for any diagram renderer. + *

+ * A diagram renderer knows how to render a specific type + * of diagram. + *

+ */ +public abstract class AbstractDiagramRenderer { + /** + * Renders a diagram. + * + * @param resourceSet the input models + * @param diagram the diagram definition + * @param diagramOutput where to render the diagram to + */ + public abstract void render(ResourceSet resourceSet, D diagram, + O diagramOutput); +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/Activator.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/Activator.java new file mode 100644 index 0000000..c86b5cc --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/Activator.java @@ -0,0 +1,34 @@ +package org.umlgraph.engine; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +/** + * The bundle activator. Only used when running in OSGi. + */ +public class Activator implements BundleActivator { + + private BundleContext context; + private static Activator instance; + + public Activator() { + instance = this; + } + + public void start(BundleContext context) throws Exception { + this.context = context; + } + + public void stop(BundleContext context) throws Exception { + this.context = null; + } + + /** + * Returns whether we are running as an OSGi bundle. + * + * @return whether we are running as an OSGi bundle + */ + static boolean isRunningOSGi() { + return instance != null && instance.context != null; + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/DOTRenderingUtils.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/DOTRenderingUtils.java new file mode 100644 index 0000000..ed4fb3f --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/DOTRenderingUtils.java @@ -0,0 +1,17 @@ +package org.umlgraph.engine; + +import java.io.PrintWriter; + +public class DOTRenderingUtils { + public static void addAttribute(PrintWriter pw, String attribute, int value) { + pw.println(attribute + " = " + value); + } + + public static void addAttribute(PrintWriter pw, String attribute, String value) { + pw.println(attribute + " = \"" + value + "\""); + } + + public static void newLine(PrintWriter pw) { + pw.print("\\n"); + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/Diagram.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/Diagram.java new file mode 100644 index 0000000..ddd8008 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/Diagram.java @@ -0,0 +1,43 @@ +package org.umlgraph.engine; + +import org.umlgraph.engine.matching.AnyMatcher; +import org.umlgraph.engine.matching.ElementMatcher; +import org.umlgraph.settings.Settings; + +/** + * Represents a diagram by selecting a set of elements that should be depicted, + * and defining how those elements are shown. + * + * Includes: + *
    + *
  • a view, which determines which elements from a model will be + * depicted + *
  • layout settings, which affect how the selected elements + * should be depicted (colors, font faces, font sizes, etc)
  • + *
+ */ +public abstract class Diagram { + private String rootNamespace; + private ElementMatcher elementMatcher; + private Settings layoutSettings; + + public Diagram(String rootNamespace, ElementMatcher matcher) { + this.rootNamespace = rootNamespace; + this.elementMatcher = matcher == null ? AnyMatcher.INSTANCE : matcher; + this.layoutSettings = createSettings(); + } + + protected abstract Settings createSettings(); + + public Settings getLayoutSettings() { + return layoutSettings; + } + + public String getRootNamespace() { + return rootNamespace; + } + + public ElementMatcher getElementMatcher() { + return elementMatcher; + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/DiagramOptions.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/DiagramOptions.java index 19c6d47..4792914 100644 --- a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/DiagramOptions.java +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/DiagramOptions.java @@ -25,22 +25,22 @@ import org.umlgraph.settings.SettingDefinitions; */ public class DiagramOptions implements SettingDefinitions { - /** The default font size. */ - public static final int DEFAULT_FONT_SIZE = 10; - /** The default font name. */ public static final String DEFAULT_FONT_NAME = "Times"; - /** - * Layout the graph in the horizontal direction (boolean). - */ - public static boolean diagramHorizontal; + /** The default font size. */ + public static final int DEFAULT_FONT_SIZE = 10; /** * Specify the graph's background color. */ public static String diagramBackgroundColor; + /** + * Layout the graph in the horizontal direction (boolean). + */ + public static boolean diagramHorizontal; + /** * Specify entities to hide from the graph. Matching is done using a * non-anchored regular match. For instance, "-hide (Big|\.)Widget" would diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/DiagramRenderer.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/DiagramRenderer.java new file mode 100644 index 0000000..6788ca8 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/DiagramRenderer.java @@ -0,0 +1,7 @@ +package org.umlgraph.engine; + +import org.eclipse.emf.ecore.resource.ResourceSet; + +public interface DiagramRenderer { + public void render(ResourceSet resourceSet, D diagram, O output); +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/EdgeOptions.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/EdgeOptions.java index 8635fd3..18fd3e0 100644 --- a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/EdgeOptions.java +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/EdgeOptions.java @@ -24,6 +24,14 @@ import org.umlgraph.settings.SettingDefinitions; * Constants for edge options. */ public class EdgeOptions implements SettingDefinitions { + /** + * Specify the color for drawing edges. + */ + public static String edgeColor; + /** + * Specify the font color to use for edge labels (String). + */ + public static String edgeFontColor; /** * Specify the font name to use for edge labels (String). */ @@ -32,12 +40,4 @@ public class EdgeOptions implements SettingDefinitions { * Specify the font size to use for edge labels (int). */ public static Integer edgeFontSize = DiagramOptions.DEFAULT_FONT_SIZE; - /** - * Specify the font color to use for edge labels (String). - */ - public static String edgeFontColor; - /** - * Specify the color for drawing edges. - */ - public static String edgeColor; } diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/NodeOptions.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/NodeOptions.java index fd75df8..dc00e7c 100644 --- a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/NodeOptions.java +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/NodeOptions.java @@ -29,6 +29,11 @@ public class NodeOptions implements SettingDefinitions { */ public static String nodeFillColor; + /** + * Specify the font color to use inside nodes (String). + */ + public static String nodeFontColor; + /** * Specify the font name to use inside nodes (String). */ @@ -38,18 +43,13 @@ public class NodeOptions implements SettingDefinitions { * Specify the font size to use inside nodes (int). */ public static Integer nodeFontSize = DiagramOptions.DEFAULT_FONT_SIZE; - /** * Specify the font name to use for the tags (String). */ public static String nodeTagFontName = DiagramOptions.DEFAULT_FONT_NAME; + /** * Specify the font size to use for the tags (int). */ public static Integer nodeTagFontSize = DiagramOptions.DEFAULT_FONT_SIZE; - - /** - * Specify the font color to use inside nodes (String). - */ - public static String nodeFontColor; } diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/RelationType.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/RelationType.java new file mode 100644 index 0000000..09808c8 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/RelationType.java @@ -0,0 +1,11 @@ +package org.umlgraph.engine; + +/** + * The type of relation that links two entities + * + * @author wolf + * + */ +public enum RelationType { + ASSOC, COMPOSED, DEPEND, EXTENDS, HAS, IMPLEMENTS, NAVASSOC; +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/Util.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/Util.java new file mode 100644 index 0000000..cc66b08 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/Util.java @@ -0,0 +1,52 @@ +package org.umlgraph.engine; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Map; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.uml2.uml.UMLPackage; +import org.eclipse.uml2.uml.resource.UMLResource; + +public class Util { + + public static String getNamespace(Class class_) { + return class_.getPackage().getName(); + } + + private static void registerUML(ResourceSet resourceSet) { + resourceSet.getPackageRegistry().put(UMLPackage.eNS_URI, + UMLPackage.eINSTANCE); + resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap() + .put(UMLResource.FILE_EXTENSION, UMLResource.Factory.INSTANCE); + Map uriMap = resourceSet.getURIConverter().getURIMap(); + URL umlMetamodelURL = Util.class.getResource("/metamodels/UML.metamodel.uml"); + if (umlMetamodelURL == null) + throw new IllegalStateException( + "UML metamodel not found in the classpath"); + URL base; + try { + base = new URL(umlMetamodelURL, ".."); + } catch (MalformedURLException e) { + // should never happen, + // the URL is an existing valid URL + '..' + throw new IllegalStateException("Could not register packages", e); + } + URI uri = URI.createURI(base.toString()); + uriMap.put(URI.createURI(UMLResource.LIBRARIES_PATHMAP), uri + .appendSegment("libraries").appendSegment("")); + uriMap.put(URI.createURI(UMLResource.METAMODELS_PATHMAP), uri + .appendSegment("metamodels").appendSegment("")); + uriMap.put(URI.createURI(UMLResource.PROFILES_PATHMAP), uri + .appendSegment("profiles").appendSegment("")); + } + + public static ResourceSet createResourceSet() { + ResourceSet newResourceSet = new ResourceSetImpl(); + if (!Activator.isRunningOSGi()) + registerUML(newResourceSet); + return newResourceSet; + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/Visibility.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/Visibility.java new file mode 100644 index 0000000..4978447 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/Visibility.java @@ -0,0 +1,31 @@ +/* + * Create a graphviz graph based on the classes in the specified java + * source files. + * + * (C) Copyright 2002-2005 Diomidis Spinellis + * + * Permission to use, copy, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id$ + * + */ +package org.umlgraph.engine; + +/** + * Enumerates the possible visibilities in a Java program. For brevity, package + * private visibility is referred as PACKAGE. + * + * @author wolf + * + */ +public enum Visibility { + PACKAGE, PRIVATE, PROTECTED, PUBLIC; +} \ No newline at end of file diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ClassDiagram.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ClassDiagram.java new file mode 100644 index 0000000..071381a --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ClassDiagram.java @@ -0,0 +1,25 @@ +package org.umlgraph.engine.classdiagram; + +import org.umlgraph.engine.Diagram; +import org.umlgraph.engine.DiagramOptions; +import org.umlgraph.engine.EdgeOptions; +import org.umlgraph.engine.NodeOptions; +import org.umlgraph.engine.matching.ElementMatcher; +import org.umlgraph.settings.Settings; + +/** + * Any features specific to class diagrams are defined here. + */ +public class ClassDiagram extends Diagram { + + public ClassDiagram(String rootNamespace, + ElementMatcher matcher) { + super(rootNamespace, matcher); + } + + @Override + protected Settings createSettings() { + return new Settings(ClassDiagramOptions.class, ClassOptions.class, PackageOptions.class, NodeOptions.class, EdgeOptions.class, DiagramOptions.class); + } + +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/ClassDiagramOptions.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ClassDiagramOptions.java similarity index 60% rename from umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/ClassDiagramOptions.java rename to umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ClassDiagramOptions.java index 9c73c07..0d347ba 100644 --- a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/ClassDiagramOptions.java +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ClassDiagramOptions.java @@ -15,41 +15,53 @@ * $Id$ * */ -package org.umlgraph.engine; +package org.umlgraph.engine.classdiagram; +import org.umlgraph.engine.RelationType; +import org.umlgraph.engine.Visibility; import org.umlgraph.settings.SettingDefinitions; /** * Constants for class diagram options. */ public class ClassDiagramOptions implements SettingDefinitions { + /** + * The type of relationship inferred when -inferrel is activated. Defaults + * to "navassoc" (see the class modelling chapter for a list of relationship + * types). + */ + public static RelationType classDiagramInferAssociationType = RelationType.NAVASSOC; + + /** + * Try to automatically infer dependencies between classes by inspecting + * operation and attribute types. See the class diagram inference chapter + * for more details. Disabled by default. + */ + public static Boolean classDiagramInferDependency = false; + + /** + * Specifies the lowest visibility level of elements used to infer + * dependencies among classes. Possible values are private, package, + * protected, public, in this order. The default value is private. Use + * higher levels to limit the number of inferred dependencies. + */ + public static Visibility classDiagramInferDependencyVisibility = Visibility.PRIVATE; + + /** + * Try to automatically infer association relationships between classes by + * inspecting attribute types. See the class diagram inference chapter for + * further details. Disabled by default. + */ + public static Boolean classDiagramInferUsage = false; + + /** + * When using qualified class names, put the package name in the line after + * the class name, in order to reduce the width of class nodes. + */ + public static Boolean classDiagramPostfixQualifiedNames = false; + /** * Produce fully-qualified class names. */ public static Boolean classDiagramQualifiedNames = false; - - /** - * When using qualified class names, put the package name in the line after the class name, in order to reduce the width of class nodes. - */ - public static Boolean classDiagramPostfixQualifiedNames = false; - - /** - * Try to automatically infer dependencies between classes by inspecting operation and attribute types. See the class diagram inference chapter for more details. Disabled by default. - */ - public static Boolean classDiagramInferDependency = false; - - /** - * Try to automatically infer association relationships between classes by inspecting attribute types. See the class diagram inference chapter for further details. Disabled by default. - */ - public static Boolean classDiagramInferUsage = false; - - /** - * The type of relationship inferred when -inferrel is activated. Defaults to "navassoc" (see the class modelling chapter for a list of relationship types). - */ - public static String classDiagramInferAssociationType = "navassoc"; - - /** - * Specifies the lowest visibility level of elements used to infer dependencies among classes. Possible values are private, package, protected, public, in this order. The default value is private. Use higher levels to limit the number of inferred dependencies. - */ - public static String classDiagramInferDependencyVisibility = "private"; } diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/ClassOptions.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ClassOptions.java similarity index 93% rename from umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/ClassOptions.java rename to umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ClassOptions.java index 1a04ff4..932c1ba 100644 --- a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/ClassOptions.java +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ClassOptions.java @@ -16,8 +16,9 @@ * */ -package org.umlgraph.engine; +package org.umlgraph.engine.classdiagram; +import org.umlgraph.engine.DiagramOptions; import org.umlgraph.settings.SettingDefinitions; /** @@ -29,44 +30,44 @@ public class ClassOptions implements SettingDefinitions { */ public static String classAbstractFontName = DiagramOptions.DEFAULT_FONT_NAME; + /** + * Specify the font name use for the class name of abstract classes + * (String). + */ + public static String classAbstractNameFontName = DiagramOptions.DEFAULT_FONT_NAME; + + /** + * Add type information to attributes and operations (boolean) + */ + public static Boolean classFeatureTypes = false; /** * Specify the font name to use for the class names (String). */ public static String classNameFontName = DiagramOptions.DEFAULT_FONT_NAME; - /** - * Specify the font name use for the class name of abstract classes - * (String). - */ - public static String classAbstractNameFontName = DiagramOptions.DEFAULT_FONT_NAME; /** * Specify the font size to use for the class names (int). */ public static Integer classNameFontSize = DiagramOptions.DEFAULT_FONT_SIZE; - /** * Show class attributes (boolean). */ public static Boolean classShowAttributes = false; + + /** + * For enumerations, also show the values they can take. (boolean) + */ + public static Boolean classShowEnumValues = false; + /** * Show class operations (Java methods) */ public static Boolean classShowOperations = false; - + /** - * Adorn class elements according to their visibility (private, public, protected, package) (boolean). + * Adorn class elements according to their visibility (private, public, + * protected, package) (boolean). */ public static Boolean classShowVisibility = false; - - /** - * Add type information to attributes and operations (boolean) - */ - public static Boolean classFeatureTypes = false; - - /** - * For enumerations, also show the values they can take. (boolean) - */ - public static Boolean classShowEnumValues = false; - - + } diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ElementRenderer.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ElementRenderer.java new file mode 100644 index 0000000..0a98894 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ElementRenderer.java @@ -0,0 +1,13 @@ +package org.umlgraph.engine.classdiagram; + +import org.eclipse.uml2.uml.Element; + + +/** + * A renderer knows how to render a specific type of object. + * + * Clients to implement. + */ +public interface ElementRenderer { + public void renderObject(C element, RenderingSession context); +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ElementRendererSelector.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ElementRendererSelector.java new file mode 100644 index 0000000..5277563 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/ElementRendererSelector.java @@ -0,0 +1,46 @@ +package org.umlgraph.engine.classdiagram; + +import java.lang.reflect.Modifier; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.uml2.uml.Element; +import org.eclipse.uml2.uml.UMLPackage; + +class ElementRendererSelector { + + private static final EClass ELEMENT_CLASS = UMLPackage.eINSTANCE.getElement(); + + private Class> findRenderer(EClass elementClass) { + if (!ELEMENT_CLASS.isSuperTypeOf(elementClass)) + return null; + String className = elementClass.getName(); + String rendererClassName = getClass().getPackage().getName() + '.' + className + "Renderer"; + try { + return (Class>) Class.forName(rendererClassName); + } catch (ClassNotFoundException e) { + // try parent + EList superTypes = elementClass.getESuperTypes(); + for (EClass superType : superTypes) { + Class> renderer = findRenderer(superType); + if (renderer != null && !Modifier.isAbstract(renderer.getModifiers())) + return renderer; + } + return null; + } + } + + public ElementRenderer select(Element element) { + Class rendererClass = findRenderer(element.eClass()); + if (rendererClass == null) + return null; + try { + return (ElementRenderer) rendererClass.newInstance(); + } catch (InstantiationException e) { + UMLRenderingUtils.logUnexpected(rendererClass.getName(), e); + } catch (IllegalAccessException e) { + UMLRenderingUtils.logUnexpected(rendererClass.getName(), e); + } + return null; + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/PackageOptions.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/PackageOptions.java similarity index 93% rename from umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/PackageOptions.java rename to umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/PackageOptions.java index fe75920..6d255ba 100644 --- a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/PackageOptions.java +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/PackageOptions.java @@ -16,8 +16,9 @@ * */ -package org.umlgraph.engine; +package org.umlgraph.engine.classdiagram; +import org.umlgraph.engine.DiagramOptions; import org.umlgraph.settings.SettingDefinitions; /** diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/RenderingSession.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/RenderingSession.java new file mode 100644 index 0000000..639404c --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/RenderingSession.java @@ -0,0 +1,44 @@ +package org.umlgraph.engine.classdiagram; + +import java.util.Collection; + +import org.eclipse.uml2.uml.Element; +import org.umlgraph.engine.classdiagram.dot.IndentedPrintWriter; + +/** + * The representation for rendering sessions. + * + * A rendering session encapsulates + */ +public class RenderingSession { + private ElementRendererSelector selector = new ElementRendererSelector(); + private IndentedPrintWriter writer; + + public RenderingSession(IndentedPrintWriter writer) { + this.writer = writer; + } + + public IndentedPrintWriter getOutput() { + return writer; + } + + /** + * Convenience method that renders a collection of elements. + */ + public void render(Collection toRender) { + for (Element element : toRender) + render(element); + } + + /** + * Renders an element (and possibly its children). + * + * @param toRender element to render + */ + @SuppressWarnings("unchecked") + public void render(C toRender) { + ElementRenderer renderer = (ElementRenderer) selector.select(toRender); + if (renderer != null) + renderer.renderObject(toRender, this); + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/UMLRenderingUtils.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/UMLRenderingUtils.java new file mode 100644 index 0000000..63e338e --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/UMLRenderingUtils.java @@ -0,0 +1,55 @@ +package org.umlgraph.engine.classdiagram; + +import org.eclipse.uml2.uml.MultiplicityElement; +import org.eclipse.uml2.uml.VisibilityKind; + +public class UMLRenderingUtils { + + public static String ID = UMLRenderingUtils.class.getPackage().getName(); + + public static String addGuillemots(String original) { + return "« " + original + " »"; + } + + public static void logUnexpected(String message, Exception e) { + //TODO adopt logging + System.err.println(message); + e.printStackTrace(); + } + + public static String renderMultiplicity(MultiplicityElement multiple, boolean brackets) { + if (!multiple.isMultivalued()) + return ""; + if (multiple.lowerBound() == multiple.upperBound()) { + if (multiple.upperBound() == -1) + return wrapInBrackets("*", brackets); + else if (multiple.upperBound() != 1) { + return wrapInBrackets(Integer.toString(multiple.upperBound()), brackets); + } + return ""; + } + StringBuffer interval = new StringBuffer(); + interval.append(multiple.lowerBound()); + interval.append(".."); + interval.append(multiple.upperBound() == -1 ? "*" : multiple.upperBound()); + return wrapInBrackets(interval.toString(), brackets); + } + + public static String renderVisibility(VisibilityKind visibility) { + switch (visibility) { + case PACKAGE_LITERAL: + return "~"; + case PRIVATE_LITERAL: + return "-"; + case PROTECTED_LITERAL: + return "#"; + case PUBLIC_LITERAL: + return "+"; + } + return ""; + } + + private static String wrapInBrackets(String original, boolean useBrackets) { + return useBrackets ? "[" + original + "]" : " " + original; + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/AssociationRenderer.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/AssociationRenderer.java new file mode 100644 index 0000000..4742b98 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/AssociationRenderer.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) Abstratt Technologies 2007. All rights reserved. + */ +package org.umlgraph.engine.classdiagram.dot; + +import java.util.List; + +import org.eclipse.uml2.uml.AggregationKind; +import org.eclipse.uml2.uml.Association; +import org.eclipse.uml2.uml.Property; +import org.eclipse.uml2.uml.Type; +import org.umlgraph.engine.DOTRenderingUtils; +import org.umlgraph.engine.classdiagram.ElementRenderer; +import org.umlgraph.engine.classdiagram.RenderingSession; +import org.umlgraph.engine.classdiagram.UMLRenderingUtils; + +public class AssociationRenderer implements ElementRenderer { + + public void renderObject(Association element, RenderingSession context) { + if (!element.isBinary()) + // we humbly admit we can't handle n-ary associations + return; + IndentedPrintWriter pw = context.getOutput(); + List ends = element.getMemberEnds(); + Property source = ends.get(0); + Property target = ends.get(1); + if (!ends.get(0).isNavigable() || ends.get(1).getAggregation() != AggregationKind.NONE_LITERAL) { + source = ends.get(1); + target = ends.get(0); + } + Type targetType = target.getType(); + Type sourceType = source.getType(); + if (targetType == null || sourceType == null) + return; + pw.print("edge "); + pw.println("["); + pw.enterLevel(); + pw.println("style = \"none\""); + String style; + boolean constraint = true; + switch (source.getAggregation()) { + case COMPOSITE_LITERAL: + style = "diamond"; + break; + case SHARED_LITERAL: + style = "ediamond"; + break; + default: + constraint = false; + style = (target.isNavigable() || !source.isNavigable()) ? "none" : "open"; + } + DOTRenderingUtils.addAttribute(pw, "labelangle", "-12.5"); + DOTRenderingUtils.addAttribute(pw, "arrowtail", style); + DOTRenderingUtils.addAttribute(pw, "arrowhead", "none"); + DOTRenderingUtils.addAttribute(pw, "taillabel", source.getName() == null ? "" : source.getName() + + UMLRenderingUtils.renderMultiplicity(source, false)); + DOTRenderingUtils.addAttribute(pw, "headlabel", target.getName() == null ? "" : target.getName() + + UMLRenderingUtils.renderMultiplicity(target, false)); + // DOTRenderingUtils.addAttribute(pw, "labeldistance", "1.5"); + DOTRenderingUtils.addAttribute(pw, "labelangle", -30); + DOTRenderingUtils.addAttribute(pw, "len", "1.5"); + DOTRenderingUtils.addAttribute(pw, "constraint", Boolean.toString(constraint)); + pw.exitLevel(); + pw.println("]"); + pw.print(targetType.getName() + " -- " + sourceType.getName() + " "); + + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/ClassDiagramRenderer.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/ClassDiagramRenderer.java new file mode 100644 index 0000000..ea16143 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/ClassDiagramRenderer.java @@ -0,0 +1,67 @@ +package org.umlgraph.engine.classdiagram.dot; + +import java.io.OutputStream; +import java.util.Collection; + +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.uml2.uml.NamedElement; +import org.eclipse.uml2.uml.Package; +import org.eclipse.uml2.uml.UMLPackage; +import org.eclipse.uml2.uml.util.UMLUtil; +import org.umlgraph.engine.AbstractDiagramRenderer; +import org.umlgraph.engine.DOTRenderingUtils; +import org.umlgraph.engine.classdiagram.ClassDiagram; +import org.umlgraph.engine.classdiagram.RenderingSession; + +/** + * Knows how render a UML class diagram using Graphviz DOT language. + */ +public class ClassDiagramRenderer extends AbstractDiagramRenderer { + + + @Override + public void render(ResourceSet resourceSet, ClassDiagram diagram, + OutputStream diagramOutput) { + + Collection rootNamespaces = UMLUtil.findNamedElements( + resourceSet, diagram.getRootNamespace(), false, + UMLPackage.Literals.PACKAGE); + if (rootNamespaces.isEmpty()) + return; + Package rootElement = (Package) rootNamespaces.iterator().next(); + IndentedPrintWriter out = new IndentedPrintWriter(diagramOutput); + RenderingSession session = new RenderingSession(out); + printPrologue(rootElement.getQualifiedName(), out); + session.render(rootElement); + printEpilogue(out); + out.close(); + } + + private void printPrologue(String modelName, IndentedPrintWriter w) { + w.println("graph " + modelName + " {"); //$NON-NLS-1$ //$NON-NLS-2$ + w.enterLevel(); + DOTRenderingUtils.addAttribute(w, "ranksep", "0.5"); + DOTRenderingUtils.addAttribute(w, "nodesep", "0.85"); + DOTRenderingUtils.addAttribute(w, "nojustify", "true"); + DOTRenderingUtils.addAttribute(w, "splines", "polygonal"); + // TODO provide choice + w.println("node ["); + w.enterLevel(); + DOTRenderingUtils.addAttribute(w, "fontsize", 12); + DOTRenderingUtils.addAttribute(w, "shape", "record"); + w.exitLevel(); + w.println("]"); + w.println("edge ["); + w.enterLevel(); + DOTRenderingUtils.addAttribute(w, "fontsize", 10); + // DOTRenderingUtils.addAttribute(w, "splines", "polyline"); + w.exitLevel(); + w.println("]"); + } + + private void printEpilogue(IndentedPrintWriter w) { + w.exitLevel(); + w.println(); + w.println("}"); //$NON-NLS-1$ + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/ClassRenderer.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/ClassRenderer.java new file mode 100644 index 0000000..33b29b0 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/ClassRenderer.java @@ -0,0 +1,49 @@ +package org.umlgraph.engine.classdiagram.dot; + +import java.util.List; + +import org.eclipse.uml2.uml.Class; +import org.eclipse.uml2.uml.Generalization; +import org.eclipse.uml2.uml.InterfaceRealization; +import org.eclipse.uml2.uml.Stereotype; +import org.umlgraph.engine.DOTRenderingUtils; +import org.umlgraph.engine.classdiagram.ElementRenderer; +import org.umlgraph.engine.classdiagram.RenderingSession; +import org.umlgraph.engine.classdiagram.UMLRenderingUtils; + +public class ClassRenderer implements ElementRenderer { + + public void renderObject(Class element, RenderingSession context) { + IndentedPrintWriter w = context.getOutput(); + w.println("// class " + element.getQualifiedName()); + w.println('"' + element.getName() + "\" ["); + w.enterLevel(); + DOTRenderingUtils.addAttribute(w, "nojustify", "true"); + w.print("label=\"{"); + if (!element.getAppliedStereotypes().isEmpty()) + for (Stereotype current : element.getAppliedStereotypes()) { + w.print(UMLRenderingUtils.addGuillemots(current.getName())); + DOTRenderingUtils.newLine(w); + } + w.print(element.getName()); + + w.enterLevel(); + if (!element.getAttributes().isEmpty()) { + w.println("|\\"); + context.render(element.getAttributes()); + } + if (!element.getOperations().isEmpty()) { + w.println("|\\"); + context.render(element.getOperations()); + } + w.exitLevel(); + w.println("}\""); + w.exitLevel(); + w.println("]"); + List generalizations = element.getGeneralizations(); + context.render(generalizations); + List realizations = element.getInterfaceRealizations(); + context.render(realizations); + + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/EnumerationLiteralRenderer.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/EnumerationLiteralRenderer.java new file mode 100644 index 0000000..ecbab45 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/EnumerationLiteralRenderer.java @@ -0,0 +1,15 @@ +package org.umlgraph.engine.classdiagram.dot; + +import org.eclipse.uml2.uml.EnumerationLiteral; +import org.umlgraph.engine.classdiagram.ElementRenderer; +import org.umlgraph.engine.classdiagram.RenderingSession; + +public class EnumerationLiteralRenderer implements ElementRenderer { + + public void renderObject(EnumerationLiteral literal, RenderingSession context) { + IndentedPrintWriter w = context.getOutput(); + w.print(literal.getName()); + w.println("\\l\\"); + } + +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/EnumerationRenderer.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/EnumerationRenderer.java new file mode 100644 index 0000000..3dda6af --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/EnumerationRenderer.java @@ -0,0 +1,43 @@ +package org.umlgraph.engine.classdiagram.dot; + +import java.util.List; + +import org.eclipse.uml2.uml.Enumeration; +import org.eclipse.uml2.uml.Generalization; +import org.umlgraph.engine.DOTRenderingUtils; +import org.umlgraph.engine.classdiagram.ElementRenderer; +import org.umlgraph.engine.classdiagram.RenderingSession; +import org.umlgraph.engine.classdiagram.UMLRenderingUtils; + +public class EnumerationRenderer implements ElementRenderer { + public void renderObject(Enumeration element, RenderingSession context) { + IndentedPrintWriter w = context.getOutput(); + w.println("// enum " + element.getQualifiedName()); + w.println('"' + element.getName() + "\" ["); + w.enterLevel(); + w.print("label=\"{"); + w.print(UMLRenderingUtils.addGuillemots("enumeration")); + DOTRenderingUtils.newLine(w); + w.print(element.getName()); + w.enterLevel(); + if (!element.getAttributes().isEmpty()) { + w.println("|\\"); + context.render(element.getAttributes()); + } + if (!element.getOperations().isEmpty()) { + w.println("|\\"); + context.render(element.getOperations()); + } + if (!element.getOwnedLiterals().isEmpty()) { + w.println("|\\"); + context.render(element.getOwnedLiterals()); + } + w.exitLevel(); + w.println("}\""); + w.exitLevel(); + w.println("]"); + List generalizations = element.getGeneralizations(); + context.render(generalizations); + } + +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/ExtensionRenderer.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/ExtensionRenderer.java new file mode 100644 index 0000000..3ddf836 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/ExtensionRenderer.java @@ -0,0 +1,29 @@ +package org.umlgraph.engine.classdiagram.dot; + +import org.eclipse.uml2.uml.Extension; +import org.umlgraph.engine.DOTRenderingUtils; +import org.umlgraph.engine.classdiagram.ElementRenderer; +import org.umlgraph.engine.classdiagram.RenderingSession; + +public class ExtensionRenderer implements ElementRenderer { + + public void renderObject(Extension element, RenderingSession context) { + IndentedPrintWriter pw = context.getOutput(); + pw.print("edge "); + // if (element.getName() != null) + // pw.print("\"" + element.getName() + "\" "); + pw.println("["); + pw.enterLevel(); + pw.println("arrowtail = \"none\""); + pw.println("arrowhead = \"normal\""); + pw.println("taillabel = \"\""); + pw.println("headlabel = \"\""); + DOTRenderingUtils.addAttribute(pw, "constraint", "true"); + pw.println("style = \"none\""); + pw.exitLevel(); + pw.println("]"); + pw.println(element.getStereotype().getName() + " -- " + element.getMetaclass().getName()); + + } + +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/GeneralizationRenderer.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/GeneralizationRenderer.java new file mode 100644 index 0000000..6f93c5e --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/GeneralizationRenderer.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) Abstratt Technologies 2007. All rights reserved. + */ +package org.umlgraph.engine.classdiagram.dot; + +import org.eclipse.uml2.uml.Generalization; +import org.umlgraph.engine.DOTRenderingUtils; +import org.umlgraph.engine.classdiagram.ElementRenderer; +import org.umlgraph.engine.classdiagram.RenderingSession; + +/** + * + */ +public class GeneralizationRenderer implements ElementRenderer { + + /* + * (non-Javadoc) + * + * @see com.abstratt.modelviewer.render.IRenderer#renderObject(java.lang.Object, + * com.abstratt.modelviewer.IndentedPrintWriter, + * com.abstratt.modelviewer.render.IRenderingSession) + */ + public void renderObject(Generalization element, RenderingSession context) { + if (element.getGeneral().getNearestPackage() != element.getSpecific().getNearestPackage()) + return; + IndentedPrintWriter pw = context.getOutput(); + pw.print("edge "); + // if (element.getName() != null) + // pw.print("\"" + element.getName() + "\" "); + pw.println("["); + pw.enterLevel(); + pw.println("arrowtail = \"empty\""); + pw.println("arrowhead = \"none\""); + pw.println("taillabel = \"\""); + pw.println("headlabel = \"\""); + DOTRenderingUtils.addAttribute(pw, "constraint", "true"); + pw.println("style = \"none\""); + pw.exitLevel(); + pw.println("]"); + pw.println(element.getGeneral().getName() + " -- " + element.getSpecific().getName()); + } + +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/IndentedPrintWriter.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/IndentedPrintWriter.java new file mode 100644 index 0000000..c7abd4c --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/IndentedPrintWriter.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2007 Abstratt Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Abstratt Technologies - initial API and implementation + *******************************************************************************/ +package org.umlgraph.engine.classdiagram.dot; + +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; + +/** + * A print writer with an extended protocol that allows increasing/descreasing + * the level of indentation. + */ +public class IndentedPrintWriter extends PrintWriter { + public static final String DEFAULT_TAB_STRING = " "; + private int indentationLevel = 0; + private char[] tabString; + private boolean indented = false; + + public IndentedPrintWriter(OutputStream os) { + this(os, false); + } + + public IndentedPrintWriter(Writer w) { + this(w, false); + } + + public IndentedPrintWriter(OutputStream os, boolean flush) { + super(os, flush); + setTabString(DEFAULT_TAB_STRING); + } + + public IndentedPrintWriter(Writer w, boolean flush) { + super(w, flush); + setTabString(DEFAULT_TAB_STRING); + } + + public void setTabString(String tabString) { + this.tabString = tabString.toCharArray(); + } + + public String getTabString() { + return new String(this.tabString); + } + + public void enterLevel() { + indentationLevel++; + } + + public void exitLevel() { + if (indentationLevel == 0) + throw new IllegalStateException("No more levels to exit"); + indentationLevel--; + } + + @Override + public void println() { + super.println(); + indented = false; + } + + @Override + public void write(String s, int off, int len) { + indentIfNeeded(); + super.write(s, off, len); + } + + @Override + public void write(char[] buf, int off, int len) { + indentIfNeeded(); + super.write(buf, off, len); + } + + @Override + public void write(int c) { + indentIfNeeded(); + super.write(c); + } + + private void indentIfNeeded() { + if (!indented) { + indented = true; + indent(); + } + } + + private void indent() { + for (int i = 0; i < indentationLevel; i++) + super.print(tabString); + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/InterfaceRealizationRenderer.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/InterfaceRealizationRenderer.java new file mode 100644 index 0000000..581285b --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/InterfaceRealizationRenderer.java @@ -0,0 +1,26 @@ +package org.umlgraph.engine.classdiagram.dot; + +import org.eclipse.uml2.uml.InterfaceRealization; +import org.umlgraph.engine.DOTRenderingUtils; +import org.umlgraph.engine.classdiagram.ElementRenderer; +import org.umlgraph.engine.classdiagram.RenderingSession; + +public class InterfaceRealizationRenderer implements ElementRenderer { + + public void renderObject(InterfaceRealization element, RenderingSession context) { + if (element.getImplementingClassifier().getNearestPackage() != element.getContract().getNearestPackage()) + return; + IndentedPrintWriter pw = context.getOutput(); + pw.print("edge "); + pw.println("["); + pw.enterLevel(); + DOTRenderingUtils.addAttribute(pw, "arrowtail", "empty"); + DOTRenderingUtils.addAttribute(pw, "arrowhead", "none"); + DOTRenderingUtils.addAttribute(pw, "taillabel", ""); + DOTRenderingUtils.addAttribute(pw, "headlabel", ""); + DOTRenderingUtils.addAttribute(pw, "syle", "dashed"); + pw.exitLevel(); + pw.println("]"); + pw.println(element.getContract().getName() + " -> " + element.getImplementingClassifier().getName()); + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/InterfaceRenderer.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/InterfaceRenderer.java new file mode 100644 index 0000000..85a28b3 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/InterfaceRenderer.java @@ -0,0 +1,40 @@ +package org.umlgraph.engine.classdiagram.dot; + +import java.util.List; + +import org.eclipse.uml2.uml.Generalization; +import org.eclipse.uml2.uml.Interface; +import org.umlgraph.engine.DOTRenderingUtils; +import org.umlgraph.engine.classdiagram.ElementRenderer; +import org.umlgraph.engine.classdiagram.RenderingSession; +import org.umlgraph.engine.classdiagram.UMLRenderingUtils; + +public class InterfaceRenderer implements ElementRenderer { + + public void renderObject(Interface element, RenderingSession context) { + IndentedPrintWriter w = context.getOutput(); + w.println("// interface " + element.getQualifiedName()); + w.println('"' + element.getName() + "\" ["); + w.enterLevel(); + w.print("label=\"{"); + w.print(UMLRenderingUtils.addGuillemots("interface")); + DOTRenderingUtils.newLine(w); + w.print(element.getName()); + w.enterLevel(); + if (!element.getAttributes().isEmpty()) { + w.println("|\\"); + context.render(element.getAttributes()); + } + if (!element.getOperations().isEmpty()) { + w.println("|\\"); + context.render(element.getOperations()); + } + w.exitLevel(); + w.println("}\""); + w.exitLevel(); + w.println("]"); + List generalizations = element.getGeneralizations(); + context.render(generalizations); + } + +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/OperationRenderer.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/OperationRenderer.java new file mode 100644 index 0000000..c772997 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/OperationRenderer.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) Abstratt Technologies 2007. All rights reserved. + */ +package org.umlgraph.engine.classdiagram.dot; + +import java.util.List; + +import org.eclipse.uml2.uml.Operation; +import org.eclipse.uml2.uml.Parameter; +import org.eclipse.uml2.uml.ParameterDirectionKind; +import org.eclipse.uml2.uml.Type; +import org.umlgraph.engine.classdiagram.ElementRenderer; +import org.umlgraph.engine.classdiagram.RenderingSession; +import org.umlgraph.engine.classdiagram.UMLRenderingUtils; + +/** + * + */ +public class OperationRenderer implements ElementRenderer { + public void renderObject(Operation operation, RenderingSession context) { + IndentedPrintWriter w = context.getOutput(); + w.print(UMLRenderingUtils.renderVisibility(operation.getVisibility())); + w.print(operation.getName()); + w.print("("); + List parameters = operation.getOwnedParameters(); + Parameter returnParameter = null; + for (int i = 0; i < parameters.size(); i++) { + Parameter parameter = parameters.get(i); + if (parameter.getDirection() == ParameterDirectionKind.RETURN_LITERAL) + returnParameter = parameter; + else { + if (i > 0) + w.print(", "); + context.render(parameter); + } + } + w.print(")"); + if (returnParameter != null) { + w.print(" : "); + Type returnType = returnParameter.getType(); + w.print(returnType != null ? returnType.getName() : "null"); + } + w.println("\\l\\"); + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/PackageRenderer.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/PackageRenderer.java new file mode 100644 index 0000000..0501fd5 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/PackageRenderer.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) Abstratt Technologies 2007. All rights reserved. + */ +package org.umlgraph.engine.classdiagram.dot; + +import org.eclipse.uml2.uml.Package; +import org.umlgraph.engine.classdiagram.ElementRenderer; +import org.umlgraph.engine.classdiagram.RenderingSession; + +/** + * + */ +public class PackageRenderer implements ElementRenderer { + public void renderObject(Package allPackage, RenderingSession context) { + context.render(allPackage.getOwnedElements()); + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/ParameterRenderer.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/ParameterRenderer.java new file mode 100644 index 0000000..3b577c7 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/ParameterRenderer.java @@ -0,0 +1,21 @@ +package org.umlgraph.engine.classdiagram.dot; + +import org.eclipse.uml2.uml.Parameter; +import org.eclipse.uml2.uml.Type; +import org.umlgraph.engine.classdiagram.ElementRenderer; +import org.umlgraph.engine.classdiagram.RenderingSession; +import org.umlgraph.engine.classdiagram.UMLRenderingUtils; + +public class ParameterRenderer implements ElementRenderer { + + public void renderObject(Parameter parameter, RenderingSession context) { + IndentedPrintWriter w = context.getOutput(); + w.print(parameter.getName()); + w.print(" : "); + Type paramType = parameter.getType(); + if (paramType == null) + return; + w.print(paramType.getName()); + w.print(UMLRenderingUtils.renderMultiplicity(parameter, true)); + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/PropertyRenderer.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/PropertyRenderer.java new file mode 100644 index 0000000..95a415c --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/PropertyRenderer.java @@ -0,0 +1,20 @@ +package org.umlgraph.engine.classdiagram.dot; + +import org.eclipse.uml2.uml.Property; +import org.umlgraph.engine.classdiagram.ElementRenderer; +import org.umlgraph.engine.classdiagram.RenderingSession; +import org.umlgraph.engine.classdiagram.UMLRenderingUtils; + +public class PropertyRenderer implements ElementRenderer { + public void renderObject(Property property, RenderingSession context) { + IndentedPrintWriter w = context.getOutput(); + w.print(UMLRenderingUtils.renderVisibility(property.getVisibility())); + w.print(property.getName()); + if (property.getType() != null) { + w.print(" : "); + w.print(property.getType().getName()); + w.print(UMLRenderingUtils.renderMultiplicity(property, true)); + } + w.println("\\l\\"); + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/package.html b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/package.html new file mode 100644 index 0000000..2a4443d --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/dot/package.html @@ -0,0 +1,4 @@ +

+This package contains the class diagram DOT-based renderer (and all +supporting element renderers). +

\ No newline at end of file diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/package.html b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/package.html new file mode 100644 index 0000000..7b17a50 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/classdiagram/package.html @@ -0,0 +1,4 @@ +

+This package contains the class diagram-related features, including +the basic infrastructure for rendering. +

\ No newline at end of file diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/AndMatcher.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/AndMatcher.java new file mode 100644 index 0000000..2c3197a --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/AndMatcher.java @@ -0,0 +1,23 @@ +package org.umlgraph.engine.matching; + +import org.eclipse.uml2.uml.Element; + +/** + * A conjunction composite matcher. + */ +public class AndMatcher implements ElementMatcher { + + private ElementMatcher[] subMatchers; + + public AndMatcher(ElementMatcher... subMatchers) { + this.subMatchers = subMatchers; + } + + public boolean matches(Element element) { + for (ElementMatcher current : subMatchers) + if (!current.matches(element)) + return false; + return true; + } + +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/AnyMatcher.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/AnyMatcher.java new file mode 100644 index 0000000..6f39569 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/AnyMatcher.java @@ -0,0 +1,10 @@ +package org.umlgraph.engine.matching; + +import org.eclipse.uml2.uml.Element; + +public class AnyMatcher implements ElementMatcher { + public final static ElementMatcher INSTANCE = new AnyMatcher(); + public boolean matches(Element element) { + return true; + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/ElementMatcher.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/ElementMatcher.java new file mode 100644 index 0000000..2c13695 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/ElementMatcher.java @@ -0,0 +1,10 @@ +package org.umlgraph.engine.matching; + +import org.eclipse.uml2.uml.Element; + +/** + * Protocol for element matchers. + */ +public interface ElementMatcher { + public boolean matches(Element element); +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/GeneralizationTreeMatcher.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/GeneralizationTreeMatcher.java new file mode 100644 index 0000000..12ea246 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/GeneralizationTreeMatcher.java @@ -0,0 +1,29 @@ +package org.umlgraph.engine.matching; + +import org.eclipse.uml2.uml.Classifier; +import org.eclipse.uml2.uml.Element; + +public class GeneralizationTreeMatcher implements ElementMatcher { + private String generalName; + public GeneralizationTreeMatcher(String generalName) { + this.generalName = generalName; + } + public boolean matches(Element element) { + if (!(element instanceof Classifier)) + return false; + Classifier classifier = (Classifier) element; + if (classifier.getQualifiedName().equals(generalName)) + return true; + return isDescendant(classifier); + } + + private boolean isDescendant(Classifier current) { + if (current.getGeneral(generalName) != null) + return true; + for (Classifier general : current.getGenerals()) + if (isDescendant(general)) + return true; + return false; + } + +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/MatchingHelper.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/MatchingHelper.java new file mode 100644 index 0000000..47cc915 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/MatchingHelper.java @@ -0,0 +1,9 @@ +package org.umlgraph.engine.matching; + +import org.eclipse.emf.ecore.EClass; + +public class MatchingHelper { + public static ElementMatcher matchNameAndMetaClass(String name, EClass metaClass) { + return new AndMatcher(new NameMatcher(name, false), new MetaClassMatcher(metaClass, false)); + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/MetaClassMatcher.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/MetaClassMatcher.java new file mode 100644 index 0000000..4b7c892 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/MetaClassMatcher.java @@ -0,0 +1,21 @@ +package org.umlgraph.engine.matching; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.uml2.uml.Element; + +public class MetaClassMatcher implements ElementMatcher { + + private boolean exact; + private EClass metaClass; + + public MetaClassMatcher(EClass metaClass, boolean exact) { + this.metaClass = metaClass; + this.exact = exact; + } + + public boolean matches(Element element) { + return exact ? metaClass == element.eClass() : metaClass + .isInstance(element); + } + +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/NameMatcher.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/NameMatcher.java new file mode 100644 index 0000000..8a3982e --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/NameMatcher.java @@ -0,0 +1,25 @@ +package org.umlgraph.engine.matching; + +import org.eclipse.uml2.uml.Element; +import org.eclipse.uml2.uml.NamedElement; + +public class NameMatcher implements ElementMatcher { + + private boolean caseSensitive; + private String name; + + public NameMatcher(String name, boolean caseSensitive) { + this.name = name; + this.caseSensitive = caseSensitive; + } + + public boolean matches(Element element) { + if (!(element instanceof NamedElement)) + return false; + NamedElement named = (NamedElement) element; + String elementName = named.getQualifiedName(); + return caseSensitive ? name.equals(elementName) : name + .equalsIgnoreCase(elementName); + } + +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/NotMatcher.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/NotMatcher.java new file mode 100644 index 0000000..bdd0742 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/NotMatcher.java @@ -0,0 +1,21 @@ +package org.umlgraph.engine.matching; + +import org.eclipse.uml2.uml.Element; + +/** + * A negation matcher. + */ +public class NotMatcher implements ElementMatcher { + + private ElementMatcher baseMatcher; + + public boolean matches(Element element) { + return !baseMatcher.matches(element); + } + + public NotMatcher(ElementMatcher baseMatcher) { + super(); + this.baseMatcher = baseMatcher; + } + +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/OrMatcher.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/OrMatcher.java new file mode 100644 index 0000000..bf59160 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/OrMatcher.java @@ -0,0 +1,25 @@ +package org.umlgraph.engine.matching; + +import org.eclipse.uml2.uml.Element; + +/** + * A disjunction composite matcher. + * + */ +public class OrMatcher implements ElementMatcher { + + private ElementMatcher[] subMatchers; + + public OrMatcher(ElementMatcher[] subMatchers) { + super(); + this.subMatchers = subMatchers; + } + + public boolean matches(Element element) { + for (ElementMatcher current : subMatchers) + if (current.matches(element)) + return true; + return false; + } + +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/PatternMatcher.java b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/PatternMatcher.java new file mode 100644 index 0000000..5b39acb --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/PatternMatcher.java @@ -0,0 +1,49 @@ +/* + * Contributed by Andrea Aime + * (C) Copyright 2005-2008 Diomidis Spinellis + * (C) Copyright 2008 Abstratt Technologies + * + * Permission to use, copy, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id$ + * + */ +package org.umlgraph.engine.matching; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.uml2.uml.Element; +import org.eclipse.uml2.uml.NamedElement; + +/** + * Matches named elements performing a regular expression match on the element's + * qualified name. + * + * @author wolf + * @author rchaves + */ +public class PatternMatcher implements ElementMatcher { + private Pattern pattern; + + public PatternMatcher(Pattern pattern) { + this.pattern = pattern; + } + + public boolean matches(Element element) { + if (!(element instanceof NamedElement)) + return false; + NamedElement named = (NamedElement) element; + String elementName = named.getQualifiedName(); + Matcher matcher = pattern.matcher(elementName); + return matcher.matches(); + } +} diff --git a/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/package.html b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/package.html new file mode 100644 index 0000000..0fe0fa0 --- /dev/null +++ b/umlgraph_ng/org.umlgraph.engine/src/org/umlgraph/engine/matching/package.html @@ -0,0 +1,3 @@ +

+This package describes element matchers. +

\ No newline at end of file