activefacts 0.8.9 → 0.8.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. data/.gemtest +0 -0
  2. data/Manifest.txt +28 -33
  3. data/Rakefile +11 -12
  4. data/bin/cql +90 -46
  5. data/examples/CQL/Blog.cql +2 -1
  6. data/examples/CQL/CompanyDirectorEmployee.cql +2 -2
  7. data/examples/CQL/Death.cql +1 -1
  8. data/examples/CQL/Diplomacy.cql +9 -9
  9. data/examples/CQL/Genealogy.cql +3 -2
  10. data/examples/CQL/Insurance.cql +10 -7
  11. data/examples/CQL/JoinEquality.cql +2 -2
  12. data/examples/CQL/Marriage.cql +1 -1
  13. data/examples/CQL/Metamodel.cql +73 -53
  14. data/examples/CQL/MetamodelNext.cql +89 -67
  15. data/examples/CQL/OneToOnes.cql +2 -2
  16. data/examples/CQL/ServiceDirector.cql +10 -5
  17. data/examples/CQL/Supervision.cql +3 -3
  18. data/examples/CQL/Tests.Test5.Load.cql +1 -1
  19. data/examples/CQL/Warehousing.cql +4 -2
  20. data/lib/activefacts/cql/CQLParser.treetop +26 -60
  21. data/lib/activefacts/cql/Context.treetop +12 -2
  22. data/lib/activefacts/cql/Expressions.treetop +14 -30
  23. data/lib/activefacts/cql/FactTypes.treetop +165 -110
  24. data/lib/activefacts/cql/Language/English.treetop +167 -54
  25. data/lib/activefacts/cql/LexicalRules.treetop +16 -2
  26. data/lib/activefacts/cql/{Concepts.treetop → ObjectTypes.treetop} +36 -37
  27. data/lib/activefacts/cql/Terms.treetop +57 -27
  28. data/lib/activefacts/cql/ValueTypes.treetop +39 -13
  29. data/lib/activefacts/cql/compiler.rb +5 -3
  30. data/lib/activefacts/cql/compiler/{reading.rb → clause.rb} +407 -285
  31. data/lib/activefacts/cql/compiler/constraint.rb +178 -275
  32. data/lib/activefacts/cql/compiler/entity_type.rb +73 -64
  33. data/lib/activefacts/cql/compiler/expression.rb +418 -0
  34. data/lib/activefacts/cql/compiler/fact.rb +146 -145
  35. data/lib/activefacts/cql/compiler/fact_type.rb +197 -80
  36. data/lib/activefacts/cql/compiler/join.rb +159 -0
  37. data/lib/activefacts/cql/compiler/shared.rb +51 -23
  38. data/lib/activefacts/cql/compiler/value_type.rb +56 -2
  39. data/lib/activefacts/cql/parser.rb +15 -4
  40. data/lib/activefacts/generate/absorption.rb +7 -7
  41. data/lib/activefacts/generate/cql.rb +100 -37
  42. data/lib/activefacts/generate/oo.rb +28 -51
  43. data/lib/activefacts/generate/ordered.rb +60 -36
  44. data/lib/activefacts/generate/ruby.rb +6 -6
  45. data/lib/activefacts/generate/sql/server.rb +4 -4
  46. data/lib/activefacts/input/orm.rb +71 -53
  47. data/lib/activefacts/persistence.rb +1 -1
  48. data/lib/activefacts/persistence/columns.rb +27 -23
  49. data/lib/activefacts/persistence/foreignkey.rb +6 -6
  50. data/lib/activefacts/persistence/index.rb +17 -17
  51. data/lib/activefacts/persistence/{concept.rb → object_type.rb} +9 -9
  52. data/lib/activefacts/persistence/reference.rb +61 -36
  53. data/lib/activefacts/persistence/tables.rb +61 -59
  54. data/lib/activefacts/support.rb +54 -29
  55. data/lib/activefacts/version.rb +1 -1
  56. data/lib/activefacts/vocabulary/extensions.rb +99 -54
  57. data/lib/activefacts/vocabulary/metamodel.rb +43 -37
  58. data/lib/activefacts/vocabulary/verbaliser.rb +134 -109
  59. data/spec/absorption_spec.rb +8 -8
  60. data/spec/cql/comparison_spec.rb +91 -0
  61. data/spec/cql/contractions_spec.rb +251 -0
  62. data/spec/cql/entity_type_spec.rb +319 -0
  63. data/spec/cql/expressions_spec.rb +63 -0
  64. data/spec/cql/fact_type_matching_spec.rb +283 -0
  65. data/spec/cql/french_spec.rb +21 -0
  66. data/spec/cql/parser/bad_literals_spec.rb +86 -0
  67. data/spec/cql/parser/constraints_spec.rb +19 -0
  68. data/spec/cql/parser/entity_types_spec.rb +106 -0
  69. data/spec/cql/parser/expressions_spec.rb +179 -0
  70. data/spec/cql/parser/fact_types_spec.rb +41 -0
  71. data/spec/cql/parser/literals_spec.rb +312 -0
  72. data/spec/cql/parser/pragmas_spec.rb +89 -0
  73. data/spec/cql/parser/value_types_spec.rb +42 -0
  74. data/spec/cql/role_matching_spec.rb +147 -0
  75. data/spec/cql/samples_spec.rb +9 -9
  76. data/spec/cql_cql_spec.rb +1 -1
  77. data/spec/cql_dm_spec.rb +116 -0
  78. data/spec/cql_mysql_spec.rb +1 -1
  79. data/spec/cql_ruby_spec.rb +1 -1
  80. data/spec/cql_sql_spec.rb +3 -3
  81. data/spec/cql_symbol_tables_spec.rb +30 -30
  82. data/spec/cqldump_spec.rb +4 -4
  83. data/spec/helpers/array_matcher.rb +32 -27
  84. data/spec/helpers/diff_matcher.rb +6 -26
  85. data/spec/helpers/file_matcher.rb +41 -32
  86. data/spec/helpers/parse_to_ast_matcher.rb +76 -0
  87. data/spec/helpers/string_matcher.rb +32 -31
  88. data/spec/norma_cql_spec.rb +1 -1
  89. data/spec/norma_ruby_spec.rb +1 -1
  90. data/spec/norma_ruby_sql_spec.rb +1 -1
  91. data/spec/norma_sql_spec.rb +3 -1
  92. data/spec/norma_tables_spec.rb +1 -1
  93. data/spec/ruby_api_spec.rb +23 -0
  94. data/spec/spec_helper.rb +5 -4
  95. metadata +66 -66
  96. data/examples/CQL/OrienteeringER.cql +0 -58
  97. data/lib/activefacts/api.rb +0 -44
  98. data/lib/activefacts/api/concept.rb +0 -410
  99. data/lib/activefacts/api/constellation.rb +0 -128
  100. data/lib/activefacts/api/entity.rb +0 -256
  101. data/lib/activefacts/api/instance.rb +0 -60
  102. data/lib/activefacts/api/instance_index.rb +0 -80
  103. data/lib/activefacts/api/numeric.rb +0 -167
  104. data/lib/activefacts/api/role.rb +0 -80
  105. data/lib/activefacts/api/role_proxy.rb +0 -70
  106. data/lib/activefacts/api/role_values.rb +0 -117
  107. data/lib/activefacts/api/standard_types.rb +0 -87
  108. data/lib/activefacts/api/support.rb +0 -65
  109. data/lib/activefacts/api/value.rb +0 -135
  110. data/lib/activefacts/api/vocabulary.rb +0 -82
  111. data/spec/api/autocounter.rb +0 -82
  112. data/spec/api/constellation.rb +0 -130
  113. data/spec/api/entity_type.rb +0 -103
  114. data/spec/api/instance.rb +0 -461
  115. data/spec/api/roles.rb +0 -124
  116. data/spec/api/value_type.rb +0 -112
  117. data/spec/api_spec.rb +0 -13
  118. data/spec/cql/matching_spec.rb +0 -517
  119. data/spec/cql/unit_spec.rb +0 -394
  120. data/spec/spec.opts +0 -1
