My favorites | Sign in
Project Home Wiki Issues Source
Checkout   Browse   Changes    
 
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
import iaml;

// NOTE: checks cannot have a semicolon in the exception, otherwise the
// OAW parser won't be able to parse beyond it
extension metamodel::Extensions;

// TODO add test cases for model validation
// both through Eclipse and through manual test cases (code generation)
context model::InternetApplication ERROR "No frames in internet application" :
!(scopes.typeSelect(model::visual::Frame).isEmpty &&
scopes.scopes.typeSelect(model::visual::Frame).isEmpty);

context model::visual::Frame ERROR "Frame must have a name" :
name.length > 0;

context model::Operation ERROR "Operation must have a name" :
name.length > 0;

context model::components::LoginHandler ERROR "A login handler must have an incoming parameter to check against" :
!inParameterEdges.isEmpty;

context model::components::LoginHandler ERROR "A login handler of type USER must have at least one incoming parameter of type Role or Permission":
type != model::components::LoginHandlerTypes::USER ||
!(inParameterEdges.parameterValue.typeSelect(model::users::Role).isEmpty && inParameterEdges.parameterValue.typeSelect(model::users::Permission).isEmpty);

context model::components::LoginHandler ERROR "A login handler of type DOMAIN_OBJECT must have at least one incoming parameter of type DomainAttribute":
type != model::components::LoginHandlerTypes::DOMAIN_OBJECT ||
!inParameterEdges.parameterValue.typeSelect(domain::DomainAttribute).isEmpty;

context model::components::LoginHandler ERROR "A login handler of type SECRET_KEY must have exactly one incoming parameter":
type != model::components::LoginHandlerTypes::SECRET_KEY ||
inParameterEdges.size == 1;

context model::components::LoginHandler ERROR "A login handler of type SECRET_KEY cannot have an incoming Role as a parameter":
!(type == model::components::LoginHandlerTypes::SECRET_KEY &&
!inParameterEdges.parameterValue.typeSelect(model::users::Role).isEmpty);

context model::components::LoginHandler ERROR "All incoming DomainAttribute parameters for a DOMAIN_OBJECT LoginHandler must belong to the same DomainType":
type != model::components::LoginHandlerTypes::DOMAIN_OBJECT ||
inParameterEdges.parameterValue.eContainer.typeSelect(model::domain::DomainType).toSet().size == 1;

context model::operations::DecisionNode ERROR "A compare DecisionNode must have at least two data flows in to compare" :
(name == "equal?" && inFlows.size >= 2)
|| (name != "equal?");

context model::operations::DecisionNode ERROR "A DecisionNode can only have at most two out execution edges" :
outExecutions.size <= 2;

context model::wires::SyncWire ERROR "You cannot have a SyncWire that connects to a read-only Property":
!(model::Value.isInstance(from) && ((model::Value) from).readOnly) &&
!(model::Value.isInstance(to) && ((model::Value) to).readOnly);

context model::wires::SyncWire ERROR "You cannot have a SyncWire that connects to a QueryParameter":
!model::QueryParameter.isInstance(from) &&
!model::QueryParameter.isInstance(to);

context model::wires::SyncWire ERROR "A SyncWire cannot connect to itself":
from != to;

context model::wires::SyncWire ERROR "You cannot have a SyncWire connecting two Values":
!(model::Value.isInstance(from) &&
model::Value.isInstance(to));

context model::domain::DomainType ERROR "You cannot have a DomainType called single_values (reserved word)" :
toString(name) != "single_values";

/**
* Important: If this message changes, it must also be updated in org.openiaml.model.custom.actions.GenerateCodeAction#couldBePhantomEdges()
*/
context model::Wire ERROR "A Wire must have a 'from'" :
from != null;

/**
* Important: If this message changes, it must also be updated in org.openiaml.model.custom.actions.GenerateCodeAction#couldBePhantomEdges()
*/
context model::Wire ERROR "A Wire must have a 'to'" :
to != null;

