Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 726a561de80f0d8062e60b57d2314a62ee406a4c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*******************************************************************************
 * Copyright (c) 2009, 2020 Borland Software Corporation, CEA LIST, Artal & others
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/ 
 * 
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors: 
 *    Artem Tikhomirov (Borland) - initial API and implementation
 *    Guillaume Hillairet (Montages A.G.)
 *    Aurelien Didier (ARTAL) - aurelien.didier51@gmail.com - Bug 569174
 */
library Audits;
 
import Utils;
import Mappings;
import gmf.GenModelAccess;

modeltype GMFMAP uses mappings('http://www.eclipse.org/papyrus/gmf/2020/mappings');
modeltype GMFTOOL uses tooldef('http://www.eclipse.org/papyrus/gmf/2020/ToolDefinition');
modeltype GMFGEN uses gmfgen('http://www.eclipse.org/papyrus/gmf/2020/GenModel');
modeltype GMFGRAPH uses gmfgraph('http://www.eclipse.org/papyrus/gmf/2020/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;
	};

Back to the top