@@ -1,124 +0,0 @@
1
- #
2
- # ActiveFacts tests: Roles of concept classes in the Runtime API
3
- # Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
4
- #
5
- require 'activefacts/api'
6
-
7
- describe "Roles" do
8
- before :each do
9
- Object.send :remove_const, :Mod if Object.const_defined?("Mod")
10
- module Mod
11
- class Name < String
12
- value_type
13
- end
14
- class LegalEntity
15
- identified_by :name
16
- has_one :name
17
- end
18
- class Contract
19
- identified_by :first, :second
20
- has_one :first, :class => LegalEntity
21
- has_one :second, :class => LegalEntity
22
- end
23
- class Person < LegalEntity
24
- # identified_by # No identifier needed, inherit from superclass
25
- # New identifier:
26
- identified_by :family, :given
27
- has_one :family, :class => Name
28
- has_one :given, :class => Name
29
- has_one :related_to, :class => LegalEntity
30
- end
31
- end
32
- # print "concept: "; p Mod.concept
33
- end
34
-
35
- it "should associate a role name with a matching existing concept" do
36
- module Mod
37
- class Existing1 < String
38
- value_type
39
- has_one :name
40
- end
41
- end
42
- role = Mod::Existing1.roles(:name)
43
- role.should_not be_nil
44
- role.counterpart_concept.should == Mod::Name
45
- end
46
-
47
- it "should inject the respective role name into the matching concept" do
48
- module Mod
49
- class Existing1 < String
50
- value_type
51
- has_one :name
52
- end
53
- end
54
- Mod::Name.roles(:all_existing1).should_not be_nil
55
- Mod::LegalEntity.roles(:all_contract_as_first).should_not be_nil
56
- end
57
-
58
- it "should associate a role name with a matching concept after it's created" do
59
- module Mod
60
- class Existing2 < String
61
- value_type
62
- has_one :given_name
63
- end
64
- end
65
- # print "Mod::Existing2.roles = "; p Mod::Existing2.roles
66
- r = Mod::Existing2.roles(:given_name)
67
- r.should_not be_nil
68
- Symbol.should === r.counterpart_concept
69
- module Mod
70
- class GivenName < String
71
- value_type
72
- end
73
- end
74
- # puts "Should resolve now:"
75
- r = Mod::Existing2.roles(:given_name)
76
- r.should_not be_nil
77
- r.counterpart_concept.should == Mod::GivenName
78
- end
79
-
80
- it "should handle subtyping a value type" do
81
- module Mod
82
- class FamilyName < Name
83
- value_type
84
- one_to_one :patriarch, :class => Person
85
- end
86
- end
87
- r = Mod::FamilyName.roles(:patriarch)
88
- r.should_not be_nil
89
- r.counterpart_concept.should == Mod::Person
90
- r.counterpart_concept.roles(:family_name_as_patriarch).counterpart_concept.should == Mod::FamilyName
91
- end
92
-
93
- it "should instantiate the matching concept on assignment" do
94
- c = ActiveFacts::API::Constellation.new(Mod)
95
- bloggs = c.LegalEntity("Bloggs")
96
- acme = c.LegalEntity("Acme, Inc")
97
- contract = c.Contract("Bloggs", acme)
98
- #contract = c.Contract("Bloggs", "Acme, Inc")
99
- contract.first.should == bloggs
100
- contract.second.should == acme
101
- end
102
-
103
- it "should append the counterpart into the respective role array in the matching concept" do
104
- foo = Mod::Name.new("Foo")
105
- le = Mod::LegalEntity.new(foo)
106
- le.respond_to?(:name).should be_true
107
- name = le.name
108
- name.respond_to?(:all_legal_entity).should be_true
109
-
110
- #pending
111
- Array(name.all_legal_entity).should === [le]
112
- end
113
-
114
- it "should instantiate subclasses sensibly" do
115
- c = ActiveFacts::API::Constellation.new(Mod)
116
- bloggs = c.LegalEntity("Bloggs & Co")
117
- #pending
118
- p = c.Person("Fred", "Bloggs")
119
- p.related_to = "Bloggs & Co"
120
- p.related_to.should be_is_a(Mod::LegalEntity)
121
- bloggs.object_id.should == p.related_to.object_id
122
- end
123
-
124
- end
@@ -1,112 +0,0 @@
1
- #
2
- # ActiveFacts tests: Value types in the Runtime API
3
- # Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
4
- #
5
- describe "Value Type class definitions" do
6
- before :each do
7
- Object.send :remove_const, :Mod if Object.const_defined?("Mod")
8
- module Mod
9
- class Name < String
10
- value_type
11
- has_one :name
12
- end
13
- class Year < Int
14
- value_type
15
- has_one :name
16
- end
17
- class Weight < Real
18
- value_type
19
- has_one :name
20
- end
21
- end
22
-
23
- @classes = [Mod::Name, Mod::Year,Mod::Weight]
24
- @attrs = [:name, :name, :name]
25
-
26
- end
27
-
28
- it "should respond_to verbalise" do
29
- @classes.each { |klass|
30
- klass.respond_to?(:verbalise).should be_true
31
- }
32
- end
33
-
34
- it "should not pollute the value class" do
35
- @classes.each { |klass|
36
- klass.superclass.respond_to?(:verbalise).should_not be_true
37
- }
38
- end
39
-
40
- it "should return a string from verbalise" do
41
- @classes.each { |klass|
42
- v = klass.verbalise
43
- v.should_not be_nil
44
- v.should_not =~ /REVISIT/
45
- }
46
- end
47
-
48
- it "should respond_to vocabulary" do
49
- @classes.each { |klass|
50
- klass.respond_to?(:vocabulary).should be_true
51
- }
52
- end
53
-
54
- it "should return the parent module as the vocabulary" do
55
- @classes.each { |klass|
56
- vocabulary = klass.vocabulary
57
- vocabulary.should == Mod
58
- }
59
- end
60
-
61
- it "should return a vocabulary that knows about this concept" do
62
- @classes.each { |klass|
63
- vocabulary = klass.vocabulary
64
- vocabulary.respond_to?(:concept).should be_true
65
- vocabulary.concept.has_key?(klass.basename).should be_true
66
- }
67
- end
68
-
69
- it "should respond to roles()" do
70
- @classes.each { |klass|
71
- klass.respond_to?(:roles).should be_true
72
- }
73
- end
74
-
75
- it "should contain only the added role definitions" do
76
- Mod::Name.roles.size.should == 4
77
- (@classes-[Mod::Name]).each { |klass|
78
- klass.roles.size.should == 1
79
- }
80
- end
81
-
82
- it "should return the role definition" do
83
- # Check the role definition may not be accessed by passing an index:
84
- Mod::Name.roles(0).should be_nil
85
-
86
- @classes.zip(@attrs).each { |pair|
87
- klass, attr = *pair
88
- role = klass.roles(attr)
89
- role.should_not be_nil
90
-
91
- role = klass.roles(attr.to_s)
92
- role.should_not be_nil
93
-
94
- # Check the role definition may be accessed by indexing the returned array:
95
- role = klass.roles[attr]
96
- role.should_not be_nil
97
-
98
- # Check the role definition array by .include?
99
- klass.roles.include?(attr).should be_true
100
- }
101
- end
102
-
103
- # REVISIT: role value constraints
104
-
105
- it "should fail on a non-ValueClass" do
106
- lambda{
107
- class NameNotString
108
- value_type
109
- end
110
- }.should raise_error
111
- end
112
- end
@@ -1,13 +0,0 @@
1
- #
2
- # ActiveFacts tests: Run the API tests
3
- # Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
4
- #
5
- require 'activefacts/api'
6
-
7
- base = File.dirname(__FILE__)+"/"
8
- require base+'api/constellation'
9
- require base+'api/entity_type'
10
- require base+'api/instance'
11
- require base+'api/autocounter'
12
- require base+'api/value_type'
13
- require base+'api/roles'
@@ -1,517 +0,0 @@
1
- #
2
- # ActiveFacts CQL Fact Type matching tests
3
- # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
4
- #
5
-
6
- require 'activefacts/support'
7
- require 'activefacts/api/support'
8
- require 'activefacts/cql/compiler'
9
- # require File.dirname(__FILE__) + '/../helpers/compiler_helper' # Can't see how to include/extend these methods correctly
10
-
11
- describe "Fact Type Role Matching" do
12
- MatchingPrefix = %q{
13
- vocabulary Tests;
14
- Boy is written as String;
15
- Girl is written as String;
16
- }
17
- BaseConcepts = 3 # String, Boy, Girl
18
-
19
- def self.SingleFact &b
20
- lambda {|c|
21
- real_fact_types = c.FactType.values-c.ImplicitFactType.values
22
- real_fact_types.size.should == 1
23
- @fact_type = real_fact_types[0]
24
- b.call(@fact_type) if b
25
- @fact_type
26
- }
27
- end
28
-
29
- def self.FactHavingPlayers(*a, &b)
30
- lambda {|c|
31
- @fact_type = c.FactType.detect do |key, ft|
32
- ft.all_role.map{|r| r.concept.name}.sort == a.sort
33
- end
34
- b.call(@fact_type) if b
35
- @fact_type
36
- }
37
- end
38
-
39
- def self.PresenceConstraints fact_type, &b
40
- @presence_constraints =
41
- fact_type.all_role.map{|r|
42
- r.all_role_ref.map{|rr|
43
- rr.role_sequence.all_presence_constraint.to_a
44
- }
45
- }.flatten.uniq
46
- b.call(@presence_constraints) if b
47
- @presence_constraints
48
- end
49
-
50
- def self.Readings fact_type, &b
51
- @readings = fact_type.all_reading.sort_by{|r| r.ordinal}
52
- b.call(@readings) if b
53
- @readings
54
- end
55
-
56
- def self.ReadingCount n
57
- lambda {|c|
58
- unless @fact_type.all_reading.size == n
59
- puts "SPEC FAILED, wrong number of readings (should be #{n}):\n\t#{
60
- @fact_type.all_reading.map{ |r| r.expand}*"\n\t"
61
- }"
62
- end
63
- @fact_type.all_reading.size.should == n
64
- }
65
- end
66
-
67
- def self.PresenceConstraintCount n
68
- lambda{ |c|
69
- @fact_type.all_role.map{|r|
70
- r.all_role_ref.map{|rr|
71
- rr.role_sequence.all_presence_constraint.to_a
72
- }
73
- }.flatten.uniq.size.should == n
74
- }
75
- end
76
-
77
- def self.ConceptCount n
78
- lambda {|c|
79
- @constellation = c
80
- c.Concept.values.size.should == n
81
- }
82
- end
83
-
84
- def self.Concept name, &b
85
- lambda {|c|
86
- @concept = c.Concept[[["Tests"], name]]
87
- @concept.should_not == nil
88
- b.call(@concept) if b
89
- @concept
90
- }
91
- end
92
-
93
- def self.WrittenAs name
94
- lambda {|c|
95
- @base_type = c.Concept[[["Tests"], name]]
96
- @base_type.class.should == ActiveFacts::Metamodel::ValueType
97
- @concept.class.should == ActiveFacts::Metamodel::ValueType
98
- @concept.supertype.should == @base_type
99
- }
100
- end
101
-
102
- def self.PreferredIdentifier num_roles
103
- lambda {|c|
104
- @preferred_identifier = @concept.preferred_identifier
105
- @preferred_identifier.should_not == nil
106
- @preferred_identifier.role_sequence.all_role_ref.size.should == num_roles
107
- #@preferred_identifier.min_frequency.should == 1
108
- @preferred_identifier.max_frequency.should == 1
109
- @preferred_identifier.is_preferred_identifier.should == true
110
- }
111
- end
112
-
113
- def self.PreferredIdentifierRolePlayedBy name, num = 0
114
- lambda {|c|
115
- @preferred_identifier.role_sequence.all_role_ref.sort_by{|rr| rr.ordinal}[num].role.concept.name.should == name
116
- }
117
- end
118
-
119
- class BlackHole
120
- def method_missing(m,*a,&b)
121
- self
122
- end
123
- end
124
- class PendingSilencer
125
- def STDOUT; BlackHole.new; end
126
- def puts; BlackHole.new; end
127
- def p; BlackHole.new; end
128
- end
129
-
130
- def self.pending(msg = "TODO", &b)
131
- lambda {|*c|
132
- raised = nil
133
- begin
134
- example = b.call
135
- eval(lambda { example.call(*c) }, BlackHole.new)
136
- rescue => raised
137
- end
138
- raise Spec::Example::PendingExampleFixedError.new(msg) unless raised
139
- raise Spec::Example::ExamplePendingError.new(msg)
140
- }
141
- end
142
-
143
- def self.ReadingContainsHyphenatedWord reading_num
144
- lambda {|c|
145
- hyphenated_reading =
146
- c.FactType.values[0].all_reading.select {|reading|
147
- reading.ordinal == reading_num
148
- }[0]
149
- hyphenated_reading.should_not == nil
150
- (hyphenated_reading.text =~ /[a-z]-[a-z]/).should_not == nil
151
- }
152
- end
153
-
154
- SimpleBinaryFactTypeTests = [
155
- [ # Simple create
156
- %q{Girl is going out with at most one Boy; },
157
- SingleFact() do |fact_type|
158
- Readings(fact_type).size.should == 1
159
- PresenceConstraints(fact_type) do |pcs|
160
- pcs.size.should == 1
161
- end
162
- end
163
- ],
164
- [ # Create with explicit adjective
165
- %q{Girl is going out with at most one ugly-Boy;},
166
- SingleFact() do |fact_type|
167
- Readings(fact_type).size.should == 1
168
- PresenceConstraints(fact_type).size.should == 1
169
- end
170
- ],
171
- [ # Simple match
172
- %q{Girl is going out with at most one Boy; },
173
- %q{
174
- Girl is going out with Boy,
175
- Boy is going out with Girl;
176
- },
177
- SingleFact() do |fact_type|
178
- Readings(fact_type).size.should == 2
179
- PresenceConstraints(fact_type).size.should == 1
180
- end
181
- ],
182
- [ # Simple match with repetition
183
- %q{Girl is going out with at most one Boy; },
184
- %q{
185
- Girl is going out with Boy,
186
- Girl is going out with Boy,
187
- Boy is going out with Girl,
188
- Boy is going out with Girl;
189
- },
190
- SingleFact() do |fact_type|
191
- PresenceConstraints(fact_type).size.should == 1
192
- pending("duplicate new clauses are not eliminated") do
193
- Readings(fact_type).size.should == 2
194
- end.call # Must call the pending block
195
- end,
196
- # pending("duplicate new clauses are not eliminated") do
197
- # @readings.size.should == 2
198
- # end
199
- ],
200
- [ # Simple match with a new presence Constraint
201
- %q{Girl is going out with at most one Boy; },
202
- %q{
203
- Girl is going out with Boy,
204
- Boy is going out with at most one Girl;
205
- },
206
- SingleFact() do |fact_type|
207
- Readings(fact_type).size.should == 2
208
- PresenceConstraints(fact_type).size.should == 2
209
- end
210
- ],
211
- [ # RoleName matching
212
- %q{Girl is going out with at most one Boy;},
213
- %q{
214
- Boy is going out with Girlfriend,
215
- Girl (as Girlfriend) is going out with at most one Boy;
216
- },
217
- SingleFact() do |fact_type|
218
- Readings(fact_type).size.should == 3
219
- PresenceConstraints(fact_type).size.should == 1
220
- end
221
- ],
222
- [ # Match with explicit adjective
223
- %q{Girl is going out with at most one ugly-Boy;},
224
- %q{Girl is going out with at most one ugly-Boy,
225
- ugly-Boy is best friend of Girl;
226
- },
227
- SingleFact() do |fact_type|
228
- Readings(fact_type).size.should == 2
229
- PresenceConstraints(fact_type).size.should == 1
230
- end
231
- ],
232
- [ # Match with implicit adjective
233
- %q{Girl is going out with at most one ugly-Boy;},
234
- %q{Girl is going out with ugly Boy,
235
- Boy is going out with Girl;
236
- },
237
- SingleFact() do |fact_type|
238
- Readings(fact_type).size.should == 2
239
- PresenceConstraints(fact_type).size.should == 1
240
- end
241
- ],
242
- [ # Match with explicit trailing adjective
243
- %q{Girl is going out with at most one Boy-monster;},
244
- %q{Girl is going out with Boy-monster,
245
- Boy is going out with Girl;
246
- },
247
- SingleFact() do |fact_type|
248
- Readings(fact_type).size.should == 2
249
- PresenceConstraints(fact_type).size.should == 1
250
- end
251
- ],
252
- [ # Match with implicit trailing adjective
253
- %q{Girl is going out with at most one Boy-monster;},
254
- %q{Girl is going out with Boy monster,
255
- Boy is going out with Girl;
256
- },
257
- SingleFact() do |fact_type|
258
- Readings(fact_type).size.should == 2
259
- PresenceConstraints(fact_type).size.should == 1
260
- end
261
- ],
262
- [ # Match with two explicit adjectives
263
- %q{Girl is going out with at most one ugly- bad Boy;},
264
- %q{Girl is going out with ugly- bad Boy,
265
- ugly- bad Boy is going out with Girl;
266
- },
267
- SingleFact() do |fact_type|
268
- Readings(fact_type).size.should == 2
269
- PresenceConstraints(fact_type).size.should == 1
270
- end
271
- ],
272
- [ # Match with two implicit adjective
273
- %q{Girl is going out with at most one ugly- bad Boy;},
274
- %q{Girl is going out with ugly bad Boy,
275
- Boy is going out with Girl;
276
- },
277
- SingleFact(),
278
- ReadingCount(2),
279
- PresenceConstraintCount(1)
280
- ],
281
- [ # Match with two explicit trailing adjective
282
- %q{Girl is going out with at most one Boy real -monster;},
283
- %q{Girl is going out with Boy real -monster,
284
- Boy is going out with Girl;
285
- },
286
- SingleFact() do |fact_type|
287
- Readings(fact_type).size.should == 2
288
- PresenceConstraints(fact_type).size.should == 1
289
- end
290
- ],
291
- [ # Match with two implicit trailing adjectives
292
- %q{Girl is going out with at most one Boy real -monster;},
293
- %q{Girl is going out with Boy real monster,
294
- Boy is going out with Girl;
295
- },
296
- SingleFact() do |fact_type|
297
- Readings(fact_type).size.should == 2
298
- PresenceConstraints(fact_type).size.should == 1
299
- end
300
- ],
301
- [ # Match with hyphenated word
302
- %q{Girl is going out with at most one Boy; },
303
- %q{
304
- Girl is going out with Boy,
305
- Boy is out driving a semi-trailer with Girl;
306
- },
307
- SingleFact() do |fact_type|
308
- (readings = Readings(fact_type)).size.should == 2
309
- ## REVISIT: Refactor test
310
- #ReadingContainsHyphenatedWord(readings[1])
311
- ReadingContainsHyphenatedWord(1)
312
- PresenceConstraintCount(1)
313
- end
314
- ],
315
- [ # Match with implicit leading ignoring explicit trailing adjective
316
- %q{Girl is going out with at most one ugly-Boy;},
317
- %q{Girl is going out with ugly Boy-monster,
318
- Boy is going out with Girl;
319
- },
320
- SingleFact() do |fact_type|
321
- Readings(fact_type).size.should == 3
322
- PresenceConstraints(fact_type).size.should == 1
323
- end
324
- ],
325
- [ # Match with implicit leading ignoring implicit trailing adjective
326
- %q{Girl is going out with at most one ugly-Boy;},
327
- %q{Girl is going out with ugly Boy monster,
328
- Boy-monster is going out with Girl;
329
- },
330
- SingleFact(),
331
- ReadingCount(3),
332
- PresenceConstraintCount(1)
333
- ],
334
- [ # Match with implicit trailing ignoring explicit leading adjective
335
- %q{Girl is going out with at most one Boy-monster;},
336
- %q{Girl is going out with ugly-Boy monster,
337
- Boy is going out with Girl;
338
- },
339
- SingleFact() do |fact_type|
340
- Readings(fact_type).size.should == 3
341
- PresenceConstraints(fact_type).size.should == 1
342
- end
343
- ],
344
- [ # Match with implicit trailing ignoring implicit leading adjective
345
- %q{Girl is going out with at most one Boy-monster;},
346
- %q{Girl is going out with ugly Boy monster,
347
- ugly-Boy is going out with Girl;
348
- },
349
- SingleFact() do |fact_type|
350
- Readings(fact_type).size.should == 3
351
- PresenceConstraints(fact_type).size.should == 1
352
- end
353
- ],
354
- ]
355
-
356
- EntityIdentificationTests = [
357
- [
358
- # REVISIT: At present, this doesn't add the minimum frequency constraint that a preferred identifier requires.
359
- %q{Thong is written as String;},
360
- %q{Thing is identified by Thong where Thing has one Thong;},
361
- SingleFact() do |fact_type|
362
- Readings(fact_type).size.should == 1
363
- PresenceConstraints(fact_type).size.should == 2
364
- end,
365
- Concept('Thong') do |concept|
366
- concept.class.should == ActiveFacts::Metamodel::ValueType
367
- # REVISIT: Figure out how WrittenAs can access the constellation.
368
- WrittenAs('String')
369
- end,
370
- ConceptCount(2+BaseConcepts),
371
- Concept('Thing'),
372
- PreferredIdentifier(1),
373
- PreferredIdentifierRolePlayedBy('Thong'),
374
- ],
375
-
376
- [ # Auto-create Id and Thing Id:
377
- %q{Thing is identified by its Id;},
378
- SingleFact() do |fact_type|
379
- Readings(fact_type).size.should == 2
380
- PresenceConstraints(fact_type).size.should == 2
381
- end,
382
- ConceptCount(3+BaseConcepts),
383
- Concept('Thing'),
384
- PreferredIdentifier(1),
385
- PreferredIdentifierRolePlayedBy('Thing Id'),
386
- ],
387
-
388
- [ # Auto-create Thing Id:
389
- %q{Id is written as String;},
390
- %q{Thing is identified by its Id;},
391
- SingleFact() do |fact_type|
392
- Readings(fact_type).size.should == 2
393
- PresenceConstraints(fact_type).size.should == 2
394
- end,
395
- ConceptCount(3+BaseConcepts),
396
- Concept('Thing'),
397
- PreferredIdentifier(1),
398
- PreferredIdentifierRolePlayedBy('Thing Id'),
399
- ],
400
-
401
- [ # Auto-create nothing (identifying value type exists already)
402
- %q{Thing Id is written as String;},
403
- %q{Thing is identified by its Id;},
404
- SingleFact() do |fact_type|
405
- Readings(fact_type).size.should == 2
406
- PresenceConstraints(fact_type).size.should == 2
407
- end,
408
- ConceptCount(2+BaseConcepts),
409
- Concept('Thing'),
410
- PreferredIdentifier(1),
411
- PreferredIdentifierRolePlayedBy('Thing Id'),
412
- ],
413
-
414
- [ # Auto-create nothing (identifying entity type exists already so don't create a VT)
415
- %q{Id is written as Id;},
416
- %q{Thing Id is identified by Id where Thing Id has one Id, Id is of one Thing Id;},
417
- %q{Thing is identified by its Id;},
418
- FactHavingPlayers("Thing", "Thing Id") do |fact_type|
419
- Readings(fact_type).size.should == 2
420
- PresenceConstraints(fact_type).size.should == 2
421
- end,
422
- ConceptCount(3+BaseConcepts),
423
- Concept('Thing'),
424
- PreferredIdentifier(1),
425
- PreferredIdentifierRolePlayedBy('Thing Id'),
426
- ],
427
-
428
- [
429
- %q{Thong is written as String;},
430
- %q{Thing is identified by Thong where Thing has one Thong, Thong is of one Thing;},
431
- SingleFact() do |fact_type|
432
- Readings(fact_type).size.should == 2
433
- PresenceConstraints(fact_type).size.should == 2
434
- end,
435
- ConceptCount(2+BaseConcepts),
436
- Concept('Thing'),
437
- PreferredIdentifier(1),
438
- PreferredIdentifierRolePlayedBy('Thong'),
439
- ],
440
-
441
- [ # Objectified fact type with internal identification
442
- %q{Relationship is where Boy relates to Girl;},
443
- SingleFact() do |fact_type|
444
- Readings(fact_type).size.should == 1
445
- PresenceConstraints(fact_type).size.should == 1
446
- end,
447
- ConceptCount(1+BaseConcepts),
448
- Concept('Relationship'),
449
- PreferredIdentifier(2),
450
- # PreferredIdentifierRolePlayedBy('Thong'),
451
- ],
452
-
453
- [ # Objectified fact type with external identification
454
- %q{Relationship is identified by its Id where Boy relates to Girl;},
455
- ConceptCount(3+BaseConcepts),
456
- Concept('Relationship'),
457
- PreferredIdentifier(1), # 1 role in PI
458
- PreferredIdentifierRolePlayedBy('Relationship Id'),
459
- FactHavingPlayers('Relationship', 'Relationship Id') do |fact_type|
460
- Readings(fact_type).size.should == 2
461
- PresenceConstraints(fact_type).size.should == 2
462
- fact_type.all_reading.detect{|r| r.text == '{0} has {1}'}.should_not == nil
463
- fact_type.all_reading.detect{|r| r.text == '{0} is of {1}'}.should_not == nil
464
- end,
465
- FactHavingPlayers('Boy', 'Girl') do |fact_type|
466
- fact_type.entity_type.should == @concept
467
- end,
468
- ],
469
-
470
- [ # Objectified fact type with external identification and explicit reading
471
- %q{Relationship is identified by its Id where Boy relates to Girl, Relationship is known by Relationship Id;},
472
- ConceptCount(3+BaseConcepts),
473
- Concept('Relationship'),
474
- PreferredIdentifier(1),
475
- PreferredIdentifierRolePlayedBy('Relationship Id'),
476
- FactHavingPlayers('Relationship', 'Relationship Id') do |fact_type|
477
- Readings(fact_type).size.should == 2
478
- PresenceConstraints(fact_type).size.should == 2
479
- fact_type.all_reading.detect{|r| r.text == '{0} is known by {1}'}.should_not == nil
480
- fact_type.all_reading.detect{|r| r.text == '{0} is of {1}'}.should_not == nil
481
- end,
482
- FactHavingPlayers('Boy', 'Girl') do |fact_type|
483
- fact_type.entity_type.should == @concept
484
- end,
485
- ],
486
-
487
- ]
488
- AllTests =
489
- # SimpleBinaryFactTypeTests +
490
- EntityIdentificationTests
491
-
492
- before :each do
493
- @compiler = ActiveFacts::CQL::Compiler.new('Test')
494
- end
495
-
496
- AllTests.each do |tests|
497
- it "should process '#{(tests.select{|t| t.is_a?(String)}*' ').gsub(/\s+/m,' ')}' correctly" do
498
- tests.each do |test|
499
- case test
500
- when String
501
- result = @compiler.compile(MatchingPrefix+test)
502
- puts @compiler.failure_reason unless result
503
- result.should_not be_nil
504
- when Proc
505
- begin
506
- test.call(@compiler.vocabulary.constellation)
507
- rescue Spec::Example::ExamplePendingError
508
- raise
509
- rescue => e
510
- puts "Failed on\n\t"+tests.select{|t| t.is_a?(String)}*" "
511
- raise
512
- end
513
- end
514
- end
515
- end
516
- end
517
- end