activefacts 0.8.5 → 0.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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