activefacts-metamodel 1.7.2 → 1.8.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.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/Gemfile +3 -2
- data/Rakefile +17 -0
- data/activefacts-metamodel.gemspec +3 -3
- data/cql/Metamodel.cql +79 -69
- data/images/Compositions.png +0 -0
- data/images/Concepts.png +0 -0
- data/images/Constraints.png +0 -0
- data/images/ContextNote.png +0 -0
- data/images/Diagrams.png +0 -0
- data/images/Language.png +0 -0
- data/images/LinkFactTypes.png +0 -0
- data/images/Objects.png +0 -0
- data/images/Populations.png +0 -0
- data/images/Queries.png +0 -0
- data/images/Units.png +0 -0
- data/images/ValueConstraints.png +0 -0
- data/images/ValueTypes.png +0 -0
- data/lib/activefacts/metamodel/extensions.rb +127 -138
- data/lib/activefacts/metamodel/metamodel.rb +17 -8
- data/lib/activefacts/metamodel/version.rb +1 -1
- data/orm/Metamodel.orm +3471 -3154
- metadata +35 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e18edf07c9d30ebe02c45d63b87d1dabc328bcc0
|
4
|
+
data.tar.gz: 775315e7031db7f4b6f30cdf0efbac0cef5e2547
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37f78ca38e9bfa027e90114db134f23b022ae0bb6d8b45f28460cb63ce4d728a54df61f9d0fe104ad55a5b80a8b8c776fd4dd70b24e863144c55f3911d0c519c
|
7
|
+
data.tar.gz: 1efd187a64997af03320b3efb48e068f4ea7ac037bffcf5765e92eded11b88ff1ba136fd196cd6cdf78d0a89b382f6a89485189d2c24e3198a6f2d8a70f9d341
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
# Specify your gem's dependencies in activefacts-metamodel.gemspec
|
4
3
|
gemspec
|
5
|
-
|
4
|
+
|
5
|
+
if ENV['PWD'] =~ %r{\A#{ENV['HOME']}/work}
|
6
|
+
$stdout.puts "Using work area gems for #{File.basename(File.dirname(__FILE__))} from activefacts-metamodel"
|
6
7
|
gem 'activefacts-api', path: '/Users/cjh/work/activefacts/api'
|
7
8
|
# gem 'activefacts-api', git: 'git://github.com/cjheath/activefacts-api.git'
|
8
9
|
end
|
data/Rakefile
CHANGED
@@ -1,6 +1,23 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rspec/core/rake_task"
|
3
|
+
require "pp"
|
3
4
|
|
4
5
|
RSpec::Core::RakeTask.new(:spec)
|
5
6
|
|
6
7
|
task :default => :spec
|
8
|
+
|
9
|
+
task :bump do
|
10
|
+
path = File.expand_path('../lib/activefacts/metamodel/version.rb', __FILE__)
|
11
|
+
lines = File.open(path) do |fp| fp.readlines; end
|
12
|
+
File.open(path, "w") do |fp|
|
13
|
+
fp.write(
|
14
|
+
lines.map do |line|
|
15
|
+
line.gsub(/(VERSION *= *"[0-9.]*\.)([0-9]+)"\n/) do
|
16
|
+
version = "#{$1}#{$2.to_i+1}"
|
17
|
+
puts "Version bumped to #{version}\""
|
18
|
+
version+"\"\n"
|
19
|
+
end
|
20
|
+
end*''
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
@@ -20,9 +20,9 @@ This gem provides the core representations for the Fact Modeling tools of Active
|
|
20
20
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
|
-
spec.add_development_dependency "bundler", "~> 1.10.
|
23
|
+
spec.add_development_dependency "bundler", ">= 1.10", "~> 1.10.6"
|
24
24
|
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
-
spec.add_development_dependency "rspec"
|
25
|
+
spec.add_development_dependency "rspec", "~> 3.3"
|
26
26
|
|
27
|
-
spec.add_runtime_dependency "activefacts-api"
|
27
|
+
spec.add_runtime_dependency "activefacts-api", ">= 1.8", "~> 1.8.4"
|
28
28
|
end
|
data/cql/Metamodel.cql
CHANGED
@@ -53,6 +53,17 @@ Coefficient is identified by Numerator and Denominator and Coefficient is precis
|
|
53
53
|
Coefficient has one Denominator,
|
54
54
|
Coefficient is precise;
|
55
55
|
|
56
|
+
Component is identified by Guid where
|
57
|
+
Component has one Guid,
|
58
|
+
Guid is of at most one Component;
|
59
|
+
Component projects at most one Name;
|
60
|
+
|
61
|
+
Composition is identified by Guid where
|
62
|
+
Composition has one Guid,
|
63
|
+
Guid is of at most one Composition;
|
64
|
+
Composition is called one Name,
|
65
|
+
Name is of at most one Composition;
|
66
|
+
|
56
67
|
Concept is identified by Guid where
|
57
68
|
Concept has one Guid,
|
58
69
|
Guid is of at most one Concept;
|
@@ -75,6 +86,8 @@ Context Note has one Discussion,
|
|
75
86
|
Context Note applies to at most one relevant-Concept,
|
76
87
|
Concept has Context Note;
|
77
88
|
|
89
|
+
Discriminator is a kind of Component;
|
90
|
+
|
78
91
|
Enforcement is identified by Constraint where
|
79
92
|
Constraint requires at most one Enforcement,
|
80
93
|
Enforcement applies to one Constraint;
|
@@ -92,6 +105,8 @@ Fact is of one Fact Type;
|
|
92
105
|
Implication Rule is identified by its Name;
|
93
106
|
Concept is implied by at most one Implication Rule;
|
94
107
|
|
108
|
+
Indicator is a kind of Component;
|
109
|
+
|
95
110
|
Instance is identified by Concept where
|
96
111
|
Instance is an instance of one Concept;
|
97
112
|
Instance objectifies at most one Fact,
|
@@ -103,6 +118,10 @@ Location is identified by X and Y where
|
|
103
118
|
Location is at one X,
|
104
119
|
Location is at one Y;
|
105
120
|
|
121
|
+
Mapping is a kind of Component;
|
122
|
+
Mapping (as Parent) contains Component (as Member) [acyclic, stronglyintransitive],
|
123
|
+
Member belongs to at most one Parent;
|
124
|
+
|
106
125
|
Presence Constraint is a kind of Constraint;
|
107
126
|
Presence Constraint has at most one max-Frequency restricted to {1..};
|
108
127
|
Presence Constraint has at most one min-Frequency restricted to {2..};
|
@@ -128,6 +147,7 @@ Role is identified by Fact Type and Ordinal where
|
|
128
147
|
Fact Type contains Role,
|
129
148
|
Role fills one Ordinal,
|
130
149
|
Ordinal applies to Role;
|
150
|
+
Indicator indicates one Role played;
|
131
151
|
Link Fact Type has one implying-Role,
|
132
152
|
implying-Role implies at most one Link Fact Type;
|
133
153
|
Ring Constraint has at most one other-Role,
|
@@ -154,6 +174,8 @@ Role Value is identified by Fact and Role where
|
|
154
174
|
Instance plays Role Value,
|
155
175
|
Role Value is of one Instance;
|
156
176
|
|
177
|
+
Scoping is a kind of Mapping;
|
178
|
+
|
157
179
|
Set Constraint is a kind of Constraint;
|
158
180
|
|
159
181
|
Shape is identified by Guid where
|
@@ -229,6 +251,12 @@ Vocabulary contains Constraint,
|
|
229
251
|
Vocabulary includes Unit,
|
230
252
|
Unit is in one Vocabulary;
|
231
253
|
|
254
|
+
Absorption is a kind of Mapping;
|
255
|
+
Absorption traverses to one child-Role;
|
256
|
+
Absorption traverses from one parent-Role;
|
257
|
+
Absorption is matched by at most one reverse-Absorption;
|
258
|
+
Absorption flattens;
|
259
|
+
|
232
260
|
Aggregation is where
|
233
261
|
Variable is bound to Aggregate over aggregated-Variable,
|
234
262
|
Aggregate of aggregated-Variable is bound as one Variable;
|
@@ -244,6 +272,12 @@ Bound is identified by Value and Bound is inclusive where
|
|
244
272
|
Value is of at least one Bound,
|
245
273
|
Bound is inclusive;
|
246
274
|
|
275
|
+
Composite is identified by Mapping where
|
276
|
+
Mapping projects at most one Composite,
|
277
|
+
Composite consists of one Mapping;
|
278
|
+
Composition contains Composite,
|
279
|
+
Composite belongs to one Composition;
|
280
|
+
|
247
281
|
Constraint Shape is a kind of Shape;
|
248
282
|
Constraint Shape is for one Constraint;
|
249
283
|
|
@@ -266,15 +300,30 @@ Diagram is identified by Vocabulary and Name where
|
|
266
300
|
Diagram is called one Name,
|
267
301
|
Name is of Diagram;
|
268
302
|
|
303
|
+
Discriminated Role is where
|
304
|
+
Discriminator distinguishes Role using one Value,
|
305
|
+
Role is indicated by Value for Discriminator;
|
306
|
+
|
269
307
|
Fact Type Shape is a kind of Shape;
|
270
308
|
Fact Type Shape has at most one Display Role Names Setting;
|
271
309
|
Fact Type Shape is for one Fact Type,
|
272
310
|
Fact Type has Fact Type Shape;
|
273
311
|
Fact Type Shape has at most one Rotation Setting;
|
274
312
|
|
313
|
+
Injection is a kind of Mapping;
|
314
|
+
|
315
|
+
Mirror Role is a kind of Role;
|
316
|
+
Mirror Role is for at most one Role (as Base Role),
|
317
|
+
Base Role implies at most one Mirror Role;
|
318
|
+
|
275
319
|
Model Note Shape is a kind of Shape;
|
276
320
|
Model Note Shape is for one Context Note;
|
277
321
|
|
322
|
+
Nesting is where
|
323
|
+
Absorption is nested under index-Role in Ordinal position,
|
324
|
+
Absorption in Ordinal position is nested under one Role,
|
325
|
+
Role keys nesting of Absorption at Ordinal priority;
|
326
|
+
|
278
327
|
ORM Diagram is a kind of Diagram;
|
279
328
|
Shape is in one ORM Diagram,
|
280
329
|
ORM Diagram includes Shape;
|
@@ -283,6 +332,7 @@ Object Type is identified by Vocabulary and Name where
|
|
283
332
|
Object Type belongs to one Vocabulary,
|
284
333
|
Object Type is called one Name;
|
285
334
|
Instance is of one Object Type;
|
335
|
+
Mapping represents one Object Type;
|
286
336
|
Object Type is an instance of one Concept;
|
287
337
|
Object Type uses at most one Pronoun;
|
288
338
|
Object Type plays Role,
|
@@ -374,8 +424,8 @@ Allowed Range is where
|
|
374
424
|
Domain Object Type is a kind of Object Type;
|
375
425
|
|
376
426
|
Entity Type is a kind of Domain Object Type;
|
377
|
-
Entity Type
|
378
|
-
Fact Type is
|
427
|
+
Entity Type objectifies at most one Fact Type,
|
428
|
+
Fact Type is objectified as at most one Entity Type;
|
379
429
|
|
380
430
|
Type Inheritance is a kind of Fact Type identified by Subtype and Supertype where
|
381
431
|
Entity Type (as Subtype) is subtype of super-Entity Type (as Supertype) [acyclic, intransitive],
|
@@ -408,11 +458,14 @@ Value Type Parameter Restriction is where
|
|
408
458
|
Value Type Parameter applies to Value Type;
|
409
459
|
Value Type Parameter Restriction has one Value;
|
410
460
|
|
411
|
-
Implicit Boolean Value Type is a kind of Value Type;
|
412
|
-
|
413
461
|
/*
|
414
462
|
* Constraints:
|
415
463
|
*/
|
464
|
+
either Component belongs to Mapping(1) or Component is a Mapping(2) that projects Composite but not both;
|
465
|
+
for each Component exactly one of these holds:
|
466
|
+
Component is a Mapping,
|
467
|
+
Component is an Indicator,
|
468
|
+
Component is a Discriminator;
|
416
469
|
for each Concept exactly one of these holds:
|
417
470
|
Object Type is an instance of Concept,
|
418
471
|
Fact Type is an instance of Concept,
|
@@ -424,12 +477,18 @@ for each Concept exactly one of these holds:
|
|
424
477
|
Fact is an instance of Concept,
|
425
478
|
Population is an instance of Concept,
|
426
479
|
Query is an instance of Concept;
|
480
|
+
either Constraint Shape is a Ring Constraint Shape or Constraint Shape is a Value Constraint Shape but not both;
|
427
481
|
for each Constraint exactly one of these holds:
|
428
482
|
Constraint is a Set Constraint,
|
429
483
|
Constraint is a Presence Constraint,
|
430
484
|
Constraint is a Ring Constraint,
|
431
485
|
Constraint is a Value Constraint;
|
432
486
|
either Domain Object Type is a Value Type or Domain Object Type is an Entity Type but not both;
|
487
|
+
for each Mapping exactly one of these holds:
|
488
|
+
Mapping is an Absorption,
|
489
|
+
Mapping is an Injection,
|
490
|
+
Mapping is a Scoping,
|
491
|
+
Mapping projects Composite;
|
433
492
|
for each Role Sequence exactly one of these holds:
|
434
493
|
Role Sequence is for Reading,
|
435
494
|
Presence Constraint covers Role Sequence,
|
@@ -451,6 +510,9 @@ either Unit is fundamental or Unit is derived from base-Unit but not both;
|
|
451
510
|
either Value Constraint Shape is for Object Type Shape or Value Constraint Shape is for Role Display but not both;
|
452
511
|
either Value Constraint allows Value Range or Value Constraint requires matching Regular Expression but not both;
|
453
512
|
either Value Constraint constrains Value Type or Value Constraint applies to Role but not both;
|
513
|
+
for each Mapping at most one of these holds:
|
514
|
+
Mapping is an Absorption that flattens,
|
515
|
+
Mapping projects Composite;
|
454
516
|
for each Instance at most one of these holds:
|
455
517
|
Instance has Value,
|
456
518
|
Instance objectifies Fact;
|
@@ -466,19 +528,32 @@ Step specifies Fact Type that contains Role
|
|
466
528
|
Variable is for Object Type that plays Role
|
467
529
|
if and only if
|
468
530
|
Variable is restricted by Role of Step;
|
531
|
+
/*
|
532
|
+
Absorption traverses from parent Role that is played by Object Type and Mapping(1) is a kind of Component(2) and Mapping(1) is an Absorption
|
533
|
+
only if Member belongs to Mapping(2) that represents Object Type;
|
534
|
+
Absorption traverses to child Role that is played by Object Type and Absorption is a kind of Mapping(2)
|
535
|
+
only if Mapping(1) represents Object Type;
|
536
|
+
*/
|
469
537
|
Presence Constraint is preferred identifier
|
470
538
|
only if Presence Constraint has max Frequency;
|
471
539
|
Value Type has Scale
|
472
540
|
only if Value Type has Length;
|
473
541
|
Variable matches nesting over Step
|
474
542
|
only if Variable is for Object Type and Step specifies Fact Type;
|
543
|
+
each Absorption(1) occurs at most one time in
|
544
|
+
Absorption(2) is matched by reverse Absorption(1);
|
475
545
|
either Agreement was reached by Agent or Agreement was on Date;
|
546
|
+
// either Component projects Name or Component is some Absorption that flattens;
|
476
547
|
each Concept occurs at most one time in
|
477
548
|
Object Type is an instance of Concept;
|
478
549
|
each Concept occurs at most one time in
|
479
550
|
Population is an instance of Concept;
|
480
551
|
each Concept occurs at most one time in
|
481
552
|
Role is an instance of Concept;
|
553
|
+
each Discriminator occurs at least 2 times in
|
554
|
+
Discriminator distinguishes Role using Value;
|
555
|
+
each combination Discriminator, Value occurs one time in
|
556
|
+
Discriminator distinguishes Role using Value;
|
482
557
|
each combination Entity Type(1), Type Inheritance occurs at most one time in
|
483
558
|
Entity Type(1) is subtype of super Entity Type(2),
|
484
559
|
Type Inheritance provides identification;
|
@@ -500,68 +575,3 @@ each combination Vocabulary, Name occurs at most one time in
|
|
500
575
|
each combination Vocabulary, Name occurs at most one time in
|
501
576
|
Unit is in Vocabulary,
|
502
577
|
Unit is called Name;
|
503
|
-
|
504
|
-
/*
|
505
|
-
* Compositions
|
506
|
-
*/
|
507
|
-
Component is identified by Guid where
|
508
|
-
Component has one Guid,
|
509
|
-
Guid is of at most one Component;
|
510
|
-
Component projects at most one Name;
|
511
|
-
|
512
|
-
Composition is identified by Guid where
|
513
|
-
Composition has one Guid,
|
514
|
-
Guid is of at most one Composition;
|
515
|
-
Composition is called one Name,
|
516
|
-
Name is of at most one Composition;
|
517
|
-
|
518
|
-
Discriminator is a kind of Component;
|
519
|
-
|
520
|
-
Indicator is a kind of Component;
|
521
|
-
Indicator indicates one Role played;
|
522
|
-
|
523
|
-
Mapping is a kind of Component;
|
524
|
-
Mapping contains Component (as Member) [acyclic, stronglyintransitive],
|
525
|
-
Member belongs to at most one parent-Mapping;
|
526
|
-
Mapping represents one Object Type;
|
527
|
-
|
528
|
-
Nesting is a kind of Mapping;
|
529
|
-
|
530
|
-
Absorption is a kind of Mapping;
|
531
|
-
Absorption traverses to one child-Role;
|
532
|
-
Absorption is nested under at most one index-Role;
|
533
|
-
Absorption traverses from one parent-Role;
|
534
|
-
Absorption flattens;
|
535
|
-
|
536
|
-
Composite is identified by Mapping where
|
537
|
-
Mapping projects at most one Composite,
|
538
|
-
Composite consists of one Mapping;
|
539
|
-
Composition contains Composite,
|
540
|
-
Composite belongs to one Composition;
|
541
|
-
|
542
|
-
Discriminated Role is where
|
543
|
-
Discriminator distinguishes Role using one Value,
|
544
|
-
Role is indicated by Value for Discriminator;
|
545
|
-
|
546
|
-
Injection is a kind of Mapping;
|
547
|
-
for each Component exactly one of these holds:
|
548
|
-
that Component is a Mapping,
|
549
|
-
that Component is an Indicator,
|
550
|
-
that Component is a Discriminator;
|
551
|
-
either Component is a Mapping(2) that projects some Composite or Component belongs to parent Mapping(1) but not both;
|
552
|
-
for each Mapping exactly one of these holds:
|
553
|
-
that Mapping is an Absorption,
|
554
|
-
that Mapping is an Injection,
|
555
|
-
that Mapping is a Nesting,
|
556
|
-
that Mapping projects some Composite;
|
557
|
-
for each Mapping at most one of these holds:
|
558
|
-
that Mapping projects some Composite,
|
559
|
-
that Mapping is an Absorption and that Absorption flattens;
|
560
|
-
some Mapping represents some Object Type
|
561
|
-
if and only if
|
562
|
-
that Mapping is an Absorption that traverses to some child- Role and that Role is played by that Object Type;
|
563
|
-
either Component projects some Name or that Component flattens;
|
564
|
-
each Discriminator occurs at least 2 times in
|
565
|
-
Discriminator distinguishes Role using Value;
|
566
|
-
each combination Discriminator, Value occurs one time in
|
567
|
-
Discriminator distinguishes Role using Value;
|
Binary file
|
data/images/Concepts.png
ADDED
Binary file
|
Binary file
|
Binary file
|
data/images/Diagrams.png
ADDED
Binary file
|
data/images/Language.png
ADDED
Binary file
|
Binary file
|
data/images/Objects.png
ADDED
Binary file
|
Binary file
|
data/images/Queries.png
ADDED
Binary file
|
data/images/Units.png
ADDED
Binary file
|
Binary file
|
Binary file
|
@@ -232,27 +232,10 @@ module ActiveFacts
|
|
232
232
|
end.flatten.compact.uniq
|
233
233
|
end
|
234
234
|
|
235
|
-
def implicit_boolean_type vocabulary
|
236
|
-
@constellation.ImplicitBooleanValueType[[vocabulary.identifying_role_values, "_ImplicitBooleanValueType"]] or
|
237
|
-
@constellation.ImplicitBooleanValueType(vocabulary.identifying_role_values, "_ImplicitBooleanValueType", :concept => [:new, :implication_rule => 'unary'])
|
238
|
-
end
|
239
|
-
|
240
|
-
# This entity type has just objectified a fact type. Create the necessary ImplicitFactTypes with phantom roles
|
241
|
-
def create_implicit_fact_type_for_unary
|
242
|
-
role = all_role.single
|
243
|
-
return if role.link_fact_type # Already exists
|
244
|
-
# NORMA doesn't create an implicit fact type here, rather the fact type has an implicit extra role, so looks like a binary
|
245
|
-
# We only do it when the unary fact type is not objectified
|
246
|
-
link_fact_type = @constellation.LinkFactType(:new, :implying_role => role)
|
247
|
-
link_fact_type.concept.implication_rule = 'unary'
|
248
|
-
entity_type = @entity_type || implicit_boolean_type(role.object_type.vocabulary)
|
249
|
-
phantom_role = @constellation.Role(link_fact_type, 0, :object_type => entity_type, :concept => :new)
|
250
|
-
end
|
251
|
-
|
252
235
|
def reading_preferably_starting_with_role role, negated = false
|
253
236
|
all_reading_by_ordinal.detect do |reading|
|
254
|
-
reading.text =~ /\{\d\}/ and
|
255
|
-
reading.role_sequence.all_role_ref_in_order[$1.to_i].role == role and
|
237
|
+
reading.text =~ /\{(\d+)\}/ and
|
238
|
+
reading.role_sequence.all_role_ref_in_order[$1.to_i].role.base_role == role and
|
256
239
|
reading.is_negative == !!negated
|
257
240
|
end || preferred_reading(negated)
|
258
241
|
end
|
@@ -273,28 +256,19 @@ module ActiveFacts
|
|
273
256
|
end
|
274
257
|
|
275
258
|
class Role
|
276
|
-
|
277
|
-
|
259
|
+
# Mirror Role defines this, but it's more convenient not to have to type-check.
|
260
|
+
# A Role that's not a Mirror Role is its own base role.
|
261
|
+
def base_role
|
262
|
+
self
|
278
263
|
end
|
279
264
|
|
280
|
-
|
281
|
-
|
282
|
-
all_role_ref.detect{|rr|
|
283
|
-
rs = rr.role_sequence
|
284
|
-
rs.all_role_ref.size == 1 and
|
285
|
-
rs.all_presence_constraint.each{|pc|
|
286
|
-
return pc if pc.max_frequency == 1
|
287
|
-
}
|
288
|
-
}
|
289
|
-
nil
|
290
|
-
end
|
291
|
-
|
292
|
-
# Is there are internal uniqueness constraint on this role only?
|
293
|
-
def unique
|
294
|
-
uniqueness_constraint ? true : false
|
265
|
+
def describe(highlight = nil)
|
266
|
+
object_type.name + (self == highlight ? "*" : "")
|
295
267
|
end
|
296
268
|
|
297
269
|
def is_mandatory
|
270
|
+
# REVISIT: An objectification role is always mandatory
|
271
|
+
# REVISIT: Handle mirror roles
|
298
272
|
return fact_type.implying_role.is_mandatory if fact_type.is_a?(LinkFactType)
|
299
273
|
all_role_ref.detect{|rr|
|
300
274
|
rs = rr.role_sequence
|
@@ -312,18 +286,31 @@ module ActiveFacts
|
|
312
286
|
# Return true if this role is functional (has only one instance wrt its player)
|
313
287
|
# A role in an objectified fact type is deemed to refer to the implicit role of the objectification.
|
314
288
|
def is_functional
|
289
|
+
# REVISIT: Handle mirror and objectification roles
|
315
290
|
fact_type.entity_type or
|
316
291
|
fact_type.all_role.size != 2 or
|
317
|
-
|
292
|
+
uniqueness_constraint
|
318
293
|
end
|
319
294
|
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
295
|
+
# Find any internal uniqueness constraint on this role only
|
296
|
+
def uniqueness_constraint
|
297
|
+
base_role.all_role_ref.detect{|rr|
|
298
|
+
rs = rr.role_sequence
|
299
|
+
rs.all_role_ref.size == 1 and
|
300
|
+
rs.all_presence_constraint.detect do |pc|
|
324
301
|
pc.max_frequency == 1 and !pc.enforcement # Alethic uniqueness constraint
|
325
302
|
end
|
326
|
-
|
303
|
+
}
|
304
|
+
end
|
305
|
+
|
306
|
+
# Is there are internal uniqueness constraint on this role only?
|
307
|
+
def is_unique
|
308
|
+
# REVISIT: Handle objectification roles
|
309
|
+
uniqueness_constraint ? true : false
|
310
|
+
end
|
311
|
+
|
312
|
+
def unique
|
313
|
+
raise "REVISIT: unique is deprecated. Call is_unique instead"
|
327
314
|
end
|
328
315
|
|
329
316
|
def name
|
@@ -346,7 +333,7 @@ module ActiveFacts
|
|
346
333
|
name_array =
|
347
334
|
if role.fact_type.all_role.size == 1
|
348
335
|
if role.fact_type.is_a?(LinkFactType)
|
349
|
-
"#{role.object_type.name}
|
336
|
+
"#{role.object_type.name} objectification role for #{role.fact_type.role.object_type.name}"
|
350
337
|
else
|
351
338
|
role.fact_type.preferred_reading.text.gsub(/\{[0-9]\}/,'').strip.split(/\s/)
|
352
339
|
end
|
@@ -516,7 +503,7 @@ module ActiveFacts
|
|
516
503
|
all_supertypes = supertypes_transitive
|
517
504
|
trace :pi, "PI roles must be played by one of #{all_supertypes.map(&:name)*", "}" if all_supertypes.size > 1
|
518
505
|
all_role.each{|role|
|
519
|
-
next unless role.
|
506
|
+
next unless role.is_unique || fact_type
|
520
507
|
ftroles = Array(role.fact_type.all_role)
|
521
508
|
|
522
509
|
# Skip roles in ternary and higher fact types, they're objectified, and in unaries, they can't identify us.
|
@@ -604,7 +591,7 @@ module ActiveFacts
|
|
604
591
|
pi = possible_pi
|
605
592
|
end
|
606
593
|
else
|
607
|
-
|
594
|
+
debugger
|
608
595
|
trace :pi, "No PI found for #{name}"
|
609
596
|
end
|
610
597
|
end
|
@@ -663,15 +650,69 @@ module ActiveFacts
|
|
663
650
|
candidates[0] # REVISIT: This might not be the closest supertype
|
664
651
|
end
|
665
652
|
|
666
|
-
|
667
|
-
|
653
|
+
def add_supertype(supertype, is_identifying_supertype, assimilation)
|
654
|
+
inheritance_fact = constellation.TypeInheritance(self, supertype, :concept => :new)
|
655
|
+
|
656
|
+
inheritance_fact.assimilation = assimilation
|
657
|
+
|
658
|
+
# Create a reading:
|
659
|
+
sub_role = constellation.Role(inheritance_fact, 0, :object_type => self, :concept => :new)
|
660
|
+
super_role = constellation.Role(inheritance_fact, 1, :object_type => supertype, :concept => :new)
|
661
|
+
|
662
|
+
rs = constellation.RoleSequence(:new)
|
663
|
+
constellation.RoleRef(rs, 0, :role => sub_role)
|
664
|
+
constellation.RoleRef(rs, 1, :role => super_role)
|
665
|
+
constellation.Reading(inheritance_fact, 0, :role_sequence => rs, :text => "{0} is a kind of {1}", :is_negative => false)
|
666
|
+
|
667
|
+
rs2 = constellation.RoleSequence(:new)
|
668
|
+
constellation.RoleRef(rs2, 0, :role => super_role)
|
669
|
+
constellation.RoleRef(rs2, 1, :role => sub_role)
|
670
|
+
# Decide in which order to include is a/is an. Provide both, but in order.
|
671
|
+
n = 'aeioh'.include?(sub_role.object_type.name.downcase[0]) ? 'n' : ''
|
672
|
+
constellation.Reading(inheritance_fact, 2, :role_sequence => rs2, :text => "{0} is a#{n} {1}", :is_negative => false)
|
673
|
+
|
674
|
+
if is_identifying_supertype
|
675
|
+
inheritance_fact.provides_identification = true
|
676
|
+
end
|
677
|
+
|
678
|
+
# Create uniqueness constraints over the subtyping fact type.
|
679
|
+
p1rs = constellation.RoleSequence(:new)
|
680
|
+
constellation.RoleRef(p1rs, 0).role = sub_role
|
681
|
+
pc1 = constellation.PresenceConstraint(:new, :vocabulary => vocabulary)
|
682
|
+
pc1.name = "#{name}MustHaveSupertype#{supertype.name}"
|
683
|
+
pc1.role_sequence = p1rs
|
684
|
+
pc1.is_mandatory = true # A subtype instance must have a supertype instance
|
685
|
+
pc1.min_frequency = 1
|
686
|
+
pc1.max_frequency = 1
|
687
|
+
pc1.is_preferred_identifier = false
|
688
|
+
trace :constraint, "Made new subtype PC GUID=#{pc1.concept.guid} min=1 max=1 over #{p1rs.describe}"
|
689
|
+
|
690
|
+
p2rs = constellation.RoleSequence(:new)
|
691
|
+
constellation.RoleRef(p2rs, 0).role = super_role
|
692
|
+
pc2 = constellation.PresenceConstraint(:new, :vocabulary => vocabulary)
|
693
|
+
pc2.name = "#{supertype.name}MayBeA#{name}"
|
694
|
+
pc2.role_sequence = p2rs
|
695
|
+
pc2.is_mandatory = false
|
696
|
+
pc2.min_frequency = 0
|
697
|
+
pc2.max_frequency = 1
|
698
|
+
# The supertype role often identifies the subtype:
|
699
|
+
pc2.is_preferred_identifier = inheritance_fact.provides_identification
|
700
|
+
trace :supertype, "identification of #{name} via supertype #{supertype.name} was #{inheritance_fact.provides_identification ? '' : 'not '}added"
|
701
|
+
trace :constraint, "Made new supertype PC GUID=#{pc2.concept.guid} min=1 max=1 over #{p2rs.describe}"
|
702
|
+
end
|
703
|
+
|
704
|
+
# This entity type has just objectified a fact type.
|
705
|
+
# Create the necessary ImplicitFactTypes with objectification and mirror roles
|
706
|
+
def create_link_fact_types
|
668
707
|
fact_type.all_role.map do |role|
|
669
|
-
next if role.
|
708
|
+
next if role.mirror_role_as_base_role # Already exists
|
670
709
|
link_fact_type = @constellation.LinkFactType(:new, :implying_role => role)
|
671
|
-
link_fact_type
|
672
|
-
|
673
|
-
|
674
|
-
|
710
|
+
objectification_role = @constellation.Role(link_fact_type, 0, :object_type => self, :concept => :new)
|
711
|
+
mirror_role = @constellation.MirrorRole(link_fact_type, 1, :concept => :new, :object_type => role.object_type, :base_role => role)
|
712
|
+
|
713
|
+
link_fact_type.concept.implication_rule =
|
714
|
+
objectification_role.concept.implication_rule =
|
715
|
+
mirror_role.concept.implication_rule = 'objectification'
|
675
716
|
link_fact_type
|
676
717
|
end
|
677
718
|
end
|
@@ -968,10 +1009,6 @@ module ActiveFacts
|
|
968
1009
|
def is_objectification_step
|
969
1010
|
!!objectification_variable
|
970
1011
|
end
|
971
|
-
|
972
|
-
def external_fact_type
|
973
|
-
fact_type.is_a?(LinkFactType) ? fact_type.role.fact_type : fact_type
|
974
|
-
end
|
975
1012
|
end
|
976
1013
|
|
977
1014
|
class Variable
|
@@ -1066,99 +1103,50 @@ module ActiveFacts
|
|
1066
1103
|
end
|
1067
1104
|
|
1068
1105
|
class LinkFactType
|
1069
|
-
def
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1106
|
+
def all_reading
|
1107
|
+
if super.size == 0
|
1108
|
+
# REVISIT: Should we create reading orders independently?
|
1109
|
+
# No user-defined readings have been defined, so it's time to stop being lazy:
|
1110
|
+
objectification_role, mirror_role = *all_role_in_order
|
1111
|
+
rs = constellation.RoleSequence(:new)
|
1112
|
+
rr0 = constellation.RoleRef(rs, 0, :role => objectification_role)
|
1113
|
+
rr1 = constellation.RoleRef(rs, 1, :role => mirror_role)
|
1114
|
+
r0 = constellation.Reading(self, 0, :role_sequence => rs, :text => "{0} involves {1}", :is_negative => false) # REVISIT: This assumes English!
|
1115
|
+
r1 = constellation.Reading(self, 1, :role_sequence => rs, :text => "{1} is involved in {0}", :is_negative => false)
|
1116
|
+
end
|
1117
|
+
@all_reading
|
1077
1118
|
end
|
1119
|
+
end
|
1078
1120
|
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1121
|
+
class MirrorRole
|
1122
|
+
def is_mandatory
|
1123
|
+
true # An objectified fact type must have a player for each role
|
1082
1124
|
end
|
1083
1125
|
|
1084
|
-
def
|
1085
|
-
|
1086
|
-
[ ImplicitReading.new(
|
1087
|
-
self,
|
1088
|
-
implying_role.fact_type.entity_type ? "{0} involves {1}" : implying_role.fact_type.default_reading+" Boolean"
|
1089
|
-
)
|
1090
|
-
] +
|
1091
|
-
Array(implying_role.fact_type.entity_type ? ImplicitReading.new(self, "{1} is involved in {0}") : nil)
|
1126
|
+
def is_unique
|
1127
|
+
true # A mirror role exists is played exactly once for each objectification
|
1092
1128
|
end
|
1093
1129
|
|
1094
|
-
def
|
1095
|
-
|
1130
|
+
def is_functional
|
1131
|
+
true
|
1096
1132
|
end
|
1097
1133
|
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
attr_reader :is_negative # Never true
|
1102
|
-
|
1103
|
-
def initialize(fact_type, text)
|
1104
|
-
@fact_type = fact_type
|
1105
|
-
@text = text
|
1106
|
-
end
|
1107
|
-
|
1108
|
-
class ImplicitReadingRoleSequence
|
1109
|
-
class ImplicitReadingRoleRef
|
1110
|
-
attr_reader :role
|
1111
|
-
attr_reader :role_sequence
|
1112
|
-
def initialize(role, role_sequence)
|
1113
|
-
@role = role
|
1114
|
-
@role_sequence = role_sequence
|
1115
|
-
end
|
1116
|
-
def variable; nil; end
|
1117
|
-
def play; nil; end
|
1118
|
-
def leading_adjective; nil; end
|
1119
|
-
def trailing_adjective; nil; end
|
1120
|
-
def describe
|
1121
|
-
@role.object_type.name
|
1122
|
-
end
|
1123
|
-
end
|
1124
|
-
|
1125
|
-
def initialize roles
|
1126
|
-
@role_refs = roles.map{|role| ImplicitReadingRoleRef.new(role, self) }
|
1127
|
-
end
|
1128
|
-
|
1129
|
-
def all_role_ref
|
1130
|
-
@role_refs
|
1131
|
-
end
|
1132
|
-
def all_role_ref_in_order
|
1133
|
-
@role_refs
|
1134
|
-
end
|
1135
|
-
def describe
|
1136
|
-
'('+@role_refs.map(&:describe)*', '+')'
|
1137
|
-
end
|
1138
|
-
def all_reading
|
1139
|
-
[]
|
1140
|
-
end
|
1141
|
-
end
|
1142
|
-
|
1143
|
-
def role_sequence
|
1144
|
-
ImplicitReadingRoleSequence.new([@fact_type.implying_role, @fact_type.all_role.single])
|
1145
|
-
end
|
1146
|
-
|
1147
|
-
def ordinal; 0; end
|
1134
|
+
def uniqueness_constraint
|
1135
|
+
raise "A MirrorRole should not be asked for its uniqueness constraints"
|
1136
|
+
end
|
1148
1137
|
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
end
|
1138
|
+
%w{all_ring_constraint_as_other_role all_ring_constraint all_role_value role_value_constraint mirror_role_as_base_role
|
1139
|
+
}.each do |accessor|
|
1140
|
+
define_method(accessor.to_sym) do
|
1141
|
+
base_role.send(accessor.to_sym)
|
1142
|
+
end
|
1143
|
+
define_method("#{accessor}=".to_sym) do |*a|
|
1144
|
+
raise "REVISIT: It's a bad idea to try to set #{accessor} for a MirrorRole"
|
1145
|
+
end
|
1158
1146
|
end
|
1159
1147
|
end
|
1160
1148
|
|
1161
|
-
# Some queries must be over the proximate roles, some over the counterpart roles.
|
1149
|
+
# Some queries in constraints must be over the proximate roles, some over the counterpart roles.
|
1162
1150
|
# Return the common superclass of the appropriate roles, and the actual roles
|
1163
1151
|
def self.plays_over roles, options = :both # Or :proximate, :counterpart
|
1164
1152
|
# If we can stay inside this objectified FT, there's no query:
|
@@ -1204,7 +1192,8 @@ module ActiveFacts
|
|
1204
1192
|
if fact_type.entity_type
|
1205
1193
|
objectification_role_supertypes =
|
1206
1194
|
fact_type.entity_type.supertypes_transitive+object_type.supertypes_transitive
|
1207
|
-
|
1195
|
+
# Find the objectification role here:
|
1196
|
+
objectification_role = role.link_fact_type.all_role.detect{|r| !r.is_a?(MirrorRole)}
|
1208
1197
|
else
|
1209
1198
|
objectification_role_supertypes = counterpart_role_supertypes
|
1210
1199
|
objectification_role = counterpart_role
|