activefacts-metamodel 1.9.5 → 1.9.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1f7f44626a2f296fa2526060928c417750b40470
4
- data.tar.gz: 8eafb8c56e8d769a71f63109126b85f1c8c6380a
3
+ metadata.gz: 7b1f0ae97a0a31369e5681e2310eb8deeb663390
4
+ data.tar.gz: d5cbf6dc32862b3982eb8c2f26aa28fb033d2afe
5
5
  SHA512:
6
- metadata.gz: 9e8f19d52180aad423c425b6277d8f13daf33e3cb66e812185e85c6796507ffb0d63623c7d81a4f6e7e61f815387f5acede0b4f7ea203c0fccc4bf711965263d
7
- data.tar.gz: c2dab88c77154b6eef9ef0cf38d8fd26ca405f2bfa1ddb03e1b04ab56d1819ca66574725179947ada99ebfa70ebeb0c3684446e6aa6c75be031d30d23bc9c6b3
6
+ metadata.gz: 9031e41a724f5eb9c57aa7aa8f5ea2c8f22d0de1b6c9ea8808b6ebb062b31450cff6f08b8b19b744868fcee2b3f3db8d51cac187a0073292f2d044ee6bb78944
7
+ data.tar.gz: d9922fc63374fb60f7d553e0251c6d91b0a6dfd1d0c784f17a0c5a4ce03fab7b1e9fa2cf9eb51adb19ba509aa5b9e73524aee4c0bad12f8725e20eb5ff545398
data/Gemfile CHANGED
@@ -2,7 +2,11 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- if ENV['PWD'] =~ %r{\A#{ENV['HOME']}/work}i
6
- $stderr.puts "Using work area gems for #{File.basename(File.dirname(__FILE__))} from activefacts-metamodel"
7
- gem 'activefacts-api', path: '../api'
5
+ this_file = File.absolute_path(__FILE__)
6
+ if this_file =~ %r{\A#{ENV['HOME']}}i
7
+ dir = File.dirname(File.dirname(this_file))
8
+ $stderr.puts "Using work area gems in #{dir} from activefacts-metamodel"
9
+ gem 'activefacts-cql', path: dir+'/cql'
10
+ gem 'activefacts-compositions', path: dir+'/compositions'
11
+ gem 'activefacts-api', path: dir+'/api'
8
12
  end
data/Rakefile CHANGED
@@ -36,15 +36,7 @@ end
36
36
  desc "Generate new Ruby from the CQL file"
37
37
  task :ruby do
38
38
  system %q{
39
- afgen --ruby cql/Metamodel.cql 2>/dev/null |
40
- sed '2a\
41
- module ActiveFacts
42
-
43
- 3s/:://
44
- 3,$s/^/ /
45
- $a\
46
- end
47
- ' > metamodel.rb
39
+ schema_compositor --binary --ruby=scope=ActiveFacts cql/Metamodel.cql > metamodel.rb &&
40
+ diff -ub lib/activefacts/metamodel/metamodel.rb metamodel.rb
48
41
  }
49
- system "diff -ub lib/activefacts/metamodel/metamodel.rb metamodel.rb"
50
42
  end
@@ -24,6 +24,8 @@ This gem provides the core representations for the Fact Modeling tools of Active
24
24
  spec.add_development_dependency "rake", "~> 10.0"
25
25
  spec.add_development_dependency "rspec", "~> 3.3"
26
26
 
27
- spec.add_runtime_dependency "activefacts-api", "~> 1", ">= 1.9.4"
28
- spec.add_development_dependency "activefacts", "~> 1", "~> 1.8"
27
+ spec.add_development_dependency "activefacts-compositions", ">= 1.9.6" # Needed for schema_compositor to emit Ruby from CQL
28
+ spec.add_development_dependency "activefacts", "~> 1", ">= 1.8" # Needed to emit CQL from ORM (and check it from CQL)
29
+
30
+ spec.add_runtime_dependency "activefacts-api", "~> 1", ">= 1.9.5"
29
31
  end
data/cql/Metamodel.cql CHANGED
@@ -446,11 +446,6 @@ Composite is identified by Mapping where
446
446
  Composition contains Composite,
447
447
  Composite belongs to one Composition;
448
448
 
449
- Scoping is a kind of Mapping;
450
- Injection is a kind of Mapping;
451
- Value Field is a kind of Injection;
452
- Surrogate Key is a kind of Injection;
453
-
454
449
  Absorption is a kind of Mapping;
455
450
  Absorption traverses to one child-Role;
456
451
  Absorption traverses from one parent-Role;
@@ -473,6 +468,26 @@ some Object Type is involved in some Full Absorption that applies to some Absorp
473
468
  that Mapping represents that Object Type;
474
469
  */
475
470
 
471
+ /*
472
+ * Composition constraint categories
473
+ */
474
+ Leaf Constraint is where
475
+ Component has leaf-Constraint,
476
+ Constraint applies to Component;
477
+
478
+ Local Constraint is where
479
+ Composite contains local-Constraint,
480
+ local-Constraint connects leaves of Composite;
481
+
482
+ Spanning Constraint is where
483
+ Composite has spanning-Constraint,
484
+ Constraint spans Composite;
485
+
486
+ Scoping is a kind of Mapping;
487
+ Injection is a kind of Mapping;
488
+ Value Field is a kind of Injection;
489
+ Surrogate Key is a kind of Injection;
490
+
476
491
  /* Access Paths */
477
492
  Access Path is identified by Guid where
478
493
  Access Path has one Guid,
@@ -334,7 +334,18 @@ module ActiveFacts
334
334
  end
335
335
 
336
336
  def unary_name
337
- fact_type.preferred_reading.text.gsub(/\{[0-9]\}/,'').words.titlewords*' '
337
+ fact_type.
338
+ preferred_reading.
339
+ text.
340
+ gsub(/(.*)\{[0-9]\}(.*)/) do
341
+ if $1.empty? or $2.empty?
342
+ "#{$1} #{$2}"
343
+ else
344
+ "#{$1} #{object_type.name} #{$2}"
345
+ end
346
+ end.
347
+ words.
348
+ titlewords*' '
338
349
  end
339
350
 
340
351
  def is_link_role
@@ -359,11 +370,26 @@ module ActiveFacts
359
370
  nil # raise "counterpart roles are undefined in n-ary fact types"
360
371
  end
361
372
  end
373
+
374
+ # return an array of all the constraints on this role (not including ValueConstraint on a ValueType player)
375
+ def all_constraint
376
+ (
377
+ Array(role_value_constraint) +
378
+ all_role_ref.to_a.flat_map do |rr|
379
+ rr.role_sequence.all_presence_constraint.to_a +
380
+ rr.role_sequence.all_subset_constraint_as_superset_role_sequence +
381
+ rr.role_sequence.all_subset_constraint_as_subset_role_sequence +
382
+ rr.role_sequence.all_set_comparison_roles.map(&:set_comparison_constraint)
383
+ end +
384
+ all_ring_constraint.to_a +
385
+ all_ring_constraint_as_other_role.to_a
386
+ ).uniq
387
+ end
362
388
  end
363
389
 
364
390
  class RoleRef
365
391
  def describe
366
- role_name
392
+ role.name + " in (#{role.fact_type.default_reading})"
367
393
  end
368
394
 
369
395
  def preferred_reference
@@ -434,7 +460,9 @@ module ActiveFacts
434
460
  class RoleSequence
435
461
  def describe(highlighted_role_ref = nil)
436
462
  "("+
437
- all_role_ref.sort_by{|rr| rr.ordinal}.map{|rr| rr.describe + (highlighted_role_ref == rr ? '*' : '') }*", "+
463
+ all_role_ref_in_order.map{|rr| rr.role.name + (highlighted_role_ref == rr ? '*' : '') }*", " +
464
+ " in " +
465
+ all_role_ref.map(&:role).map(&:fact_type).uniq.map(&:default_reading).map(&:inspect)*', ' +
438
466
  ")"
439
467
  end
440
468
 
@@ -457,6 +485,10 @@ module ActiveFacts
457
485
  end
458
486
 
459
487
  class ValueType
488
+ def all_supertype
489
+ Array(supertype)
490
+ end
491
+
460
492
  def supertypes_transitive
461
493
  [self] + (supertype ? supertype.supertypes_transitive : [])
462
494
  end
@@ -694,6 +726,10 @@ module ActiveFacts
694
726
  }
695
727
  end
696
728
 
729
+ def all_supertype
730
+ supertypes
731
+ end
732
+
697
733
  # An array of all direct subtypes
698
734
  def all_subtype
699
735
  all_type_inheritance_as_supertype.map(&:subtype)
@@ -935,6 +971,10 @@ module ActiveFacts
935
971
  all_allowed_range.single.to_s
936
972
  end
937
973
  end
974
+
975
+ def all_constrained_role
976
+ Array(role_as_role_value_constraint) # Empty unless it's a role value constraint
977
+ end
938
978
  end
939
979
 
940
980
  class AllowedRange
@@ -1009,16 +1049,35 @@ module ActiveFacts
1009
1049
  def covers_role role
1010
1050
  role_sequence.all_role_ref.map(&:role).include?(role)
1011
1051
  end
1052
+
1053
+ def all_constrained_role
1054
+ role_sequence.all_role_ref.map(&:role)
1055
+ end
1012
1056
  end
1013
1057
 
1014
1058
  class SubsetConstraint
1015
1059
  def describe
1016
1060
  'SubsetConstraint(' +
1017
- subset_role_sequence.describe
1018
- ' < ' +
1061
+ subset_role_sequence.describe +
1062
+ ' only if ' +
1019
1063
  superset_role_sequence.describe +
1020
1064
  ')'
1021
1065
  end
1066
+
1067
+ def all_constrained_role
1068
+ subset_role_sequence.all_role_ref.map(&:role) +
1069
+ superset_role_sequence.all_role_ref.map(&:role)
1070
+ end
1071
+ end
1072
+
1073
+ class SetComparisonRoles
1074
+ def describe
1075
+ "("+
1076
+ role_sequence.all_role_ref_in_order.map{|rr| rr.role.name }*", " +
1077
+ " in " +
1078
+ role_sequence.all_role_ref.map(&:role).map(&:fact_type).uniq.map(&:default_reading).map(&:inspect)*', ' +
1079
+ ")"
1080
+ end
1022
1081
  end
1023
1082
 
1024
1083
  class SetComparisonConstraint
@@ -1033,8 +1092,26 @@ module ActiveFacts
1033
1092
  end*',' +
1034
1093
  ')'
1035
1094
  end
1095
+
1096
+ def all_constrained_role
1097
+ all_set_comparison_roles.map(&:role_sequence).flat_map(&:all_role_ref).map(&:role).uniq
1098
+ end
1036
1099
  end
1037
1100
 
1101
+ class SetEqualityConstraint
1102
+ def describe
1103
+ all_set_comparison_roles.map(&:describe) * " if and only if "
1104
+ end
1105
+ end
1106
+
1107
+ class SetExclusionConstraint
1108
+ def describe
1109
+ (is_mandatory ? "exactly one of " : "at most one of ") +
1110
+ all_set_comparison_roles.map(&:describe) * " or "
1111
+ end
1112
+ end
1113
+
1114
+
1038
1115
  class RingConstraint
1039
1116
  def describe
1040
1117
  'RingConstraint(' +
@@ -1044,6 +1121,10 @@ module ActiveFacts
1044
1121
  role.fact_type.default_reading +
1045
1122
  ')'
1046
1123
  end
1124
+
1125
+ def all_constrained_role
1126
+ [role, other_role]
1127
+ end
1047
1128
  end
1048
1129
 
1049
1130
  class TypeInheritance
@@ -1438,16 +1519,19 @@ module ActiveFacts
1438
1519
  "Composite #{mapping.inspect}"
1439
1520
  end
1440
1521
 
1522
+ def all_index
1523
+ all_access_path.
1524
+ select{|ap| ap.is_a?(Index)}.
1525
+ sort_by{|ap| [ap.composite_as_primary_index ? 0 : 1] + Array(ap.name)+ap.all_index_field.map(&:inspect) } # REVISIT: Fix hack for stable ordering
1526
+ end
1527
+
1441
1528
  def show_trace
1442
1529
  trace :composition, inspect do
1443
1530
  trace :composition?, "Columns" do
1444
1531
  mapping.show_trace
1445
1532
  end
1446
1533
 
1447
- indices =
1448
- all_access_path.
1449
- select{|ap| ap.is_a?(Index)}.
1450
- sort_by{|ap| [ap.composite_as_primary_index ? 0 : 1] + Array(ap.name)+ap.all_index_field.map(&:inspect) } # REVISIT: Fix hack for stable ordering
1534
+ indices = all_index
1451
1535
  unless indices.empty?
1452
1536
  trace :composition, "Indices" do
1453
1537
  indices.each do |ap|
@@ -1590,6 +1674,14 @@ module ActiveFacts
1590
1674
  end
1591
1675
  end
1592
1676
  end
1677
+
1678
+ def is_mandatory
1679
+ true
1680
+ end
1681
+
1682
+ def path_mandatory
1683
+ true
1684
+ end
1593
1685
  end
1594
1686
 
1595
1687
  class Nesting
@@ -1707,6 +1799,22 @@ module ActiveFacts
1707
1799
  end
1708
1800
  end
1709
1801
 
1802
+ def all_role
1803
+ ([child_role, parent_role] + all_nesting.map(&:index_role)).flat_map{|role| [role, role.base_role]}.uniq
1804
+ end
1805
+
1806
+ def value_constraints
1807
+ return [] unless object_type.is_a?(ValueType)
1808
+ object_type.supertypes_transitive.flat_map{|vt| Array(vt.value_constraint)}
1809
+ end
1810
+
1811
+ def is_mandatory
1812
+ parent_role.is_mandatory
1813
+ end
1814
+
1815
+ def path_mandatory
1816
+ is_mandatory && parent.path_mandatory
1817
+ end
1710
1818
  end
1711
1819
 
1712
1820
  class FullAbsorption
@@ -1723,6 +1831,14 @@ module ActiveFacts
1723
1831
  def show_trace
1724
1832
  trace :composition, "#{ordinal ? "#{ordinal}: " : ''}#{inspect} #{name ? "(as #{name.inspect})" : ''}"
1725
1833
  end
1834
+
1835
+ def all_role
1836
+ [role, role.base_role].uniq
1837
+ end
1838
+
1839
+ def is_mandatory
1840
+ false
1841
+ end
1726
1842
  end
1727
1843
 
1728
1844
  class Discriminator
@@ -1733,6 +1849,10 @@ module ActiveFacts
1733
1849
  def show_trace
1734
1850
  trace :composition, "#{ordinal ? "#{ordinal}: " : ''}#{inspect} #{name ? " (as #{name.inspect})" : ''}"
1735
1851
  end
1852
+
1853
+ def all_role
1854
+ all_discriminated_role.map(&:role).flat_map{|role| [role, role.base_role]}.uniq
1855
+ end
1736
1856
  end
1737
1857
 
1738
1858
  class ValueField
@@ -1881,6 +2001,18 @@ module ActiveFacts
1881
2001
  (parent ? parent.path+[self] : [self])
1882
2002
  end
1883
2003
 
2004
+ def is_mandatory
2005
+ parent.is_mandatory
2006
+ end
2007
+
2008
+ def path_mandatory
2009
+ parent.path_mandatory
2010
+ end
2011
+
2012
+ def all_role
2013
+ []
2014
+ end
2015
+
1884
2016
  def rank_path
1885
2017
  (parent ? parent.rank_path+[ordinal] : [ordinal])
1886
2018
  end