first cut of UML2-based dot rendering (yet to adopt UMLGraph rendering code)

This commit is contained in:
Rafael Chaves 2008-01-14 07:45:24 +00:00
parent 5827cbcdf9
commit dd8886f5c4
55 changed files with 1408 additions and 72 deletions

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test-resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>

View File

@ -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

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,10 @@
<?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="_Qs0f4MJKEdyYwNdUIscG9w" name="payment">
<packagedElement xmi:type="uml:Class" xmi:id="_VMrWYMJKEdyYwNdUIscG9w" name="PaymentMethod"/>
<packagedElement xmi:type="uml:Class" xmi:id="_YjVwMMJKEdyYwNdUIscG9w" name="Cheque">
<generalization xmi:id="_rb_4QMJKEdyYwNdUIscG9w"/>
</packagedElement>
<packagedElement xmi:type="uml:Class" xmi:id="_bvgxQMJKEdyYwNdUIscG9w" name="CreditCard">
<generalization xmi:id="_usexkMJKEdyYwNdUIscG9w" general="_VMrWYMJKEdyYwNdUIscG9w"/>
</packagedElement>
</uml:Package>

View File

@ -0,0 +1,4 @@
<?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="_cCP-sMJYEdyYwNdUIscG9w" name="sample">
<packagedElement xmi:type="uml:Class" xmi:id="_e4CgEMJYEdyYwNdUIscG9w" name="SampleClass"/>
</uml:Package>

View File

@ -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

View File

@ -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.
* <p>
* A diagram renderer knows how to render a specific type
* of diagram.
* </p>
*/
public abstract class AbstractDiagramRenderer<D extends Diagram,O> {
/**
* 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);
}

View File

@ -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;
}
}

View File

@ -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");
}
}

View File

@ -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:
* <ul>
* <li>a view, which determines <em>which</em> elements from a model will be
* depicted
* <li>layout settings, which affect <em>how</em> the selected elements
* should be depicted (colors, font faces, font sizes, etc)</li>
* </ul>
*/
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;
}
}

View File

@ -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

View File

@ -0,0 +1,7 @@
package org.umlgraph.engine;
import org.eclipse.emf.ecore.resource.ResourceSet;
public interface DiagramRenderer<D extends Diagram, O> {
public void render(ResourceSet resourceSet, D diagram, O output);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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<URI, URI> 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;
}
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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";
}

View File

@ -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;
}

View File

@ -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<C extends Element> {
public void renderObject(C element, RenderingSession context);
}

View File

@ -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<? extends ElementRenderer<?>> findRenderer(EClass elementClass) {
if (!ELEMENT_CLASS.isSuperTypeOf(elementClass))
return null;
String className = elementClass.getName();
String rendererClassName = getClass().getPackage().getName() + '.' + className + "Renderer";
try {
return (Class<? extends ElementRenderer<?>>) Class.forName(rendererClassName);
} catch (ClassNotFoundException e) {
// try parent
EList<EClass> superTypes = elementClass.getESuperTypes();
for (EClass superType : superTypes) {
Class<? extends ElementRenderer<?>> 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;
}
}

View File

@ -16,8 +16,9 @@
*
*/
package org.umlgraph.engine;
package org.umlgraph.engine.classdiagram;
import org.umlgraph.engine.DiagramOptions;
import org.umlgraph.settings.SettingDefinitions;
/**

View File

@ -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<? extends Element> toRender) {
for (Element element : toRender)
render(element);
}
/**
* Renders an element (and possibly its children).
*
* @param toRender element to render
*/
@SuppressWarnings("unchecked")
public <C extends Element> void render(C toRender) {
ElementRenderer<C> renderer = (ElementRenderer<C>) selector.select(toRender);
if (renderer != null)
renderer.renderObject(toRender, this);
}
}

View File

@ -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 "&laquo; " + original + " &raquo;";
}
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;
}
}

View File

@ -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<Association> {
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<Property> 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() + " ");
}
}

View File

@ -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<ClassDiagram, OutputStream> {
@Override
public void render(ResourceSet resourceSet, ClassDiagram diagram,
OutputStream diagramOutput) {
Collection<NamedElement> 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$
}
}

View File

@ -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<Class> {
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<Generalization> generalizations = element.getGeneralizations();
context.render(generalizations);
List<InterfaceRealization> realizations = element.getInterfaceRealizations();
context.render(realizations);
}
}

View File

@ -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<EnumerationLiteral> {
public void renderObject(EnumerationLiteral literal, RenderingSession context) {
IndentedPrintWriter w = context.getOutput();
w.print(literal.getName());
w.println("\\l\\");
}
}

View File

@ -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<Enumeration> {
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<Generalization> generalizations = element.getGeneralizations();
context.render(generalizations);
}
}

View File

@ -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<Extension> {
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());
}
}

View File

@ -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<Generalization> {
/*
* (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());
}
}

View File

@ -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);
}
}

View File

@ -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<InterfaceRealization> {
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());
}
}

View File

@ -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<Interface> {
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<Generalization> generalizations = element.getGeneralizations();
context.render(generalizations);
}
}

View File

@ -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<Operation> {
public void renderObject(Operation operation, RenderingSession context) {
IndentedPrintWriter w = context.getOutput();
w.print(UMLRenderingUtils.renderVisibility(operation.getVisibility()));
w.print(operation.getName());
w.print("(");
List<Parameter> 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\\");
}
}

View File

@ -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<Package> {
public void renderObject(Package allPackage, RenderingSession context) {
context.render(allPackage.getOwnedElements());
}
}

View File

@ -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<Parameter> {
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));
}
}

View File

@ -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<Property> {
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\\");
}
}

View File

@ -0,0 +1,4 @@
<p>
This package contains the class diagram DOT-based renderer (and all
supporting element renderers).
</p>

View File

@ -0,0 +1,4 @@
<p>
This package contains the class diagram-related features, including
the basic infrastructure for rendering.
</p>

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -0,0 +1,3 @@
<p>
This package describes element matchers.
</p>