activefacts 0.8.6 → 0.8.8
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +33 -2
- data/README.rdoc +30 -36
- data/Rakefile +16 -20
- data/bin/afgen +17 -11
- data/bin/cql +313 -36
- data/download.html +43 -19
- data/examples/CQL/Address.cql +15 -15
- data/examples/CQL/Blog.cql +8 -8
- data/examples/CQL/CompanyDirectorEmployee.cql +6 -5
- data/examples/CQL/Death.cql +3 -3
- data/examples/CQL/Diplomacy.cql +48 -0
- data/examples/CQL/Genealogy.cql +41 -41
- data/examples/CQL/Insurance.cql +311 -0
- data/examples/CQL/JoinEquality.cql +35 -0
- data/examples/CQL/Marriage.cql +1 -1
- data/examples/CQL/Metamodel.cql +290 -185
- data/examples/CQL/MetamodelNext.cql +420 -0
- data/examples/CQL/Monogamy.cql +24 -0
- data/examples/CQL/MonthInSeason.cql +27 -0
- data/examples/CQL/Moon.cql +23 -0
- data/examples/CQL/MultiInheritance.cql +4 -4
- data/examples/CQL/NonRoleId.cql +14 -0
- data/examples/CQL/OddIdentifier.cql +18 -0
- data/examples/CQL/OilSupply.cql +24 -24
- data/examples/CQL/OneToOnes.cql +17 -0
- data/examples/CQL/Orienteering.cql +55 -55
- data/examples/CQL/OrienteeringER.cql +58 -0
- data/examples/CQL/PersonPlaysGame.cql +2 -2
- data/examples/CQL/RedundantDependency.cql +34 -0
- data/examples/CQL/SchoolActivities.cql +5 -5
- data/examples/CQL/SeparateSubtype.cql +28 -0
- data/examples/CQL/ServiceDirector.cql +283 -0
- data/examples/CQL/SimplestUnary.cql +2 -2
- data/examples/CQL/SubtypePI.cql +11 -11
- data/examples/CQL/Supervision.cql +38 -0
- data/examples/CQL/Tests.Test5.Load.cql +38 -0
- data/examples/CQL/WaiterTips.cql +33 -0
- data/examples/CQL/Warehousing.cql +55 -53
- data/examples/CQL/WindowInRoomInBldg.cql +9 -9
- data/examples/CQL/unit.cql +433 -544
- data/examples/index.html +314 -170
- data/examples/intro.html +6 -176
- data/examples/local.css +8 -4
- data/index.html +40 -25
- data/lib/activefacts/api/concept.rb +2 -2
- data/lib/activefacts/api/constellation.rb +4 -4
- data/lib/activefacts/api/instance.rb +2 -2
- data/lib/activefacts/api/instance_index.rb +4 -0
- data/lib/activefacts/api/numeric.rb +3 -1
- data/lib/activefacts/api/role.rb +1 -1
- data/lib/activefacts/api/standard_types.rb +23 -16
- data/lib/activefacts/api/support.rb +3 -1
- data/lib/activefacts/api/vocabulary.rb +4 -0
- data/lib/activefacts/cql/CQLParser.treetop +87 -39
- data/lib/activefacts/cql/Concepts.treetop +95 -69
- data/lib/activefacts/cql/Context.treetop +11 -2
- data/lib/activefacts/cql/Expressions.treetop +23 -59
- data/lib/activefacts/cql/FactTypes.treetop +141 -95
- data/lib/activefacts/cql/Language/English.treetop +33 -21
- data/lib/activefacts/cql/LexicalRules.treetop +6 -1
- data/lib/activefacts/cql/Terms.treetop +75 -26
- data/lib/activefacts/cql/ValueTypes.treetop +52 -54
- data/lib/activefacts/cql/compiler.rb +46 -1691
- data/lib/activefacts/cql/compiler/constraint.rb +602 -0
- data/lib/activefacts/cql/compiler/entity_type.rb +425 -0
- data/lib/activefacts/cql/compiler/fact.rb +300 -0
- data/lib/activefacts/cql/compiler/fact_type.rb +230 -0
- data/lib/activefacts/cql/compiler/reading.rb +832 -0
- data/lib/activefacts/cql/compiler/shared.rb +109 -0
- data/lib/activefacts/cql/compiler/value_type.rb +104 -0
- data/lib/activefacts/cql/parser.rb +132 -81
- data/lib/activefacts/generate/cql.rb +397 -274
- data/lib/activefacts/generate/oo.rb +13 -12
- data/lib/activefacts/generate/ordered.rb +107 -117
- data/lib/activefacts/generate/ruby.rb +34 -38
- data/lib/activefacts/generate/sql/mysql.rb +62 -45
- data/lib/activefacts/generate/sql/server.rb +59 -42
- data/lib/activefacts/input/cql.rb +6 -3
- data/lib/activefacts/input/orm.rb +991 -557
- data/lib/activefacts/persistence/columns.rb +16 -12
- data/lib/activefacts/persistence/foreignkey.rb +7 -4
- data/lib/activefacts/persistence/index.rb +3 -4
- data/lib/activefacts/persistence/reference.rb +5 -2
- data/lib/activefacts/support.rb +20 -14
- data/lib/activefacts/version.rb +1 -1
- data/lib/activefacts/vocabulary.rb +1 -0
- data/lib/activefacts/vocabulary/extensions.rb +328 -44
- data/lib/activefacts/vocabulary/metamodel.rb +145 -20
- data/lib/activefacts/vocabulary/verbaliser.rb +621 -0
- data/spec/absorption_spec.rb +4 -4
- data/spec/api/value_type.rb +1 -1
- data/spec/cql/context_spec.rb +45 -22
- data/spec/cql/deontic_spec.rb +88 -0
- data/spec/cql/matching_spec.rb +517 -0
- data/spec/cql/samples_spec.rb +88 -31
- data/spec/cql/unit_spec.rb +58 -37
- data/spec/cql_cql_spec.rb +12 -7
- data/spec/cql_mysql_spec.rb +3 -7
- data/spec/cql_parse_spec.rb +0 -4
- data/spec/cql_ruby_spec.rb +1 -4
- data/spec/cql_sql_spec.rb +5 -18
- data/spec/cql_symbol_tables_spec.rb +3 -0
- data/spec/cqldump_spec.rb +0 -2
- data/spec/helpers/array_matcher.rb +35 -0
- data/spec/helpers/ctrl_c_support.rb +52 -0
- data/spec/helpers/diff_matcher.rb +38 -0
- data/spec/helpers/file_matcher.rb +5 -3
- data/spec/helpers/string_matcher.rb +39 -0
- data/spec/helpers/test_parser.rb +13 -0
- data/spec/norma_cql_spec.rb +13 -5
- data/spec/norma_ruby_spec.rb +11 -3
- data/spec/{absorption_ruby_spec.rb → norma_ruby_sql_spec.rb} +37 -32
- data/spec/norma_sql_spec.rb +11 -5
- data/spec/norma_tables_spec.rb +33 -29
- data/spec/spec_helper.rb +4 -1
- data/status.html +92 -23
- metadata +102 -36
- data/lib/activefacts/generate/cql/html.rb +0 -403
data/spec/cql/samples_spec.rb
CHANGED
@@ -7,69 +7,93 @@ require 'activefacts/support'
|
|
7
7
|
require 'activefacts/api/support'
|
8
8
|
require 'activefacts/input/cql'
|
9
9
|
|
10
|
+
require 'set'
|
11
|
+
|
10
12
|
describe "Sample data" do
|
11
13
|
SamplePrefix = %q{
|
12
14
|
vocabulary V;
|
13
15
|
|
14
|
-
|
16
|
+
Company Name is written as String;
|
15
17
|
Company is identified by its Name;
|
16
|
-
Person is identified by its Name where Person is called
|
18
|
+
Person is identified by its Name where Person is called Person Name;
|
17
19
|
Directorship is where
|
18
20
|
Company is directed by Person;
|
19
21
|
}
|
20
22
|
|
21
|
-
|
23
|
+
GoodSamples = [
|
22
24
|
[ # A simple ValueType instance
|
23
|
-
"
|
24
|
-
[{:facts=>[], :instances=>["
|
25
|
+
"Company Name 'Microsoft';",
|
26
|
+
[{:facts=>Set[], :instances=>Set["Company Name 'Microsoft'"]}]
|
25
27
|
],
|
26
28
|
[ # Re-assert the same instance
|
27
|
-
"
|
28
|
-
[{:facts=>[], :instances=>["
|
29
|
+
"Company Name 'Microsoft'; Company Name 'Microsoft';",
|
30
|
+
[{:facts=>Set[], :instances=>Set["Company Name 'Microsoft'"]}]
|
29
31
|
],
|
30
32
|
[ # The same instance, but in a named population
|
31
|
-
"example:
|
32
|
-
[{:facts=>[], :instances=>["
|
33
|
+
"example: Company Name 'Microsoft';",
|
34
|
+
[{:facts=>Set[], :instances=>Set["Company Name 'Microsoft'"]}]
|
33
35
|
],
|
34
36
|
[ # A simply-identified EntityType instance
|
35
37
|
"Company 'Microsoft';",
|
36
|
-
[{:facts=>["Company has
|
38
|
+
[{:facts=>Set["Company has Company Name 'Microsoft'"], :instances=>Set["Company is identified by Company Name where Company has Company Name 'Microsoft'", "Company Name 'Microsoft'"]}]
|
37
39
|
],
|
38
40
|
[ # Re-assert the same instance
|
39
41
|
"Company 'Microsoft'; Company 'Microsoft';",
|
40
|
-
[{:facts=>["Company has
|
42
|
+
[{:facts=>Set["Company has Company Name 'Microsoft'"], :instances=>Set["Company is identified by Company Name where Company has Company Name 'Microsoft'", "Company Name 'Microsoft'"]}]
|
41
43
|
],
|
42
44
|
[ # The same instance in a named population
|
43
45
|
"example: Company 'Microsoft';",
|
44
|
-
[{:facts=>["Company has
|
46
|
+
[{:facts=>Set["Company has Company Name 'Microsoft'"], :instances=>Set["Company is identified by Company Name where Company has Company Name 'Microsoft'", "Company Name 'Microsoft'"]}]
|
45
47
|
],
|
46
48
|
[ # The Company instance asserted with an explicit identifying fact
|
47
|
-
"Company has
|
48
|
-
[{:facts=>["Company has
|
49
|
+
"Company has Company Name 'Microsoft';",
|
50
|
+
[{:facts=>Set["Company has Company Name 'Microsoft'"], :instances=>Set["Company is identified by Company Name where Company has Company Name 'Microsoft'", "Company Name 'Microsoft'"]}]
|
49
51
|
],
|
50
52
|
[ # The Company instance asserted with an joined identifying instance
|
51
|
-
"Company has
|
52
|
-
[{:facts=>["Company has
|
53
|
+
"Company has Company Name, Company Name 'Microsoft';",
|
54
|
+
[{:facts=>Set["Company has Company Name 'Microsoft'"], :instances=>Set["Company is identified by Company Name where Company has Company Name 'Microsoft'", "Company Name 'Microsoft'"]}]
|
53
55
|
],
|
54
56
|
[ # The same, with an explicit identifying instance join
|
55
|
-
"
|
56
|
-
[{:facts=>["Company has
|
57
|
+
"Company Name 'Microsoft', Company has Company Name;",
|
58
|
+
[{:facts=>Set["Company has Company Name 'Microsoft'"], :instances=>Set["Company is identified by Company Name where Company has Company Name 'Microsoft'", "Company Name 'Microsoft'"]}]
|
57
59
|
],
|
58
60
|
[ # A simple fact instance with two simply-identified entities
|
59
61
|
"Company 'Microsoft' is directed by Person 'Gates';",
|
60
|
-
[{:facts=>["Company has
|
62
|
+
[{:facts=>Set["Company has Company Name 'Microsoft'", "Company is directed by Person", "Person is called Person Name 'Gates'"], :instances=>Set["Company is identified by Company Name where Company has Company Name 'Microsoft'", "Company Name 'Microsoft'", "Directorship where Company is directed by Person", "Person is identified by Person Name where Person is called Person Name 'Gates'", "Person Name 'Gates'"]}]
|
61
63
|
],
|
62
64
|
[ # Same with an explicit joined fact
|
63
|
-
"Company 'Microsoft' is directed by Person, Person is called
|
64
|
-
[{:facts=>["Company has
|
65
|
+
"Company 'Microsoft' is directed by Person, Person is called Person Name 'Gates';",
|
66
|
+
[{:facts=>Set["Company has Company Name 'Microsoft'", "Company is directed by Person", "Person is called Person Name 'Gates'"], :instances=>Set["Company is identified by Company Name where Company has Company Name 'Microsoft'", "Company Name 'Microsoft'", "Directorship where Company is directed by Person", "Person is identified by Person Name where Person is called Person Name 'Gates'", "Person Name 'Gates'"]}]
|
65
67
|
],
|
66
68
|
[ # Same with explicitly joined facts and instances
|
67
|
-
"Company is directed by Person, Person is called
|
68
|
-
[{:facts=>["Company has
|
69
|
+
"Company is directed by Person, Person is called Person Name, Person Name 'Gates', Company has Company Name, Company Name 'Microsoft';",
|
70
|
+
[{:facts=>Set["Company has Company Name 'Microsoft'", "Company is directed by Person", "Person is called Person Name 'Gates'"], :instances=>Set["Company is identified by Company Name where Company has Company Name 'Microsoft'", "Company Name 'Microsoft'", "Directorship where Company is directed by Person", "Person is identified by Person Name where Person is called Person Name 'Gates'", "Person Name 'Gates'"]}]
|
69
71
|
],
|
70
72
|
[ # Same in a named population
|
71
|
-
"example: Company is directed by Person, Person is called
|
72
|
-
[{:facts=>["Company has
|
73
|
+
"example: Company is directed by Person, Person is called Person Name, Person Name 'Gates', Company has Company Name, Company Name 'Microsoft';",
|
74
|
+
[{:facts=>Set["Company has Company Name 'Microsoft'", "Company is directed by Person", "Person is called Person Name 'Gates'"], :instances=>Set["Company is identified by Company Name where Company has Company Name 'Microsoft'", "Company Name 'Microsoft'", "Directorship where Company is directed by Person", "Person is identified by Person Name where Person is called Person Name 'Gates'", "Person Name 'Gates'"]}]
|
75
|
+
],
|
76
|
+
|
77
|
+
# Objectification examples
|
78
|
+
[ # Same in a named population
|
79
|
+
"Directorship (where Company 'Microsoft' is directed by Person 'Gates');",
|
80
|
+
:pending # [{:facts=>Set["Company has Company Name 'Microsoft'", "Company is directed by Person", "Person is called Person Name 'Gates'"], :instances=>Set["Company is identified by Company Name where Company has Company Name 'Microsoft'", "Company Name 'Microsoft'", "Directorship where Company is directed by Person", "Person is identified by Person Name where Person is called Person Name 'Gates'", "Person Name 'Gates'"]}]
|
81
|
+
],
|
82
|
+
]
|
83
|
+
|
84
|
+
BadSamples =
|
85
|
+
[
|
86
|
+
[
|
87
|
+
"Company Name",
|
88
|
+
"Company Name",
|
89
|
+
],
|
90
|
+
[
|
91
|
+
"foo: Company Name",
|
92
|
+
"Company Name",
|
93
|
+
],
|
94
|
+
[ # Omit the company name:
|
95
|
+
"example: Company is directed by Person, Person is called Person Name, Person Name 'Gates', Company has Company Name;",
|
96
|
+
[ "Company (lacking Company Name)", "Company Name (needs a value)" ]
|
73
97
|
],
|
74
98
|
]
|
75
99
|
|
@@ -104,7 +128,7 @@ describe "Sample data" do
|
|
104
128
|
" is identified by " +
|
105
129
|
identifying_role_refs.map do |rr|
|
106
130
|
[ (l = rr.leading_adjective) ? l+"-" : nil,
|
107
|
-
rr.role_name || rr.role.concept.name,
|
131
|
+
rr.role.role_name || rr.role.concept.name,
|
108
132
|
(t = rr.trailing_adjective) ? l+"-" : nil
|
109
133
|
].compact*""
|
110
134
|
end * " and " +
|
@@ -123,17 +147,23 @@ describe "Sample data" do
|
|
123
147
|
populations.keys.sort.map do |popname|
|
124
148
|
popvalue = populations[popname]
|
125
149
|
{
|
126
|
-
:instances => popvalue.all_instance.map { |i| instance_name(i) }
|
127
|
-
:facts => popvalue.all_fact.map { |fact| instance_name(fact) }
|
150
|
+
:instances => Set[*popvalue.all_instance.map { |i| instance_name(i) }],
|
151
|
+
:facts => Set[*popvalue.all_fact.map { |fact| instance_name(fact) }]
|
128
152
|
}
|
129
153
|
end
|
130
154
|
end
|
131
155
|
|
132
|
-
|
156
|
+
# [].
|
157
|
+
GoodSamples.
|
158
|
+
each do |c|
|
133
159
|
source, expected = *Array(c)
|
160
|
+
|
134
161
|
it "should handle #{source.inspect}" do
|
135
162
|
@text = SamplePrefix+source
|
136
|
-
|
163
|
+
pending if expected == :pending
|
164
|
+
lambda do
|
165
|
+
@vocabulary = ActiveFacts::Input::CQL.readstring(@text)
|
166
|
+
end.should_not raise_error
|
137
167
|
result = instance_data(@vocabulary)
|
138
168
|
|
139
169
|
if expected
|
@@ -146,9 +176,36 @@ describe "Sample data" do
|
|
146
176
|
it "should de-duplicate #{source.inspect}" do
|
147
177
|
# Make sure you don't get anything duplicated
|
148
178
|
@text = SamplePrefix+source+source
|
149
|
-
|
179
|
+
pending if expected == :pending
|
180
|
+
lambda do
|
181
|
+
@vocabulary = ActiveFacts::Input::CQL.readstring(@text)
|
182
|
+
end.should_not raise_error
|
150
183
|
result = instance_data(@vocabulary)
|
151
184
|
result[0].should == expected[0]
|
152
185
|
end
|
186
|
+
|
153
187
|
end
|
188
|
+
|
189
|
+
BadSamples.each do |c|
|
190
|
+
source, missing = *Array(c)
|
191
|
+
it "should detect missing joins in #{source.inspect}" do
|
192
|
+
@text = SamplePrefix+source
|
193
|
+
lambda do
|
194
|
+
begin
|
195
|
+
@vocabulary = ActiveFacts::Input::CQL.readstring(@text)
|
196
|
+
rescue => @exception
|
197
|
+
raise
|
198
|
+
end
|
199
|
+
end.should raise_error
|
200
|
+
|
201
|
+
if missing
|
202
|
+
missing.each do |m|
|
203
|
+
@exception.message.should =~ (m.is_a?(Regexp) ? m : Regexp.new(Regexp.escape(m)))
|
204
|
+
end
|
205
|
+
else
|
206
|
+
pending "raised #{@exception}"
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
154
211
|
end
|
data/spec/cql/unit_spec.rb
CHANGED
@@ -3,13 +3,19 @@
|
|
3
3
|
# Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
|
4
4
|
#
|
5
5
|
|
6
|
+
=begin
|
7
|
+
REVISIT: These tests are important, but the intermediate layer they test no longer exists. Find another solution!
|
8
|
+
|
9
|
+
require 'spec/helpers/test_parser'
|
6
10
|
require 'activefacts/support'
|
7
11
|
require 'activefacts/api/support'
|
8
12
|
require 'activefacts/cql/parser'
|
13
|
+
require File.dirname(__FILE__) + '/../helpers/test_parser'
|
9
14
|
|
10
15
|
describe "Valid Numbers, Strings and Ranges" do
|
11
16
|
ValidNumbersEtc = [
|
12
17
|
"a is written as b;", # Value type declaration, no params, minimal whitespace
|
18
|
+
"a is written as B;", # Value type declaration, no params, minimal whitespace
|
13
19
|
"a is written as b();", # Value type declaration, minimal whitespace
|
14
20
|
"a is written as b ;", # Value type declaration, no params, trailing whitespace
|
15
21
|
"a is written as b ( ) ; ", # Value type declaration, maximal whitespace
|
@@ -58,7 +64,7 @@ describe "Valid Numbers, Strings and Ranges" do
|
|
58
64
|
"a is written as b inch^2/minute^-1;", # Value type declaration with unit and divided unit with exponents
|
59
65
|
"a is written as b() second^-1/mm^-1 mm^-1;", # Value type declaration with repeated divided unit
|
60
66
|
|
61
|
-
# Integer value
|
67
|
+
# Integer value constraints
|
62
68
|
"a is written as b()restricted to{1};", # Integer, minimal whitespace
|
63
69
|
"a is written as b() restricted to { 1 } ;", # Integer, maximal whitespace
|
64
70
|
"a is written as b() restricted to {1..2};", # Integer range, minimal whitespace
|
@@ -76,7 +82,7 @@ describe "Valid Numbers, Strings and Ranges" do
|
|
76
82
|
"a is written as b() restricted to { 1e-4 } ;", # Integer with negative exponent
|
77
83
|
"a is written as b() restricted to { -1e-4 } ;", # Negative integer with negative exponent
|
78
84
|
|
79
|
-
# Real value
|
85
|
+
# Real value constraints
|
80
86
|
"a is written as b() restricted to {1.0};", # Real, minimal whitespace
|
81
87
|
"a is written as b() restricted to { 1.0 } ;", # Real, maximal whitespace
|
82
88
|
"a is written as b() restricted to { 1.0e4 } ;", # Real with exponent
|
@@ -91,7 +97,7 @@ describe "Valid Numbers, Strings and Ranges" do
|
|
91
97
|
"a is written as b() restricted to { 1.1.. };", # Real range with open end
|
92
98
|
"a is written as b() restricted to { 1.1.., 2 };", # Real range with open end and following integer
|
93
99
|
|
94
|
-
# Strings and string value
|
100
|
+
# Strings and string value constraints
|
95
101
|
"a is written as b() restricted to {''};", # String, empty, minimal whitespace
|
96
102
|
"a is written as b() restricted to {'A'};", # String, minimal whitespace
|
97
103
|
"a is written as b() restricted to { 'A' };", # String, maximal whitespace
|
@@ -107,13 +113,13 @@ describe "Valid Numbers, Strings and Ranges" do
|
|
107
113
|
"a is written as b() restricted to { ..'F' };", # String range, open start
|
108
114
|
"a is written as b() restricted to { 'A'.. };", # String range, open end
|
109
115
|
|
110
|
-
# Value
|
111
|
-
"a is written as b() restricted to {1} inches^2/second;", #
|
112
|
-
"a is written as b() second^-1/mm^-1 mm^-1 restricted to {1} inches^2/second;", # type with unit and
|
116
|
+
# Value constraints with units
|
117
|
+
"a is written as b() restricted to {1} inches^2/second;", # constraint with units and exponent
|
118
|
+
"a is written as b() second^-1/mm^-1 mm^-1 restricted to {1} inches^2/second;", # type with unit and constraint with units and exponent
|
113
119
|
]
|
114
120
|
|
115
121
|
before :each do
|
116
|
-
@parser =
|
122
|
+
@parser = TestParser.new
|
117
123
|
end
|
118
124
|
|
119
125
|
ValidNumbersEtc.each do |c|
|
@@ -150,7 +156,7 @@ describe "Invalid Numbers and Strings" do
|
|
150
156
|
]
|
151
157
|
|
152
158
|
before :each do
|
153
|
-
@parser =
|
159
|
+
@parser = TestParser.new
|
154
160
|
end
|
155
161
|
|
156
162
|
InvalidValueTypes.each do |c|
|
@@ -175,7 +181,7 @@ describe "Value Types" do
|
|
175
181
|
]
|
176
182
|
|
177
183
|
before :each do
|
178
|
-
@parser =
|
184
|
+
@parser = TestParser.new
|
179
185
|
end
|
180
186
|
|
181
187
|
ValueTypes.each do |c|
|
@@ -195,49 +201,49 @@ end
|
|
195
201
|
describe "Entity Types" do
|
196
202
|
EntityTypes_RefMode = [
|
197
203
|
[ "a is identified by its id;", # Entity type declaration with reference mode
|
198
|
-
[["a", [:entity_type, [], {:enforcement=>nil, :mode=>"id", :parameters=>[], :
|
204
|
+
[["a", [:entity_type, [], {:enforcement=>nil, :mode=>"id", :parameters=>[], :value_constraint=>nil}, [], nil]]]
|
199
205
|
],
|
200
206
|
[ "a is identified by its number(12);", # Entity type declaration with reference mode
|
201
|
-
[["a", [:entity_type, [], {:enforcement=>nil, :mode=>"number", :parameters=>[12], :
|
207
|
+
[["a", [:entity_type, [], {:enforcement=>nil, :mode=>"number", :parameters=>[12], :value_constraint=>nil}, [], nil]]]
|
202
208
|
],
|
203
209
|
[ "a is identified by its id:c;", # Entity type declaration with reference mode and fact type(s)
|
204
|
-
[["a", [:entity_type, [], {:enforcement=>nil, :mode=>"id", :parameters=>[], :
|
210
|
+
[["a", [:entity_type, [], {:enforcement=>nil, :mode=>"id", :parameters=>[], :value_constraint=>nil}, [], [[:fact_clause, [], ["c"], nil]]]]]
|
205
211
|
],
|
206
212
|
[ "a is identified by its id where c;", # Entity type declaration with reference mode and where
|
207
|
-
[["a", [:entity_type, [], {:enforcement=>nil, :mode=>"id", :parameters=>[], :
|
213
|
+
[["a", [:entity_type, [], {:enforcement=>nil, :mode=>"id", :parameters=>[], :value_constraint=>nil}, [], [[:fact_clause, [], ["c"], nil]]]]]
|
208
214
|
],
|
209
215
|
]
|
210
216
|
|
211
217
|
EntityTypes_Simple = [
|
212
218
|
[ "a is identified by b: c;", # Entity type declaration
|
213
|
-
[["a", [:entity_type, [], {:roles=>[["b"]]}, [], [[:fact_clause, [], [
|
219
|
+
[["a", [:entity_type, [], {:roles=>[["b"]]}, [], [[:fact_clause, [], ["c"], nil]]]]]
|
214
220
|
],
|
215
221
|
[ "a is identified by b where c;", # Entity type declaration with where
|
216
|
-
[["a", [:entity_type, [], {:roles=>[["b"]]}, [], [[:fact_clause, [], [
|
222
|
+
[["a", [:entity_type, [], {:roles=>[["b"]]}, [], [[:fact_clause, [], ["c"], nil]]]]]
|
217
223
|
],
|
218
224
|
[ "a is identified by b and c: d;", # Entity type declaration with two-part identifier
|
219
|
-
[["a", [:entity_type, [], {:roles=>[["b"], ["c"]]}, [], [[:fact_clause, [], [
|
225
|
+
[["a", [:entity_type, [], {:roles=>[["b"], ["c"]]}, [], [[:fact_clause, [], ["d"], nil]]]]]
|
220
226
|
],
|
221
227
|
[ "a is identified by b, c: d;", # Entity type declaration with two-part identifier
|
222
|
-
[["a", [:entity_type, [], {:roles=>[["b"], ["c"]]}, [], [[:fact_clause, [], [
|
228
|
+
[["a", [:entity_type, [], {:roles=>[["b"], ["c"]]}, [], [[:fact_clause, [], ["d"], nil]]]]]
|
223
229
|
],
|
224
230
|
[ "a is written as b(); c is identified by a:d;",
|
225
|
-
[["a", [:value_type, "b", [], [], [], [], nil]], ["c", [:entity_type, [], {:roles=>[["a"]]}, [], [[:fact_clause, [], [
|
231
|
+
[["a", [:value_type, "b", [], [], [], [], nil]], ["c", [:entity_type, [], {:roles=>[["a"]]}, [], [[:fact_clause, [], ["d"], nil]]]]]
|
226
232
|
],
|
227
233
|
[ " a is written as b ( ) ; c is identified by a : d ; ",
|
228
|
-
[["a", [:value_type, "b", [], [], [], [], nil]], ["c", [:entity_type, [], {:roles=>[["a"]]}, [], [[:fact_clause, [], [
|
234
|
+
[["a", [:value_type, "b", [], [], [], [], nil]], ["c", [:entity_type, [], {:roles=>[["a"]]}, [], [[:fact_clause, [], ["d"], nil]]]]]
|
229
235
|
],
|
230
236
|
[ "a is identified by c:maybe d;",
|
231
|
-
[["a", [:entity_type, [], {:roles=>[["c"]]}, [], [[:fact_clause, ["maybe"], [
|
237
|
+
[["a", [:entity_type, [], {:roles=>[["c"]]}, [], [[:fact_clause, ["maybe"], ["d"], nil]]]]]
|
232
238
|
],
|
233
239
|
]
|
234
240
|
|
235
241
|
EntityTypes_Objectified = [
|
236
242
|
[ "Director is where Person directs Company, Company is directed by Person;",
|
237
|
-
[["Director", [:fact_type, [[:fact_clause, [], [{:word=>"Person"
|
243
|
+
[["Director", [:fact_type, [[:fact_clause, [], [{:word=>"Person", :term=>"Person"}, "directs", {:word=>"Company", :term=>"Company"}], nil], [:fact_clause, [], [{:word=>"Company", :term=>"Company"}, "is", "directed", "by", {:word=>"Person", :term=>"Person"}], nil]], []]]]
|
238
244
|
],
|
239
245
|
[ "Director: Person directs company;",
|
240
|
-
[[nil, [:fact_type, [[:fact_clause, [], [{:word=>"Director"}], nil]], [[:fact_clause, [], [{:word=>"Person"
|
246
|
+
[[nil, [:fact_type, [[:fact_clause, [], [{:word=>"Director", :term=>"Director"}], nil]], [[:fact_clause, [], [{:word=>"Person", :term=>"Person"}, "directs", "company"], nil]]]]]
|
241
247
|
],
|
242
248
|
]
|
243
249
|
|
@@ -269,7 +275,7 @@ describe "Entity Types" do
|
|
269
275
|
EntityTypes_Subtypes
|
270
276
|
|
271
277
|
before :each do
|
272
|
-
@parser =
|
278
|
+
@parser = TestParser.new
|
273
279
|
end
|
274
280
|
|
275
281
|
EntityTypes.each do |c|
|
@@ -291,31 +297,43 @@ end
|
|
291
297
|
|
292
298
|
describe "Fact Types" do
|
293
299
|
FactTypes = [
|
294
|
-
[ "
|
295
|
-
[nil, [:fact_type, [[:fact_clause, [], [{:word=>"
|
300
|
+
[ "Foo has at most one Bar, Bar is of one Foo restricted to {1..10};",
|
301
|
+
[nil, [:fact_type, [[:fact_clause, [], [{:word=>"Foo", :term=>"Foo"}, "has", {:quantifier_restriction=>[], :word=>"Bar", :term=>"Bar", :quantifier=>[nil, 1]}], nil], [:fact_clause, [], [{:word=>"Bar", :term=>"Bar"}, "is", "of", {:value_constraint=>[[1, 10]], :quantifier_restriction=>[], :word=>"Foo", :term=>"Foo", :quantifier=>[1, 1], :value_constraint_enforcement=>[]}], nil]], []]]
|
302
|
+
],
|
303
|
+
[ "Bar(1) is related to Bar(2), primary-Bar(1) has secondary-Bar(2);",
|
304
|
+
[nil, [:fact_type, [[:fact_clause, [], [{:word=>"Bar", :term=>"Bar", :role_name=>1}, "is", "related", "to", {:word=>"Bar", :term=>"Bar", :role_name=>2}], nil], [:fact_clause, [], [{:leading_adjective=>"primary", :word=>"primary Bar", :term=>"Bar", :role_name=>1}, "has", {:leading_adjective=>"secondary", :word=>"secondary Bar", :term=>"Bar", :role_name=>2}], nil]], []]]
|
305
|
+
],
|
306
|
+
[ "Director is old: Person directs company, Person is of Age, Age > 60;",
|
307
|
+
[nil, [:fact_type, [[:fact_clause, [], [{:word=>"Director", :term=>"Director"}, "is", "old"], nil]], [[:fact_clause, [], [{:word=>"Person", :term=>"Person"}, "directs", "company"], nil], [:fact_clause, [], [{:word=>"Person", :term=>"Person"}, "is", "of", {:word=>"Age", :term=>"Age"}], nil], [">", [:variable, "Age"], 60]]]]
|
296
308
|
],
|
297
|
-
[ "a: maybe
|
298
|
-
[nil, [:fact_type, [[:fact_clause, [], [{:word=>"a"
|
309
|
+
[ "A is a farce: maybe A has completely- B [transitive, acyclic], B -c = 2;",
|
310
|
+
[nil, [:fact_type, [[:fact_clause, [], [{:word=>"A", :term=>"A"}, "is", "a", "farce"], nil]], [[:fact_clause, ["maybe", "transitive", "acyclic"], [{:word=>"A", :term=>"A"}, "has", {:leading_adjective=>"completely", :word=>"completely B", :term=>"B"}], nil], ["=", [:variable, "B c"], 2]]]]
|
311
|
+
],
|
312
|
+
[ "A is a farce: maybe A has completely- green B [transitive, acyclic], B -c = 2;",
|
313
|
+
[nil, [:fact_type, [[:fact_clause, [], [{:word=>"A", :term=>"A"}, "is", "a", "farce"], nil]], [[:fact_clause, ["maybe", "transitive", "acyclic"], [{:word=>"A", :term=>"A"}, "has", {:leading_adjective=>"completely green", :word=>"completely green B", :term=>"B"}], nil], ["=", [:variable, "B c"], 2]]]]
|
314
|
+
],
|
315
|
+
[ "A is a farce: maybe A has B green -totally [transitive, acyclic], B -c = 2;",
|
316
|
+
[nil, [:fact_type, [[:fact_clause, [], [{:word=>"A", :term=>"A"}, "is", "a", "farce"], nil]], [[:fact_clause, ["maybe", "transitive", "acyclic"], [{:word=>"A", :term=>"A"}, "has", {:trailing_adjective=>"green totally", :word=>"B green totally", :term=>"B"}], nil], ["=", [:variable, "B c"], 2]]]]
|
299
317
|
],
|
300
318
|
[ "Person is independent: Person has taxable- Income, taxable Income >= 20000 dollars;",
|
301
|
-
[nil, [:fact_type, [[:fact_clause, [], [{:word=>"Person"
|
319
|
+
[nil, [:fact_type, [[:fact_clause, [], [{:word=>"Person", :term=>"Person"}, "is", "independent"], nil]], [[:fact_clause, [], [{:word=>"Person", :term=>"Person"}, "has", {:leading_adjective=>"taxable", :word=>"taxable Income", :term=>"Income"}], nil], [">=", [:variable, "taxable Income"], [20000, "dollars"]]]]]
|
302
320
|
],
|
303
|
-
[ "Window requires toughening: Window has
|
304
|
-
[nil, [:fact_type, [[:fact_clause, [], [{:word=>"Window"
|
321
|
+
[ "Window requires toughening: Window has Width -mm, Window has Height -mm, Width mm * Height mm >= 10 foot^2;",
|
322
|
+
[nil, [:fact_type, [[:fact_clause, [], [{:word=>"Window", :term=>"Window"}, "requires", "toughening"], nil]], [[:fact_clause, [], [{:word=>"Window", :term=>"Window"}, "has", {:trailing_adjective=>"mm", :word=>"Width mm", :term=>"Width"}], nil], [:fact_clause, [], [{:word=>"Window", :term=>"Window"}, "has", {:trailing_adjective=>"mm", :word=>"Height mm", :term=>"Height"}], nil], [">=", [:*, [:variable, "Width mm"], [:variable, "Height mm"]], [10, "foot^2"]]]]]
|
305
323
|
],
|
306
324
|
# REVISIT: Test all quantifiers
|
307
325
|
# REVISIT: Test all post-qualifiers
|
308
326
|
# REVISIT: Test functions
|
309
|
-
[ "AnnualIncome is where Person has total- Income in Year: Person has total- Income.sum(), Income was earned in current-
|
310
|
-
["AnnualIncome", [:fact_type, [[:fact_clause, [], [{:word=>"Person"
|
327
|
+
[ "AnnualIncome is where Person has total- Income in Year: Person has total- Income.sum(), Income was earned in current- Time.Year() (as Year);",
|
328
|
+
["AnnualIncome", [:fact_type, [[:fact_clause, [], [{:word=>"Person", :term=>"Person"}, "has", {:leading_adjective=>"total", :word=>"total Income", :term=>"Income"}, "in", {:word=>"Year", :term=>"Year"}], nil]], [[:fact_clause, [], [{:word=>"Person", :term=>"Person"}, "has", {:leading_adjective=>"total", :function=>[:"(", "sum"], :word=>"total Income", :term=>"Income"}], nil], [:fact_clause, [], [{:word=>"Income", :term=>"Income"}, "was", "earned", "in", {:leading_adjective=>"current", :function=>[:"(", "Year"], :role_name=>"Year", :word=>"current Time", :term=>"Time"}], nil]]]]
|
311
329
|
],
|
312
|
-
[ "
|
313
|
-
[nil, [:fact_type, [[:fact_clause, [], [{:word=>"
|
330
|
+
[ "A is interesting : b- C has F -g;",
|
331
|
+
[nil, [:fact_type, [[:fact_clause, [], [{:word=>"A", :term=>"A"}, "is", "interesting"], nil]], [[:fact_clause, [], [{:leading_adjective=>"b", :word=>"b C", :term=>"C"}, "has", {:trailing_adjective=>"g", :word=>"F g", :term=>"F"}], nil]]]]
|
314
332
|
]
|
315
333
|
]
|
316
334
|
|
317
335
|
before :each do
|
318
|
-
@parser =
|
336
|
+
@parser = TestParser.new
|
319
337
|
end
|
320
338
|
|
321
339
|
FactTypes.each do |c|
|
@@ -338,15 +356,17 @@ describe "Fact Types" do
|
|
338
356
|
puts result.map{|d| d.value}.inspect unless ast
|
339
357
|
end
|
340
358
|
end
|
359
|
+
end
|
341
360
|
|
361
|
+
describe "Constraint" do
|
342
362
|
Constraints = [
|
343
363
|
[ "each combination FamilyName, GivenName occurs at most one time in Competitor has FamilyName, Competitor has GivenName;",
|
344
|
-
[nil, [:constraint, :presence, [["FamilyName"], ["GivenName"]], [nil, 1], [[[{:word=>"Competitor"
|
364
|
+
[nil, [:constraint, :presence, [["FamilyName"], ["GivenName"]], [nil, 1], [[[{:word=>"Competitor", :term=>"Competitor"}, "has", {:word=>"FamilyName", :term=>"FamilyName"}]], [[{:word=>"Competitor", :term=>"Competitor"}, "has", {:word=>"GivenName", :term=>"GivenName"}]]], nil, []]]
|
345
365
|
],
|
346
366
|
]
|
347
367
|
|
348
368
|
before :each do
|
349
|
-
@parser =
|
369
|
+
@parser = TestParser.new
|
350
370
|
end
|
351
371
|
|
352
372
|
Constraints.each do |c|
|
@@ -371,3 +391,4 @@ describe "Fact Types" do
|
|
371
391
|
end
|
372
392
|
end
|
373
393
|
end
|
394
|
+
=end
|
data/spec/cql_cql_spec.rb
CHANGED
@@ -10,18 +10,17 @@ require 'activefacts/support'
|
|
10
10
|
require 'activefacts/input/cql'
|
11
11
|
require 'activefacts/generate/cql'
|
12
12
|
|
13
|
-
include ActiveFacts
|
14
|
-
|
15
13
|
describe "CQL Loader" do
|
16
14
|
cql_failures = {
|
17
15
|
"Airline" => "Contains queries, unsupported",
|
18
16
|
"CompanyQuery" => "Contains queries, unsupported",
|
19
|
-
"MetamodelNext" => "Fails due to weak adjective/role matching",
|
20
|
-
"
|
21
|
-
"
|
17
|
+
#"MetamodelNext" => "Fails due to weak adjective/role matching",
|
18
|
+
#"ServiceDirector" => "Doesn't parse some constraints due to mis-matched adjectives",
|
19
|
+
#"OddIdentifier" => "The odd identifier is built correctly but cannot be found by the current implementation",
|
20
|
+
"units" => "Unit verbalisation into CQL is not implemented"
|
22
21
|
}
|
23
22
|
cql_cql_failures = {
|
24
|
-
"Insurance" => "Misses a
|
23
|
+
# "Insurance" => "Misses a join in a subset constraint",
|
25
24
|
# "OddIdentifier" => "Doesn't support identification of object fact types using mixed external/internal roles",
|
26
25
|
}
|
27
26
|
# Generate and return the CQL for the given vocabulary
|
@@ -45,7 +44,13 @@ describe "CQL Loader" do
|
|
45
44
|
vocabulary = ActiveFacts::Input::CQL.readfile(cql_file)
|
46
45
|
}
|
47
46
|
else
|
48
|
-
|
47
|
+
begin
|
48
|
+
vocabulary = ActiveFacts::Input::CQL.readfile(cql_file)
|
49
|
+
rescue => e
|
50
|
+
debug :exception, "#{e.message}\n" +
|
51
|
+
"\t#{e.backtrace*"\n\t"}"
|
52
|
+
raise
|
53
|
+
end
|
49
54
|
end
|
50
55
|
|
51
56
|
# Build and save the actual file:
|