context model::ECARule ERROR "An ECARule must have a 'trigger'" :
trigger != null;
context model::ECARule ERROR "An ECARule must have a 'target'" :
target != null;

context model::wires::ExtendsEdge ERROR "A Role cannot extend itself" :
from != to;

/*
* isInstance() definitely works in OAW checks for abstract supertypes.
* if a check isn't working, make sure that you are following the OAW
* checks logic correctly; the predicate is expected to be _true_,
* and will only throw an exception if the predicate is false.
*
* i.e.: "name != 'single_values'"
*/

context model::operations::OperationCallNode ERROR "An OperationCallNode must have exactly one ECARule connecting it to an Operation" :
listeners.size == 1
&& model::Operation.isInstance(listeners.first().target);

context model::ECARule WARNING "This ECA Rule will not do anything: consider naming it 'onClick'" :
!(model::VisibleThing.isInstance(trigger) && !(name == "click" || name == "onClick"));

context model::Value WARNING "A session value used as part of a login handler should have a default value set, otherwise secure frames will crash with an exception rather than going to the login frame" :
!(defaultValue == null && inWires.typeSelect(model::wires::SetWire).from.typeSelect(model::components::LoginHandler).size > 0);

context model::components::LoginHandler ERROR "A LoginHandler[user] can not have more than one incoming Parameter" :
(type != model::components::LoginHandlerTypes::USER) || inParameterEdges.size <= 1;

context model::domain::DomainIterator ERROR "A DomainIterator has incoming Parameters, but does not have a query to use them" :
inParameterEdges.isEmpty || (query != null && query.length > 0);

context model::scopes::Session ERROR "A Session can only contain one LoginHandler" :
loginHandlers.size <= 1;

context model::visual::Frame ERROR "A Frame cannot contain a LoginHandler" :
loginHandlers.size == 0;

context model::operations::ActivityOperation ERROR "An ActivityOperation can only contain one StartNode" :
nodes.typeSelect(model::operations::StartNode).size <= 1;

context model::operations::ActivityPredicate ERROR "An ActivityPredicate can only contain one StartNode" :
nodes.typeSelect(model::operations::StartNode).size <= 1;

// issue 98: unused BuiltinOperation names should issue a warning
// issue 136: CompositeOperations should not have this warning
context model::BuiltinOperation WARNING "Unknown builtin operation name '" + name + "'" :
model::operations::ActivityOperation.isInstance(this) ||
(eContainer != null && model::domain::DomainIterator.isInstance(eContainer) && ((model::domain::DomainIterator) eContainer).next == this) ||
(eContainer != null && model::domain::DomainIterator.isInstance(eContainer) && ((model::domain::DomainIterator) eContainer).previous == this) ||
(eContainer != null && model::domain::DomainIterator.isInstance(eContainer) && ((model::domain::DomainIterator) eContainer).reset == this) ||
(eContainer != null && model::domain::DomainIterator.isInstance(eContainer) && ((model::domain::DomainIterator) eContainer).skip == this) ||
(eContainer != null && model::domain::DomainIterator.isInstance(eContainer) && ((model::domain::DomainIterator) eContainer).jump == this) ||
(eContainer != null && model::VisibleThing.isInstance(eContainer) && name == "update") ||
(eContainer != null && model::domain::DomainAttribute.isInstance(eContainer) && name == "update") ||
(eContainer != null && model::domain::DomainAttributeInstance.isInstance(eContainer) && name == "update") ||
(eContainer != null && model::VisibleThing.isInstance(eContainer) && name == "init") ||

// primitive operations defined with no parent
(name == "set" ||
name == "alert" || name == "save" ||
name == "new" ||
name == "equal?" || name == "add role" ||
name == "add permission" || name == "remove role" ||
name == "remove permission" || name == "check permissions" ||
(model::VisibleThing.isInstance(eContainer) &&
(name == "hide" || name == "show")) ||
(model::messaging::Email.isInstance(eContainer) &&
(name == "send")) ||
name == "true?" || name == "can cast?") ||

