| /** |
| * 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 Audits; |
| |
| import Utils; |
| import Mappings; |
| import gmf.GenModelAccess; |
| |
| 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'); |
| |
| -- |
| -- Audits |
| -- |
| |
| mapping GMFMAP::AuditContainer::audits() : GMFGEN::GenAuditRoot { |
| result.categories += self.allContainers().map category(); |
| result.rules += self.allContainers().audits.map rule(); |
| |
| var allRulesWithContext := result.rules->select(not target.oclIsUndefined()); |
| var rulesWithDiagramElementTarget := allRulesWithContext->select(target.oclIsTypeOf(GMFGEN::GenDiagramElementTarget)); |
| rulesWithDiagramElementTarget.target[GMFGEN::GenDiagramElementTarget]->forEach(t) { |
| -- Basically, all rules with targets != null |
| -- get a context (emf.validation), which is a scope or set of elements audit is evaluated against. |
| -- For certain cases, e.g. diagram elements as audit targets, special logic to select these |
| -- elements should get generated - to filter diagram views by visualID, and hence |
| -- there's another implementation of IClientSelector and dedicated context. |
| var ctx : GMFGEN::GenAuditContext; |
| -- use of exists seems to be sufficient, as all ruleTargets for a given context should get same elements |
| -- by the nature of construction. However, more honest way would be to use forAll, accompanied with not isEmpty(): |
| -- not cc.ruleTargets[GMFGEN::GenDiagramElementTarget]->isEmpty() and cc.ruleTargets[...]->forAll(element = t.element) |
| ctx := result.clientContexts->selectOne(cc | cc.ruleTargets[GMFGEN::GenDiagramElementTarget]->exists(element = t.element)); |
| -- there might be already a context to pick same elements this target has |
| if ctx.oclIsUndefined() then { |
| ctx := object GMFGEN::GenAuditContext { |
| id := t.element.visualID.repr()->asList()->joinfields('_','Ctx_','') |
| }; |
| result.clientContexts += ctx; |
| } endif; |
| t.contextSelector := ctx; |
| }; |
| var defaultAuditContext := object GMFGEN::GenAuditContext {}; |
| result.clientContexts += defaultAuditContext; |
| (allRulesWithContext - rulesWithDiagramElementTarget).target->forEach(t) { t.contextSelector := defaultAuditContext }; |
| } |
| |
| mapping GMFMAP::AuditContainer::category() : GMFGEN::GenAuditContainer { |
| id := self.id; |
| name := self.name; |
| description := self.description; |
| path += self.parentContainer.resolveone(GMFGEN::GenAuditContainer).path; |
| -- alternative, not sure which one is better: |
| -- path += self.parentContainer.map category().path; |
| path += result; |
| } |
| |
| mapping GMFMAP::AuditRule::rule() : GMFGEN::GenAuditRule { |
| id := self.id; |
| name := self.name; |
| message := self.message; |
| description := self.description; |
| useInLiveMode := self.useInLiveMode; |
| target := self.target.map auditTarget(); |
| rule := self.rule.map createConstraint(); |
| severity := self.severity.severity(); |
| category := self.container.map category(); |
| } |
| |
| mapping GMFMAP::Auditable::auditTarget() : GMFGEN::GenAuditable |
| disjuncts |
| GMFMAP::DomainElementTarget::ruleTarget, |
| GMFMAP::NotationElementTarget::ruleTarget, |
| GMFMAP::DiagramElementTarget::ruleTarget, |
| GMFMAP::AuditedMetricTarget::ruleTarget, |
| GMFMAP::DomainAttributeTarget::ruleTarget |
| {} --assert (false) with log ('Unknown rule target', self); |
| |
| mapping GMFMAP::DomainElementTarget::ruleTarget() : GMFGEN::GenDomainElementTarget { |
| element := self.element.findGenClass(); |
| } |
| |
| mapping GMFMAP::NotationElementTarget::ruleTarget() : GMFGEN::GenNotationElementTarget { |
| element := self.element.findGenClass(); -- XXX double-check if domain's genmodel should be consulted here, not notation's |
| } |
| |
| mapping GMFMAP::DiagramElementTarget::ruleTarget() : GMFGEN::GenDiagramElementTarget { |
| -- alternatives: |
| if self.element.oclIsKindOf(LinkMapping) then { |
| element += self.element.oclAsType(LinkMapping).map structure(); |
| } else if self.element.oclIsKindOf(NodeMapping) then { |
| var el := self.element.container(); |
| if el.oclIsKindOf(TopNodeReference) then |
| element += el.oclAsType(TopNodeReference).map structure() |
| else |
| element += el.oclAsType(ChildReference).map structure(self.element.oclAsType(NodeMapping)) |
| endif |
| } endif |
| endif; |
| -- element += self.element.resolveIn(GMFMAP::NodeMapping::structure, GMFGEN::GenCommonBase); |
| -- element += self.element.resolveIn(GMFMAP::LinkMapping::structure, GMFGEN::GenCommonBase); |
| -- element += self.element.resolveIn(GMFMAP::TopNodeReference::structure, GMFGEN::GenCommonBase); |
| -- element += self.element.resolve(GMFGEN::GenCommonBase); |
| } |
| |
| mapping GMFMAP::AuditedMetricTarget::ruleTarget() : GMFGEN::GenAuditedMetricTarget { |
| result.metric := self.metric.map rule(); |
| var resultClassifier := loadEcoreGenModel().genPackages->first().genClassifiers[GENMODEL::GenDataType]->selectOne(ecoreDataType.name='EDoubleObject'); |
| assert (not resultClassifier.oclIsUndefined()) with log ('Troubles loading ecore.genmodel and accessing EDoubleObject'); |
| result.metricValueContext := resultClassifier; |
| } |
| |
| mapping GMFMAP::DomainAttributeTarget::ruleTarget() : GMFGEN::GenDomainAttributeTarget { |
| attribute := self.attribute.findGenFeature(); |
| nullAsError := self.nullAsError; |
| } |
| |
| -- |
| -- Metrics |
| -- |
| |
| mapping GMFMAP::MetricContainer::metrics() : GMFGEN::GenMetricContainer { |
| metrics += self.metrics.map rule(); |
| } |
| |
| mapping GMFMAP::MetricRule::rule() : GMFGEN::GenMetricRule { |
| key := self.key; |
| name := self.name; |
| description := self.description; |
| lowLimit := self.lowLimit; |
| highLimit := self.highLimit; |
| rule := self.rule.map createValueExpression(); |
| target := self.target.map metricTarget(); |
| } |
| |
| mapping GMFMAP::Measurable::metricTarget() : GMFGEN::GenMeasurable |
| disjuncts |
| GMFMAP::DomainElementTarget::ruleTarget, |
| GMFMAP::NotationElementTarget::ruleTarget, |
| GMFMAP::DiagramElementTarget::ruleTarget |
| {} --assert (false) with log ('Unknown rule target', self); |
| |
| -- |
| -- Queries |
| -- |
| |
| query GMFMAP::AuditContainer::allContainers() : Sequence(GMFMAP::AuditContainer) = |
| self.childContainers.allContainers()->flatten()->prepend(self); |
| |
| query GMFMAP::Severity::severity() : GMFGEN::GenSeverity = |
| switch { |
| case (self = GMFMAP::Severity::INFO) return GMFGEN::GenSeverity::INFO; |
| case (self = GMFMAP::Severity::WARNING) return GMFGEN::GenSeverity::WARNING; |
| case (self = GMFMAP::Severity::ERROR) return GMFGEN::GenSeverity::ERROR; |
| else return null; |
| }; |