activefacts 0.8.16 → 0.8.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/Manifest.txt +10 -4
- data/bin/afgen +26 -20
- data/bin/cql +1 -1
- data/css/orm2.css +89 -9
- data/examples/CQL/CompanyDirectorEmployee.cql +4 -4
- data/examples/CQL/Genealogy.cql +5 -5
- data/examples/CQL/Metamodel.cql +121 -91
- data/examples/CQL/MonthInSeason.cql +2 -6
- data/examples/CQL/SeparateSubtype.cql +11 -9
- data/examples/CQL/ServiceDirector.cql +21 -33
- data/examples/CQL/Supervision.cql +0 -3
- data/examples/CQL/WindowInRoomInBldg.cql +10 -4
- data/examples/CQL/unit.cql +1 -1
- data/lib/activefacts.rb +1 -0
- data/lib/activefacts/cql/CQLParser.treetop +5 -1
- data/lib/activefacts/cql/Context.treetop +2 -7
- data/lib/activefacts/cql/Expressions.treetop +2 -2
- data/lib/activefacts/cql/FactTypes.treetop +37 -31
- data/lib/activefacts/cql/Language/English.treetop +21 -4
- data/lib/activefacts/cql/LexicalRules.treetop +59 -1
- data/lib/activefacts/cql/ObjectTypes.treetop +22 -12
- data/lib/activefacts/cql/Terms.treetop +13 -9
- data/lib/activefacts/cql/ValueTypes.treetop +30 -11
- data/lib/activefacts/cql/compiler.rb +34 -5
- data/lib/activefacts/cql/compiler/clause.rb +207 -116
- data/lib/activefacts/cql/compiler/constraint.rb +129 -105
- data/lib/activefacts/cql/compiler/entity_type.rb +49 -27
- data/lib/activefacts/cql/compiler/expression.rb +71 -42
- data/lib/activefacts/cql/compiler/fact.rb +70 -64
- data/lib/activefacts/cql/compiler/fact_type.rb +108 -57
- data/lib/activefacts/cql/compiler/query.rb +178 -0
- data/lib/activefacts/cql/compiler/shared.rb +13 -12
- data/lib/activefacts/cql/compiler/value_type.rb +10 -4
- data/lib/activefacts/cql/nodes.rb +1 -1
- data/lib/activefacts/cql/parser.rb +6 -2
- data/lib/activefacts/generate/absorption.rb +6 -3
- data/lib/activefacts/generate/cql.rb +140 -84
- data/lib/activefacts/generate/dm.rb +12 -6
- data/lib/activefacts/generate/help.rb +25 -6
- data/lib/activefacts/generate/helpers/oo.rb +195 -0
- data/lib/activefacts/generate/helpers/ordered.rb +589 -0
- data/lib/activefacts/generate/helpers/rails.rb +57 -0
- data/lib/activefacts/generate/html/glossary.rb +274 -54
- data/lib/activefacts/generate/json.rb +25 -22
- data/lib/activefacts/generate/null.rb +1 -0
- data/lib/activefacts/generate/rails/models.rb +244 -0
- data/lib/activefacts/generate/rails/schema.rb +185 -0
- data/lib/activefacts/generate/records.rb +1 -0
- data/lib/activefacts/generate/ruby.rb +51 -30
- data/lib/activefacts/generate/sql/mysql.rb +5 -3
- data/lib/activefacts/generate/sql/server.rb +8 -4
- data/lib/activefacts/generate/text.rb +1 -0
- data/lib/activefacts/generate/transform/surrogate.rb +209 -0
- data/lib/activefacts/generate/version.rb +1 -0
- data/lib/activefacts/input/orm.rb +234 -181
- data/lib/activefacts/mapping/rails.rb +122 -0
- data/lib/activefacts/persistence/columns.rb +34 -18
- data/lib/activefacts/persistence/foreignkey.rb +129 -71
- data/lib/activefacts/persistence/index.rb +42 -12
- data/lib/activefacts/persistence/reference.rb +37 -23
- data/lib/activefacts/persistence/tables.rb +53 -19
- data/lib/activefacts/registry.rb +11 -0
- data/lib/activefacts/support.rb +28 -10
- data/lib/activefacts/version.rb +1 -1
- data/lib/activefacts/vocabulary/extensions.rb +246 -117
- data/lib/activefacts/vocabulary/metamodel.rb +105 -65
- data/lib/activefacts/vocabulary/verbaliser.rb +226 -194
- data/spec/absorption_spec.rb +1 -0
- data/spec/cql/comparison_spec.rb +8 -8
- data/spec/cql/contractions_spec.rb +16 -43
- data/spec/cql/entity_type_spec.rb +2 -1
- data/spec/cql/expressions_spec.rb +2 -2
- data/spec/cql/fact_type_matching_spec.rb +4 -1
- data/spec/cql/parser/bad_literals_spec.rb +30 -30
- data/spec/cql/parser/entity_types_spec.rb +6 -6
- data/spec/cql/parser/expressions_spec.rb +25 -19
- data/spec/cql/samples_spec.rb +5 -4
- data/spec/cql_cql_spec.rb +2 -1
- data/spec/cql_dm_spec.rb +4 -0
- data/spec/cql_mysql_spec.rb +4 -0
- data/spec/cql_parse_spec.rb +2 -0
- data/spec/cql_ruby_spec.rb +4 -0
- data/spec/cql_sql_spec.rb +4 -0
- data/spec/cqldump_spec.rb +7 -4
- data/spec/helpers/parse_to_ast_matcher.rb +7 -3
- data/spec/helpers/test_parser.rb +2 -0
- data/spec/norma_cql_spec.rb +5 -2
- data/spec/norma_ruby_spec.rb +4 -1
- data/spec/norma_ruby_sql_spec.rb +4 -1
- data/spec/norma_sql_spec.rb +4 -1
- data/spec/norma_tables_spec.rb +2 -2
- data/spec/ruby_api_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -0
- data/spec/transform_surrogate_spec.rb +59 -0
- metadata +70 -60
- data/TODO +0 -308
- data/lib/activefacts/cql/compiler/join.rb +0 -162
- data/lib/activefacts/generate/oo.rb +0 -176
- data/lib/activefacts/generate/ordered.rb +0 -602
data/TODO
DELETED
@@ -1,308 +0,0 @@
|
|
1
|
-
ActiveFacts ToDo list
|
2
|
-
|
3
|
-
Metamodel
|
4
|
-
ALWAYS Integrate Metamodel changes through lib/activefacts/vocabulary/metamodel.rb
|
5
|
-
SOON Add Terms for Object Types
|
6
|
-
using Words? (which include adjectives/rolenames)
|
7
|
-
Notes (Extend context notes)
|
8
|
-
comments in CQL?
|
9
|
-
Derivation notes?
|
10
|
-
HelpText?
|
11
|
-
FBM Standards Metamodel
|
12
|
-
Migrate towards standard terminology
|
13
|
-
Make ORM model emit good CQL
|
14
|
-
Use UUIDs
|
15
|
-
Renamed from ("Person (was called User) ...")
|
16
|
-
Multiple revisions?
|
17
|
-
Extensions (new vocabularies?) for Metamodel
|
18
|
-
security
|
19
|
-
processes
|
20
|
-
discussion/conversation
|
21
|
-
Implement abstract supertypes?
|
22
|
-
Allow Object naming "Paris means City 'Paris'"
|
23
|
-
Use subtype extension in Metamodel (based on abstract SBVR supertypes as shown?)
|
24
|
-
Meaning
|
25
|
-
Concept
|
26
|
-
NounConcept
|
27
|
-
ObjectType
|
28
|
-
RolePlaying
|
29
|
-
FactType
|
30
|
-
Fact
|
31
|
-
Value
|
32
|
-
Query
|
33
|
-
Lexeme (language/locale sensitive text)
|
34
|
-
Term
|
35
|
-
Reading (template text, adjectives)
|
36
|
-
Value (literal)
|
37
|
-
Or just have per-locale syntax parser/generator to/from canonical form?
|
38
|
-
Role names
|
39
|
-
need to attach to RoleRefs instead of Roles
|
40
|
-
Refactor RoleRef and RoleSequence so RoleSequence isn't re-used out of context
|
41
|
-
Index/access-path/ordering pragmas
|
42
|
-
Temporal literals (expressions using current time)
|
43
|
-
Temporal: e.g. Date/Time {{/not} {after/before}} Date/Time
|
44
|
-
SOON Refactor Derived Fact Types (Queries) using new terminology
|
45
|
-
|
46
|
-
CQL
|
47
|
-
Object Types
|
48
|
-
ValueTypes
|
49
|
-
Change so Data Types are not inherited
|
50
|
-
Implement named parameters
|
51
|
-
Autogenerated
|
52
|
-
On assert (UUID)
|
53
|
-
On save (ID, Timestamp, etc)
|
54
|
-
Partial auto-counters (Role, *Ordinal*)
|
55
|
-
Implement base VTs
|
56
|
-
SOON "vt is written;" syntax
|
57
|
-
Entity Types
|
58
|
-
SOON "Et is identified;" forward-reference syntax
|
59
|
-
Allow other possessive pronouns "Ship is identified by her Name"
|
60
|
-
Allow shorthand for multi-part identification
|
61
|
-
"Person is identified by his given-Name and family-Name;"
|
62
|
-
Subtypes
|
63
|
-
Support Role subtypes as distinct (subtype migration allowed)
|
64
|
-
Subtyping fact type role names?
|
65
|
-
Object Names
|
66
|
-
"Paris means City 'Paris'"
|
67
|
-
|
68
|
-
Joins
|
69
|
-
SOON Anti-joins (no, none, negation, "it is not the case that", etc)
|
70
|
-
SOON Double-contraction "Person who came to Party and was not invited to"
|
71
|
-
SOON Outer joins ("maybe")
|
72
|
-
SOON Compile Value join nodes
|
73
|
-
STARTED, DIFFICULT Implement comparison operators as derived fact types (<, etc)
|
74
|
-
Automatically detect type conversion joins
|
75
|
-
|
76
|
-
Queries
|
77
|
-
Expression clauses
|
78
|
-
Redo grammar as normal clause (A < B -> A rel B)
|
79
|
-
User-defined expression operators/clauses?
|
80
|
-
Fact Type Negation (A rel no B, no A rel B)
|
81
|
-
"returning" clause
|
82
|
-
Invoke queries using defined role names:
|
83
|
-
Company has young Person (as Director) where ...
|
84
|
-
(invoke as "Company has young Director")
|
85
|
-
Temporal terms and phrases
|
86
|
-
"now" "4 year ago", "3 minutes from now"
|
87
|
-
Temporal ValueType to act as a Universal fact type over the domain
|
88
|
-
e.g. Time.hour -> all possible hours
|
89
|
-
Figure out what base constraints propagate to the result set
|
90
|
-
Allow "which" to project roles from a query "which Person gatecrashed Party?"
|
91
|
-
Value range restrictions (in {1,2,4}) instead of (restricted to {...})
|
92
|
-
|
93
|
-
Linguistic aspects
|
94
|
-
UTF-8 Support
|
95
|
-
Other languages
|
96
|
-
Define syntax for and handle Gender
|
97
|
-
French
|
98
|
-
Spanish
|
99
|
-
Use filename to select (Bar.fr.cql or Bar.cql.fr?)
|
100
|
-
Use metamodel predicates instead of pragmas
|
101
|
-
e.g. for "Object type is independent", say "Object Type 'Foo' is independent";
|
102
|
-
How to handle Fact Type names in the above syntax? Objectify? But need ring constraint roles.
|
103
|
-
Vocabulary name is implicit here...
|
104
|
-
SOON Allow more than one Business Context Note per item
|
105
|
-
Fact type binding
|
106
|
-
Use non-local role names in fact type matching?
|
107
|
-
Check that subscripts are being tested properly
|
108
|
-
Implement some/that binding
|
109
|
-
subscripts not necessary where "that" is unambiguous.
|
110
|
-
which/that: "which Person likes that Person?"
|
111
|
-
Double-hyphen for hyphenated adjectives
|
112
|
-
|
113
|
-
Constraints
|
114
|
-
SOON Implement "maybe" to make min-frequency non-mandatory
|
115
|
-
Value Literal syntax constraints
|
116
|
-
Regexp: "vt is written to match /xyz/"
|
117
|
-
Regexp for role values
|
118
|
-
subtype of Value Constraint
|
119
|
-
PEG Grammars for literals? (extend CQL grammar)
|
120
|
-
Ring constraints
|
121
|
-
how to handle ambiguous rings, e.g. in ternaries?
|
122
|
-
how to handle multiple rings in one FT?
|
123
|
-
Think about syntax to allow this
|
124
|
-
Populate Ring Types in metamodel (five unaries?)
|
125
|
-
Constraint names (esp Presence Constraints, they become index names)
|
126
|
-
Temporal Modeling ([at most] one at a time)
|
127
|
-
single table mapping
|
128
|
-
two tables mappings (current/history)
|
129
|
-
Add Exclusion constraint syntax using negative clause:
|
130
|
-
Person is ceo if and only if no Manager manages (that?) Person
|
131
|
-
Similar case exists for subset constraint?
|
132
|
-
A rel B only if no B rel C - think through
|
133
|
-
Delay creation of default identifying constraints for objectified fact types
|
134
|
-
Perhaps before relational/object mapping?
|
135
|
-
Or don't create them at all - handle missing PI for OFTs instead
|
136
|
-
Asserted instances
|
137
|
-
"including {'foo', 'bar', ...}" akin to "restricted to"...
|
138
|
-
|
139
|
-
Importing vocabularies
|
140
|
-
Distinguish "import" from "use"?
|
141
|
-
Bind to imported ValueTypes (and other object types?)
|
142
|
-
Base vocabularies for SQL
|
143
|
-
Multiple SQL base vocabs, using db pref to choose between.
|
144
|
-
|
145
|
-
CQL Verbaliser
|
146
|
-
SOON Detect new fact types that would be interpreted as an existing (only adjectives differ), and use single reading (before double-reading) e.g. other-Role of RingConstraint
|
147
|
-
Implement some/that binding
|
148
|
-
use some/that where "that" is unambiguous
|
149
|
-
Don't emit some/that until binding will use it properly
|
150
|
-
Instance data verbalisation
|
151
|
-
Emit objectification joins
|
152
|
-
Contractions (use Verbaliser!)
|
153
|
-
Emit example fact from ORM2009 presentation
|
154
|
-
Output clustering
|
155
|
-
Emit Value Types just before first use
|
156
|
-
Emit Constraints as soon as possible
|
157
|
-
Choose "focus" items with most 1st and 2nd generation dependencies, and do all precursors/followers before choosing another
|
158
|
-
Left-contraction of joins "Xyz is ... and is ...;"
|
159
|
-
|
160
|
-
Units
|
161
|
-
SOON Store sample data with specified unit
|
162
|
-
Handle storing numeric Instance values (noted to be in the lexical form; but strings aren't!)
|
163
|
-
SOON Save Units on ValueTypes
|
164
|
-
Generate conversion formula to fundamental types
|
165
|
-
|
166
|
-
CQL Shell
|
167
|
-
Save definitions, including instances
|
168
|
-
/sql; generate the SQL for this vocabulary
|
169
|
-
/valid; check all metamodel constraints over the vocabulary, and/or vocabulary constraints over the population
|
170
|
-
Queries
|
171
|
-
/population {open, check, create} database_name
|
172
|
-
/ruby
|
173
|
-
/cql
|
174
|
-
|
175
|
-
NORMA reader
|
176
|
-
NORMA Joins
|
177
|
-
Detect and store implicit joins in presence constraints (if needed???)
|
178
|
-
Convert all NORMA Join paths
|
179
|
-
NORMA input: Warn when preferred reading role order doesn't match the preferred identifier for objectified FTs
|
180
|
-
Import instance data for objectified fact types
|
181
|
-
Double-hyphen for hyphenated adjectives
|
182
|
-
|
183
|
-
Generators
|
184
|
-
Ruby generator
|
185
|
-
Emit a module method for each example population
|
186
|
-
|
187
|
-
Relational Composition
|
188
|
-
Subtype Mapping
|
189
|
-
extension (subtype in separate table)
|
190
|
-
partition (separate and include all supertype roles)
|
191
|
-
Make sure all test scenarios are covered
|
192
|
-
Transforms
|
193
|
-
Rails ID injection
|
194
|
-
Subtype discriminator injection where no mandatory role on subtype
|
195
|
-
Don't introduce additional discriminator for sub-sub-type
|
196
|
-
Detect non-exclusive subtypes and discriminate combinations
|
197
|
-
Column name generation
|
198
|
-
Provide alternative generation pattern(s) (snake-case)
|
199
|
-
Duplicate column names (detect, handle)
|
200
|
-
SQL Generation
|
201
|
-
Auto-generated column types
|
202
|
-
IDentity fields
|
203
|
-
GUIDs
|
204
|
-
partial auto-counters (Ordinal)
|
205
|
-
Timestamps
|
206
|
-
other auto-counters?
|
207
|
-
Foreign Key fields
|
208
|
-
Index both ends
|
209
|
-
Determine cascading based on mandatory-ness
|
210
|
-
Emit triggers where PK is in a subtype (and view was generated)
|
211
|
-
Existing database/vocabulary
|
212
|
-
Minimal impact vs refactor and migrate
|
213
|
-
|
214
|
-
Runtime API
|
215
|
-
Autogenerated Data Types
|
216
|
-
GUID, Ordinal
|
217
|
-
Entity
|
218
|
-
Save identifying roles as Role objects not symbols
|
219
|
-
SOON Propagate retract() properly (replace delete?)
|
220
|
-
Subtype migration
|
221
|
-
Replace instance by instance of different class, de-/re-assign all roles?
|
222
|
-
Re-use same role proxy/ies?
|
223
|
-
Role value array proxy class
|
224
|
-
Handle sorting by residual fields in counterpart's key
|
225
|
-
Detect & preserve adds/deletes
|
226
|
-
Correctly handle values across multiple constellations or in no constellation
|
227
|
-
Verbalisation
|
228
|
-
SOON Add readings to API
|
229
|
-
Redo all verbalisation to use readings
|
230
|
-
Use existing verbalise for to_s
|
231
|
-
Ensure that all objects and classes verbalise and to_s
|
232
|
-
SOON verbalise Role Value Array
|
233
|
-
verbalise takes optional "verbalisation context" object
|
234
|
-
Which objects have already been verbalised
|
235
|
-
What role names and/or subscripts have been assigned
|
236
|
-
Possible to implement as a single-pass process?
|
237
|
-
Queries
|
238
|
-
Query DSL/API in Ruby?
|
239
|
-
CQL Query conversion to SQL (via Ruby?)
|
240
|
-
Constellation boundaries
|
241
|
-
Record unpopulated roles and object types during query execution (nil != mu)
|
242
|
-
Hard vs soft boundary (Auto-fetch vs exception)
|
243
|
-
RDBMS Platform Support
|
244
|
-
DataObjects (SQL Server, MySQL, PostgreSQL, Oracle, DB2)
|
245
|
-
Enumerate tables instead of needing "table" keyword
|
246
|
-
Log changes to allow update
|
247
|
-
|
248
|
-
Database reverse engineering
|
249
|
-
Read Linda Bird's PhD thesis
|
250
|
-
Extract raw schema info
|
251
|
-
Tables
|
252
|
-
Columns & types
|
253
|
-
Null constraints
|
254
|
-
Unique & primary keys
|
255
|
-
Foreign keys
|
256
|
-
Check constraints
|
257
|
-
Naming Heuristics
|
258
|
-
Rails
|
259
|
-
Intuition (FK naming)
|
260
|
-
Load Rails models
|
261
|
-
Detect pluralisation
|
262
|
-
intuit common reference modes (e.g. thing_ID)
|
263
|
-
Examine data for likely FKs
|
264
|
-
count, min, max, median, distinct, count(NULL)
|
265
|
-
Check non-violation of possible FKs:
|
266
|
-
select count(*) where not exists ...
|
267
|
-
Decompose to elementary form
|
268
|
-
Schema transform by manual selection (GUI?)
|
269
|
-
Deabsorb (incl to use existing type)
|
270
|
-
Alias name
|
271
|
-
Project subclass using discriminator
|
272
|
-
... other transforms
|
273
|
-
|
274
|
-
Test stubs/mocks
|
275
|
-
Quality/usage metrics
|
276
|
-
Mock API
|
277
|
-
Mock data
|
278
|
-
Use sample population as test data
|
279
|
-
incorporate Faker, Machinist, etc
|
280
|
-
|
281
|
-
Packaging and documentation
|
282
|
-
Split into multiple gems?
|
283
|
-
|
284
|
-
Example models
|
285
|
-
Convert microformat RDF: http://microformats.org/about, http://www.data-vocabulary.org/
|
286
|
-
|
287
|
-
APRIMO
|
288
|
-
Overall design
|
289
|
-
Subscription, list/search models, friends
|
290
|
-
Diagram view
|
291
|
-
CQL view
|
292
|
-
Object type browser
|
293
|
-
Object Types
|
294
|
-
Fact Types
|
295
|
-
Constraints
|
296
|
-
Instance data
|
297
|
-
Query builder
|
298
|
-
AJAX
|
299
|
-
Design JSON API
|
300
|
-
Server
|
301
|
-
Stand-alone???
|
302
|
-
Metamodel Diagrams
|
303
|
-
Convert from metamodel to JSON
|
304
|
-
Database
|
305
|
-
Derived Fact Types
|
306
|
-
Constellation declarations
|
307
|
-
Process models
|
308
|
-
Units
|
@@ -1,162 +0,0 @@
|
|
1
|
-
module ActiveFacts
|
2
|
-
module CQL
|
3
|
-
class Compiler < ActiveFacts::CQL::Parser
|
4
|
-
class Definition
|
5
|
-
# Make a JoinNode for every variable present in these clauses
|
6
|
-
def build_join_nodes(clauses_list)
|
7
|
-
debug :join, "Building join nodes" do
|
8
|
-
join = @constellation.Join(:new)
|
9
|
-
all_variables_in_clauses(clauses_list).
|
10
|
-
each do |variable|
|
11
|
-
debug :join, "Creating join node #{join.all_join_node.size} for #{variable.inspect}"
|
12
|
-
variable.join_node = @constellation.JoinNode(join, join.all_join_node.size, :object_type => variable.player)
|
13
|
-
if literal = variable.refs.detect{|r| r.literal}
|
14
|
-
if literal.kind_of?(ActiveFacts::CQL::Compiler::VarRef)
|
15
|
-
literal = literal.literal
|
16
|
-
end
|
17
|
-
unit = @constellation.Unit.detect{|k, v| [v.name, v.plural_name].include? literal.unit} if literal.unit
|
18
|
-
variable.join_node.value = [literal.literal.to_s, literal.is_a?(String), unit]
|
19
|
-
end
|
20
|
-
end
|
21
|
-
join
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def build_all_join_steps(clauses_list)
|
26
|
-
roles_by_variable = {}
|
27
|
-
debug :join, "Building join steps" do
|
28
|
-
clauses_list.each do |clause|
|
29
|
-
next if clause.is_naked_object_type
|
30
|
-
build_join_steps(clause, roles_by_variable)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
roles_by_variable
|
34
|
-
end
|
35
|
-
|
36
|
-
def build_join_steps clause, roles_by_variable = {}, objectification_node = nil
|
37
|
-
join_roles = []
|
38
|
-
incidental_roles = []
|
39
|
-
debug :join, "Creating join Role Sequence for #{clause.inspect} with #{clause.var_refs.size} role refs" do
|
40
|
-
objectification_step = nil
|
41
|
-
clause.var_refs.each do |var_ref|
|
42
|
-
# These var_refs are the Compiler::VarRefs, which have associated Metamodel::RoleRefs,
|
43
|
-
# but we need to create JoinRoles for those roles.
|
44
|
-
# REVISIT: JoinRoles may need to save residual_adjectives
|
45
|
-
variable = var_ref.variable
|
46
|
-
role = (var_ref && var_ref.role) || (var_ref.role_ref && var_ref.role_ref.role)
|
47
|
-
join_role = nil
|
48
|
-
|
49
|
-
debugger unless clause.fact_type
|
50
|
-
if (clause.fact_type.entity_type)
|
51
|
-
# This clause is of an objectified fact type.
|
52
|
-
# We need a join step from this role to the phantom role, but not
|
53
|
-
# for a role that has only one var_ref (this one) in their variable.
|
54
|
-
# Create the JoinNode and JoinRole in any case though.
|
55
|
-
refs_count = variable.refs.size
|
56
|
-
objectification_ref_count = 0
|
57
|
-
if var_ref.nested_clauses
|
58
|
-
var_ref.nested_clauses.each do |ojc|
|
59
|
-
objectification_ref_count += ojc.var_refs.select{|var_ref| var_ref.variable.refs.size > 1}.size
|
60
|
-
end
|
61
|
-
end
|
62
|
-
refs_count += objectification_ref_count
|
63
|
-
|
64
|
-
debug :join, "Creating Join Node #{var_ref.inspect} (counts #{refs_count}/#{objectification_ref_count}) and objectification Join Step for #{var_ref.inspect}" do
|
65
|
-
|
66
|
-
raise "Internal error: Trying to add role of #{role.object_type.name} to join node for #{variable.join_node.object_type.name}" unless variable.join_node.object_type == role.object_type
|
67
|
-
join_role = @constellation.JoinRole(variable.join_node, role)
|
68
|
-
|
69
|
-
if (refs_count <= 1) # Our work here is done if there are no other refs
|
70
|
-
if objectification_step
|
71
|
-
join_role.join_step = objectification_step
|
72
|
-
else
|
73
|
-
incidental_roles << join_role
|
74
|
-
end
|
75
|
-
next
|
76
|
-
end
|
77
|
-
|
78
|
-
join_roles << join_role
|
79
|
-
unless objectification_node
|
80
|
-
# This is an implicit objectification, just the FT clause, not ET(where ...clause...)
|
81
|
-
# We need to create a JoinNode for this object, even though it has no VarRefs
|
82
|
-
join = variable.join_node.join
|
83
|
-
debug :join, "Creating JN#{join.all_join_node.size} for #{clause.fact_type.entity_type.name} in objectification"
|
84
|
-
objectification_node = @constellation.JoinNode(join, join.all_join_node.size, :object_type => clause.fact_type.entity_type)
|
85
|
-
end
|
86
|
-
raise "Internal error: Trying to add role of #{role.implicit_fact_type.all_role.single.object_type.name} to join node for #{objectification_node.object_type.name}" unless objectification_node.object_type == role.implicit_fact_type.all_role.single.object_type
|
87
|
-
|
88
|
-
irole = role.implicit_fact_type.all_role.single
|
89
|
-
raise "Internal error: Trying to add role of #{irole.object_type.name} to join node for #{objectification_node.object_type.name}" unless objectification_node.object_type == irole.object_type
|
90
|
-
objectification_role = @constellation.JoinRole(objectification_node, role.implicit_fact_type.all_role.single)
|
91
|
-
objectification_step = @constellation.JoinStep(objectification_role, join_role, :fact_type => role.implicit_fact_type)
|
92
|
-
debug :join, "New #{objectification_step.describe}"
|
93
|
-
debug :join, "Associating #{incidental_roles.map(&:describe)*', '} incidental roles with #{objectification_step.describe}" if incidental_roles.size > 0
|
94
|
-
incidental_roles.each { |jr| jr.join_step = objectification_step }
|
95
|
-
incidental_roles = []
|
96
|
-
join_roles = []
|
97
|
-
end
|
98
|
-
else
|
99
|
-
debug :join, "Creating VarRef for #{var_ref.inspect}" do
|
100
|
-
# REVISIT: If there's an implicit subtyping join here, create it; then always raise the error here.
|
101
|
-
# I don't want to do this for now because the verbaliser will always verbalise all join steps.
|
102
|
-
if variable.join_node.object_type != role.object_type and
|
103
|
-
0 == (variable.join_node.object_type.supertypes_transitive & role.object_type.supertypes_transitive).size
|
104
|
-
raise "Internal error: Trying to add role of #{role.object_type.name} to join node #{variable.join_node.ordinal} for #{variable.join_node.object_type.name} in '#{clause.fact_type.default_reading}'"
|
105
|
-
end
|
106
|
-
raise "Internal error: Trying to add role of #{role.object_type.name} to join node #{variable.join_node.ordinal} for #{variable.join_node.object_type.name}" unless variable.join_node.object_type == role.object_type
|
107
|
-
begin
|
108
|
-
join_role = @constellation.JoinRole(variable.join_node, role)
|
109
|
-
rescue ArgumentError => e
|
110
|
-
join_role = @constellation.JoinRole(variable.join_node, role)
|
111
|
-
end
|
112
|
-
join_roles << join_role
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
if var_ref.nested_clauses
|
117
|
-
# We are looking at a role whose player is an objectification of a fact type,
|
118
|
-
# which will have ImplicitFactTypes for each role.
|
119
|
-
# Each of these ImplicitFactTypes has a single phantom role played by the objectifying entity type
|
120
|
-
# One of these phantom roles is likely to be the subject of an objectification join step.
|
121
|
-
var_ref.nested_clauses.each do |r|
|
122
|
-
debug :join, "Building objectification join for #{var_ref.nested_clauses.inspect}" do
|
123
|
-
build_join_steps r, roles_by_variable, variable.join_node
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
roles_by_variable[variable] = [role, join_role]
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
if join_roles.size > 0
|
132
|
-
end_node = join_roles[-1].join_node
|
133
|
-
if !clause.fact_type.entity_type and role = clause.fact_type.all_role.single
|
134
|
-
# Don't give the ImplicitBoolean a join_node. We can live without one, for now.
|
135
|
-
# The Join Step will have a duplicate node, and the fact type will tell us what's happening
|
136
|
-
join_roles << join_roles[0]
|
137
|
-
end
|
138
|
-
# We aren't talking about objectification here, so there must be exactly two roles.
|
139
|
-
raise "REVISIT: Internal error constructing join for #{clause.inspect}" if join_roles.size != 2
|
140
|
-
js = @constellation.JoinStep(join_roles[0], join_roles[1], :fact_type => clause.fact_type)
|
141
|
-
debug :join, "New Join Step #{js.describe}"
|
142
|
-
debug :join, "Associating #{incidental_roles.map(&:describe)*', '} incidental roles with #{js.describe}" if incidental_roles.size > 0
|
143
|
-
incidental_roles.each { |jr| jr.join_step = js }
|
144
|
-
end
|
145
|
-
roles_by_variable
|
146
|
-
end
|
147
|
-
|
148
|
-
# Return the unique array of all variables in these clauses, including in objectification joins
|
149
|
-
def all_variables_in_clauses clauses
|
150
|
-
clauses.map do |clause|
|
151
|
-
clause.var_refs.map do |var_ref|
|
152
|
-
raise "Variable reference #{var_ref.inspect} is not bound to a variable" unless var_ref.variable
|
153
|
-
[var_ref.variable] + (var_ref.nested_clauses ? all_variables_in_clauses(var_ref.nested_clauses) : [])
|
154
|
-
end
|
155
|
-
end.
|
156
|
-
flatten.
|
157
|
-
uniq
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|