// a Value 'XXX' will generate a PrimitiveOperation named 'set XXX'
(eContainer != null && eContainer.eContents.typeSelect(model::Value).exists(p|name == "set " + p.name));

context model::BuiltinProperty WARNING "Unknown builtin property name '" + name + "'" :
(eContainer != null && model::domain::DomainIterator.isInstance(eContainer) && ((model::domain::DomainIterator) eContainer).hasNext == this) ||
(eContainer != null && model::domain::DomainIterator.isInstance(eContainer) && ((model::domain::DomainIterator) eContainer).hasPrevious == this) ||
(eContainer != null && model::domain::DomainIterator.isInstance(eContainer) && ((model::domain::DomainIterator) eContainer).canSave == this) ||
(eContainer != null && model::domain::DomainIterator.isInstance(eContainer) && ((model::domain::DomainIterator) eContainer).empty == this) ||
(eContainer != null && model::Changeable.isInstance(eContainer) && name == "fieldValue is set?") ||
(eContainer != null && model::Changeable.isInstance(eContainer) && name == "fieldValue is set") ||
(eContainer != null && model::Changeable.isInstance(eContainer) && name == "can cast?") ||
(eContainer != null && model::Changeable.isInstance(eContainer) && name == "can cast") ||
(eContainer != null && model::Changeable.isInstance(eContainer) && name == "empty?") ||
(eContainer != null && model::Changeable.isInstance(eContainer) && name == "empty") ||
(eContainer != null && model::Changeable.isInstance(eContainer) && name == "not empty?") ||
(eContainer != null && model::Changeable.isInstance(eContainer) && name == "not empty");

context model::operations::Arithmetic ERROR "Arithmetic must have at least one incoming data source edge" :
inFlows.size > 0;

context model::components::Gate ERROR "An entry Gate needs to have at least one incoming Condition, one outgoing RequiresEdge, or one outgoing 'first' rule, or it will never permit access" :
!model::Scope.isInstance(eContainer)
|| ((model::Scope) eContainer).entryGate != this
|| (conditions.size >= 1
|| outRequiresEdges.size >= 1
|| listeners.exists(w | w.name == "first"));

context model::components::Gate ERROR "An exit Gate needs to have at least one incoming Condition, or one outgoing 'last' rule, or it will never permit access" :
!model::Scope.isInstance(eContainer)
|| ((model::Scope) eContainer).exitGate != this
|| (conditions.size >= 1
|| listeners.exists(w | w.name == "last"));

context model::components::Gate ERROR "An entry Gate needs to have at least one outgoing ECARule" :
!model::Scope.isInstance(eContainer)
|| ((model::Scope) eContainer).entryGate != this
|| !listeners.isEmpty;

context model::components::Gate ERROR "An exit Gate needs to have at least one outgoing ECARule" :
!model::Scope.isInstance(eContainer)
|| ((model::Scope) eContainer).exitGate != this
|| !listeners.isEmpty;

context model::operations::DecisionNode ERROR "A 'can cast?' DecisionNode needs to have an incoming DataFlowEdge from a CastNode" :
name != "can cast?" ||
(inFlows.size == 1 && model::operations::CastNode.isInstance(inFlows.first().from));

context model::operations::DecisionNode ERROR "A 'can cast?' DecisionNode needs to have an incoming DataFlowEdge from a CastNode" :
name != "can cast?" ||
(inFlows.size == 1 && model::operations::CastNode.isInstance(inFlows.first().from));

context model::operations::CastNode ERROR "A CastNode needs exactly one incoming data flow edge, had: " + inFlows.size :
inFlows.size == 1;

/**
* To quickly identify problems related to issue 170: making an explicit Property called 'fieldValue'
*/
context model::ContainsValues WARNING "You should not have a contained Property named 'fieldValue', unless it is contained within the fieldValue containment feature" :
values.select(e | e.name == "fieldValue").isEmpty;

