activefacts 0.8.9 → 0.8.10
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemtest +0 -0
- data/Manifest.txt +28 -33
- data/Rakefile +11 -12
- data/bin/cql +90 -46
- data/examples/CQL/Blog.cql +2 -1
- data/examples/CQL/CompanyDirectorEmployee.cql +2 -2
- data/examples/CQL/Death.cql +1 -1
- data/examples/CQL/Diplomacy.cql +9 -9
- data/examples/CQL/Genealogy.cql +3 -2
- data/examples/CQL/Insurance.cql +10 -7
- data/examples/CQL/JoinEquality.cql +2 -2
- data/examples/CQL/Marriage.cql +1 -1
- data/examples/CQL/Metamodel.cql +73 -53
- data/examples/CQL/MetamodelNext.cql +89 -67
- data/examples/CQL/OneToOnes.cql +2 -2
- data/examples/CQL/ServiceDirector.cql +10 -5
- data/examples/CQL/Supervision.cql +3 -3
- data/examples/CQL/Tests.Test5.Load.cql +1 -1
- data/examples/CQL/Warehousing.cql +4 -2
- data/lib/activefacts/cql/CQLParser.treetop +26 -60
- data/lib/activefacts/cql/Context.treetop +12 -2
- data/lib/activefacts/cql/Expressions.treetop +14 -30
- data/lib/activefacts/cql/FactTypes.treetop +165 -110
- data/lib/activefacts/cql/Language/English.treetop +167 -54
- data/lib/activefacts/cql/LexicalRules.treetop +16 -2
- data/lib/activefacts/cql/{Concepts.treetop → ObjectTypes.treetop} +36 -37
- data/lib/activefacts/cql/Terms.treetop +57 -27
- data/lib/activefacts/cql/ValueTypes.treetop +39 -13
- data/lib/activefacts/cql/compiler.rb +5 -3
- data/lib/activefacts/cql/compiler/{reading.rb → clause.rb} +407 -285
- data/lib/activefacts/cql/compiler/constraint.rb +178 -275
- data/lib/activefacts/cql/compiler/entity_type.rb +73 -64
- data/lib/activefacts/cql/compiler/expression.rb +418 -0
- data/lib/activefacts/cql/compiler/fact.rb +146 -145
- data/lib/activefacts/cql/compiler/fact_type.rb +197 -80
- data/lib/activefacts/cql/compiler/join.rb +159 -0
- data/lib/activefacts/cql/compiler/shared.rb +51 -23
- data/lib/activefacts/cql/compiler/value_type.rb +56 -2
- data/lib/activefacts/cql/parser.rb +15 -4
- data/lib/activefacts/generate/absorption.rb +7 -7
- data/lib/activefacts/generate/cql.rb +100 -37
- data/lib/activefacts/generate/oo.rb +28 -51
- data/lib/activefacts/generate/ordered.rb +60 -36
- data/lib/activefacts/generate/ruby.rb +6 -6
- data/lib/activefacts/generate/sql/server.rb +4 -4
- data/lib/activefacts/input/orm.rb +71 -53
- data/lib/activefacts/persistence.rb +1 -1
- data/lib/activefacts/persistence/columns.rb +27 -23
- data/lib/activefacts/persistence/foreignkey.rb +6 -6
- data/lib/activefacts/persistence/index.rb +17 -17
- data/lib/activefacts/persistence/{concept.rb → object_type.rb} +9 -9
- data/lib/activefacts/persistence/reference.rb +61 -36
- data/lib/activefacts/persistence/tables.rb +61 -59
- data/lib/activefacts/support.rb +54 -29
- data/lib/activefacts/version.rb +1 -1
- data/lib/activefacts/vocabulary/extensions.rb +99 -54
- data/lib/activefacts/vocabulary/metamodel.rb +43 -37
- data/lib/activefacts/vocabulary/verbaliser.rb +134 -109
- data/spec/absorption_spec.rb +8 -8
- data/spec/cql/comparison_spec.rb +91 -0
- data/spec/cql/contractions_spec.rb +251 -0
- data/spec/cql/entity_type_spec.rb +319 -0
- data/spec/cql/expressions_spec.rb +63 -0
- data/spec/cql/fact_type_matching_spec.rb +283 -0
- data/spec/cql/french_spec.rb +21 -0
- data/spec/cql/parser/bad_literals_spec.rb +86 -0
- data/spec/cql/parser/constraints_spec.rb +19 -0
- data/spec/cql/parser/entity_types_spec.rb +106 -0
- data/spec/cql/parser/expressions_spec.rb +179 -0
- data/spec/cql/parser/fact_types_spec.rb +41 -0
- data/spec/cql/parser/literals_spec.rb +312 -0
- data/spec/cql/parser/pragmas_spec.rb +89 -0
- data/spec/cql/parser/value_types_spec.rb +42 -0
- data/spec/cql/role_matching_spec.rb +147 -0
- data/spec/cql/samples_spec.rb +9 -9
- data/spec/cql_cql_spec.rb +1 -1
- data/spec/cql_dm_spec.rb +116 -0
- data/spec/cql_mysql_spec.rb +1 -1
- data/spec/cql_ruby_spec.rb +1 -1
- data/spec/cql_sql_spec.rb +3 -3
- data/spec/cql_symbol_tables_spec.rb +30 -30
- data/spec/cqldump_spec.rb +4 -4
- data/spec/helpers/array_matcher.rb +32 -27
- data/spec/helpers/diff_matcher.rb +6 -26
- data/spec/helpers/file_matcher.rb +41 -32
- data/spec/helpers/parse_to_ast_matcher.rb +76 -0
- data/spec/helpers/string_matcher.rb +32 -31
- data/spec/norma_cql_spec.rb +1 -1
- data/spec/norma_ruby_spec.rb +1 -1
- data/spec/norma_ruby_sql_spec.rb +1 -1
- data/spec/norma_sql_spec.rb +3 -1
- data/spec/norma_tables_spec.rb +1 -1
- data/spec/ruby_api_spec.rb +23 -0
- data/spec/spec_helper.rb +5 -4
- metadata +66 -66
- data/examples/CQL/OrienteeringER.cql +0 -58
- data/lib/activefacts/api.rb +0 -44
- data/lib/activefacts/api/concept.rb +0 -410
- data/lib/activefacts/api/constellation.rb +0 -128
- data/lib/activefacts/api/entity.rb +0 -256
- data/lib/activefacts/api/instance.rb +0 -60
- data/lib/activefacts/api/instance_index.rb +0 -80
- data/lib/activefacts/api/numeric.rb +0 -167
- data/lib/activefacts/api/role.rb +0 -80
- data/lib/activefacts/api/role_proxy.rb +0 -70
- data/lib/activefacts/api/role_values.rb +0 -117
- data/lib/activefacts/api/standard_types.rb +0 -87
- data/lib/activefacts/api/support.rb +0 -65
- data/lib/activefacts/api/value.rb +0 -135
- data/lib/activefacts/api/vocabulary.rb +0 -82
- data/spec/api/autocounter.rb +0 -82
- data/spec/api/constellation.rb +0 -130
- data/spec/api/entity_type.rb +0 -103
- data/spec/api/instance.rb +0 -461
- data/spec/api/roles.rb +0 -124
- data/spec/api/value_type.rb +0 -112
- data/spec/api_spec.rb +0 -13
- data/spec/cql/matching_spec.rb +0 -517
- data/spec/cql/unit_spec.rb +0 -394
- data/spec/spec.opts +0 -1
data/spec/api/roles.rb
DELETED
@@ -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
|
data/spec/api/value_type.rb
DELETED
@@ -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
|
data/spec/api_spec.rb
DELETED
@@ -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'
|
data/spec/cql/matching_spec.rb
DELETED
@@ -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
|