activefacts 1.6.0 → 1.7.1

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 (169) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +14 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +60 -0
  8. data/Rakefile +3 -80
  9. data/activefacts.gemspec +36 -0
  10. data/bin/afgen +4 -2
  11. data/bin/cql +5 -1
  12. data/lib/activefacts.rb +3 -12
  13. data/lib/activefacts/{vocabulary/query_evaluator.rb → query/evaluator.rb} +0 -0
  14. data/lib/activefacts/version.rb +2 -2
  15. metadata +48 -296
  16. data/History.txt +0 -4
  17. data/LICENSE +0 -19
  18. data/Manifest.txt +0 -165
  19. data/README.rdoc +0 -81
  20. data/css/offline.css +0 -3
  21. data/css/orm2.css +0 -124
  22. data/css/print.css +0 -8
  23. data/css/style-print.css +0 -357
  24. data/css/style.css +0 -387
  25. data/download.html +0 -110
  26. data/examples/CQL/Address.cql +0 -44
  27. data/examples/CQL/Blog.cql +0 -54
  28. data/examples/CQL/CompanyDirectorEmployee.cql +0 -56
  29. data/examples/CQL/Death.cql +0 -17
  30. data/examples/CQL/Diplomacy.cql +0 -48
  31. data/examples/CQL/Genealogy.cql +0 -98
  32. data/examples/CQL/Insurance.cql +0 -320
  33. data/examples/CQL/Marriage.cql +0 -18
  34. data/examples/CQL/Metamodel.cql +0 -493
  35. data/examples/CQL/Monogamy.cql +0 -24
  36. data/examples/CQL/MultiInheritance.cql +0 -22
  37. data/examples/CQL/NonRoleId.cql +0 -14
  38. data/examples/CQL/OddIdentifier.cql +0 -18
  39. data/examples/CQL/OilSupply.cql +0 -53
  40. data/examples/CQL/OneToOnes.cql +0 -17
  41. data/examples/CQL/Orienteering.cql +0 -111
  42. data/examples/CQL/PersonPlaysGame.cql +0 -18
  43. data/examples/CQL/RedundantDependency.cql +0 -34
  44. data/examples/CQL/SchoolActivities.cql +0 -33
  45. data/examples/CQL/SeparateSubtype.cql +0 -30
  46. data/examples/CQL/ServiceDirector.cql +0 -276
  47. data/examples/CQL/SimplestUnary.cql +0 -12
  48. data/examples/CQL/Supervision.cql +0 -34
  49. data/examples/CQL/WaiterTips.cql +0 -33
  50. data/examples/CQL/Warehousing.cql +0 -101
  51. data/examples/CQL/WindowInRoomInBldg.cql +0 -28
  52. data/examples/CQL/unit.cql +0 -474
  53. data/examples/index.html +0 -420
  54. data/examples/intro.html +0 -327
  55. data/examples/local.css +0 -24
  56. data/index.html +0 -111
  57. data/lib/activefacts/cql.rb +0 -35
  58. data/lib/activefacts/cql/CQLParser.treetop +0 -158
  59. data/lib/activefacts/cql/Context.treetop +0 -48
  60. data/lib/activefacts/cql/Expressions.treetop +0 -67
  61. data/lib/activefacts/cql/FactTypes.treetop +0 -358
  62. data/lib/activefacts/cql/Language/English.treetop +0 -315
  63. data/lib/activefacts/cql/LexicalRules.treetop +0 -253
  64. data/lib/activefacts/cql/ObjectTypes.treetop +0 -210
  65. data/lib/activefacts/cql/Rakefile +0 -14
  66. data/lib/activefacts/cql/Terms.treetop +0 -183
  67. data/lib/activefacts/cql/ValueTypes.treetop +0 -202
  68. data/lib/activefacts/cql/compiler.rb +0 -156
  69. data/lib/activefacts/cql/compiler/clause.rb +0 -1137
  70. data/lib/activefacts/cql/compiler/constraint.rb +0 -581
  71. data/lib/activefacts/cql/compiler/entity_type.rb +0 -457
  72. data/lib/activefacts/cql/compiler/expression.rb +0 -443
  73. data/lib/activefacts/cql/compiler/fact.rb +0 -390
  74. data/lib/activefacts/cql/compiler/fact_type.rb +0 -421
  75. data/lib/activefacts/cql/compiler/query.rb +0 -106
  76. data/lib/activefacts/cql/compiler/shared.rb +0 -161
  77. data/lib/activefacts/cql/compiler/value_type.rb +0 -174
  78. data/lib/activefacts/cql/nodes.rb +0 -49
  79. data/lib/activefacts/cql/parser.rb +0 -241
  80. data/lib/activefacts/dependency_analyser.rb +0 -182
  81. data/lib/activefacts/generate/absorption.rb +0 -70
  82. data/lib/activefacts/generate/composition.rb +0 -118
  83. data/lib/activefacts/generate/cql.rb +0 -714
  84. data/lib/activefacts/generate/dm.rb +0 -279
  85. data/lib/activefacts/generate/help.rb +0 -64
  86. data/lib/activefacts/generate/helpers/inject.rb +0 -16
  87. data/lib/activefacts/generate/helpers/oo.rb +0 -162
  88. data/lib/activefacts/generate/helpers/ordered.rb +0 -605
  89. data/lib/activefacts/generate/helpers/rails.rb +0 -57
  90. data/lib/activefacts/generate/html/glossary.rb +0 -461
  91. data/lib/activefacts/generate/json.rb +0 -337
  92. data/lib/activefacts/generate/null.rb +0 -32
  93. data/lib/activefacts/generate/rails/models.rb +0 -246
  94. data/lib/activefacts/generate/rails/schema.rb +0 -216
  95. data/lib/activefacts/generate/records.rb +0 -46
  96. data/lib/activefacts/generate/ruby.rb +0 -133
  97. data/lib/activefacts/generate/sql/mysql.rb +0 -280
  98. data/lib/activefacts/generate/sql/server.rb +0 -273
  99. data/lib/activefacts/generate/stats.rb +0 -69
  100. data/lib/activefacts/generate/text.rb +0 -27
  101. data/lib/activefacts/generate/topics.rb +0 -265
  102. data/lib/activefacts/generate/traits/datavault.rb +0 -241
  103. data/lib/activefacts/generate/traits/oo.rb +0 -73
  104. data/lib/activefacts/generate/traits/ordered.rb +0 -33
  105. data/lib/activefacts/generate/traits/ruby.rb +0 -210
  106. data/lib/activefacts/generate/transform/datavault.rb +0 -266
  107. data/lib/activefacts/generate/transform/surrogate.rb +0 -214
  108. data/lib/activefacts/generate/version.rb +0 -26
  109. data/lib/activefacts/input/cql.rb +0 -43
  110. data/lib/activefacts/input/orm.rb +0 -1636
  111. data/lib/activefacts/mapping/rails.rb +0 -132
  112. data/lib/activefacts/persistence.rb +0 -15
  113. data/lib/activefacts/persistence/columns.rb +0 -446
  114. data/lib/activefacts/persistence/foreignkey.rb +0 -187
  115. data/lib/activefacts/persistence/index.rb +0 -240
  116. data/lib/activefacts/persistence/object_type.rb +0 -198
  117. data/lib/activefacts/persistence/reference.rb +0 -434
  118. data/lib/activefacts/persistence/tables.rb +0 -380
  119. data/lib/activefacts/registry.rb +0 -11
  120. data/lib/activefacts/support.rb +0 -132
  121. data/lib/activefacts/vocabulary.rb +0 -9
  122. data/lib/activefacts/vocabulary/extensions.rb +0 -1348
  123. data/lib/activefacts/vocabulary/metamodel.rb +0 -570
  124. data/lib/activefacts/vocabulary/verbaliser.rb +0 -804
  125. data/script/txt2html +0 -71
  126. data/spec/absorption_spec.rb +0 -95
  127. data/spec/cql/comparison_spec.rb +0 -89
  128. data/spec/cql/context_spec.rb +0 -94
  129. data/spec/cql/contractions_spec.rb +0 -224
  130. data/spec/cql/deontic_spec.rb +0 -88
  131. data/spec/cql/entity_type_spec.rb +0 -320
  132. data/spec/cql/expressions_spec.rb +0 -66
  133. data/spec/cql/fact_type_matching_spec.rb +0 -338
  134. data/spec/cql/french_spec.rb +0 -21
  135. data/spec/cql/parser/bad_literals_spec.rb +0 -86
  136. data/spec/cql/parser/constraints_spec.rb +0 -19
  137. data/spec/cql/parser/entity_types_spec.rb +0 -106
  138. data/spec/cql/parser/expressions_spec.rb +0 -199
  139. data/spec/cql/parser/fact_types_spec.rb +0 -44
  140. data/spec/cql/parser/literals_spec.rb +0 -312
  141. data/spec/cql/parser/pragmas_spec.rb +0 -89
  142. data/spec/cql/parser/value_types_spec.rb +0 -42
  143. data/spec/cql/role_matching_spec.rb +0 -148
  144. data/spec/cql/samples_spec.rb +0 -244
  145. data/spec/cql_cql_spec.rb +0 -73
  146. data/spec/cql_dm_spec.rb +0 -136
  147. data/spec/cql_mysql_spec.rb +0 -69
  148. data/spec/cql_parse_spec.rb +0 -34
  149. data/spec/cql_ruby_spec.rb +0 -73
  150. data/spec/cql_sql_spec.rb +0 -72
  151. data/spec/cql_symbol_tables_spec.rb +0 -261
  152. data/spec/cqldump_spec.rb +0 -170
  153. data/spec/helpers/array_matcher.rb +0 -23
  154. data/spec/helpers/ctrl_c_support.rb +0 -52
  155. data/spec/helpers/diff_matcher.rb +0 -39
  156. data/spec/helpers/file_matcher.rb +0 -34
  157. data/spec/helpers/parse_to_ast_matcher.rb +0 -80
  158. data/spec/helpers/string_matcher.rb +0 -30
  159. data/spec/helpers/test_parser.rb +0 -15
  160. data/spec/norma_cql_spec.rb +0 -66
  161. data/spec/norma_ruby_spec.rb +0 -62
  162. data/spec/norma_ruby_sql_spec.rb +0 -107
  163. data/spec/norma_sql_spec.rb +0 -57
  164. data/spec/norma_tables_spec.rb +0 -95
  165. data/spec/ruby_api_spec.rb +0 -23
  166. data/spec/spec_helper.rb +0 -35
  167. data/spec/transform_surrogate_spec.rb +0 -59
  168. data/status.html +0 -138
  169. data/why.html +0 -60