/**
* Two types are specified to be incompatible if they are different.
* TODO this should be changed, because e.g. email is compatible with string in one direction.
*/
context model::Changeable ERROR "Type '" + toString(type.name) + "' is incompatible with contained fieldValue type '" + toString(fieldValue.type.name) + "'":
type == null ||
fieldValue == null ||
fieldValue.type == null ||
type == fieldValue.type;

context model::Changeable ERROR "Contained fieldValue property has a default value, even though container already specifies one" :
defaultValue == null ||
fieldValue == null ||
fieldValue.defaultValue == null ||
defaultValue == fieldValue.defaultValue;

context model::wires::SyncWire ERROR "A SyncWire cannot connect to an Email" :
!model::messaging::Email.isInstance(to) &&
!model::messaging::Email.isInstance(from);

context model::domain::DomainAttributeInstance ERROR "A DomainAttributeInstance must extend a DomainAttribute as its definition" :
!outExtendsEdges.to.typeSelect(model::domain::DomainAttribute).isEmpty;

context model::domain::DomainSource ERROR "A DomainSource can only have one Schema" :
outSchemas.size <= 1;

context model::domain::DomainIterator ERROR "A DomainIterator can only have one Source" :
outSelects.size <= 1;

context model::domain::DomainType WARNING "A DomainType should have at least one DomainSource specified" :
inSchemas.size >= 1;

// TODO should this become an Error?
context model::domain::DomainIterator WARNING "A DomainIterator should have one DomainSource specified" :
outSelects.size == 1;

context model::wires::AutocompleteWire WARNING "An AutocompleteWire should have a 'match' attribute specified" :
match != null;

context model::ECARule WARNING "Unknown outgoing ECARule '" + name + "' from this AccessControlHandler" :
(!model::components::AccessControlHandler.isInstance(trigger)) ||
(name == "login" || name == "logout" || name == "success");

context model::ECARule WARNING "Unknown outgoing ECARule '" + name + "' from this LoginHandler" :
(!model::components::LoginHandler.isInstance(trigger)) ||
(name == "login" || name == "logout" || name == "success");

/*
context model::operations::DecisionNode WARNING "Unknown DecisionNode '" + name + "'" :
name == "xpathMatch" || name == "emailAddress" || name == "is set"
|| name == "equal" || name == "true" || name == "can cast"
|| name == "empty"
|| name == "xpathMatch?" || name == "emailAddress?" || name == "is set?"
|| name == "equal?" || name == "true?" || name == "can cast?"
|| name == "empty?";
*/

context model::operations::DataFlowEdge ERROR "Readonly Properties can not be set" :
!(to != null
&& model::operations::ExternalValue.isInstance(to)
&& ((model::operations::ExternalValue) to).value != null
&& ((model::operations::ExternalValue) to).value.readOnly);

context model::Value ERROR "Readonly Values must have a default value set" :
!(readOnly && defaultValue == null);

/**
* Based on SQLite docs. This should be the list of reserved words in SQL99
* (or a related standard); however, different RDBMSes allow different reserved
* words to also be column names. TODO IAML should instead allow all names, but
* modify their runtime name if they are a reserved word (issue 211).
*/
context model::domain::DomainAttribute ERROR "Using a reserved SQL word for a DomainAttribute name" :
!{"alter", "analyze", "attach", "begin", "commit", "create",
"delete", "detach", "drop", "end", "explain", "from", "group", "having", "indexed",
"insert", "limit", "not", "on", "order", "pragma", "reindex", "release", "replace",
"rollback", "savepoint", "select", "union", "update", "using", "vacuum", "where"}.contains(toString(name).toLowerCase());

/**
* A 'login' ECARule for an AccessControlHandler should not be in the
* same Scope as the handler; this will cause an infinite redirection,
* as the login page can never be accessed.
*/
context model::ECARule ERROR "A 'login' ECARule for an AccessControlHandler should not be in the same Scope as the handler; this will cause an infinite redirection, as the login page can never be accessed." :
!(trigger != null && target != null && model::components::AccessControlHandler.isInstance(trigger)
&& name == "login" && target.eContainer != null && trigger.eContainer != null
&& target.eContainer == trigger.eContainer);

