diff options
author | Florian Noyrit | 2016-02-10 10:50:11 +0000 |
---|---|---|
committer | florian noyrit | 2016-02-22 13:29:42 +0000 |
commit | 22c69dd32293c88628fc86a0082a61429f440960 (patch) | |
tree | 5716e5b0c8660e75220b214e544875d7fd61e02e /plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types | |
parent | bd8eb4a1d14a5aa246561fc9be9e72088e26307b (diff) | |
download | org.eclipse.papyrus-22c69dd32293c88628fc86a0082a61429f440960.tar.gz org.eclipse.papyrus-22c69dd32293c88628fc86a0082a61429f440960.tar.xz org.eclipse.papyrus-22c69dd32293c88628fc86a0082a61429f440960.zip |
Bug 487480 - Refactor elementtypesconfiguration framework
Insert a "oep/infra/types" layer to host the core
elementtypesconfiguration framework.
Move UML elementtypesconfiguration extensions to "oep/uml"
Move EMF elementtypesconfiguration extensions to "oep/infra/emf"
Move elementtypesconfiguration tests to
oep/tests/junit/plugins/infra/types
Rename all elementtypesconfiguration plugins (core, dev, tests and
extensions) and corresponfing packages to shorter qualifiers as follows:
oep.infra.elementtypesconfigurations -> oep.infra.types.core and
oep.infra.types
oep.infra.elementtypesconfigurations.edit -> oep.infra.types.edit
oep.infra.elementtypesconfigurations.editor -> oep.infra.types.editor
oep.infra.elementtypesconfigurations.ui -> oep.infra.types.ui
oep.infra.elementtypesconfigurations.invarianttypes ->
oep.infra.types.rulebased
oep.infra.elementtypesconfigurations.emf -> oep.infra.emf.types
oep.infra.elementtypesconfigurations.emf.ui -> oep.infra.emf.types.ui
oep.uml.elementtypesconfigurations -> oep.uml.types
oep.elementtypesconfigurations.developer -> oep.dev.types
oep.infra.elementtypesconfigurations.tests -> oep.infra.types.tests
oep.infra.elementtypesconfigurations.ui.tests ->
oep.infra.types.ui.tests
Change-Id: Iad7f5689b183e6ad29daab06a1cc2858ee408aa7
Diffstat (limited to 'plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types')
13 files changed, 1069 insertions, 0 deletions
diff --git a/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/AbstractGenerator.java b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/AbstractGenerator.java new file mode 100644 index 00000000000..3dfe2472595 --- /dev/null +++ b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/AbstractGenerator.java @@ -0,0 +1,153 @@ +/***************************************************************************** + * Copyright (c) 2014, 2015 Christian W. Damus 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.profile.types.generator; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Set; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.papyrus.infra.emf.utils.EMFHelper; +import org.eclipse.papyrus.uml.profile.types.generator.internal.Activator; +import org.eclipse.uml2.common.util.UML2Util; + +import com.google.common.base.Strings; +import com.google.common.collect.Sets; +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.Injector; + +/** + * Scaffolding for an Xtend model-to-model transformation. + * + * @param <T> + * the kind of model element that I generate from a UML profile + */ +public abstract class AbstractGenerator<I extends EObject, O extends EObject> { + + private final Injector injector; + + @Inject + @InputModel + private EClass inputType; + + @Inject + @OutputModel + private EClass outputType; + + @Inject + private Identifiers identifiers; + + public AbstractGenerator(Identifiers identifiers) { + this(new GeneratorModule(identifiers)); + } + + public AbstractGenerator(GeneratorModule module) { + super(); + + this.injector = Guice.createInjector(module); + injector.injectMembers(this); + } + + public String getLabel() { + String result = identifiers.getLabel(outputType); + + return Strings.isNullOrEmpty(result) ? "output model" : result; + } + + public IStatus generate(URI inputURI, URI outputURI) { + IStatus result; + ResourceSet resourceSet = new ResourceSetImpl(); + + try { + I input = UML2Util.load(resourceSet, inputURI, inputType); + result = generate(input, outputURI); + } finally { + EMFHelper.unload(resourceSet); + } + + return result; + } + + public IStatus generate(I input, URI outputURI) { + IStatus result; + ResourceSet resourceSet = new ResourceSetImpl(); + + try { + Resource output = resourceSet.createResource(outputURI); + + result = generate(input, output.getContents()); + + try { + output.save(null); + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Failed to save output", e)); + } + refreshContainer(outputURI); + } catch (CoreException e) { + result = e.getStatus(); + } finally { + EMFHelper.unload(resourceSet); + } + + return result; + } + + public IStatus generate(I input, EList<? super EObject> output) { + IStatus result = Status.OK_STATUS; + + output.add(generate(input)); + + return result; + } + + protected abstract O generate(I input); + + protected void refreshContainer(URI resourceURI) throws CoreException { + if (resourceURI.isPlatformResource()) { + IContainer container = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(resourceURI.toPlatformString(true))).getParent(); + if ((container != null) && container.isAccessible()) { + container.refreshLocal(IResource.DEPTH_ONE, null); + } + } else if (resourceURI.isFile()) { + try { + IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(new java.net.URI(resourceURI.toString())); + Set<IContainer> containers = Sets.newHashSet(); + for (IFile next : files) { + containers.add(next.getParent()); + } + + for (IContainer next : containers) { + next.refreshLocal(IResource.DEPTH_ONE, null); + } + } catch (URISyntaxException e) { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Bad resource URI", e)); + } + } + } +} diff --git a/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/ApplyStereotypeAdviceRule.xtend b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/ApplyStereotypeAdviceRule.xtend new file mode 100644 index 00000000000..7619fed8c3f --- /dev/null +++ b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/ApplyStereotypeAdviceRule.xtend @@ -0,0 +1,45 @@ +/***************************************************************************** + * Copyright (c) 2014, 2015 Christian W. Damus 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.profile.types.generator + +import javax.inject.Inject +import javax.inject.Singleton +import org.eclipse.papyrus.infra.types.ElementTypeConfiguration +import org.eclipse.uml2.uml.Stereotype +import org.eclipse.papyrus.uml.types.core.advices.applystereotype.ApplyStereotypeAdviceFactory + +/** + * Transformation rule for generating an {@link ApplyStereotypeAdviceConfiguration} from a UML {@link Stereotype}. + */ +@Singleton +class ApplyStereotypeAdviceRule { + static extension ApplyStereotypeAdviceFactory applyStereotypeAdviceConfigurationFactory = ApplyStereotypeAdviceFactory. + eINSTANCE + + @Inject extension ElementTypeRule + @Inject extension Identifiers + + def create createApplyStereotypeAdviceConfiguration toAdviceConfiguration(Stereotype umlStereotype, + ImpliedExtension umlExtension, ElementTypeConfiguration supertype) { + + identifier = umlStereotype.name.toFirstLower.qualified + supertype.hintSuffix + stereotypesToApply.add(umlStereotype.toStereotypeToApply(supertype)) + target = umlExtension.toElementType(supertype) + } + + private def create createStereotypeToApply toStereotypeToApply(Stereotype umlStereotype, ElementTypeConfiguration supertype) { + requiredProfiles.add(umlStereotype.profile.qualifiedName) + stereotypeQualifiedName = umlStereotype.qualifiedName + updateName = true + } +} diff --git a/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/ConfigurationSetRule.xtend b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/ConfigurationSetRule.xtend new file mode 100644 index 00000000000..ccb28f016c6 --- /dev/null +++ b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/ConfigurationSetRule.xtend @@ -0,0 +1,60 @@ +/***************************************************************************** + * Copyright (c) 2014, 2015 Christian W. Damus 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: + * Christian W. Damus - Initial API and implementation + * Benoit Maggi - #474408 : order by identifier the generated file + *****************************************************************************/ +package org.eclipse.papyrus.uml.profile.types.generator + +import java.util.List +import javax.inject.Inject +import javax.inject.Singleton +import org.eclipse.papyrus.infra.types.AbstractAdviceBindingConfiguration +import org.eclipse.papyrus.infra.types.ElementTypeConfiguration +import org.eclipse.papyrus.infra.types.ElementTypeSetConfiguration +import org.eclipse.uml2.uml.Profile +import org.eclipse.uml2.uml.UMLPackage +import org.eclipse.papyrus.infra.types.ElementTypesConfigurationsFactory + +/** + * Transformation rule for generating an {@link ElementTypeSetConfiguration} from a UML {@link Profile}. + */ +@Singleton +class ConfigurationSetRule { + static extension ElementTypesConfigurationsFactory elementtypesconfigurationsFactory = ElementTypesConfigurationsFactory. + eINSTANCE + + @Inject extension Identifiers + @Inject extension UML + @Inject extension UMLElementTypes + @Inject extension ElementTypeRule + @Inject extension ApplyStereotypeAdviceRule + + def create createElementTypeSetConfiguration toConfigurationSet(Profile umlProfile) { + + // Initialize the generation of IDs + umlProfile.setIdentifierBase + + identifier = "elementTypes".qualified + metamodelNsURI = baseUMLElementTypeSet?.metamodelNsURI ?: UMLPackage.eNS_URI; + + val List<ElementTypeConfiguration> elementTypeConfigurationList = newArrayList() + val List<AbstractAdviceBindingConfiguration> adviceBindingConfigurationList = newArrayList() + + umlProfile.allExtensions.forEach[ext | + elementTypeConfigurationList.addAll(ext.metaclass.diagramSpecificElementTypes.map[ext.toElementType(it)]) + + // We only need to generate advice bindings for element types that won't inherit the from a parent semantic type + val typesNeedingAdvice = ext.metaclass.diagramSpecificElementTypes.filter[!hasSemanticSupertype] + adviceBindingConfigurationList.addAll(typesNeedingAdvice.map[ext.stereotype.toAdviceConfiguration(ext, it)]) + ] + adviceBindingsConfigurations.addAll(adviceBindingConfigurationList.sortBy[identifier]) + elementTypeConfigurations.addAll(elementTypeConfigurationList.sortBy[identifier]) + } +} diff --git a/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/ElementTypeRule.xtend b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/ElementTypeRule.xtend new file mode 100644 index 00000000000..9d37c8f1844 --- /dev/null +++ b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/ElementTypeRule.xtend @@ -0,0 +1,101 @@ +/***************************************************************************** + * Copyright (c) 2014, 2015 Christian W. Damus 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.profile.types.generator + +import javax.inject.Inject +import javax.inject.Singleton +import org.eclipse.core.resources.ResourcesPlugin +import org.eclipse.emf.common.util.URI +import org.eclipse.emf.ecore.EObject + +import org.eclipse.uml2.uml.Stereotype + +import static extension org.eclipse.emf.common.util.URI.decode +import org.eclipse.papyrus.infra.types.SpecializationTypeConfiguration +import org.eclipse.papyrus.infra.types.ElementTypeConfiguration +import org.eclipse.papyrus.infra.types.ElementTypesConfigurationsFactory +import org.eclipse.papyrus.uml.types.core.matchers.stereotype.StereotypeApplicationMatcherFactory + +/** + * Transformation rule for generating a {@link SpecializationTypeConfiguration} from a UML metaclass {@link Extension}. + */ +@Singleton +class ElementTypeRule { + static extension ElementTypesConfigurationsFactory elementtypesconfigurationsFactory = ElementTypesConfigurationsFactory. + eINSTANCE + static extension StereotypeApplicationMatcherFactory stereotypeApplicationMatcherConfigurationFactory = StereotypeApplicationMatcherFactory. + eINSTANCE + + @Inject extension UMLElementTypes + @Inject extension Identifiers + + def create createSpecializationTypeConfiguration toElementType(ImpliedExtension umlExtension, + ElementTypeConfiguration supertype) { + + // Basics + identifier = umlExtension.toElementTypeID(supertype) + if (supertype.hasSemanticSupertype) { + // Add the base semantic type in addition to the parent visual type + specializedTypesID.add(umlExtension.toElementTypeID(umlExtension.metaclass.elementTypeConfiguration)) + } + specializedTypesID.add(supertype.identifier) + hint = supertype.hint + name = umlExtension.toElementTypeName(supertype) + + // Icon + var icon = umlExtension.stereotype.iconEntry + iconEntry = if(icon != null) icon else umlExtension.metaclass.iconEntry + + // Add stereotype matcher, if it isn't inherited from a semantic supertype + if (!supertype.hasSemanticSupertype) { + matcherConfiguration = umlExtension.toMatcherConfiguration(supertype) + } + } + + private def create createStereotypeApplicationMatcherConfiguration toMatcherConfiguration(ImpliedExtension umlExtension, + ElementTypeConfiguration supertype) { + + stereotypesQualifiedNames.add(umlExtension.stereotype.qualifiedName) + } + + private def getIconEntry(Stereotype stereotype) { + val image = stereotype.icons.findFirst[!location.nullOrEmpty] + if (image != null) { + val uri = URI.createURI(image.location, true) + + if (uri != null) { + createIconEntry => [ + if (uri.platform) { + + // Explicit platform-scheme URI + bundleId = uri.segment(1) + iconPath = "/" + uri.segmentsList.drop(2).join("/", [decode]) + } else if (uri.relative) { + + // Bundle-relative path. Infer the bundle ID from the containing project + bundleId = stereotype.containingProject.name + iconPath = "/" + uri.toString.decode + } else { + + // Absolute URI: use as is; don't decode it + iconPath = uri.toString + } + ] + } + } + } + + private def containingProject(EObject object) { + ResourcesPlugin.workspace.root.getProject(object.eResource.URI.segment(2)) + } +} diff --git a/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/ElementTypesGenerator.java b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/ElementTypesGenerator.java new file mode 100644 index 00000000000..e300a7d62f5 --- /dev/null +++ b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/ElementTypesGenerator.java @@ -0,0 +1,41 @@ +/***************************************************************************** + * Copyright (c) 2014, 2015 Christian W. Damus 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.profile.types.generator; + +import org.eclipse.papyrus.infra.types.ElementTypeSetConfiguration; +import org.eclipse.uml2.uml.Profile; + +import com.google.inject.Inject; + +/** + * The generator facade for the UML Profile to Element Types Set Configuration transformation. + */ +public class ElementTypesGenerator extends AbstractGenerator<Profile, ElementTypeSetConfiguration> { + + @Inject + private ConfigurationSetRule mainRule; + + public ElementTypesGenerator(Identifiers identifiers) { + this(new GeneratorModule(identifiers)); + } + + public ElementTypesGenerator(GeneratorModule module) { + super(module); + } + + @Override + protected ElementTypeSetConfiguration generate(Profile profile) { + return mainRule.toConfigurationSet(profile); + } +} diff --git a/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/GeneratorModule.java b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/GeneratorModule.java new file mode 100644 index 00000000000..1a69f63f9c7 --- /dev/null +++ b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/GeneratorModule.java @@ -0,0 +1,77 @@ +/***************************************************************************** + * Copyright (c) 2014, 2015 Christian W. Damus 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.profile.types.generator; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.papyrus.infra.types.ElementTypesConfigurationsPackage; +import org.eclipse.uml2.uml.UMLPackage; + +import com.google.inject.AbstractModule; + +/** + * The base Guice injector module for the UML Profile to Element Types Set Configuration transformation. + */ +public class GeneratorModule extends AbstractModule { + private final Identifiers identifiers; + + public GeneratorModule(Identifiers identifiers) { + super(); + + this.identifiers = identifiers; + } + + @Override + protected void configure() { + // bind transformation parameters + bindInputType(); + bindOutputType(); + + // bind extensions + bindIdentifiers(); + bindUMLElementTypes(); + + // bind transformation rules + bindConfigurationSetRule(); + bindElementTypeRule(); + bindApplyStereotypeAdviceRule(); + } + + protected void bindInputType() { + bind(EClass.class).annotatedWith(InputModel.class).toInstance(UMLPackage.Literals.PROFILE); + } + + protected void bindOutputType() { + bind(EClass.class).annotatedWith(OutputModel.class).toInstance(ElementTypesConfigurationsPackage.Literals.ELEMENT_TYPE_SET_CONFIGURATION); + } + + protected void bindIdentifiers() { + bind(Identifiers.class).toInstance(identifiers); + } + + protected void bindUMLElementTypes() { + // Pass + } + + protected void bindConfigurationSetRule() { + // Pass + } + + protected void bindElementTypeRule() { + // Pass + } + + protected void bindApplyStereotypeAdviceRule() { + // Pass + } +} diff --git a/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/Identifiers.xtend b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/Identifiers.xtend new file mode 100644 index 00000000000..17693cbbdbe --- /dev/null +++ b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/Identifiers.xtend @@ -0,0 +1,112 @@ +/***************************************************************************** + * Copyright (c) 2014, 2015 Christian W. Damus 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.profile.types.generator + +import static extension org.eclipse.uml2.common.util.UML2Util.getValidJavaIdentifier + +import org.eclipse.xtend.lib.annotations.Accessors +import javax.inject.Singleton +import org.eclipse.papyrus.infra.types.ElementTypeConfiguration +import org.eclipse.papyrus.infra.types.SpecializationTypeConfiguration +import javax.inject.Inject +import org.eclipse.papyrus.infra.types.ElementTypeSetConfiguration +import org.eclipse.emf.common.notify.AdapterFactory +import org.eclipse.emf.ecore.EObject +import org.eclipse.emf.edit.provider.IItemLabelProvider +import org.eclipse.emf.ecore.EClassifier +import org.eclipse.emf.common.util.ResourceLocator + +/** + * Utility extensions for working with and generating unique identifiers in the element types model. + */ +@Singleton +class Identifiers { + @Inject extension UMLElementTypes + + @Accessors + String prefix + + @Accessors + final String umlElementTypesSet = "org.eclipse.papyrus.uml.service.types.UMLElementTypeSet" + + @Accessors + final String contextId = "org.eclipse.papyrus.infra.services.edit.TypeContext"; + + @Accessors + String baseElementTypesSet = umlElementTypesSet + + @Accessors + ElementTypeSetConfiguration baseElementTypesSetConfiguration + + @Accessors + boolean suppressSemanticSuperElementTypes + + @Accessors + AdapterFactory adapterFactory + + String identifierBase + + def setIdentifierBase(org.eclipse.uml2.uml.Package umlPackage) { + identifierBase = prefix + } + + def getQualified(String id) { + identifierBase + "." + id + } + + def toElementTypeID(ImpliedExtension umlExtension, ElementTypeConfiguration supertype) { + val stereo = umlExtension.stereotype + var name = if (stereo.allExtendedMetaclasses.size <= 1) stereo.name else stereo.name + "_" + umlExtension.metaclass.name + name.validJavaIdentifier.qualified + supertype.hintSuffix + } + + def toElementTypeName(ImpliedExtension umlExtension, ElementTypeConfiguration supertype) { + val stereo = umlExtension.stereotype + val discriminators = newArrayList() => [ + if (stereo.extensions.size > 1) add(umlExtension.metaclass.name) + if (!supertype.hint.nullOrEmpty && (umlExtension.metaclass.diagramSpecificElementTypes.size > 1)) add(supertype.hint) + ] + + if (discriminators.nullOrEmpty) + if (stereo.allExtendedMetaclasses.size <= 1) stereo.name + else stereo.name + " " + umlExtension.metaclass.name + else stereo.name + discriminators.join(" (", ", ", ")")[toString] + } + + def dispatch hintSuffix(ElementTypeConfiguration elementType) { + "" + } + + def dispatch hintSuffix(SpecializationTypeConfiguration elementType) { + if (elementType.hint.nullOrEmpty) "" else "_" + elementType.hint + } + + def dispatch getLabel(EObject object) { + val labels = adapterFactory?.adapt(object, IItemLabelProvider) as IItemLabelProvider + labels?.getText(object) + } + + def dispatch getLabel(EClassifier eClassifier) { + try { + eClassifier.resourceLocator?.getString("_UI_" + eClassifier.name + "_type") + } catch (Exception e) { + eClassifier.name + } + } + + private def ResourceLocator getResourceLocator(EObject object) { + switch adapter : adapterFactory?.adapt(object, IItemLabelProvider) { + ResourceLocator : adapter + } + } +} diff --git a/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/ImpliedExtension.xtend b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/ImpliedExtension.xtend new file mode 100644 index 00000000000..97cc26e94e2 --- /dev/null +++ b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/ImpliedExtension.xtend @@ -0,0 +1,28 @@ +/***************************************************************************** + * Copyright (c) 2015 Christian W. Damus 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.profile.types.generator + +import org.eclipse.xtend.lib.annotations.Data +import org.eclipse.uml2.uml.Class +import org.eclipse.uml2.uml.Stereotype + +/** + * An analogue of the UML {@code Extension} metaclass that represents an implied metaclass extension. + * This may be modeled in the profile either directly, via an extension, or indirectly, via an + * inherited extension. + */ +@Data class ImpliedExtension { + Stereotype stereotype + Class metaclass +} diff --git a/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/InputModel.java b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/InputModel.java new file mode 100644 index 00000000000..08eb000227a --- /dev/null +++ b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/InputModel.java @@ -0,0 +1,31 @@ +/***************************************************************************** + * Copyright (c) 2015 Christian W. Damus 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.profile.types.generator; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import com.google.inject.BindingAnnotation; + +/** + * Injector annotation for the model-to-model transformation's input model type. + */ +@BindingAnnotation +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER }) +public @interface InputModel { + // Empty +} diff --git a/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/OutputModel.java b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/OutputModel.java new file mode 100644 index 00000000000..50b34bb4a98 --- /dev/null +++ b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/OutputModel.java @@ -0,0 +1,31 @@ +/***************************************************************************** + * Copyright (c) 2015 Christian W. Damus 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.profile.types.generator; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import com.google.inject.BindingAnnotation; + +/** + * Injector annotation for the model-to-model transformation's output model type. + */ +@BindingAnnotation +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER }) +public @interface OutputModel { + // Empty +} diff --git a/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/UML.xtend b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/UML.xtend new file mode 100644 index 00000000000..3befa66d888 --- /dev/null +++ b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/UML.xtend @@ -0,0 +1,117 @@ +/***************************************************************************** + * Copyright (c) 2014, 2015 Christian W. Damus 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.profile.types.generator + +import static org.eclipse.uml2.uml.UMLPackage.Literals.* + +import javax.inject.Singleton +import org.eclipse.uml2.uml.NamedElement +import org.eclipse.uml2.uml.Stereotype +import org.eclipse.uml2.uml.Profile +import org.eclipse.emf.ecore.EClass +import org.eclipse.emf.ecore.EReference +import java.util.Set + +/** + * Utility extensions for working with UML models and elements. + */ +@Singleton +class UML { + + // Each of these corresponds to a case in the getSourceReferences(...) and getTargetReferences(...) extensions + final Set<EClass> relationshipLikeUMLMetaclasses = #{ RELATIONSHIP, GENERALIZATION_SET, CONNECTOR, ACTIVITY_EDGE, TRANSITION, MESSAGE } + + def dispatch getProfile(Profile element) { + element + } + + def dispatch getProfile(NamedElement element) { + element.allOwningPackages.filter(Profile).head + } + + def dispatch getProfile(ImpliedExtension umlExtension) { + umlExtension.stereotype.profile + } + + def dispatch Profile getRootProfile(Profile element) { + element.namespace?.rootProfile ?: element + } + def dispatch getRootProfile(NamedElement element) { + element.allOwningPackages.filter(Profile).last + } + + def Iterable<ImpliedExtension> getAllExtensions(org.eclipse.uml2.uml.Package package_) { + package_.ownedTypes.filter(Stereotype).map[impliedExtensions].flatten + + package_.nestedPackages.map[allExtensions].flatten + } + + def Iterable<ImpliedExtension> impliedExtensions(Stereotype stereotype) { + stereotype.allExtendedMetaclasses.map[new ImpliedExtension(stereotype, it)] + } + + def isRelationship(EClass eClass) { + relationshipLikeUMLMetaclasses.exists[isSuperTypeOf(eClass)] + } + + def getSourceReferences(EClass relationshipClass) { + switch relationshipClass { + case DIRECTED_RELATIONSHIP.isSuperTypeOf(relationshipClass): + relationshipClass.EAllReferences.filter[!derived && changeable && subsets(DIRECTED_RELATIONSHIP__SOURCE)] + case ASSOCIATION.isSuperTypeOf(relationshipClass): + // ends are both source and target + #[ASSOCIATION__END_TYPE] + case CONNECTOR.isSuperTypeOf(relationshipClass): + // ends are both source and target + #[CONNECTOR__END] + case ACTIVITY_EDGE.isSuperTypeOf(relationshipClass): + #[ACTIVITY_EDGE__SOURCE] + case TRANSITION.isSuperTypeOf(relationshipClass): + #[TRANSITION__SOURCE] + case MESSAGE.isSuperTypeOf(relationshipClass): + #[MESSAGE__SEND_EVENT] + case GENERALIZATION_SET.isSuperTypeOf(relationshipClass): + // generalization sets just connect a bunch of generalizations + #[GENERALIZATION_SET__GENERALIZATION] + default: + #[] + } + } + + def getTargetReferences(EClass relationshipClass) { + switch relationshipClass { + case DIRECTED_RELATIONSHIP.isSuperTypeOf(relationshipClass): + relationshipClass.EAllReferences.filter[!derived && changeable && subsets(DIRECTED_RELATIONSHIP__TARGET)] + case ASSOCIATION.isSuperTypeOf(relationshipClass): + // ends are both source and target + #[ASSOCIATION__END_TYPE] + case CONNECTOR.isSuperTypeOf(relationshipClass): + // ends are both source and target + #[CONNECTOR__END] + case ACTIVITY_EDGE.isSuperTypeOf(relationshipClass): + #[ACTIVITY_EDGE__TARGET] + case TRANSITION.isSuperTypeOf(relationshipClass): + #[TRANSITION__TARGET] + case MESSAGE.isSuperTypeOf(relationshipClass): + #[MESSAGE__RECEIVE_EVENT] + case GENERALIZATION_SET.isSuperTypeOf(relationshipClass): + // generalization sets just connect a bunch of generalizations + #[GENERALIZATION_SET__GENERALIZATION] + default: + #[] + } + } + + def subsets(EReference subset, EReference superset) { + subset.getEAnnotation("subsets")?.references?.contains(superset) + } +} diff --git a/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/UMLElementTypes.xtend b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/UMLElementTypes.xtend new file mode 100644 index 00000000000..38c844db6f9 --- /dev/null +++ b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/UMLElementTypes.xtend @@ -0,0 +1,226 @@ +/***************************************************************************** + * Copyright (c) 2014, 2015 Christian W. Damus 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ +package org.eclipse.papyrus.uml.profile.types.generator + +import javax.inject.Inject +import javax.inject.Singleton +import org.eclipse.emf.ecore.EClass +import org.eclipse.gmf.runtime.emf.type.core.ElementTypeRegistry +import org.eclipse.gmf.runtime.emf.type.core.IElementType +import org.eclipse.gmf.runtime.emf.type.core.IMetamodelType +import org.eclipse.gmf.runtime.emf.type.core.ISpecializationType +import org.eclipse.papyrus.infra.types.ElementTypeConfiguration +import org.eclipse.papyrus.infra.types.IconEntry +import org.eclipse.papyrus.infra.types.MetamodelTypeConfiguration +import org.eclipse.papyrus.infra.types.SpecializationTypeConfiguration +import org.eclipse.papyrus.infra.types.core.registries.ElementTypeSetConfigurationRegistry +import org.eclipse.uml2.uml.Class +import org.eclipse.uml2.uml.UMLPackage +import java.util.regex.Pattern +import org.eclipse.papyrus.infra.types.ElementTypesConfigurationsFactory + +/** + * Utility extensions for working with and generating objects for the base UML element types specialized by the profile. + */ +@Singleton +class UMLElementTypes { + private static final Pattern VISUAL_ID_PATTERN = Pattern.compile("\\d{4}"); + + static extension ElementTypesConfigurationsFactory elementtypesconfigurationsFactory = ElementTypesConfigurationsFactory. + eINSTANCE + + @Inject extension Identifiers + @Inject extension UML + + def getElementTypeID(Class metaclass) { + "org.eclipse.papyrus.uml." + metaclass.name + } + + def getElementTypeConfiguration(Class metaclass) { + baseUMLElementTypeSet.elementTypeConfigurations.findFirst[identifier == metaclass.elementTypeID] + } + + def getBaseUMLElementTypeSet() { + ElementTypeSetConfigurationRegistry.getInstance.getElementTypeSetConfigurations().get(contextId).get(umlElementTypesSet) + } + + def getBaseUMLElementTypes() { + baseUMLElementTypeSet.elementTypeConfigurations.map [ + ElementTypeRegistry.getInstance.getType(identifier) + ].filterNull + } + + def getEClass(Class metaclass) { + UMLPackage.eINSTANCE.getEClassifier(metaclass.name) as EClass + } + + def getIconEntry(Class metaclass) { + metaclass.elementTypeConfiguration?.iconEntry.copy() + } + + private def copy(IconEntry prototype) { + createIconEntry() => [ + bundleId = prototype.bundleId + iconPath = prototype.iconPath + ] + } + + def getBaseElementTypeSet() { + baseElementTypesSetConfiguration ?: ElementTypeSetConfigurationRegistry.getInstance.getElementTypeSetConfigurations().get(contextId).get(baseElementTypesSet) + } + + def getBaseElementTypes() { + baseElementTypeSet.elementTypeConfigurations.filter[validType] + } + + def validType(ElementTypeConfiguration elementType) { + elementType.metaclass != null; + } + + private def isDiagramSpecific() { + baseElementTypeSet != baseUMLElementTypeSet + } + + def isDiagramSpecific(ElementTypeConfiguration type) { + type.hint.isVisualID + } + + def hasSemanticSupertype(ElementTypeConfiguration type) { + type.isDiagramSpecific && !suppressSemanticSuperElementTypes + } + + private def isVisualID(String string) { + !string.nullOrEmpty && VISUAL_ID_PATTERN.matcher(string).matches + } + + def getDiagramSpecificElementTypes(Class metaclass) { + // If we're based on the UML element types, themselves, then we're not looking for specializations + if (!diagramSpecific) + baseUMLElementTypeSet.elementTypeConfigurations.filter [ + validType && (identifier == metaclass.elementTypeID) + ] + else + baseElementTypeSet.elementTypeConfigurations.filter(SpecializationTypeConfiguration).filter [ + validType && specializedTypesID.contains(metaclass.elementTypeID) + ] + } + + private def canContain(IElementType containerType, EClass containedEClass) { + containerType.EClass.EAllContainments.exists[EReferenceType.isSuperTypeOf(containedEClass)] + } + + private def canContain(ElementTypeConfiguration containerType, EClass containedEClass) { + ElementTypeRegistry.getInstance.getType(containerType.identifier)?.canContain(containedEClass) + } + + def dispatch canContainType(ElementTypeConfiguration containerType, ElementTypeConfiguration containedTypeConfiguration) { + false + } + + def dispatch canContainType(ElementTypeConfiguration containerType, MetamodelTypeConfiguration containedTypeConfiguration) { + containerType.canContain(containedTypeConfiguration.EClass) + } + + def dispatch canContainType(ElementTypeConfiguration containerType, SpecializationTypeConfiguration containedTypeConfiguration) { + containedTypeConfiguration.specializedTypesID.exists [ supertype | + containerType.canContain(ElementTypeRegistry.getInstance.getType(supertype).EClass) + ] + } + + def isRelationship(IElementType elementType) { + // If the EClass is null, then assume it's something like the Constraint::annotatedElement reference type + // which is like a relationship + (elementType.EClass == null) || elementType.EClass.relationship + } + + def isRelationship(ElementTypeConfiguration elementType) { + // If the EClass is null, then assume it's something like the Constraint::annotatedElement reference type + // which is like a relationship + (elementType.metaclass == null) || elementType.metaclass.relationship + } + + private def dispatch EClass getMetaclass(ElementTypeConfiguration elementType) { + null + } + + private def dispatch EClass getMetaclass(SpecializationTypeConfiguration elementType) { + var IElementType registered = ElementTypeRegistry.instance.getType(elementType.identifier) + if (registered != null) { + registered.metaclass + } else { + elementType.specializedTypesID.map[ElementTypeRegistry.instance.getType(it)].filterNull.head?.EClass + } + } + + private def dispatch EClass getMetaclass(MetamodelTypeConfiguration elementType) { + elementType.EClass + } + + private def dispatch EClass getMetaclass(IElementType elementType) { + null + } + + private def dispatch EClass getMetaclass(IMetamodelType elementType) { + elementType.EClass + } + + private def dispatch EClass getMetaclass(ISpecializationType elementType) { + elementType.metamodelType?.EClass + } + + private def canSourceTo(IElementType sourceType, EClass relationshipEClass) { + relationshipEClass.sourceReferences.exists[EReferenceType.isSuperTypeOf(sourceType.EClass)] + } + + private def canSourceTo(ElementTypeConfiguration sourceType, EClass relationshipEClass) { + ElementTypeRegistry.getInstance.getType(sourceType?.identifier)?.canSourceTo(relationshipEClass) + } + + def dispatch canSourceToType(ElementTypeConfiguration sourceType, ElementTypeConfiguration relationshipTypeConfiguration) { + false + } + + def dispatch canSourceToType(ElementTypeConfiguration sourceType, MetamodelTypeConfiguration relationshipTypeConfiguration) { + sourceType.canSourceTo(relationshipTypeConfiguration.EClass) + } + + def dispatch canSourceToType(ElementTypeConfiguration sourceType, SpecializationTypeConfiguration relationshipTypeConfiguration) { + relationshipTypeConfiguration.specializedTypesID.exists [ supertypeID | + val supertype = ElementTypeRegistry.getInstance.getType(supertypeID) + (supertype != null) && supertype.EClass.isRelationship && sourceType.canSourceTo(supertype.EClass) + ] + } + + private def canTargetFrom(IElementType targetType, EClass relationshipEClass) { + relationshipEClass.targetReferences.exists[EReferenceType.isSuperTypeOf(targetType.EClass)] + } + + private def canTargetFrom(ElementTypeConfiguration targetType, EClass relationshipEClass) { + ElementTypeRegistry.getInstance.getType(targetType?.identifier)?.canTargetFrom(relationshipEClass) + } + + def dispatch canTargetFromType(ElementTypeConfiguration targetType, ElementTypeConfiguration relationshipTypeConfiguration) { + false + } + + def dispatch canTargetFromType(ElementTypeConfiguration targetType, MetamodelTypeConfiguration relationshipTypeConfiguration) { + targetType.canTargetFrom(relationshipTypeConfiguration.EClass) + } + + def dispatch canTargetFromType(ElementTypeConfiguration targetType, SpecializationTypeConfiguration relationshipTypeConfiguration) { + relationshipTypeConfiguration.specializedTypesID.exists [ supertypeID | + val supertype = ElementTypeRegistry.getInstance.getType(supertypeID) + (supertype != null) && supertype.EClass.isRelationship && targetType.canTargetFrom(supertype.EClass) + ] + } +} diff --git a/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/internal/Activator.java b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/internal/Activator.java new file mode 100644 index 00000000000..d7461b9aa10 --- /dev/null +++ b/plugins/uml/assistants/org.eclipse.papyrus.uml.profile.types.generator/src/org/eclipse/papyrus/uml/profile/types/generator/internal/Activator.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2014 Christian W. Damus 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: + * Christian W. Damus - Initial API and implementation + */ +package org.eclipse.papyrus.uml.profile.types.generator.internal; + +import org.eclipse.core.runtime.Plugin; +import org.eclipse.papyrus.infra.core.log.LogHelper; +import org.osgi.framework.BundleContext; + +/** + * This is the central singleton for the UML Profile Element Types Configuration ElementTypesGenerator plugin. + */ +public final class Activator extends Plugin { + public static final String PLUGIN_ID = "org.eclipse.papyrus.uml.profile.types.generator"; //$NON-NLS-1$ + + /** + * Keep track of the singleton. + */ + private static Activator INSTANCE; + + /** Logging helper */ + public static LogHelper log = new LogHelper(); + + public Activator() { + super(); + } + + public static Activator getInstance() { + return INSTANCE; + } + + @Override + public void start(BundleContext context) throws Exception { + INSTANCE = this; + log.setPlugin(this); + + super.start(context); + } +} |