@@ -1,71 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- load File.dirname(__FILE__) + "/../Rakefile"
4
- require 'rubyforge'
5
- require 'redcloth'
6
- require 'syntax/convertors/html'
7
- require 'erb'
8
-
9
- download = "http://rubyforge.org/projects/#{$hoe.rubyforge_name}"
10
- version = $hoe.version
11
-
12
- def rubyforge_project_id
13
- RubyForge.new.configure.autoconfig["group_ids"][$hoe.rubyforge_name]
14
- end
15
-
16
- class Fixnum
17
- def ordinal
18
- # teens
19
- return 'th' if (10..19).include?(self % 100)
20
- # others
21
- case self % 10
22
- when 1: return 'st'
23
- when 2: return 'nd'
24
- when 3: return 'rd'
25
- else return 'th'
26
- end
27
- end
28
- end
29
-
30
- class Time
31
- def pretty
32
- return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
33
- end
34
- end
35
-
36
- def convert_syntax(syntax, source)
37
- return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
38
- end
39
-
40
- if ARGV.length >= 1
41
- src, template = ARGV
42
- template ||= File.join(File.dirname(__FILE__), '/../website/template.html.erb')
43
- else
44
- puts("Usage: #{File.split($0).last} source.txt [template.html.erb] > output.html")
45
- exit!
46
- end
47
-
48
- template = ERB.new(File.open(template).read)
49
-
50
- title = nil
51
- body = nil
52
- File.open(src) do |fsrc|
53
- title_text = fsrc.readline
54
- body_text_template = fsrc.read
55
- body_text = ERB.new(body_text_template).result(binding)
56
- syntax_items = []
57
- body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
58
- ident = syntax_items.length
59
- element, syntax, source = $1, $2, $3
60
- syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
61
- "syntax-temp-#{ident}"
62
- }
63
- title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
64
- body = RedCloth.new(body_text).to_html
65
- body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
66
- end
67
- stat = File.stat(src)
68
- created = stat.ctime
69
- modified = stat.mtime
70
-
71
- $stdout << template.result(binding)
@@ -1,95 +0,0 @@
1
- #
2
- # ActiveFacts tests: Test the relational absorption by compiling CQL fragments.
3
- # Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
4
- #
5
-
6
- require 'spec_helper'
7
- require 'activefacts/support'
8
- require 'activefacts/api/support'
9
- require 'activefacts/input/cql'
10
- require 'activefacts/persistence'
11
-
12
- describe "Absorption" do
13
- AT_Prologue = %Q{
14
- vocabulary Test;
15
- DateTime is written as DateAndTime();
16
- Month is written as VariableLengthText(3);
17
- Season is written as VariableLengthText(6);
18
- PartyID is written as AutoCounter();
19
- ClaimID is written as AutoCounter();
20
- }
21
- AT_Claim = %Q{
22
- Claim is identified by ClaimID where
23
- Claim has exactly one ClaimID,
24
- ClaimID is of at most one Claim;
25
- Claim was reported on one DateTime;
26
- }
27
- AT_Incident = %Q{
28
- Incident is identified by Claim where
29
- Claim concerns at most one Incident,
30
- Incident is of exactly one Claim;
31
- }
32
- AT_Party = %Q{
33
- Party is identified by PartyID where
34
- Party has exactly one PartyID,
35
- PartyID is of at most one Party;
36
- }
37
- AT_Person = %Q{
38
- Person is a kind of Party;
39
- }
40
-
41
- Tests = [
42
- { :should => "inject a value column into the table for an independent ValueType",
43
- :cql => %Q{
44
- #{AT_Prologue}
45
- Month is in exactly one Season;
46
- },
47
- :tables => { "Month" => [["Month", "Value"], ["Season"]] }
48
- },
49
-
50
- { :should => "absorb a one-to-one along the identification path",
51
- :cql => %Q{
52
- #{AT_Prologue} #{AT_Claim} #{AT_Incident}
53
- Incident relates to loss on exactly one DateTime;
54
- },
55
- :tables => { "Claim" => [%w{Claim ID}, %w{Date Time}, %w{Incident Date Time}]}
56
- },
57
-
58
- { :should => "absorb an objectified binary with single-role UC",
59
- :cql => %Q{
60
- #{AT_Prologue} #{AT_Claim} #{AT_Party} #{AT_Person}
61
- Lodgement is where
62
- Claim was lodged by at most one Person;
63
- Lodgement was made at at most one DateTime;
64
- Person has exactly one birth-DateTime;
65
- },
66
- :tables => {
67
- "Claim" => [%w{Claim ID}, %w{Date Time}, %w{Lodgement Date Time}, %w{Lodgement Person ID}],
68
- "Party" => [%w{Party ID}, %w{Person Birth Date Time}]
69
- }
70
- },
71
-
72
- ]
73
-
74
- Tests.each do |test|
75
- should = test[:should]
76
- cql = test[:cql]
77
- expected_tables = test[:tables]
78
- it "should #{should}" do
79
- @compiler = ActiveFacts::CQL::Compiler.new(should)
80
- @vocabulary = @compiler.compile(cql)
81
-
82
- # puts cql
83
-
84
- # Ensure that the same tables were generated:
85
- tables = @vocabulary.tables.sort_by(&:name)
86
- tables.map(&:name).should == expected_tables.keys.sort
87
-
88
- # Ensure that the same column descriptions were generated:
89
- tables.each do |table|
90
- column_descriptions = table.columns.map{|col| col.name(nil) }.sort
91
- column_descriptions.should == expected_tables[table.name].map{|c| Array(c) }.sort
92
- end
93
- end
94
- end
95
- end
@@ -1,89 +0,0 @@
1
- #
2
- # ActiveFacts CQL Comparison Fact Type tests
3
- # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
4
- #
5
-
6
- require 'rspec/expectations'
7
-
8
- require 'activefacts/support'
9
- require 'activefacts/api/support'
10
- require 'activefacts/cql/compiler'
11
- require File.dirname(__FILE__) + '/../helpers/compile_helpers'
12
-
13
- describe "When matching a reading with an existing fact type" do
14
- before :each do
15
- extend CompileHelpers
16
-
17
- prefix = %q{
18
- vocabulary Tests;
19
- Name is written as String;
20
- year/years converts to 365.25 day;
21
- Age is written as Integer year;
22
- Person is identified by its Name;
23
- Person is of Age;
24
-
25
- // Company is identified by its Name;
26
- // Directorship is where Person directs Company;
27
- }
28
- @compiler = ActiveFacts::CQL::Compiler.new('Test')
29
- @compiler.compile(prefix)
30
- @constellation = @compiler.vocabulary.constellation
31
-
32
- baseline
33
- end
34
-
35
- describe "equality comparisons" do
36
- before :each do
37
- #debug_enable("binding"); debug_enable("matching"); debug_enable("matching_fails"); debug_enable("parse")
38
- end
39
- after :each do
40
- #debug_disable("binding"); debug_disable("matching"); debug_disable("matching_fails"); debug_disable("parse")
41
- end
42
-
43
- def value_should_match value, lit, unit = nil
44
- value.should_not be_nil
45
- value.literal.should == lit.to_s
46
- (!!value.is_literal_string).should == lit.is_a?(String)
47
- if unit
48
- value.unit.should_not be_nil
49
- value.unit.name.should == unit
50
- else
51
- value.unit.should be_nil
52
- end
53
- end
54
-
55
- def one_query_with_value v, unit = nil
56
- queries.size.should == 1
57
- (jss = steps).size.should == 2
58
- (jns = variables).size.should == 3
59
- integer_node = jns.detect{|jn| jn.object_type.name == 'Integer'}
60
- integer_node.should_not be_nil
61
- value_should_match integer_node.value, v, unit
62
- # pending should test content of the steps
63
- end
64
-
65
- it "should create a comparison fact type" do
66
- compile %q{Person is old where Person is of Age >= 60 years; }
67
- (new_fact_types = fact_types).size.should == 2
68
-
69
- is_old_ft = new_fact_types.detect{|ft| ft.all_reading.detect{|r| r.text =~ /is old/} }
70
- (is_old_ft.all_reading.map{ |r| r.expand }*', ').should == "Person is old"
71
-
72
- comparison_ft = (new_fact_types - [is_old_ft])[0]
73
- (comparison_ft.all_reading.map{ |r| r.expand }*', ').should == "Boolean = Age >= Integer"
74
-
75
- one_query_with_value 60, 'year'
76
- end
77
-
78
- it "should create a comparison fact type twice without duplication"
79
-
80
- it "should parse a query and comparison fact type" do
81
- compile %q{Person is of Age >= 60 years? }
82
- (new_fact_types = fact_types).size.should == 1
83
- (readings = new_fact_types[0].all_reading).size.should == 1
84
- readings.single.text.should == '{0} = {1} >= {2}'
85
-
86
- one_query_with_value 60, 'year'
87
- end
88
- end
89
- end
@@ -1,94 +0,0 @@
1
- #
2
- # ActiveFacts CQL Business Context Note 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
-
10
- describe "Business Context Notes" do
11
- # (according_to people ',')? (because / as_opposed_to / so_that / to_avoid) discussion (',' as_agreed_by)? s
12
- ContextNotePrefix = %q{
13
- vocabulary Test;
14
- Person is written as Person;
15
- Person is employed;
16
- Person is unemployed;
17
- Person is a bad credit risk;
18
- Person is good credit risk;
19
- Bar is written as Bar;
20
- Baz is written as Baz;
21
- }
22
- Notes = [
23
- # Constraints:
24
- [ 'each Person occurs one time in Person is employed, Person is unemployed (because it can be no other way!);',
25
- 1, 'because'
26
- ],
27
- [ 'each Person occurs one time in Person is employed, Person is unemployed (as opposed to blah!);',
28
- 1, 'as_opposed_to'
29
- ],
30
- [ 'for each Person at least one of these holds: Person is employed, Person is a bad credit risk (so that blah);',
31
- 1, 'so_that'
32
- ],
33
- [ 'Person is good credit risk only if Person is employed (to avoid lending to people who can\'t repay);',
34
- 1, 'to_avoid'
35
- ],
36
- [ 'Person is good credit risk if and only if Person is employed (to avoid lending to people who can\'t repay);',
37
- 1, 'to_avoid'
38
- ],
39
- [ 'Person is good credit risk if and only if Person is employed (to avoid lending to people who can\'t repay, as agreed by Jim);',
40
- 1, 'to_avoid', nil, ['Jim']
41
- ],
42
- # Entity and Fact types
43
- # Entity and Fact types
44
- [ 'Foo is identified by Bar [independent] where Foo has one(to avoid fuckups) Bar (so that we have an id);',
45
- 1, 'so_that'
46
- ],
47
- [ 'Baz has one Bar (so that we have an id), Bar is of one Baz (because we need that);',
48
- 2
49
- ],
50
- # REVISIT: No context notes on quantifiers yet
51
- # As agreed by:
52
- [ 'for each Person at least one of these holds: Person is employed, Person is a bad credit risk (so that blah, as agreed by Jim);',
53
- 1, 'so_that', nil, ['Jim']
54
- ],
55
- # REVISIT: Populate an "as agreed by" with a date
56
- [ 'for each Person at least one of these holds: Person is employed, Person is a bad credit risk (so that blah, as agreed on 10-04-10 by Jim);',
57
- 1, 'so_that', nil, ['Jim'], '10-04-10'
58
- ],
59
- # According to:
60
- [ 'for each Person at least one of these holds: Person is employed, Person is a bad credit risk (according to jim, so that blah);',
61
- 1, 'so_that', ['jim']
62
- ],
63
- ]
64
-
65
- before :each do
66
- @compiler = ActiveFacts::CQL::Compiler.new('Test')
67
- end
68
-
69
- Notes.each do |c|
70
- source, count, kind, according_to, agreed_by, agreed_date = *c
71
- it "should parse #{source.inspect}" do
72
-
73
- result =
74
- begin
75
- @compiler.compile(ContextNotePrefix+source)
76
- rescue => e
77
- puts "#{e}:\n\t#{e.backtrace*"\n\t"}"
78
- end
79
- puts @compiler.failure_reason unless result
80
- result.should_not be_nil
81
- constellation = @compiler.vocabulary.constellation
82
-
83
- # constellation.ContextNote.each{|k,cn| puts "#{k.inspect} => #{cn.inspect}" }
84
- constellation.ContextNote.size.should == (count || 1)
85
- context_note = constellation.ContextNote.values[0]
86
- context_note.context_note_kind.should == kind if kind
87
- context_note.all_context_according_to.map{|cat| cat.agent.agent_name }.sort.should == according_to if according_to
88
- # context_note.discussion.should == discussion if discussion
89
- context_note.agreement.should_not be_nil if agreed_by || agreed_date
90
- context_note.agreement.all_context_agreed_by.map{|cab| cab.agent.agent_name}.sort.should == agreed_by if agreed_by
91
- context_note.agreement.date.should == Date.parse(agreed_date) if agreed_date
92
- end
93
- end
94
- end
@@ -1,224 +0,0 @@
1
- #
2
- # ActiveFacts CQL Fact Type matching tests - contractions.
3
- # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
4
- #
5
- # Contractions are where a fact type clause is followed by another (with
6
- # some conjunction except for comparisons) with one player *implicit* in
7
- # the following clause.
8
- #
9
- # Right contraction elides the repetition of the right-most player,
10
- # and left contraction elides the left-most player.
11
- #
12
- # So, using the notation "A rel B" for binaries,
13
- # "A relA B relA C" for ternaries, and "C prop" for properties,
14
- # we can write equivalences as follows.
15
- #
16
- # Note 1: Terms may be more than one word.
17
- # Note 2: For any "A rel B", the example also applies to a ternary or
18
- # higher, as appropriate.
19
-
20
- =begin
21
- Right contractions with 'and':
22
- A rel B and B prop
23
- -> A rel B who/that prop
24
- E.g. Person pats Cat that is asleep
25
-
26
- A rel B and B rel2 C
27
- -> A rel B who/that rel2 C
28
- E.g. Person pats Cat that is lying on Mat
29
-
30
- A rel B and B rel2A C rel2A D
31
- -> A rel B who/that rel2A C rel2B D
32
- E.g. Person pats Cat that ate Food at Time
33
-
34
- A rel B and B > C
35
- -> A rel B > C
36
- E.g. Person is of Age >= 21
37
-
38
- A > B and B rel C
39
- -> A > B rel C
40
- E.g. 21 > Age of Person
41
-
42
- Right contractions with ',':
43
- A rel B, B rel2 C
44
- -> A rel B who/that rel2 C
45
-
46
- A rel B, B prop
47
- -> A rel B who/that prop
48
-
49
- A rel B, B > C
50
- -> A rel B > C
51
-
52
- A > B, B rel C
53
- -> A > B rel C
54
-
55
- Left contractions with 'and':
56
- A rel B and A rel2 C
57
- -> A rel B and rel2 C
58
- E.g. Boy seduces Girl and is drunk
59
-
60
- A rel B and A prop
61
- -> A rel B and prop
62
-
63
- A rel B and A > C
64
- -> A rel B and > C
65
-
66
- Left contractions with 'or':
67
- A rel B or A rel2 C
68
- -> A rel B or rel2 C
69
-
70
- A rel B or A prop
71
- -> A rel B or prop
72
-
73
- A rel B or A > C
74
- -> A rel B or > C
75
-
76
- A > B or A rel C
77
- -> A > B or rel C
78
-
79
- Double contractions (not supported in CQL yet):
80
- A rel B and A rel2 B
81
- -> A rel B and rel2
82
- E.g. Person came to Party and was invited to
83
-
84
- Extended contractions (not supported in CQL yet) (note the ambiguity - if allowed, the first takes precedence!):
85
- A rel B and B rel2 C and B prop
86
- -> A rel B that rel2 C and prop
87
- E.g. LazyDogOwner is a Person who owns Dog that barks and Dog is lazy.
88
-
89
- A rel B and B rel2 C and A prop
90
- -> A rel B that rel2 C and prop
91
- E.g. LazyDogOwner is a Person who owns Dog that barks and Person is lazy.
92
-
93
- And/or resolution:
94
- A rel B and B rel2 C or A rel3 D
95
- A rel B and B rel2 C or B rel3 D -> Logical, A must rel B but B can carry either rel
96
- A rel B and B rel2 C or C rel3 D -> Illogical form (mandates B rel2 C so 'or' is meaningless)
97
-
98
- Ambiguous, disallowed:
99
- A > 2 + B > C
100
-
101
- Comments from Matt on contraction and verbalisation:
102
-
103
- I have two types of list phrases which I classify as 'header' and 'inline'.
104
- And and or are inline, the other four (negated and/or, positive or negative
105
- xor) all use header forms. There is also a header form of negation (it is not
106
- true that...). The header forms (all of the following must be true: etc) can
107
- introduce vars in the starting context, but not those introduced by previous
108
- elements in the list.
109
-
110
- You'll likely need something similar, though, on nested expressions. You also
111
- have to decide where your implicit existential placement is if you use the
112
- same var in multiple branches or under negation. Lots of fun stuff.
113
-
114
- =end
115
-
116
-
117
- require 'rspec/expectations'
118
-
119
- require 'activefacts/support'
120
- require 'activefacts/api/support'
121
- require 'activefacts/cql/compiler'
122
- require File.dirname(__FILE__) + '/../helpers/compile_helpers' # Can't see how to include/extend these methods correctly
123
-
124
- describe "When compiling a query, " do
125
- before :each do
126
- extend CompileHelpers
127
-
128
- prefix = %q{
129
- vocabulary Tests;
130
- Boy is written as String;
131
- Girl is written as Integer;
132
- Age is written as Integer;
133
- Boy is of Age;
134
- Boy is going out with Girl, Girl is going out with Boy;
135
- }
136
- @compiler = ActiveFacts::CQL::Compiler.new('Test')
137
- @compiler.compile(prefix)
138
- @constellation = @compiler.vocabulary.constellation
139
-
140
- baseline
141
-
142
- def self.compile string
143
- lambda {
144
- @compiler.compile string
145
- }.should_not raise_error
146
- end
147
- end
148
-
149
- shared_examples_for "single contractions" do
150
- it "should produce one fact type" do
151
- (new_fact_types = fact_types).size.should == 1
152
- end
153
- it "the fact type should have one reading" do
154
- fact_type = fact_types[0]
155
- fact_type.all_reading.size.should == 1
156
- end
157
- it "the fact type should have no presence constraints" do
158
- fact_type = fact_types[0]
159
- (pcs = fact_pcs(fact_type)).size.should == 0
160
- end
161
- it "should produce one query" do
162
- fact_type = fact_types[0]
163
- query = derivation(fact_type)
164
- end
165
- it "the query should have 3 variables" do
166
- fact_type = fact_types[0]
167
- query = derivation(fact_type)
168
- variables = query.all_variable.to_a
169
- variables.size.should == 3
170
- end
171
- it "the query should have 2 steps" do
172
- fact_type = fact_types[0]
173
- query = derivation(fact_type)
174
- steps = query.all_step.to_a
175
- steps.size.should == 2
176
- end
177
-
178
- it "and should project the fact type roles from the query" do
179
- skip "Plays are not yet projected" do
180
- query = derivation(fact_type)
181
- queries = fact_type.all_role.map{|r| r.all_play.map{|play| play.query}}.flatten.uniq
182
- queries.size == 1
183
- queries.should == [query]
184
- end
185
- end
186
- end
187
-
188
- describe "right contractions having" do
189
- describe "a single contraction using 'who'" do
190
- before :each do
191
- compile %q{Boy is relevant where Girl is going out with Boy who is of Age; }
192
- end
193
-
194
- it_should_behave_like "single contractions"
195
- end
196
-
197
- describe "a single contraction using 'that'" do
198
- before :each do
199
- compile %q{Boy is relevant where Girl is going out with Boy that is of Age; }
200
- end
201
-
202
- it_should_behave_like "single contractions"
203
- end
204
- end
205
-
206
- describe "left contractions having" do
207
- describe "a single contraction" do
208
- before :each do
209
- compile %q{Boy is relevant where Boy is of Age and is going out with Girl; }
210
- end
211
-
212
- it_should_behave_like "single contractions"
213
- end
214
- end
215
- end
216
-
217
- =begin
218
- Examples on the Blog model:
219
-
220
- Post is nice where Post was written by Author and belongs to Topic and includes Ordinal paragraph;
221
- Post is nice where Post was written by Author and belongs to Topic or Post includes Ordinal paragraph or has Post Id;
222
- Post is nice where Post was written by Author and belongs to Topic or includes Ordinal paragraph;
223
- Post is nice where Post was written by Author and belongs to Topic or Post includes Ordinal paragraph or has Post Id;
224
- =end