activefacts 0.8.5 → 0.8.6
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/activefacts/cql/CQLParser.treetop +20 -11
- data/lib/activefacts/cql/Concepts.treetop +10 -2
- data/lib/activefacts/cql/Context.treetop +2 -2
- data/lib/activefacts/cql/FactTypes.treetop +10 -4
- data/lib/activefacts/cql/Language/English.treetop +12 -6
- data/lib/activefacts/cql/ValueTypes.treetop +4 -3
- data/lib/activefacts/cql/compiler.rb +26 -19
- data/lib/activefacts/cql/parser.rb +8 -0
- data/lib/activefacts/version.rb +1 -1
- data/lib/activefacts/vocabulary/metamodel.rb +19 -19
- data/spec/absorption_ruby_spec.rb +1 -1
- data/spec/cql/context_spec.rb +10 -10
- data/spec/cql/unit_spec.rb +8 -10
- data/spec/cql_cql_spec.rb +1 -1
- data/spec/norma_tables_spec.rb +1 -1
- metadata +3 -3
@@ -75,30 +75,39 @@ module ActiveFacts
|
|
75
75
|
# REVISIT: / value_constraint
|
76
76
|
end
|
77
77
|
|
78
|
+
rule enforcement
|
79
|
+
s '(' s otherwise s action s agent? s ')' s
|
80
|
+
{ def value; [action.text_value, agent.empty? ? nil : agent.text_value]; end }
|
81
|
+
/
|
82
|
+
''
|
83
|
+
{ def value; []; end }
|
84
|
+
end
|
85
|
+
|
78
86
|
# presence constraint:
|
79
87
|
rule presence_constraint
|
80
|
-
s 'each' s ('combination' S)? role_list s 'occurs' s quantifier s 'time' s 'in' s
|
88
|
+
s 'each' s ('combination' S)? role_list s 'occurs' s quantifier s 'time' s enforcement 'in' s
|
81
89
|
readings_list s
|
82
90
|
c:context? ';' s
|
83
|
-
{ def value; [ nil, [ :constraint, :presence, role_list.roles, quantifier.value, readings_list.value, c.empty? ? nil : c.value ] ]; end }
|
91
|
+
{ def value; [ nil, [ :constraint, :presence, role_list.roles, quantifier.value, readings_list.value, c.empty? ? nil : c.value, enforcement.value ] ]; end }
|
84
92
|
end
|
85
93
|
|
86
94
|
# set (exclusion, mandatory exclusion, complex equality) constraint
|
87
95
|
rule set_constraint
|
88
|
-
s 'for' s 'each' s role_list s quantifier s 'of' s 'these' s 'holds' s ':' s
|
96
|
+
s 'for' s 'each' s role_list s quantifier s 'of' s 'these' s 'holds' s enforcement ':' s
|
89
97
|
readings_list s
|
90
98
|
c:context? ';' s
|
91
|
-
{ def value; [ nil, [ :constraint, :set, role_list.roles, quantifier.value, readings_list.value, c.empty? ? nil : c.value
|
99
|
+
{ def value; [ nil, [ :constraint, :set, role_list.roles, quantifier.value, readings_list.value, c.empty? ? nil : c.value, enforcement.value ] ]; end }
|
92
100
|
/
|
93
|
-
s either? s r1:readings s or s r2:readings exclusion:(but s not s both s)? c:context? ';' s
|
101
|
+
s either? s r1:readings s or s r2:readings exclusion:(but s not s both s)? c:context? enforcement ';' s
|
94
102
|
{ def value;
|
95
103
|
[ nil, [ :constraint, :set,
|
96
104
|
nil, # No roles names, rely on the join
|
97
105
|
exclusion.text_value.empty? ?
|
98
|
-
[1, nil] :
|
106
|
+
[1, nil] : # At least one (meaning 1 or 2/more)
|
99
107
|
[1,1], # Exactly one (1 and only 1)
|
100
108
|
[r1.value, r2.value],
|
101
|
-
c.empty? ? nil : c.value
|
109
|
+
c.empty? ? nil : c.value,
|
110
|
+
enforcement.value
|
102
111
|
] ];
|
103
112
|
end
|
104
113
|
}
|
@@ -106,14 +115,14 @@ module ActiveFacts
|
|
106
115
|
|
107
116
|
rule subset_constraint
|
108
117
|
s readings s only s if s r2:readings s
|
109
|
-
c:context? ';' s
|
110
|
-
{ def value; [ nil, [ :constraint, :subset, [readings.value, r2.value], c.empty? ? nil : c.value ] ]; end }
|
118
|
+
c:context? enforcement ';' s
|
119
|
+
{ def value; [ nil, [ :constraint, :subset, [readings.value, r2.value], c.empty? ? nil : c.value, enforcement.value ] ]; end }
|
111
120
|
end
|
112
121
|
|
113
122
|
rule equality_constraint
|
114
123
|
s readings s tail:( if s and s only s if s readings s)+
|
115
|
-
c:context? ';' s
|
116
|
-
{ def value; [ nil, [ :constraint, :equality, [readings.value] + tail.elements.map{|e| e.readings.value }, c.empty? ? nil : c.value ]]; end }
|
124
|
+
c:context? enforcement ';' s
|
125
|
+
{ def value; [ nil, [ :constraint, :equality, [readings.value] + tail.elements.map{|e| e.readings.value }, c.empty? ? nil : c.value, enforcement.value ]]; end }
|
117
126
|
end
|
118
127
|
|
119
128
|
rule readings_list
|
@@ -69,8 +69,16 @@ module ActiveFacts
|
|
69
69
|
|
70
70
|
rule identification
|
71
71
|
# REVISIT: Consider distinguishing "-Id" from just "Id", and not prepending the entity type name if no "-"
|
72
|
-
identified_by its s id value_type_parameters
|
73
|
-
|
72
|
+
identified_by its s id value_type_parameters
|
73
|
+
r:(restriction enforcement)? # Reference Mode; restriction may be needed for the ValueType
|
74
|
+
{ def value
|
75
|
+
{ :mode => id.value,
|
76
|
+
:restriction => (r.text_value.empty? ? nil : r.restriction.ranges),
|
77
|
+
:enforcement => (r.text_value.empty? ? nil : r.enforcement.value),
|
78
|
+
:parameters => value_type_parameters.values
|
79
|
+
}
|
80
|
+
end
|
81
|
+
}
|
74
82
|
/
|
75
83
|
identified_by role_list
|
76
84
|
{ def value; {:roles => role_list.roles }; end }
|
@@ -123,18 +123,21 @@ module ActiveFacts
|
|
123
123
|
# When we have an expression, we will come down here perhaps multiple times,
|
124
124
|
# but find no way out as soon as we hit the trailing non_role.
|
125
125
|
rule role
|
126
|
-
q:quantifier?
|
126
|
+
q:(quantifier enforcement)?
|
127
127
|
adj0:(a:role_word '-' s)?
|
128
128
|
player:role_word !'-' s?
|
129
129
|
adj1:( '-' a:(a:role_word s)? )?
|
130
130
|
func:function_call?
|
131
131
|
role_id:(role_name / subscript )?
|
132
|
-
lr:( literal / restriction )?
|
132
|
+
lr:( literal / restriction enforcement )?
|
133
133
|
!non_role
|
134
134
|
{
|
135
135
|
def value
|
136
136
|
r = {}
|
137
|
-
|
137
|
+
if !q.empty?
|
138
|
+
quantifier = q.quantifier.value # "some" quantifier has nil value
|
139
|
+
r[:quantifier_restriction] = q.enforcement.value
|
140
|
+
end
|
138
141
|
|
139
142
|
r[:quantifier] = quantifier if quantifier
|
140
143
|
r[:leading_adjective] = adj0.a.value unless adj0.empty?
|
@@ -144,7 +147,10 @@ module ActiveFacts
|
|
144
147
|
r[:trailing_adjective] = adj1.a.a.value unless adj1.empty?
|
145
148
|
r[:function] = func.value if !func.empty?
|
146
149
|
r[:role_name] = role_id.value unless role_id.empty?
|
147
|
-
|
150
|
+
if !lr.empty? && lr.respond_to?(:restriction)
|
151
|
+
r[:restriction] = lr.restriction.ranges
|
152
|
+
r[:restriction_enforcement] = lr.enforcement.value
|
153
|
+
end
|
148
154
|
r[:literal] = lr.value if !lr.empty? && lr.respond_to?(:value)
|
149
155
|
|
150
156
|
r
|
@@ -68,8 +68,8 @@ module ActiveFacts
|
|
68
68
|
end
|
69
69
|
|
70
70
|
rule as_agreed_by
|
71
|
-
s as s 'agreed' s d:('on' S date)? by s
|
72
|
-
{ def value; [ d.empty? ? nil : d.date.value,
|
71
|
+
s as s 'agreed' s d:('on' S date)? by s agents
|
72
|
+
{ def value; [ d.empty? ? nil : d.date.value, agents.value ]; end }
|
73
73
|
end
|
74
74
|
|
75
75
|
rule date
|
@@ -77,15 +77,20 @@ module ActiveFacts
|
|
77
77
|
{ def value; d.text_value.strip; end }
|
78
78
|
end
|
79
79
|
|
80
|
-
rule
|
81
|
-
s h:
|
82
|
-
{ def value; [h.text_value] + t.elements.map{|e| e.
|
80
|
+
rule agents
|
81
|
+
s h:agent s t:(',' s !context_type agent s)*
|
82
|
+
{ def value; [h.text_value] + t.elements.map{|e| e.agent.text_value }; end }
|
83
83
|
end
|
84
84
|
|
85
|
-
rule
|
85
|
+
rule agent
|
86
86
|
id (s id)*
|
87
87
|
end
|
88
88
|
|
89
|
+
# An enforcement action, like SMS, email, log, alarm, etc.
|
90
|
+
rule action
|
91
|
+
id
|
92
|
+
end
|
93
|
+
|
89
94
|
rule acyclic 'acyclic' !alphanumeric end
|
90
95
|
rule alias 'alias' !alphanumeric end
|
91
96
|
rule all 'all' !alphanumeric end
|
@@ -126,6 +131,7 @@ module ActiveFacts
|
|
126
131
|
rule one 'one' !alphanumeric end
|
127
132
|
rule only 'only' !alphanumeric end
|
128
133
|
rule or 'or' !alphanumeric end
|
134
|
+
rule otherwise 'otherwise' !alphanumeric end
|
129
135
|
rule partitioned 'partitioned' !alphanumeric end
|
130
136
|
rule personal 'personal' !alphanumeric end
|
131
137
|
rule restricted 'restricted' !alphanumeric end
|
@@ -14,7 +14,7 @@ module ActiveFacts
|
|
14
14
|
base:id s
|
15
15
|
value_type_parameters
|
16
16
|
units
|
17
|
-
r:restriction?
|
17
|
+
r:(restriction enforcement)?
|
18
18
|
mapping_pragmas
|
19
19
|
s ';' s
|
20
20
|
{
|
@@ -24,8 +24,9 @@ module ActiveFacts
|
|
24
24
|
base.value,
|
25
25
|
value_type_parameters.values,
|
26
26
|
units.value,
|
27
|
-
(!r.empty? ? r.ranges : []),
|
28
|
-
mapping_pragmas.value
|
27
|
+
(!r.empty? ? r.restriction.ranges : []),
|
28
|
+
mapping_pragmas.value,
|
29
|
+
(!r.empty? ? r.enforcement.value : nil)
|
29
30
|
]
|
30
31
|
end
|
31
32
|
|
@@ -69,7 +69,7 @@ module ActiveFacts
|
|
69
69
|
end
|
70
70
|
|
71
71
|
private
|
72
|
-
def value_type(name, base_type_name, parameters, unit, ranges, mapping_pragmas)
|
72
|
+
def value_type(name, base_type_name, parameters, unit, ranges, mapping_pragmas, enforcement)
|
73
73
|
length, scale = *parameters
|
74
74
|
|
75
75
|
# Create the base type:
|
@@ -91,11 +91,11 @@ module ActiveFacts
|
|
91
91
|
# REVISIT: Find and apply the units
|
92
92
|
|
93
93
|
if ranges.size != 0
|
94
|
-
vt.value_restriction = value_restriction
|
94
|
+
vt.value_restriction = value_restriction(ranges, enforcement)
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
-
def value_restriction(ranges)
|
98
|
+
def value_restriction(ranges, enforcement)
|
99
99
|
vr = @constellation.ValueRestriction(:new)
|
100
100
|
ranges.each do |range|
|
101
101
|
min, max = Array === range ? range : [range, range]
|
@@ -105,9 +105,15 @@ module ActiveFacts
|
|
105
105
|
)
|
106
106
|
ar = @constellation.AllowedRange(vr, v_range)
|
107
107
|
end
|
108
|
+
apply_enforcement(vr, enforcement) if enforcement
|
108
109
|
vr
|
109
110
|
end
|
110
111
|
|
112
|
+
def apply_enforcement(constraint, enforcement)
|
113
|
+
constraint.enforcement = enforcement[0]
|
114
|
+
constraint.enforcement.agent = enforcement[1] if enforcement[1]
|
115
|
+
end
|
116
|
+
|
111
117
|
def entity_type(name, supertypes, identification, mapping_pragmas, clauses)
|
112
118
|
#puts "Entity Type #{name}, supertypes #{supertypes.inspect}, id #{identification.inspect}, clauses = #{clauses.inspect}"
|
113
119
|
debug :entity, "Defining Entity Type #{name}" do
|
@@ -139,7 +145,7 @@ module ActiveFacts
|
|
139
145
|
end
|
140
146
|
# REVISIT: If we do this, it gets emitted twice when we generate CQL. The generator should detect that the restriction is the same and not emit it.
|
141
147
|
#if (ranges = identification[:restriction])
|
142
|
-
# vt.value_restriction = value_restriction(ranges)
|
148
|
+
# vt.value_restriction = value_restriction(ranges, identification[:enforcement])
|
143
149
|
#end
|
144
150
|
end
|
145
151
|
|
@@ -269,7 +275,7 @@ player, binding = @symbols.bind(names)
|
|
269
275
|
|
270
276
|
# REVISIT: The restriction applies only to the value role. There is good reason to apply it above to the value type as well.
|
271
277
|
if (ranges = identification[:restriction])
|
272
|
-
value_role.role_value_restriction = value_restriction(ranges)
|
278
|
+
value_role.role_value_restriction = value_restriction(ranges, identification[:enforcement])
|
273
279
|
end
|
274
280
|
|
275
281
|
# Forward reading, if it doesn't already exist:
|
@@ -315,10 +321,9 @@ player, binding = @symbols.bind(names)
|
|
315
321
|
debug :mode, "Using existing EntityType role sequence"
|
316
322
|
end
|
317
323
|
if (rs0.all_presence_constraint.size == 0)
|
318
|
-
@constellation.PresenceConstraint(
|
324
|
+
constraint = @constellation.PresenceConstraint(
|
319
325
|
:new,
|
320
326
|
:name => '',
|
321
|
-
:enforcement => '',
|
322
327
|
:vocabulary => @vocabulary,
|
323
328
|
:role_sequence => rs0,
|
324
329
|
:min_frequency => 1,
|
@@ -344,10 +349,9 @@ player, binding = @symbols.bind(names)
|
|
344
349
|
debug :mode, "Using existing ValueType role sequence"
|
345
350
|
end
|
346
351
|
if (rs1.all_presence_constraint.size == 0)
|
347
|
-
@constellation.PresenceConstraint(
|
352
|
+
constraint = @constellation.PresenceConstraint(
|
348
353
|
:new,
|
349
354
|
:name => '',
|
350
|
-
:enforcement => '',
|
351
355
|
:vocabulary => @vocabulary,
|
352
356
|
:role_sequence => rs1,
|
353
357
|
:min_frequency => 0,
|
@@ -870,7 +874,7 @@ player, binding = @symbols.bind(names)
|
|
870
874
|
role_sequences
|
871
875
|
end
|
872
876
|
|
873
|
-
def presence_constraint(constrained_role_names, quantifier, phrases_list, context)
|
877
|
+
def presence_constraint(constrained_role_names, quantifier, phrases_list, context, enforcement)
|
874
878
|
raise "REVISIT: Join presence constraints not supported yet" if phrases_list[0].size > 1
|
875
879
|
phrases_list = phrases_list.map{|r| r[0] }
|
876
880
|
#p phrases_list
|
@@ -929,10 +933,9 @@ player, binding = @symbols.bind(names)
|
|
929
933
|
|
930
934
|
# REVISIT: Check that no existing PC spans the same roles (nor a superset nor subset?)
|
931
935
|
|
932
|
-
@constellation.PresenceConstraint(
|
936
|
+
constraint = @constellation.PresenceConstraint(
|
933
937
|
:new,
|
934
938
|
:name => '',
|
935
|
-
:enforcement => '',
|
936
939
|
:vocabulary => @vocabulary,
|
937
940
|
:role_sequence => rs,
|
938
941
|
:min_frequency => quantifier[0],
|
@@ -940,9 +943,10 @@ player, binding = @symbols.bind(names)
|
|
940
943
|
:is_preferred_identifier => false,
|
941
944
|
:is_mandatory => quantifier[0] && quantifier[0] > 0
|
942
945
|
)
|
946
|
+
apply_enforcement(constraint, enforcement) if enforcement
|
943
947
|
end
|
944
948
|
|
945
|
-
def set_constraint(constrained_roles, quantifier, joins_list, context)
|
949
|
+
def set_constraint(constrained_roles, quantifier, joins_list, context, enforcement)
|
946
950
|
role_sequences = bind_joins_as_role_sequences(joins_list)
|
947
951
|
|
948
952
|
if quantifier[1] == nil
|
@@ -953,10 +957,9 @@ player, binding = @symbols.bind(names)
|
|
953
957
|
second_role_ref = @constellation.RoleRef(:role_sequence => role_sequences[0], :ordinal => 1, :role => second_role)
|
954
958
|
@constellation.deny(role_sequences[1].all_role_ref.single)
|
955
959
|
@constellation.deny(role_sequences[1])
|
956
|
-
@constellation.PresenceConstraint(
|
960
|
+
constraint = @constellation.PresenceConstraint(
|
957
961
|
:new,
|
958
962
|
:name => '',
|
959
|
-
:enforcement => '',
|
960
963
|
:vocabulary => @vocabulary,
|
961
964
|
:role_sequence => role_sequences[0],
|
962
965
|
:min_frequency => quantifier[0],
|
@@ -964,6 +967,7 @@ player, binding = @symbols.bind(names)
|
|
964
967
|
:is_preferred_identifier => false,
|
965
968
|
:is_mandatory => true
|
966
969
|
)
|
970
|
+
apply_enforcement(constraint, enforcement) if enforcement
|
967
971
|
else
|
968
972
|
# Create a normal (mandatory) exclusion constraint:
|
969
973
|
constraint = @constellation.SetExclusionConstraint(:new)
|
@@ -971,11 +975,12 @@ player, binding = @symbols.bind(names)
|
|
971
975
|
role_sequences.each_with_index do |rs, i|
|
972
976
|
@constellation.SetComparisonRoles(constraint, i, :role_sequence => rs)
|
973
977
|
end
|
978
|
+
apply_enforcement(constraint, enforcement) if enforcement
|
974
979
|
constraint.is_mandatory = quantifier[0] == 1
|
975
980
|
end
|
976
981
|
end
|
977
982
|
|
978
|
-
def subset_constraint(joins_list, context)
|
983
|
+
def subset_constraint(joins_list, context, enforcement)
|
979
984
|
role_sequences = bind_joins_as_role_sequences(joins_list)
|
980
985
|
|
981
986
|
#puts "subset_constraint:\n\t#{subset_readings.inspect}\n\t#{superset_readings.inspect}"
|
@@ -990,10 +995,11 @@ player, binding = @symbols.bind(names)
|
|
990
995
|
#constraint.enforcement =
|
991
996
|
constraint.subset_role_sequence = role_sequences[0]
|
992
997
|
constraint.superset_role_sequence = role_sequences[1]
|
998
|
+
apply_enforcement(constraint, enforcement) if enforcement
|
993
999
|
end
|
994
1000
|
|
995
|
-
def equality_constraint(joins_list, context)
|
996
|
-
#puts "
|
1001
|
+
def equality_constraint(joins_list, context, enforcement)
|
1002
|
+
#puts "equality\n\t#{joins_list.map{|rl| rl.inspect}*"\n\tif and only if\n\t"}"
|
997
1003
|
|
998
1004
|
role_sequences = bind_joins_as_role_sequences(joins_list)
|
999
1005
|
|
@@ -1003,6 +1009,7 @@ player, binding = @symbols.bind(names)
|
|
1003
1009
|
role_sequences.each_with_index do |rs, i|
|
1004
1010
|
@constellation.SetComparisonRoles(constraint, i, :role_sequence => rs)
|
1005
1011
|
end
|
1012
|
+
apply_enforcement(constraint, enforcement) if enforcement
|
1006
1013
|
end
|
1007
1014
|
|
1008
1015
|
# Search the supertypes of 'subtype' looking for an inheritance path to 'supertype',
|
@@ -1195,7 +1202,7 @@ player, binding = @symbols.bind(names)
|
|
1195
1202
|
|
1196
1203
|
# Save a role value restriction
|
1197
1204
|
if (ranges = role_phrase[:restriction])
|
1198
|
-
role.role_value_restriction = value_restriction(ranges)
|
1205
|
+
role.role_value_restriction = value_restriction(ranges, role_phrase[:restriction_enforcement])
|
1199
1206
|
end
|
1200
1207
|
|
1201
1208
|
roles << role
|
data/lib/activefacts/version.rb
CHANGED
@@ -7,6 +7,10 @@ module ActiveFacts
|
|
7
7
|
value_type :length => 64
|
8
8
|
end
|
9
9
|
|
10
|
+
class AgentName < String
|
11
|
+
value_type
|
12
|
+
end
|
13
|
+
|
10
14
|
class Assimilation < String
|
11
15
|
value_type
|
12
16
|
restrict 'partitioned', 'separate'
|
@@ -37,7 +41,7 @@ module ActiveFacts
|
|
37
41
|
value_type
|
38
42
|
end
|
39
43
|
|
40
|
-
class
|
44
|
+
class EnforcementCode < String
|
41
45
|
value_type :length => 16
|
42
46
|
end
|
43
47
|
|
@@ -85,10 +89,6 @@ module ActiveFacts
|
|
85
89
|
value_type :length => 32
|
86
90
|
end
|
87
91
|
|
88
|
-
class PersonName < String
|
89
|
-
value_type
|
90
|
-
end
|
91
|
-
|
92
92
|
class Pronoun < String
|
93
93
|
value_type :length => 20
|
94
94
|
restrict 'feminine', 'masculine', 'neuter', 'personal'
|
@@ -114,8 +114,9 @@ module ActiveFacts
|
|
114
114
|
value_type
|
115
115
|
end
|
116
116
|
|
117
|
-
class
|
118
|
-
|
117
|
+
class Agent
|
118
|
+
identified_by :agent_name
|
119
|
+
one_to_one :agent_name, :mandatory => true # See AgentName.agent
|
119
120
|
end
|
120
121
|
|
121
122
|
class Coefficient
|
@@ -143,6 +144,12 @@ module ActiveFacts
|
|
143
144
|
has_one :fact_type # See FactType.all_context_note
|
144
145
|
end
|
145
146
|
|
147
|
+
class Enforcement
|
148
|
+
identified_by :enforcement_code
|
149
|
+
has_one :agent # See Agent.all_enforcement
|
150
|
+
one_to_one :enforcement_code, :mandatory => true # See EnforcementCode.enforcement
|
151
|
+
end
|
152
|
+
|
146
153
|
class Fact
|
147
154
|
identified_by :fact_id
|
148
155
|
one_to_one :fact_id, :mandatory => true # See FactId.fact
|
@@ -164,11 +171,6 @@ module ActiveFacts
|
|
164
171
|
has_one :value # See Value.all_instance
|
165
172
|
end
|
166
173
|
|
167
|
-
class Person
|
168
|
-
identified_by :person_name
|
169
|
-
one_to_one :person_name, :mandatory => true # See PersonName.person
|
170
|
-
end
|
171
|
-
|
172
174
|
class PresenceConstraint < Constraint
|
173
175
|
maybe :is_mandatory
|
174
176
|
maybe :is_preferred_identifier
|
@@ -239,9 +241,7 @@ module ActiveFacts
|
|
239
241
|
has_one :unit # See Unit.all_value
|
240
242
|
end
|
241
243
|
|
242
|
-
class ValueRestriction
|
243
|
-
identified_by :value_restriction_id
|
244
|
-
one_to_one :value_restriction_id, :mandatory => true # See ValueRestrictionId.value_restriction
|
244
|
+
class ValueRestriction < Constraint
|
245
245
|
end
|
246
246
|
|
247
247
|
class Vocabulary
|
@@ -270,15 +270,15 @@ module ActiveFacts
|
|
270
270
|
end
|
271
271
|
|
272
272
|
class ContextAccordingTo
|
273
|
-
identified_by :context_note, :
|
273
|
+
identified_by :context_note, :agent
|
274
|
+
has_one :agent, :mandatory => true # See Agent.all_context_according_to
|
274
275
|
has_one :context_note, :mandatory => true # See ContextNote.all_context_according_to
|
275
|
-
has_one :person, :mandatory => true # See Person.all_context_according_to
|
276
276
|
end
|
277
277
|
|
278
278
|
class ContextAgreedBy
|
279
|
-
identified_by :agreement, :
|
279
|
+
identified_by :agreement, :agent
|
280
|
+
has_one :agent, :mandatory => true # See Agent.all_context_agreed_by
|
280
281
|
has_one :agreement, :mandatory => true # See Agreement.all_context_agreed_by
|
281
|
-
has_one :person, :mandatory => true # See Person.all_context_agreed_by
|
282
282
|
end
|
283
283
|
|
284
284
|
class Derivation
|
@@ -15,7 +15,7 @@ include ActiveFacts
|
|
15
15
|
describe "Column lists from absorption compared with Ruby's" do
|
16
16
|
ABSORPTION_RUBY_FAILURES = {
|
17
17
|
"Metamodel" => "Overlaps with ActiveFacts Metamodel",
|
18
|
-
"
|
18
|
+
"MetamodelNext" => "Overlaps with ActiveFacts Metamodel",
|
19
19
|
"ServiceDirector" => "Lacks standard AutoTimestamp class"
|
20
20
|
}
|
21
21
|
|
data/spec/cql/context_spec.rb
CHANGED
@@ -15,39 +15,39 @@ describe "Business Context Notes" do
|
|
15
15
|
Notes = [
|
16
16
|
# Constraints:
|
17
17
|
[ 'each Person occurs one time in Person is employed, Person is unemployed (because it can be no other way!);',
|
18
|
-
[["Person", [:value_type, "Person", [], [], [], []]], [nil, [:constraint, :presence, [["Person"]], [1, 1], [[[{:word=>"Person"}, {:word=>"is"}, {:word=>"employed"}]], [[{:word=>"Person"}, {:word=>"is"}, {:word=>"unemployed"}]]], [nil, "because", "it can be no other way!", []]]]]
|
18
|
+
[["Person", [:value_type, "Person", [], [], [], [], nil]], [nil, [:constraint, :presence, [["Person"]], [1, 1], [[[{:word=>"Person"}, {:word=>"is"}, {:word=>"employed"}]], [[{:word=>"Person"}, {:word=>"is"}, {:word=>"unemployed"}]]], [nil, "because", "it can be no other way!", []], []]]]
|
19
19
|
],
|
20
20
|
[ 'each Person occurs one time in Person is employed, Person is unemployed (as opposed to blah!);',
|
21
|
-
[["Person", [:value_type, "Person", [], [], [], []]], [nil, [:constraint, :presence, [["Person"]], [1, 1], [[[{:word=>"Person"}, {:word=>"is"}, {:word=>"employed"}]], [[{:word=>"Person"}, {:word=>"is"}, {:word=>"unemployed"}]]], [nil, "as_opposed_to", " blah!", []]]]]
|
21
|
+
[["Person", [:value_type, "Person", [], [], [], [], nil]], [nil, [:constraint, :presence, [["Person"]], [1, 1], [[[{:word=>"Person"}, {:word=>"is"}, {:word=>"employed"}]], [[{:word=>"Person"}, {:word=>"is"}, {:word=>"unemployed"}]]], [nil, "as_opposed_to", " blah!", []], []]]]
|
22
22
|
],
|
23
23
|
[ 'for each Person at least one of these holds: Person is employed, Person is a bad credit risk (so that blah);',
|
24
|
-
[["Person", [:value_type, "Person", [], [], [], []]], [nil, [:constraint, :set, [["Person"]], [1, nil], [[[{:word=>"Person"}, {:word=>"is"}, {:word=>"employed"}]], [[{:word=>"Person"}, {:word=>"is"}, {:word=>"a"}, {:word=>"bad"}, {:word=>"credit"}, {:word=>"risk"}]]], [nil, "so_that", " blah", []]]]]
|
24
|
+
[["Person", [:value_type, "Person", [], [], [], [], nil]], [nil, [:constraint, :set, [["Person"]], [1, nil], [[[{:word=>"Person"}, {:word=>"is"}, {:word=>"employed"}]], [[{:word=>"Person"}, {:word=>"is"}, {:word=>"a"}, {:word=>"bad"}, {:word=>"credit"}, {:word=>"risk"}]]], [nil, "so_that", " blah", []], []]]]
|
25
25
|
],
|
26
26
|
[ 'Person is good credit risk only if Person is employed (to avoid lending to people who can\'t repay);',
|
27
|
-
[["Person", [:value_type, "Person", [], [], [], []]], [nil, [:constraint, :subset, [[[{:word=>"Person"}, {:word=>"is"}, {:word=>"good"}, {:word=>"credit"}, {:word=>"risk"}]], [[{:word=>"Person"}, {:word=>"is"}, {:word=>"employed"}]]], [nil, "to_avoid", " lending to people who can't repay", []]]]]
|
27
|
+
[["Person", [:value_type, "Person", [], [], [], [], nil]], [nil, [:constraint, :subset, [[[{:word=>"Person"}, {:word=>"is"}, {:word=>"good"}, {:word=>"credit"}, {:word=>"risk"}]], [[{:word=>"Person"}, {:word=>"is"}, {:word=>"employed"}]]], [nil, "to_avoid", " lending to people who can't repay", []], []]]]
|
28
28
|
],
|
29
29
|
[ 'Person is good credit risk if and only if Person is employed (to avoid lending to people who can\'t repay);',
|
30
|
-
[["Person", [:value_type, "Person", [], [], [], []]], [nil, [:constraint, :equality, [[[{:word=>"Person"}, {:word=>"is"}, {:word=>"good"}, {:word=>"credit"}, {:word=>"risk"}]], [[{:word=>"Person"}, {:word=>"is"}, {:word=>"employed"}]]], [nil, "to_avoid", " lending to people who can't repay", []]]]]
|
30
|
+
[["Person", [:value_type, "Person", [], [], [], [], nil]], [nil, [:constraint, :equality, [[[{:word=>"Person"}, {:word=>"is"}, {:word=>"good"}, {:word=>"credit"}, {:word=>"risk"}]], [[{:word=>"Person"}, {:word=>"is"}, {:word=>"employed"}]]], [nil, "to_avoid", " lending to people who can't repay", []], []]]]
|
31
31
|
],
|
32
32
|
# Entity and Fact types
|
33
33
|
[ 'Foo is identified by Bar [independent] where Foo has one Bar (so that we have an id);',
|
34
|
-
[["Person", [:value_type, "Person", [], [], [], []]], ["Foo", [:entity_type, [], {:roles=>[["Bar"]]}, ["independent"], [[:fact_clause, [], [{:word=>"Foo"}, {:word=>"has"}, {:
|
34
|
+
[["Person", [:value_type, "Person", [], [], [], [], nil]], ["Foo", [:entity_type, [], {:roles=>[["Bar"]]}, ["independent"], [[:fact_clause, [], [{:word=>"Foo"}, {:word=>"has"}, {:quantifier=>[1, 1], :quantifier_restriction=>[], :word=>"Bar"}], [nil, "so_that", " we have an id", []]]]]]]
|
35
35
|
],
|
36
36
|
[ 'Foo has one Bar (so that we have an id), Bar is of one Foo (because we need that);',
|
37
|
-
[["Person", [:value_type, "Person", [], [], [], []]], [nil, [:fact_type, [[:fact_clause, [], [{:word=>"Foo"}, {:word=>"has"}, {:
|
37
|
+
[["Person", [:value_type, "Person", [], [], [], [], nil]], [nil, [:fact_type, [[:fact_clause, [], [{:word=>"Foo"}, {:word=>"has"}, {:quantifier=>[1, 1], :quantifier_restriction=>[], :word=>"Bar"}], [nil, "so_that", " we have an id", []]], [:fact_clause, [], [{:word=>"Bar"}, {:word=>"is"}, {:word=>"of"}, {:quantifier=>[1, 1], :quantifier_restriction=>[], :word=>"Foo"}], [nil, "because", "we need that", []]]], []]]]
|
38
38
|
],
|
39
39
|
# REVISIT: No context notes on quantifiers yet
|
40
40
|
# As agreed by:
|
41
41
|
[ 'for each Person at least one of these holds: Person is employed, Person is a bad credit risk (so that blah, as agreed by Jim);',
|
42
|
-
[["Person", [:value_type, "Person", [], [], [], []]], [nil, [:constraint, :set, [["Person"]], [1, nil], [[[{:word=>"Person"}, {:word=>"is"}, {:word=>"employed"}]], [[{:word=>"Person"}, {:word=>"is"}, {:word=>"a"}, {:word=>"bad"}, {:word=>"credit"}, {:word=>"risk"}]]], [nil, "so_that", " blah", [nil, ["Jim"]]]]]]
|
42
|
+
[["Person", [:value_type, "Person", [], [], [], [], nil]], [nil, [:constraint, :set, [["Person"]], [1, nil], [[[{:word=>"Person"}, {:word=>"is"}, {:word=>"employed"}]], [[{:word=>"Person"}, {:word=>"is"}, {:word=>"a"}, {:word=>"bad"}, {:word=>"credit"}, {:word=>"risk"}]]], [nil, "so_that", " blah", [nil, ["Jim"]]], []]]]
|
43
43
|
],
|
44
44
|
# REVISIT: Populate an "as agreed by" with a date
|
45
45
|
[ 'for each Person at least one of these holds: Person is employed, Person is a bad credit risk (so that blah, as agreed on 29 March by Jim);',
|
46
|
-
[["Person", [:value_type, "Person", [], [], [], []]], [nil, [:constraint, :set, [["Person"]], [1, nil], [[[{:word=>"Person"}, {:word=>"is"}, {:word=>"employed"}]], [[{:word=>"Person"}, {:word=>"is"}, {:word=>"a"}, {:word=>"bad"}, {:word=>"credit"}, {:word=>"risk"}]]], [nil, "so_that", " blah", ["29 March", ["Jim"]]]]]]
|
46
|
+
[["Person", [:value_type, "Person", [], [], [], [], nil]], [nil, [:constraint, :set, [["Person"]], [1, nil], [[[{:word=>"Person"}, {:word=>"is"}, {:word=>"employed"}]], [[{:word=>"Person"}, {:word=>"is"}, {:word=>"a"}, {:word=>"bad"}, {:word=>"credit"}, {:word=>"risk"}]]], [nil, "so_that", " blah", ["29 March", ["Jim"]]], []]]]
|
47
47
|
],
|
48
48
|
# According to:
|
49
49
|
[ 'for each Person at least one of these holds: Person is employed, Person is a bad credit risk (according to jim, so that blah);',
|
50
|
-
[["Person", [:value_type, "Person", [], [], [], []]], [nil, [:constraint, :set, [["Person"]], [1, nil], [[[{:word=>"Person"}, {:word=>"is"}, {:word=>"employed"}]], [[{:word=>"Person"}, {:word=>"is"}, {:word=>"a"}, {:word=>"bad"}, {:word=>"credit"}, {:word=>"risk"}]]], [["jim"], "so_that", " blah", []]]]]
|
50
|
+
[["Person", [:value_type, "Person", [], [], [], [], nil]], [nil, [:constraint, :set, [["Person"]], [1, nil], [[[{:word=>"Person"}, {:word=>"is"}, {:word=>"employed"}]], [[{:word=>"Person"}, {:word=>"is"}, {:word=>"a"}, {:word=>"bad"}, {:word=>"credit"}, {:word=>"risk"}]]], [["jim"], "so_that", " blah", []], []]]]
|
51
51
|
],
|
52
52
|
]
|
53
53
|
|
data/spec/cql/unit_spec.rb
CHANGED
@@ -167,7 +167,7 @@ end
|
|
167
167
|
describe "Value Types" do
|
168
168
|
ValueTypes = [
|
169
169
|
[ "a is written as b(1, 2) inch restricted to { 3 .. 4 } inch ;",
|
170
|
-
[["a", [:value_type, "b", [
|
170
|
+
[["a", [:value_type, "b", [1, 2], [["inch", 1]], [[3, 4]], [], []]]]
|
171
171
|
],
|
172
172
|
# [ "a c is written as b(1, 2) inch restricted to { 3 .. 4 } inch ;",
|
173
173
|
# [["a c", [:value_type, "b", [1, 2], "inch", [[3, 4]]]]]
|
@@ -195,16 +195,16 @@ end
|
|
195
195
|
describe "Entity Types" do
|
196
196
|
EntityTypes_RefMode = [
|
197
197
|
[ "a is identified by its id;", # Entity type declaration with reference mode
|
198
|
-
[["a", [:entity_type, [], {:mode=>"id", :parameters=>
|
198
|
+
[["a", [:entity_type, [], {:enforcement=>nil, :mode=>"id", :parameters=>[], :restriction=>nil}, [], nil]]]
|
199
199
|
],
|
200
200
|
[ "a is identified by its number(12);", # Entity type declaration with reference mode
|
201
|
-
[["a", [:entity_type, [], {:mode=>"number", :parameters
|
201
|
+
[["a", [:entity_type, [], {:enforcement=>nil, :mode=>"number", :parameters=>[12], :restriction=>nil}, [], nil]]]
|
202
202
|
],
|
203
203
|
[ "a is identified by its id:c;", # Entity type declaration with reference mode and fact type(s)
|
204
|
-
[["a", [:entity_type, [], {:mode=>"id", :parameters=>
|
204
|
+
[["a", [:entity_type, [], {:enforcement=>nil, :mode=>"id", :parameters=>[], :restriction=>nil}, [], [[:fact_clause, [], [{:word=>"c"}], nil]]]]]
|
205
205
|
],
|
206
206
|
[ "a is identified by its id where c;", # Entity type declaration with reference mode and where
|
207
|
-
[["a", [:entity_type, [], {:mode=>"id", :parameters=>
|
207
|
+
[["a", [:entity_type, [], {:enforcement=>nil, :mode=>"id", :parameters=>[], :restriction=>nil}, [], [[:fact_clause, [], [{:word=>"c"}], nil]]]]]
|
208
208
|
],
|
209
209
|
]
|
210
210
|
|
@@ -222,12 +222,10 @@ describe "Entity Types" do
|
|
222
222
|
[["a", [:entity_type, [], {:roles=>[["b"], ["c"]]}, [], [[:fact_clause, [], [{:word=>"d"}], nil]]]]]
|
223
223
|
],
|
224
224
|
[ "a is written as b(); c is identified by a:d;",
|
225
|
-
[["a", [:value_type, "b", [], [], [], []]],
|
226
|
-
["c", [:entity_type, [], {:roles=>[["a"]]}, [], [[:fact_clause, [], [{:word=>"d"}], nil]]]]]
|
225
|
+
[["a", [:value_type, "b", [], [], [], [], nil]], ["c", [:entity_type, [], {:roles=>[["a"]]}, [], [[:fact_clause, [], [{:word=>"d"}], nil]]]]]
|
227
226
|
],
|
228
227
|
[ " a is written as b ( ) ; c is identified by a : d ; ",
|
229
|
-
[["a", [:value_type, "b", [], [], [], []]],
|
230
|
-
["c", [:entity_type, [], {:roles=>[["a"]]}, [], [[:fact_clause, [], [{:word=>"d"}], nil]]]]]
|
228
|
+
[["a", [:value_type, "b", [], [], [], [], nil]], ["c", [:entity_type, [], {:roles=>[["a"]]}, [], [[:fact_clause, [], [{:word=>"d"}], nil]]]]]
|
231
229
|
],
|
232
230
|
[ "a is identified by c:maybe d;",
|
233
231
|
[["a", [:entity_type, [], {:roles=>[["c"]]}, [], [[:fact_clause, ["maybe"], [{:word=>"d"}], nil]]]]]
|
@@ -343,7 +341,7 @@ describe "Fact Types" do
|
|
343
341
|
|
344
342
|
Constraints = [
|
345
343
|
[ "each combination FamilyName, GivenName occurs at most one time in Competitor has FamilyName, Competitor has GivenName;",
|
346
|
-
[nil, [:constraint, :presence, [["FamilyName"], ["GivenName"]], [nil, 1], [[[{:word=>"Competitor"}, {:word=>"has"}, {:word=>"FamilyName"}]], [[{:word=>"Competitor"}, {:word=>"has"}, {:word=>"GivenName"}]]], nil]]
|
344
|
+
[nil, [:constraint, :presence, [["FamilyName"], ["GivenName"]], [nil, 1], [[[{:word=>"Competitor"}, {:word=>"has"}, {:word=>"FamilyName"}]], [[{:word=>"Competitor"}, {:word=>"has"}, {:word=>"GivenName"}]]], nil, []]]
|
347
345
|
],
|
348
346
|
]
|
349
347
|
|
data/spec/cql_cql_spec.rb
CHANGED
@@ -16,12 +16,12 @@ describe "CQL Loader" do
|
|
16
16
|
cql_failures = {
|
17
17
|
"Airline" => "Contains queries, unsupported",
|
18
18
|
"CompanyQuery" => "Contains queries, unsupported",
|
19
|
+
"MetamodelNext" => "Fails due to weak adjective/role matching",
|
19
20
|
"OrienteeringER" => "Doesn't parse due to difficult fact type match",
|
20
21
|
"ServiceDirector" => "Doesn't parse some constraints due to mis-matched adjectives"
|
21
22
|
}
|
22
23
|
cql_cql_failures = {
|
23
24
|
"Insurance" => "Misses a subtype join in a constraint verbalisation",
|
24
|
-
"MetamodelTerms" => "Fails due to weak adjective/role matching",
|
25
25
|
# "OddIdentifier" => "Doesn't support identification of object fact types using mixed external/internal roles",
|
26
26
|
}
|
27
27
|
# Generate and return the CQL for the given vocabulary
|
data/spec/norma_tables_spec.rb
CHANGED
@@ -20,7 +20,7 @@ Exceptions = {
|
|
20
20
|
"Blog" => ["Author", "Comment", "Paragraph", "Post", "Topic"],
|
21
21
|
"JoinEquality" => ["Event", "Seat", "Ticket", "Venue"],
|
22
22
|
"Metamodel" => ["AllowedRange", "Concept", "Constraint", "ContextAccordingTo", "ContextAgreedBy", "ContextNote", "Derivation", "Fact", "FactType", "Instance", "Join", "ParamValue", "Reading", "Role", "RoleRef", "RoleSequence", "RoleValue", "SetComparisonRoles", "Unit", "ValueRestriction" ],
|
23
|
-
"
|
23
|
+
"MetamodelNext" => ["AllowedRange", "Constraint", "ContextAccordingTo", "ContextAgreedBy", "ContextNote", "Derivation", "Fact", "FactType", "Instance", "Join", "ParamValue", "Reading", "Role", "RoleRef", "RoleSequence", "RoleValue", "SetComparisonRoles", "Term", "Unit", "ValueConstraint"],
|
24
24
|
"OilSupply" => ["AcceptableSubstitutes", "Month", "ProductionForecast", "RegionalDemand", "TransportRoute"],
|
25
25
|
"Orienteering" => ["Club", "Entry", "Event", "EventControl", "EventScoringMethod", "Map", "Person", "Punch", "PunchPlacement", "Series", "Visit"],
|
26
26
|
"SeparateSubtype" => ["Claim", "VehicleIncident"],
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activefacts
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Clifford Heath
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-04-09 00:00:00 +10:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -40,7 +40,7 @@ dependencies:
|
|
40
40
|
requirements:
|
41
41
|
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: 2.3.
|
43
|
+
version: 2.3.3
|
44
44
|
version:
|
45
45
|
description: |
|
46
46
|
|