| /** |
| * Copyright (c) 2009, 2011, 2012 Borland Software Corporation & 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: |
| * Artem Tikhomirov (Borland) - initial API and implementation |
| * Guillaume Hillairet (Montages A.G.) |
| */ |
| library Mappings; |
| |
| import Utils; |
| import ModelFacets; |
| import Palette; |
| import Viewmaps; |
| import ModeledViewmaps; |
| import Identity; |
| import Behaviours; |
| |
| modeltype GMFMAP uses mappings('http://www.eclipse.org/gmf/2006/mappings'); |
| modeltype GMFTOOL uses tooldef('http://www.eclipse.org/gmf/2005/ToolDefinition'); |
| modeltype GMFGEN uses gmfgen('http://www.eclipse.org/gmf/2009/GenModel'); |
| modeltype GMFGRAPH uses gmfgraph('http://www.eclipse.org/gmf/2006/GraphicalDefinition'); |
| modeltype ECORE uses ecore('http://www.eclipse.org/emf/2002/Ecore'); |
| modeltype GENMODEL uses genmodel('http://www.eclipse.org/emf/2002/GenModel'); |
| |
| -- |
| -- Mapping |
| -- |
| |
| property genEditorGenerator : GMFGEN::GenEditorGenerator = null; |
| |
| mapping GMFMAP::Mapping::structure() : GMFGEN::GenEditorGenerator { |
| init { |
| result := object GMFGEN::GenEditorGenerator { |
| diagram := self.diagram.map structure(); |
| } |
| } |
| genEditorGenerator := result; |
| |
| childReferences := self.getChildReferences(); |
| self.nodes->map structure(); |
| diagram.links := self.links->map structure(); |
| |
| diagram.getAllNodes()->forEach(n) { setupElementType(n) }; |
| diagram.links->forEach(l) { setupElementType(l) }; |
| |
| if self.expressionsByLanguages()->notEmpty() then |
| expressionProviders := self.map createProviderContainer() |
| endif; |
| } |
| |
| mapping GMFMAP::Mapping::createProviderContainer(): GMFGEN::GenExpressionProviderContainer { |
| self.expressionsByLanguages()->forEach(e) { |
| providers += e.map createExpressionProvider() |
| } |
| } |
| |
| mapping GMFMAP::CanvasMapping::structure() : GMFGEN::GenDiagram { |
| init { |
| result := object GenDiagram { |
| viewmap := self.viewmap(); |
| domainDiagramElement := self.domainMetaElement.findGenClass(); |
| iconProviderPriority := GMFGEN::ProviderPriority::Low; |
| validationProviderPriority := GMFGEN::ProviderPriority::Low; |
| } |
| } |
| |
| result.visualID := result.visualID(); |
| |
| if result.domainDiagramElement.oclIsUndefined() then |
| result.elementType := object GMFGEN::NotationType {} |
| else |
| result.elementType := result.domainDiagramElement.getOrCreateRuntimeMetamodelType() |
| endif; |
| } |
| |
| -- |
| -- TopLevelNode |
| -- |
| |
| mapping GMFMAP::TopNodeReference::structure() : GMFGEN::GenTopLevelNode { |
| init { |
| result := object GenTopLevelNode { |
| modelFacet := self.createModelFacet(); |
| viewmap := self.viewmap(); |
| } |
| } |
| genEditorGenerator.diagram.topLevelNodes += result; |
| result.visualID := result.visualID(); |
| self.child.tool.map paletteEntry().oclAsType(ToolEntry).genNodes += result; |
| |
| self.child.map abstractStructure(result); |
| |
| labels += self.child.labelMappings->map createNodeLabel(self, result); |
| behaviour += self.child.relatedDiagrams.handleRelatedDiagram(self.child); |
| behaviour += self.child.visualEffects->map createVisualEffects(result, self.child.diagramNode); |
| } |
| |
| -- |
| -- |
| -- |
| mapping GMFMAP::NodeMapping::abstractStructure(inout genNode: GMFGEN::GenNode) { |
| var mapOfCompartments : Dict(CompartmentMapping, GenCompartment) = Dict{}; |
| self.compartments->forEach(c) { |
| var childCompartment := object GMFGEN::GenCompartment { |
| title := c.compartment.name; |
| canCollapse := c.compartment.collapsible; |
| needsTitle := c.compartment.needsTitle; |
| viewmap := c.viewmap(); |
| }; |
| mapOfCompartments->put(c, childCompartment); |
| genEditorGenerator.diagram.compartments += childCompartment; |
| genNode.compartments += childCompartment; |
| childCompartment.node := genNode; |
| childCompartment.visualID := childCompartment.visualID(); |
| }; |
| |
| self.children->forEach(childNodeRef) { |
| var compartmentMapping := childNodeRef.compartment; |
| var genChildContainer : GenChildContainer = null; |
| if not compartmentMapping.oclIsUndefined() and not mapOfCompartments->get(compartmentMapping).oclIsUndefined() then |
| genChildContainer := mapOfCompartments->get(compartmentMapping) |
| else |
| genChildContainer := genNode |
| endif; |
| |
| var childNodeMapping := childNodeRef.child; |
| var node := childNodeRef.findProcessableChildReference(); |
| var childNode := node.map structure(childNodeMapping); |
| if genChildContainer.oclIsKindOf(GenCompartment) and childNodeMapping.children->size() > 0 then |
| genChildContainer.oclAsType(GenCompartment).listLayout := false |
| endif; |
| genChildContainer.childNodes += childNode; |
| }; |
| } |
| |
| -- |
| -- GenChildNode |
| -- |
| abstract mapping GMFMAP::ChildReference::abstractStructure(nodeMapping: GMFMAP::NodeMapping): GMFGEN::GenChildNode { |
| modelFacet := self.createModelFacet(); |
| viewmap := self.viewmap(nodeMapping); |
| |
| self.child.tool.map paletteEntry().oclAsType(ToolEntry).genNodes += result; |
| } |
| |
| mapping GMFMAP::ChildReference::structure(nodeMapping: GMFMAP::NodeMapping) : GMFGEN::GenChildNode |
| disjuncts |
| GMFMAP::ChildReference::createGenChildLabelNode, |
| GMFMAP::ChildReference::createGenChildSideAffixedNode, |
| GMFMAP::ChildReference::createGenChildNode |
| {} |
| |
| mapping GMFMAP::ChildReference::createGenChildLabelNode(nodeMapping: GMFMAP::NodeMapping) : GMFGEN::GenChildLabelNode |
| inherits GMFMAP::ChildReference::abstractStructure |
| when { |
| nodeMapping.isPureLabelNode() |
| } |
| { |
| init { |
| result := object GMFGEN::GenChildLabelNode {} |
| } |
| genEditorGenerator.diagram.childNodes += result; |
| result.visualID := result.visualID(); |
| |
| var soleLabel := nodeMapping.labelMappings->first(); |
| labelModelFacet := soleLabel.map createLabelModelFacet(self); |
| labelReadOnly := soleLabel.readOnly; |
| labelElementIcon := soleLabel.diagramLabel.elementIcon; |
| } |
| |
| mapping GMFMAP::ChildReference::createGenChildSideAffixedNode(nodeMapping: GMFMAP::NodeMapping) : GMFGEN::GenChildSideAffixedNode |
| inherits GMFMAP::ChildReference::abstractStructure |
| when { |
| nodeMapping.diagramNode.affixedParentSide <> GMFGRAPH::Direction::NONE |
| } |
| { |
| init { |
| result := object GMFGEN::GenChildSideAffixedNode {} |
| } |
| |
| genEditorGenerator.diagram.childNodes += result; |
| result.visualID := result.visualID(); |
| self.child.map abstractStructure(result); |
| |
| preferredSideName := nodeMapping.diagramNode.getAffixedSideAsPositionConstantsName(); |
| labels += nodeMapping.labelMappings->map createNodeLabel(self, result); |
| behaviour += nodeMapping.relatedDiagrams.handleRelatedDiagram(nodeMapping); |
| behaviour += nodeMapping.visualEffects->map createVisualEffects(result, nodeMapping.diagramNode); |
| } |
| |
| mapping GMFMAP::ChildReference::createGenChildNode(nodeMapping: GMFMAP::NodeMapping) : GMFGEN::GenChildNode |
| inherits GMFMAP::ChildReference::abstractStructure |
| { |
| init { |
| result := object GMFGEN::GenChildNode {} |
| } |
| genEditorGenerator.diagram.childNodes += result; |
| result.visualID := result.visualID(); |
| self.child.map abstractStructure(result); |
| |
| nodeMapping.labelMappings->map createNodeLabel(self, result); |
| behaviour += nodeMapping.relatedDiagrams.handleRelatedDiagram(nodeMapping); |
| behaviour += nodeMapping.visualEffects->map createVisualEffects(result, nodeMapping.diagramNode); |
| } |
| |
| -- |
| -- NodeLabel |
| -- |
| |
| mapping GMFMAP::LabelMapping::createNodeLabel(node: NodeReference, inout genNode: GMFGEN::GenNode) : GMFGEN::GenNodeLabel { |
| init { |
| if self.diagramLabel.external then |
| result := object GenExternalNodeLabel {} |
| else |
| result := object GenNodeLabel {} |
| endif |
| } |
| |
| result.viewmap := self.viewmap(); |
| result.modelFacet := self.map createLabelModelFacet(node); |
| result.readOnly := self.readOnly; |
| result.elementIcon := self.diagramLabel.elementIcon; |
| genNode.labels += result; |
| result.visualID := result.visualID(); |
| } |
| |
| -- |
| -- GenLink |
| -- |
| mapping GMFMAP::LinkMapping::structure() : GMFGEN::GenLink |
| when { |
| not self.diagramLink.oclIsUndefined() and |
| not self.linkMetaFeature.oclIsUndefined() |
| }{ |
| init { |
| result := object GMFGEN::GenLink { |
| -- model facet |
| if not (self.domainMetaElement.oclIsUndefined() and self.linkMetaFeature.oclIsUndefined()) then |
| modelFacet := self.map createModelFacet() |
| endif; |
| |
| viewmap := self.viewmap(); |
| } |
| } |
| |
| genEditorGenerator.diagram.links += result; |
| result.visualID := result.visualID(); |
| |
| -- labels |
| self.labelMappings->map structure(self, result); |
| |
| self.tool.map paletteEntry().oclAsType(ToolEntry).genLinks += result; |
| result.creationConstraints := self.creationConstraints.map structure(); |
| |
| behaviour += self.visualEffects->map createVisualEffects(result, self.diagramLink); |
| } |
| |
| mapping LabelMapping::structure(link: GMFMAP::LinkMapping, inout genLink: GMFGEN::GenLink): GenLinkLabel { |
| init { |
| result := object GMFGEN::GenLinkLabel { |
| readOnly := self.readOnly; |
| elementIcon := self.diagramLabel.elementIcon; |
| modelFacet := self.map createLabelModelFacet(link); |
| viewmap := self.viewmap(); |
| |
| var alignmentFacet := self.diagramLabel.findAlignmentFacet(); |
| if not alignmentFacet.oclIsUndefined() then |
| alignment := switch { |
| case (alignmentFacet.alignment = GMFGRAPH::Alignment::BEGINNING) LinkLabelAlignment::SOURCE; |
| case (alignmentFacet.alignment = GMFGRAPH::Alignment::CENTER) LinkLabelAlignment::MIDDLE; |
| case (alignmentFacet.alignment = GMFGRAPH::Alignment::END) LinkLabelAlignment::TARGET; |
| else LinkLabelAlignment::MIDDLE; |
| } |
| endif; |
| } |
| } |
| |
| genLink.labels += result; |
| result.visualID := result.visualID() |
| } |
| |
| |
| -- XXX ElementType as return value, disjunct? |
| mapping GENMODEL::GenClass::gmfRuntimeMetamodelType() : GMFGEN::MetamodelType {} |
| |
| -- |
| -- Helpers |
| -- |
| |
| query GENMODEL::GenClass::getOrCreateRuntimeMetamodelType() : GMFGEN::ElementType { |
| var mmt = self.resolveoneIn(GENMODEL::GenClass::gmfRuntimeMetamodelType, GMFGEN::MetamodelType); |
| if mmt.oclIsUndefined() then |
| return self.map gmfRuntimeMetamodelType() |
| endif; |
| return object GMFGEN::SpecializationType { metamodelType := mmt } |
| } |
| |
| -- XXX review - Specialization type is created again and again - why not reuse it? |
| -- static, for some reasons, helpers couldn't specify 'inout' for context element |
| -- XXX, actually, don't need GenNode here, GenClass should be sufficient |
| helper setupElementType(inout genNode : GMFGEN::GenNode) { |
| if genNode.modelFacet.oclIsUndefined() then genNode.elementType := object GMFGEN::NotationType {} |
| else genNode.elementType := genNode.modelFacet.metaClass.getOrCreateRuntimeMetamodelType() endif; |
| return; |
| } |
| |
| helper setupElementType(inout genLink : GMFGEN::GenLink) { |
| if genLink.modelFacet.oclIsUndefined() then |
| genLink.elementType := object GMFGEN::NotationType {} |
| else |
| if genLink.modelFacet.oclIsKindOf(GMFGEN::TypeModelFacet) then |
| genLink.elementType := genLink.modelFacet.oclAsType(GMFGEN::TypeModelFacet).metaClass.getOrCreateRuntimeMetamodelType() |
| else { -- ref-based link; specialize null |
| genLink.elementType := object GMFGEN::SpecializationType {}; |
| -- genLink.elementType.displayName := genLink.modelFacet.oclAsType(FeatureLinkModelFacet).metaFeature.ecoreFeature.name.firstToUpper(); |
| } endif |
| endif; |
| return; |
| } |
| |
| helper GMFMAP::CanvasMapping::viewmap(): Viewmap = |
| if useModeledViewmaps then |
| object ModeledViewmap { |
| figureModel := self.diagramCanvas.oclAsType(EObject); |
| } |
| else |
| self.diagramCanvas.map Viewmaps::viewmap() |
| endif; |
| |
| helper GMFMAP::TopNodeReference::viewmap(): Viewmap = |
| if useModeledViewmaps then |
| self.child.diagramNode.ModeledViewmaps::viewmap() |
| else |
| self.child.diagramNode.Viewmaps::viewmap() |
| endif; |
| |
| helper GMFMAP::ChildReference::viewmap(_mapping: NodeMapping): Viewmap = |
| if useModeledViewmaps then |
| self.child.diagramNode.ModeledViewmaps::viewmap() |
| else |
| self.Viewmaps::viewmap(_mapping) |
| endif; |
| |
| helper GMFMAP::LinkMapping::viewmap(): Viewmap = |
| if useModeledViewmaps then |
| self.diagramLink.ModeledViewmaps::viewmap() |
| else |
| self.diagramLink.Viewmaps::viewmap() |
| endif; |
| |
| helper GMFMAP::LabelMapping::viewmap(): Viewmap = |
| if useModeledViewmaps then |
| self.diagramLabel.ModeledViewmaps::viewmap() |
| else |
| self.diagramLabel.Viewmaps::viewmap() |
| endif; |
| |
| helper GMFMAP::CompartmentMapping::viewmap(): Viewmap = |
| if useModeledViewmaps then |
| self.compartment.ModeledViewmaps::viewmap() |
| else |
| self.compartment.Viewmaps::viewmap() |
| endif; |
| |
| -- |
| -- Queries |
| -- |
| |
| query GMFMAP::Mapping::expressionsByLanguages(): Sequence(ValueExpression) = |
| GMFMAP::ValueExpression.allInstances()->iterate(it; res: Sequence(ValueExpression) = Sequence{} | |
| if res->exists(e | e.language = it.language) then res else res->including(it) endif |
| ); |
| |
| query GMFGRAPH::Node::getAffixedSideAsPositionConstantsName() : String = |
| switch { |
| case (self.affixedParentSide = GMFGRAPH::Direction::NONE) assert (false) with log('DiagramNode is not side-affixed', self); |
| case (self.affixedParentSide = GMFGRAPH::Direction::EAST) return 'EAST'; |
| case (self.affixedParentSide = GMFGRAPH::Direction::WEST) return 'WEST'; |
| case (self.affixedParentSide = GMFGRAPH::Direction::NORTH) return 'NORTH'; |
| case (self.affixedParentSide = GMFGRAPH::Direction::SOUTH) return 'SOUTH'; |
| case (self.affixedParentSide = GMFGRAPH::Direction::NSEW) return 'NONE'; -- any side |
| else return 'NONE'; -- any side |
| }; |
| |
| query DiagramElement::findAlignmentFacet(): AlignmentFacet = |
| self.facets->selectOne(e | e.oclIsKindOf(AlignmentFacet)).oclAsType(AlignmentFacet); |