context model::ActionEdgeSource ERROR "Some of the ECARules defined for this trigger may not be executed, as an unconditional navigation will occur due to the priority order, halting ECARule execution" :
model::components::LoginHandler.isInstance(this) || /* LoginHandlers are designed to have multiple ECA rules */
!listeners.exists( r |
model::visual::Frame.isInstance(r.target) /* navigates */
&& r.conditions.isEmpty /* and is unconditional */
&& r.name != "fail" /* and is not a fail wire */
&& listeners.exists(r2 |
r != r2 /* not the same wire */
&& r2.name != "fail" /* and not a fail wire */
&& r2.priority <= r.priority) /* and another rule will not be executed */
);

/* --- Metamodel-specific checks, as per issue 235 --- */

context model::Value ERROR "A Value must be of type XSDSimpleTypeDefinition":
type != null ||
(!model::EXSDDataType.isInstance(type)
|| xsd::XSDSimpleTypeDefinition.isInstance(((model::EXSDDataType) type).definition));

context model::ComplexTerm ERROR "A ComplexTerm must define a Function":
function != null;

context model::ComplexTerm ERROR "A ComplexTerm must have the same function type as its referenced Function":
type == null
|| function.type == null
|| type == function.type;

context model::ComplexTerm ERROR "Mismatched number of slots and parameters (" + function.slotNames.size + ", " + inParameterEdges.name.size + ")":
function.slotNames.size == inParameterEdges.name.size;

context model::ComplexTerm ERROR "Parameter edge defined a named parameter that was not defined in the function, expected: (" + function.slotNames + "), was: (" + inParameterEdges.name + ")":
inParameterEdges.forAll(p | p.name == null || function.slotNames.contains(p.name));

context model::ComplexTerm ERROR "Non-unique parameter names provided to ComplexTerm":
inParameterEdges.name.toSet().size == inParameterEdges.name.size;

context model::Function ERROR "Non-unique slot names defined in Function":
slotNames.size == slotNames.toSet().size;

context model::Function ERROR "Slot names and types mismatch":
slotTypes.size == slotNames.size;

context model::Predicate ERROR "Predicate types must be boolean":
type == null ||
(model::EXSDDataType.isInstance(type) &&
(
((model::EXSDDataType) type).definition.uRI == "http://www.w3.org/2001/XMLSchema.xsd#//boolean"
|| ((model::EXSDDataType) type).definition.uRI == "platform:/plugin/org.openiaml.model/model/datatypes.xsd#//iamlBoolean"
|| ((model::EXSDDataType) type).definition.uRI == "http://www.w3.org/2001/XMLSchema#boolean"
|| ((model::EXSDDataType) type).definition.name == "boolean"
));

context model::BooleanProperty ERROR "A BooleanProperty must have a defined container":
eContainer != null;

context model::BuiltinProperty ERROR "An 'is visible' BuiltinProperty must be contained by a VisibleThing":
property.toString() != 'IS_VISIBLE'
|| model::VisibleThing.isInstance(eContainer);

context model::BuiltinProperty ERROR "A 'can save' BuiltinProperty must be contained by a DomainIterator":
property.toString() != 'CAN_SAVE'
|| model::domain::DomainIterator.isInstance(eContainer);

// TODO more BuiltinProperties

context model::SimpleCondition ERROR "A SimpleCondition must use a Predicate as a Function, was using: " + function:
model::Predicate.isInstance(function);

Change log

r3163 by soundasleep on Apr 4, 2012   Diff
spellchecking throughout project
Go to: 
Project members, sign in to write a code review

Older revisions

r3157 by soundasleep on Mar 29, 2012   Diff
adding an extra warning to assist in
development of AutocompleteWires
r3106 by soundasleep on Sep 22, 2011   Diff
minor documentation fixes throughout
project
r3101 by soundasleep on Sep 21, 2011   Diff
 issue 277 : updating inference rules
and codegen templates
All revisions of this file

File info

Size: 19545 bytes, 365 lines
Powered by Google Project Hosting