activefacts-metamodel 1.7.2 → 1.8.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|