activefacts 0.8.9 → 0.8.10

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.
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