activefacts 0.8.5 → 0.8.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 ] ]; end }
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] : # At least one (meaning 1 or 2/more)
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 r:restriction? # Reference Mode; restriction may be needed for the ValueType
73
- { def value; {:mode => id.value, :restriction => (r.text_value.empty? ? nil : r.ranges), :parameters => value_type_parameters.values }; end }
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 }
@@ -15,8 +15,8 @@ module ActiveFacts
15
15
  end
16
16
 
17
17
  rule who_says
18
- according_to people s ','
19
- { def value; people.value; end }
18
+ according_to agents s ','
19
+ { def value; agents.value; end }
20
20
  end
21
21
 
22
22
  rule context_type
@@ -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
- quantifier = !q.empty? && q.value # "some" quantifier has nil value
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
- r[:restriction] = lr.ranges if !lr.empty? && lr.respond_to?(:ranges)
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 people
72
- { def value; [ d.empty? ? nil : d.date.value, people.value ]; end }
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 people
81
- s h:person s t:(',' s !context_type person s)*
82
- { def value; [h.text_value] + t.elements.map{|e| e.person.text_value }; end }
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 person
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 ranges
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 "REVISIT: equality\n\t#{joins_list.map{|rl| rl.inspect}*"\n\tif and only if\n\t"}"
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
@@ -53,6 +53,14 @@ module ActiveFacts
53
53
  def index(*a)
54
54
  @input.index(*a)
55
55
  end
56
+
57
+ def line_of(x)
58
+ @input.line_of(x)
59
+ end
60
+
61
+ def column_of(x)
62
+ @input.column_of(x)
63
+ end
56
64
  end
57
65
 
58
66
  def context
@@ -5,5 +5,5 @@
5
5
  # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
6
6
  #
7
7
  module ActiveFacts
8
- VERSION = '0.8.5'
8
+ VERSION = '0.8.6'
9
9
  end
@@ -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 Enforcement < String
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 ValueRestrictionId < AutoCounter
118
- value_type
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, :person
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, :person
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
- "MetamodelTerms" => "Overlaps with ActiveFacts Metamodel",
18
+ "MetamodelNext" => "Overlaps with ActiveFacts Metamodel",
19
19
  "ServiceDirector" => "Lacks standard AutoTimestamp class"
20
20
  }
21
21
 
@@ -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"}, {:word=>"Bar", :quantifier=>[1, 1]}], [nil, "so_that", " we have an id", []]]]]]]
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"}, {:word=>"Bar", :quantifier=>[1, 1]}], [nil, "so_that", " we have an id", []]], [:fact_clause, [], [{:word=>"Bar"}, {:word=>"is"}, {:word=>"of"}, {:word=>"Foo", :quantifier=>[1, 1]}], [nil, "because", "we need that", []]]], []]]]
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
 
@@ -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", [ 1, 2 ], [["inch", 1]], [[3, 4]], []]]]
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=> [], :restriction=>nil}, [], nil]]]
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 => [12], :restriction=>nil}, [], nil]]]
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=> [], :restriction=>nil}, [], [[:fact_clause, [], [{:word=>"c"}], nil]]]]]
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=> [], :restriction=>nil}, [], [[:fact_clause, [], [{:word=>"c"}], nil]]]]]
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
@@ -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
- "MetamodelTerms" => ["AllowedRange", "Constraint", "ContextAccordingTo", "ContextAgreedBy", "ContextNote", "Derivation", "Fact", "FactType", "Instance", "Join", "ParamValue", "Reading", "Role", "RoleRef", "RoleSequence", "RoleValue", "SetComparisonRoles", "Term", "Unit", "ValueRestriction"],
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.5
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: 2009-09-24 00:00:00 +10:00
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.2
43
+ version: 2.3.3
44
44
  version:
45
45
  description: |
46
46