activefacts-generators 1.8.3 → 1.9.0

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.
@@ -8,23 +8,23 @@ module ActiveFacts
8
8
  module Generators
9
9
  module OOTraits
10
10
  module ObjectType
11
- # Map the ObjectType name to an OO class name
12
- def oo_type_name
13
- name.words.capcase
14
- end
11
+ # Map the ObjectType name to an OO class name
12
+ def oo_type_name
13
+ name.words.capcase
14
+ end
15
15
 
16
- # Map the OO class name to a default role name
17
- def oo_default_role_name
16
+ # Map the OO class name to a default role name
17
+ def oo_default_role_name
18
18
  name.words.snakecase
19
- end
19
+ end
20
20
  end
21
21
 
22
22
  module Role
23
- def oo_role_definition
23
+ def oo_role_definition
24
24
  return if fact_type.entity_type
25
25
 
26
26
  if fact_type.all_role.size == 1
27
- return " maybe :#{preferred_role_name}\n"
27
+ return " maybe :#{preferred_role_name}\n"
28
28
  elsif fact_type.all_role.size != 2
29
29
  # Shouldn't come here, except perhaps for an invalid model
30
30
  return # ternaries and higher are always objectified
@@ -55,8 +55,8 @@ module ActiveFacts
55
55
  counterpart_role_method = one_to_one ? role_method : "all_"+role_method
56
56
  # puts "---"+role.role_name if role.role_name
57
57
  if counterpart_role_name != counterpart_type.oo_default_role_name and
58
- role_method == self.object_type.oo_default_role_name
59
- # debugger
58
+ role_method == self.object_type.oo_default_role_name
59
+ # debugger
60
60
  counterpart_role_method += "_as_#{counterpart_role_name}"
61
61
  end
62
62
 
@@ -64,10 +64,10 @@ module ActiveFacts
64
64
  role_name = nil if role_name == object_type.oo_default_role_name
65
65
 
66
66
  as_binary(counterpart_role_name, counterpart_type, is_mandatory, one_to_one, nil, role_name, counterpart_role_method)
67
- end
67
+ end
68
68
  end
69
69
 
70
- include ActiveFacts::TraitInjector # Must be last in this module, after all submodules have been defined
70
+ include ActiveFacts::TraitInjector # Must be last in this module, after all submodules have been defined
71
71
  end
72
72
  end
73
73
  end
@@ -8,26 +8,26 @@ module ActiveFacts
8
8
  module Generators #:nodoc:
9
9
  module OrderedTraits
10
10
  module DumpedFlag
11
- attr_reader :ordered_dumped
11
+ attr_reader :ordered_dumped
12
12
 
13
- def ordered_dumped!
14
- @ordered_dumped = true
15
- end
13
+ def ordered_dumped!
14
+ @ordered_dumped = true
15
+ end
16
16
  end
17
17
 
18
18
  module ObjectType
19
- include DumpedFlag
19
+ include DumpedFlag
20
20
  end
21
21
 
22
22
  module FactType
23
- include DumpedFlag
23
+ include DumpedFlag
24
24
  end
25
25
 
26
26
  module Constraint
27
- include DumpedFlag
27
+ include DumpedFlag
28
28
  end
29
29
 
30
- include ActiveFacts::TraitInjector # Must be last in this module, after all submodules have been defined
30
+ include ActiveFacts::TraitInjector # Must be last in this module, after all submodules have been defined
31
31
  end
32
32
  end
33
33
  end
@@ -8,24 +8,24 @@ module ActiveFacts
8
8
  module Generators
9
9
  module RubyTraits
10
10
  module Vocabulary
11
- def prelude
12
- if @mapping == 'sql'
13
- require 'activefacts/rmap'
14
- @tables = self.tables
15
- end
16
-
17
- "require 'activefacts/api'\n" +
18
- (@mapping == 'sql' ? "require 'activefacts/rmap'\n" : '') +
19
- "\nmodule ::#{self.name}\n\n"
20
- end
21
-
22
- def finale
23
- "end"
24
- end
11
+ def prelude
12
+ if @mapping == 'sql'
13
+ require 'activefacts/rmap'
14
+ @tables = self.tables
15
+ end
16
+
17
+ "require 'activefacts/api'\n" +
18
+ (@mapping == 'sql' ? "require 'activefacts/rmap'\n" : '') +
19
+ "\nmodule ::#{self.name.words.capcase}\n\n"
20
+ end
21
+
22
+ def finale
23
+ "end"
24
+ end
25
25
  end
26
26
 
27
27
  module ObjectType
28
- def absorbed_roles
28
+ def absorbed_roles
29
29
  all_role.
30
30
  select do |role|
31
31
  role.fact_type.all_role.size <= 2 &&
@@ -33,41 +33,41 @@ module ActiveFacts
33
33
  end.
34
34
  sort_by do |role|
35
35
  r = role.fact_type.all_role.select{|r2| r2 != role}[0] || role
36
- r.preferred_role_name(self) + ':' + role.preferred_role_name(r.object_type)
36
+ r.preferred_role_name(self) + ':' + role.preferred_role_name(r.object_type)
37
37
  end
38
- end
39
-
40
- # Map the ObjectType name to a Ruby class name
41
- def ruby_type_name
42
- oo_type_name
43
- end
44
-
45
- # Map the Ruby class name to a default role name
46
- def ruby_default_role_name
47
- oo_default_role_name
48
- end
49
-
50
-
51
- def ruby_type_reference
52
- if !ordered_dumped
53
- '"'+name.gsub(/ /,'')+'"'
54
- else
55
- role_reference = name.gsub(/ /,'')
56
- end
57
- end
38
+ end
39
+
40
+ # Map the ObjectType name to a Ruby class name
41
+ def ruby_type_name
42
+ oo_type_name
43
+ end
44
+
45
+ # Map the Ruby class name to a default role name
46
+ def ruby_default_role_name
47
+ oo_default_role_name
48
+ end
49
+
50
+
51
+ def ruby_type_reference
52
+ if !ordered_dumped
53
+ '"'+name.gsub(/ /,'')+'"'
54
+ else
55
+ role_reference = name.gsub(/ /,'')
56
+ end
57
+ end
58
58
  end
59
59
 
60
60
  module Role
61
61
  def preferred_role_name(is_for = nil, &name_builder)
62
62
 
63
- if fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
64
- # Subtype and Supertype roles default to TitleCase names, and have no role_name to worry about:
65
- return (name_builder || proc {|names| names.titlecase}).call(object_type.name.words)
66
- end
63
+ if fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
64
+ # Subtype and Supertype roles default to TitleCase names, and have no role_name to worry about:
65
+ return (name_builder || proc {|names| names.titlecase}).call(object_type.name.words)
66
+ end
67
67
 
68
- name_builder ||= proc {|names| names.map(&:downcase)*'_' } # Make snake_case by default
68
+ name_builder ||= proc {|names| names.map(&:downcase)*'_' } # Make snake_case by default
69
69
 
70
- # Handle an objectified unary role:
70
+ # Handle an objectified unary role:
71
71
  if is_for && fact_type.entity_type == is_for && fact_type.all_role.size == 1
72
72
  return name_builder.call(object_type.name.words)
73
73
  end
@@ -80,131 +80,131 @@ module ActiveFacts
80
80
 
81
81
  if fact_type.all_role.size == 1
82
82
  return name_builder.call(
83
- role_name ?
84
- role_name.snakewords :
85
- reading.text.gsub(/ *\{0\} */,' ').gsub(/[- ]+/,'_').words
86
- )
83
+ role_name ?
84
+ role_name.words.snakewords :
85
+ reading.text.gsub(/ *\{0\} */,' ').gsub(/[- ]+/,'_').words
86
+ )
87
87
  end
88
88
 
89
- if role_name && role_name != ""
90
- role_words = [role_name]
91
- else
92
- role_words = []
89
+ if role_name && role_name != ""
90
+ role_words = [role_name]
91
+ else
92
+ role_words = []
93
93
 
94
- la = preferred_role_ref.leading_adjective
95
- role_words += la.words.snakewords if la && la != ""
94
+ la = preferred_role_ref.leading_adjective
95
+ role_words += la.words.snakewords if la && la != ""
96
96
 
97
- role_words += object_type.name.words.snakewords
97
+ role_words += object_type.name.words.snakewords
98
98
 
99
- ta = preferred_role_ref.trailing_adjective
100
- role_words += ta.words.snakewords if ta && ta != ""
101
- end
99
+ ta = preferred_role_ref.trailing_adjective
100
+ role_words += ta.words.snakewords if ta && ta != ""
101
+ end
102
102
 
103
103
  # n = role_words.map{|w| w.gsub(/([a-z])([A-Z]+)/,'\1_\2').downcase}*"_"
104
- n = role_words*'_'
104
+ n = role_words*'_'
105
105
  # trace "\tresult=#{n}"
106
106
  return name_builder.call(n.gsub(' ','_').split(/_/))
107
107
  end
108
108
 
109
- def as_binary(role_name, role_player, mandatory = nil, one_to_one = nil, readings = nil, other_role_name = nil, other_method_name = nil)
110
- ruby_role_name = ":"+role_name.words.snakecase
111
-
112
- # Find whether we need the name of the other role player, and whether it's defined yet:
113
- implied_role_name = role_player.name.gsub(/ /,'').sub(/^[a-z]/) {|i| i.upcase}
114
- if role_name.camelcase != implied_role_name
115
- # Only use Class name if it's not implied by the rolename
116
- role_reference = ":class => "+role_player.ruby_type_reference
117
- end
118
-
119
- other_role_name = ":counterpart => :"+other_role_name.gsub(/ /,'_') if other_role_name
120
-
121
- if vr = role_value_constraint
122
- value_restriction = ":restrict => #{vr}"
123
- end
124
-
125
- options = [
126
- ruby_role_name,
127
- role_reference,
128
- mandatory ? ":mandatory => true" : nil,
129
- readings,
130
- other_role_name,
131
- value_restriction
132
- ].compact
133
-
134
- debugger if ruby_role_name == 'astronomicalobject'
135
-
136
- line = " #{one_to_one ? "one_to_one" : "has_one" } #{options*', '} "
137
- if other_method_name
138
- line += " "*(48-line.length) if line.length < 48
139
- line += "\# See #{role_player.name.gsub(/ /,'')}.#{other_method_name}"
140
- end
141
- line+"\n"
142
- end
143
-
144
- def ruby_role_definition
145
- oo_role_definition
146
- end
109
+ def as_binary(role_name, role_player, mandatory = nil, one_to_one = nil, readings = nil, other_role_name = nil, other_method_name = nil)
110
+ ruby_role_name = ":"+role_name.words.snakecase
111
+
112
+ # Find whether we need the name of the other role player, and whether it's defined yet:
113
+ implied_role_name = role_player.name.gsub(/ /,'').sub(/^[a-z]/) {|i| i.upcase}
114
+ if role_name.camelcase != implied_role_name
115
+ # Only use Class name if it's not implied by the rolename
116
+ role_reference = ":class => "+role_player.ruby_type_reference
117
+ end
118
+
119
+ other_role_name = ":counterpart => :"+other_role_name.gsub(/ /,'_') if other_role_name
120
+
121
+ if vr = role_value_constraint
122
+ value_restriction = ":restrict => #{vr}"
123
+ end
124
+
125
+ options = [
126
+ ruby_role_name,
127
+ role_reference,
128
+ mandatory ? ":mandatory => true" : nil,
129
+ readings,
130
+ other_role_name,
131
+ value_restriction
132
+ ].compact
133
+
134
+ debugger if ruby_role_name == 'astronomicalobject'
135
+
136
+ line = " #{one_to_one ? "one_to_one" : "has_one" } #{options*', '} "
137
+ if other_method_name
138
+ line += " "*(48-line.length) if line.length < 48
139
+ line += "\# See #{role_player.name.gsub(/ /,'')}.#{other_method_name}"
140
+ end
141
+ line+"\n"
142
+ end
143
+
144
+ def ruby_role_definition
145
+ oo_role_definition
146
+ end
147
147
  end
148
148
 
149
149
  module ValueType
150
- def ruby_definition
151
- return if name == "_ImplicitBooleanValueType"
152
-
153
- ruby_length = length && length > 0 ? ":length => #{length}" : nil
154
- ruby_scale = scale && scale > 0 ? ":scale => #{scale}" : nil
155
- params = [ruby_length,ruby_scale].compact * ", "
156
-
157
- base_type = supertype || self
158
- base_type_name = base_type.ruby_type_name
159
- ruby_name = ruby_type_name
160
- if base_type_name == ruby_name
161
- base_type_name = '::'+base_type_name
162
- end
163
-
164
- " class #{ruby_name} < #{base_type_name}\n" +
165
- " value_type #{params}\n" +
166
- #emit_mapping self if is_table
167
- (value_constraint ?
168
- " restrict #{value_constraint.all_allowed_range_sorted.map{|ar| ar.to_s}*", "}\n" :
169
- ""
170
- ) +
171
- (unit ?
172
- " \# REVISIT: #{ruby_name} is in units of #{unit.name}\n" :
173
- ""
174
- ) +
175
- absorbed_roles.map do |role|
176
- role.ruby_role_definition
177
- end.
178
- compact*"" +
179
- " end\n\n"
180
- end
150
+ def ruby_definition
151
+ return if name == "_ImplicitBooleanValueType"
152
+
153
+ ruby_length = length && length > 0 ? ":length => #{length}" : nil
154
+ ruby_scale = scale && scale > 0 ? ":scale => #{scale}" : nil
155
+ params = [ruby_length,ruby_scale].compact * ", "
156
+
157
+ base_type = supertype || self
158
+ base_type_name = base_type.ruby_type_name
159
+ ruby_name = ruby_type_name
160
+ if base_type_name == ruby_name
161
+ base_type_name = '::'+base_type_name
162
+ end
163
+
164
+ " class #{ruby_name} < #{base_type_name}\n" +
165
+ " value_type #{params}\n" +
166
+ #emit_mapping self if is_table
167
+ (value_constraint ?
168
+ " restrict #{value_constraint.all_allowed_range_sorted.map{|ar| ar.to_s}*", "}\n" :
169
+ ""
170
+ ) +
171
+ (unit ?
172
+ " \# REVISIT: #{ruby_name} is in units of #{unit.name}\n" :
173
+ ""
174
+ ) +
175
+ absorbed_roles.map do |role|
176
+ role.ruby_role_definition
177
+ end.
178
+ compact*"" +
179
+ " end\n\n"
180
+ end
181
181
  end
182
182
 
183
183
  module FactType
184
184
  # An objectified fact type has internal roles that are always "has_one":
185
185
  def fact_roles
186
- raise "Fact #{describe} type is not objectified" unless entity_type
186
+ raise "Fact #{describe} type is not objectified" unless entity_type
187
187
  all_role.sort_by do |role|
188
- role.preferred_role_name(entity_type)
189
- end.
190
- map do |role|
191
- role_name = role.preferred_role_name(entity_type)
192
- one_to_one = role.all_role_ref.detect{|rr|
193
- rr.role_sequence.all_role_ref.size == 1 &&
194
- rr.role_sequence.all_presence_constraint.detect{|pc|
195
- pc.max_frequency == 1
196
- }
197
- }
198
- counterpart_role_method = (one_to_one ? "" : "all_") +
199
- entity_type.oo_default_role_name +
200
- (role_name != role.object_type.oo_default_role_name ? "_as_#{role_name}" : '')
201
- role.as_binary(role_name, role.object_type, true, one_to_one, nil, nil, counterpart_role_method)
202
- end.
203
- join('')
204
- end
188
+ role.preferred_role_name(entity_type)
189
+ end.
190
+ map do |role|
191
+ role_name = role.preferred_role_name(entity_type)
192
+ one_to_one = role.all_role_ref.detect{|rr|
193
+ rr.role_sequence.all_role_ref.size == 1 &&
194
+ rr.role_sequence.all_presence_constraint.detect{|pc|
195
+ pc.max_frequency == 1
196
+ }
197
+ }
198
+ counterpart_role_method = (one_to_one ? "" : "all_") +
199
+ entity_type.oo_default_role_name +
200
+ (role_name != role.object_type.oo_default_role_name ? "_as_#{role_name}" : '')
201
+ role.as_binary(role_name, role.object_type, true, one_to_one, nil, nil, counterpart_role_method)
202
+ end.
203
+ join('')
204
+ end
205
205
  end
206
206
 
207
- include ActiveFacts::TraitInjector # Must be last in this module, after all submodules have been defined
207
+ include ActiveFacts::TraitInjector # Must be last in this module, after all submodules have been defined
208
208
  end
209
209
  end
210
210
  end
@@ -9,43 +9,43 @@ module ActiveFacts
9
9
  module Generators
10
10
  module ScalaTraits
11
11
  module Vocabulary
12
- def scala_prelude
13
- title_name = name.words.titlecase
14
-
15
- "package model\n"+
16
- "\n"+
17
- "import scala.language.implicitConversions\n" +
18
- "\n" +
19
- "object #{title_name} extends LocalStorageConstellation with #{title_name}\n" +
20
- "\n" +
21
- "trait #{title_name} extends Model {\n" +
22
- # REVISIT: I think this next line should be model, not metaModel
23
- " val metaModel = new #{title_name}Model()\n" +
24
- "\n"
25
- end
26
-
27
- def scala_prelude_metamodel
28
- title_name = name.words.titlecase
29
- "class #{title_name}Model extends FBMModel with LocalStorageConstellation {\n" +
30
- " implicit val constellation: Constellation = this\n"
31
- end
32
-
33
- def scala_finale
34
- "}\n"+
35
- "\n"
36
- end
12
+ def scala_prelude
13
+ title_name = name.words.titlecase
14
+
15
+ "package model\n"+
16
+ "\n"+
17
+ "import scala.language.implicitConversions\n" +
18
+ "\n" +
19
+ "object #{title_name} extends LocalStorageConstellation with #{title_name}\n" +
20
+ "\n" +
21
+ "trait #{title_name} extends Model {\n" +
22
+ # REVISIT: I think this next line should be model, not metaModel
23
+ " val metaModel = new #{title_name}Model()\n" +
24
+ "\n"
25
+ end
26
+
27
+ def scala_prelude_metamodel
28
+ title_name = name.words.titlecase
29
+ "class #{title_name}Model extends FBMModel with LocalStorageConstellation {\n" +
30
+ " implicit val constellation: Constellation = this\n"
31
+ end
32
+
33
+ def scala_finale
34
+ "}\n"+
35
+ "\n"
36
+ end
37
37
  end
38
38
 
39
39
  module ObjectType
40
- # Map the ObjectType name to a Scala class name
41
- def scala_type_name
42
- oo_type_name
43
- end
40
+ # Map the ObjectType name to a Scala class name
41
+ def scala_type_name
42
+ oo_type_name
43
+ end
44
44
 
45
- # Map the Scala class name to a default role name
46
- def scala_default_role_name
47
- oo_default_role_name
48
- end
45
+ # Map the Scala class name to a default role name
46
+ def scala_default_role_name
47
+ oo_default_role_name
48
+ end
49
49
 
50
50
  def absorbed_roles
51
51
  all_role.
@@ -62,16 +62,16 @@ module ActiveFacts
62
62
 
63
63
  module Role
64
64
  def scala_preferred_role_name(is_for = nil, &name_builder)
65
- # REVISIT: Modify this to suit Scala
65
+ # REVISIT: Modify this to suit Scala
66
66
 
67
- if fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
68
- # Subtype and Supertype roles default to TitleCase names, and have no role_name to worry about:
69
- return (name_builder || proc {|names| names.titlecase}).call(object_type.name.words)
70
- end
67
+ if fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
68
+ # Subtype and Supertype roles default to TitleCase names, and have no role_name to worry about:
69
+ return (name_builder || proc {|names| names.titlecase}).call(object_type.name.words)
70
+ end
71
71
 
72
- name_builder ||= proc {|names| names.map(&:downcase)*'_' } # Make snake_case by default
72
+ name_builder ||= proc {|names| names.map(&:downcase)*'_' } # Make snake_case by default
73
73
 
74
- # Handle an objectified unary role:
74
+ # Handle an objectified unary role:
75
75
  if is_for && fact_type.entity_type == is_for && fact_type.all_role.size == 1
76
76
  return name_builder.call(object_type.name.words)
77
77
  end
@@ -84,304 +84,304 @@ module ActiveFacts
84
84
 
85
85
  if fact_type.all_role.size == 1
86
86
  return name_builder.call(
87
- role_name ?
88
- role_name.snakewords :
89
- reading.text.gsub(/ *\{0\} */,' ').gsub(/[- ]+/,'_').words
90
- )
87
+ role_name ?
88
+ role_name.snakewords :
89
+ reading.text.gsub(/ *\{0\} */,' ').gsub(/[- ]+/,'_').words
90
+ )
91
91
  end
92
92
 
93
- if role_name && role_name != ""
94
- role_words = [role_name]
95
- else
96
- role_words = []
93
+ if role_name && role_name != ""
94
+ role_words = [role_name]
95
+ else
96
+ role_words = []
97
97
 
98
- la = preferred_role_ref.leading_adjective
99
- role_words += la.words.snakewords if la && la != ""
98
+ la = preferred_role_ref.leading_adjective
99
+ role_words += la.words.snakewords if la && la != ""
100
100
 
101
- role_words += object_type.name.words.snakewords
101
+ role_words += object_type.name.words.snakewords
102
102
 
103
- ta = preferred_role_ref.trailing_adjective
104
- role_words += ta.words.snakewords if ta && ta != ""
105
- end
103
+ ta = preferred_role_ref.trailing_adjective
104
+ role_words += ta.words.snakewords if ta && ta != ""
105
+ end
106
106
 
107
107
  # n = role_words.map{|w| w.gsub(/([a-z])([A-Z]+)/,'\1_\2').downcase}*"_"
108
- n = role_words*'_'
108
+ n = role_words*'_'
109
109
  # trace "\tresult=#{n}"
110
110
  return name_builder.call(n.gsub(' ','_').split(/_/))
111
111
  end
112
112
 
113
- def scala_role_definition
114
- return if fact_type.entity_type
115
-
116
- if fact_type.all_role.size == 1
117
- scala_role_name = scala_preferred_role_name.words.camelcase
118
- return " val #{scala_role_name}: Boolean"
119
- elsif fact_type.all_role.size != 2
120
- # Shouldn't come here, except perhaps for an invalid model
121
- return # ternaries and higher are always objectified
122
- end
123
-
124
- return if fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
125
-
126
- other_role = fact_type.all_role.select{|r| r != self}[0]
127
- other_role_name = other_role.scala_preferred_role_name
128
- scala_role_name = other_role_name.words.camelcase
129
- other_type_name = other_role.object_type.name.words.titlecase
130
-
131
- if is_functional
132
- if is_mandatory
133
- # Define a getter for a mandatory value:
134
- " val #{scala_role_name}: #{other_type_name}"
135
- if !fact_type.is_existential
136
- " def #{scala_role_name}_=(_value: #{other_type_name}) = { #{scala_role_name} = _value }"
137
- end
138
- else
139
- # Define a getter for an optional value:
140
- # REVISIT: The role number here depends on the metamodel ordering of the fact type roles.
141
- # This likely should follow the role order of the preferred reading, from which the fact name is derived.
142
- # The code here collows the order of definition of the roles in the fact type,
143
- # which might not be the same as the order of the preferred reading:
144
- fact_name = fact_type.scala_name.titlecase
145
- role_number = fact_type.all_role_in_order.index(other_role)+1
146
-
147
- " def #{scala_role_name}: Option[#{other_type_name}] = {\n" +
148
- " constellation.getBinaryFact(metaModel.#{fact_name.words.camelcase}, this).map(x => {\n" +
149
- " x.head.asInstanceOf[FBMModel.BinaryFact].rolePlayers._#{role_number}.asInstanceOf[#{other_type_name}]\n" +
150
- " })\n" +
151
- " }\n" +
152
- if !fact_type.is_existential
153
- # Define a setter for an optional value:
154
- " def #{scala_role_name}_=(value: Option[#{other_type_name}]) = {\n" +
155
- " value match {\n" +
156
- " case None =>\n" +
157
- " case Some(m) => constellation.assertBinaryFact(#{fact_name.words.titlecase}(this, m))\n" +
158
- " }\n" +
159
- " }"
160
- else
161
- ''
162
- end
163
- end
164
- elsif other_role.object_type.fact_type
165
- # An objectified fact type
166
- <<"END"
113
+ def scala_role_definition
114
+ return if fact_type.entity_type
115
+
116
+ if fact_type.all_role.size == 1
117
+ scala_role_name = scala_preferred_role_name.words.camelcase
118
+ return " val #{scala_role_name}: Boolean"
119
+ elsif fact_type.all_role.size != 2
120
+ # Shouldn't come here, except perhaps for an invalid model
121
+ return # ternaries and higher are always objectified
122
+ end
123
+
124
+ return if fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
125
+
126
+ other_role = fact_type.all_role.select{|r| r != self}[0]
127
+ other_role_name = other_role.scala_preferred_role_name
128
+ scala_role_name = other_role_name.words.camelcase
129
+ other_type_name = other_role.object_type.name.words.titlecase
130
+
131
+ if is_functional
132
+ if is_mandatory
133
+ # Define a getter for a mandatory value:
134
+ " val #{scala_role_name}: #{other_type_name}"
135
+ if !fact_type.is_existential
136
+ " def #{scala_role_name}_=(_value: #{other_type_name}) = { #{scala_role_name} = _value }"
137
+ end
138
+ else
139
+ # Define a getter for an optional value:
140
+ # REVISIT: The role number here depends on the metamodel ordering of the fact type roles.
141
+ # This likely should follow the role order of the preferred reading, from which the fact name is derived.
142
+ # The code here collows the order of definition of the roles in the fact type,
143
+ # which might not be the same as the order of the preferred reading:
144
+ fact_name = fact_type.scala_name.titlecase
145
+ role_number = fact_type.all_role_in_order.index(other_role)+1
146
+
147
+ " def #{scala_role_name}: Option[#{other_type_name}] = {\n" +
148
+ " constellation.getBinaryFact(metaModel.#{fact_name.words.camelcase}, this).map(x => {\n" +
149
+ " x.head.asInstanceOf[FBMModel.BinaryFact].rolePlayers._#{role_number}.asInstanceOf[#{other_type_name}]\n" +
150
+ " })\n" +
151
+ " }\n" +
152
+ if !fact_type.is_existential
153
+ # Define a setter for an optional value:
154
+ " def #{scala_role_name}_=(value: Option[#{other_type_name}]) = {\n" +
155
+ " value match {\n" +
156
+ " case None =>\n" +
157
+ " case Some(m) => constellation.assertBinaryFact(#{fact_name.words.titlecase}(this, m))\n" +
158
+ " }\n" +
159
+ " }"
160
+ else
161
+ ''
162
+ end
163
+ end
164
+ elsif other_role.object_type.fact_type
165
+ # An objectified fact type
166
+ <<"END"
167
167
  def all#{scala_role_name.words.titlecase}(implicit constellation: Constellation): Seq[#{other_type_name}] = {
168
- constellation.getObjectifiedFact(metaModel.#{scala_role_name.words.camelcase}, this).getOrElse(Nil).flatMap(x => x match {
169
- case o: #{other_type_name} => Some(o)
170
- case _ => None
171
- })
168
+ constellation.getObjectifiedFact(metaModel.#{scala_role_name.words.camelcase}, this).getOrElse(Nil).flatMap(x => x match {
169
+ case o: #{other_type_name} => Some(o)
170
+ case _ => None
171
+ })
172
172
  }
173
173
  END
174
- else
175
- <<"END"
174
+ else
175
+ <<"END"
176
176
  /*
177
177
  def all#{scala_role_name.words.titlecase}(implicit constellation: Constellation): Seq[#{other_type_name}] = {
178
- constellation.getFact(metaModel.#{scala_role_name.words.camelcase}, this).getOrElse(Nil).flatMap(x => x match {
179
- # REVISIT: This is incorrect; we want to return the other role player in the fact
180
- case o: #{other_type_name} => Some(o)
181
- case _ => None
182
- })
178
+ constellation.getFact(metaModel.#{scala_role_name.words.camelcase}, this).getOrElse(Nil).flatMap(x => x match {
179
+ # REVISIT: This is incorrect; we want to return the other role player in the fact
180
+ case o: #{other_type_name} => Some(o)
181
+ case _ => None
182
+ })
183
183
  }
184
184
  */
185
185
  END
186
- end
187
- end
186
+ end
187
+ end
188
188
  end
189
189
 
190
190
  module ValueType
191
- DataTypeMap = {
192
- "Signed Integer" => "Int",
193
- "Unsigned Integer" => "Int",
194
- "Real" => "Double",
195
- "Char" => "String",
196
- # REVISIT: More will be needed here.
197
- }
198
- LengthTypes = [ "String", "Decimal" ]
199
- ScaleTypes = [ "Decimal" ]
200
-
201
- def scala_definition(super_type_name, facets)
202
- vt_name = name.words.titlecase
203
- if d = DataTypeMap[super_type_name]
204
- super_type_name = d
205
- end
206
- super_type_title = super_type_name.words.titlecase
207
- super_type_camel = super_type_name.words.camelcase
208
-
209
- sometimes_optional = all_role.detect do |r|
210
- r.fact_type.all_role.size == 2 && (c = (r.fact_type.all_role.to_a-[r])[0]) and !c.is_mandatory
211
- end
212
-
213
- " case class #{vt_name}(value: #{super_type_title})(implicit val constellation: Constellation) extends FBMModel.ValueTypeValue[#{super_type_title}] {\n" +
214
- " val objectType = metaModel.#{vt_name.words.camelcase}\n" +
215
- # REVISIT: scala_type_params +
216
- # REVISIT: scala_value_restriction + # puts " restrict #{value_constraint.all_allowed_range_sorted.map{|ar| ar.to_s}*", "}\n" if value_constraint
217
- # REVISIT: scala_units + # puts " \# REVISIT: #{vt_name} is in units of #{unit.name}\n" if unit
218
- absorbed_roles.map do |role|
191
+ DataTypeMap = {
192
+ "Signed Integer" => "Int",
193
+ "Unsigned Integer" => "Int",
194
+ "Real" => "Double",
195
+ "Char" => "String",
196
+ # REVISIT: More will be needed here.
197
+ }
198
+ LengthTypes = [ "String", "Decimal" ]
199
+ ScaleTypes = [ "Decimal" ]
200
+
201
+ def scala_definition(super_type_name, facets)
202
+ vt_name = name.words.titlecase
203
+ if d = DataTypeMap[super_type_name]
204
+ super_type_name = d
205
+ end
206
+ super_type_title = super_type_name.words.titlecase
207
+ super_type_camel = super_type_name.words.camelcase
208
+
209
+ sometimes_optional = all_role.detect do |r|
210
+ r.fact_type.all_role.size == 2 && (c = (r.fact_type.all_role.to_a-[r])[0]) and !c.is_mandatory
211
+ end
212
+
213
+ " case class #{vt_name}(value: #{super_type_title})(implicit val constellation: Constellation) extends FBMModel.ValueTypeValue[#{super_type_title}] {\n" +
214
+ " val objectType = metaModel.#{vt_name.words.camelcase}\n" +
215
+ # REVISIT: scala_type_params +
216
+ # REVISIT: scala_value_restriction + # puts " restrict #{value_constraint.all_allowed_range_sorted.map{|ar| ar.to_s}*", "}\n" if value_constraint
217
+ # REVISIT: scala_units + # puts " \# REVISIT: #{vt_name} is in units of #{unit.name}\n" if unit
218
+ absorbed_roles.map do |role|
219
219
  role.scala_role_definition
220
220
  end.
221
221
  compact*"\n" +
222
- " }\n" +
223
-
224
- # Add implicit casts for the underlying data type:
225
- " implicit def #{super_type_camel}2#{vt_name}(value: #{super_type_title})(implicit constellation: Constellation): #{vt_name} = #{vt_name}(value)\n" +
226
- if sometimes_optional
227
- " implicit def #{super_type_camel}2#{vt_name}Option(value: #{super_type_title})(implicit constellation: Constellation): Option[#{vt_name}] = Some(#{vt_name}(value))\n"
228
- else
229
- ""
230
- end +
231
- "\n"
232
- end
233
-
234
- def scala_metamodel(super_type_name, facets)
235
- vt_name = name.words.titlecase
236
- super_type_title = super_type_name.words.titlecase
237
- # REVISIT: Remove facets that do not apply to the Scala data types
238
- params = [
239
- LengthTypes.include?(super_type_name) ? facets[:length] : nil,
240
- ScaleTypes.include?(super_type_name) ? facets[:scale] : nil
241
- ].compact * ", "
242
-
243
- " val #{name.words.camelcase} = assertEntity(FBMModel.ValueType(FBMModel.DomainObjectTypeName(\"#{vt_name}\"), FBMModel.#{super_type_title}Type(#{params}), Nil))\n"
244
- end
222
+ " }\n" +
223
+
224
+ # Add implicit casts for the underlying data type:
225
+ " implicit def #{super_type_camel}2#{vt_name}(value: #{super_type_title})(implicit constellation: Constellation): #{vt_name} = #{vt_name}(value)\n" +
226
+ if sometimes_optional
227
+ " implicit def #{super_type_camel}2#{vt_name}Option(value: #{super_type_title})(implicit constellation: Constellation): Option[#{vt_name}] = Some(#{vt_name}(value))\n"
228
+ else
229
+ ""
230
+ end +
231
+ "\n"
232
+ end
233
+
234
+ def scala_metamodel(super_type_name, facets)
235
+ vt_name = name.words.titlecase
236
+ super_type_title = super_type_name.words.titlecase
237
+ # REVISIT: Remove facets that do not apply to the Scala data types
238
+ params = [
239
+ LengthTypes.include?(super_type_name) ? facets[:length] : nil,
240
+ ScaleTypes.include?(super_type_name) ? facets[:scale] : nil
241
+ ].compact * ", "
242
+
243
+ " val #{name.words.camelcase} = assertEntity(FBMModel.ValueType(FBMModel.DomainObjectTypeName(\"#{vt_name}\"), FBMModel.#{super_type_title}Type(#{params}), Nil))\n"
244
+ end
245
245
  end
246
246
 
247
247
  module EntityType
248
- def scala_object(title_name, id_names, id_types)
249
- " object #{title_name} {\n" +
250
- " def apply(" +
251
- (id_names.zip(id_types).map do |(name, type_name)|
252
- "#{name}: #{type_name}"
253
- end * ', '
254
- ) +
255
- ")(implicit constellation: Constellation) = {\n" +
256
-
257
- # Define the constant storage for the identifying role values:
258
- id_names.map do |name|
259
- " val _#{name} = #{name}"
260
- end*"\n" +
261
- " val _constellation = constellation\n" +
262
- " assertEntity(new #{title_name} {\n" +
263
- id_names.map do |name|
264
- " val #{name} = _#{name}"
265
- end*"\n" +
266
- " val constellation = _constellation\n" +
267
- " })\n" + # Ends new block and assertEntity
268
- " }\n" + # Ends apply()
269
- " }\n" + # Ends object{}
270
- "\n"
271
- end
272
-
273
- def scala_trait(title_name, primary_supertype, pis)
274
- s = 'override ' unless supertypes.empty?
275
-
276
- " trait #{title_name} extends #{primary_supertype ? primary_supertype.name.words.titlecase : 'FBMModel.Entity'} {\n" +
277
- " #{s}val objectType = metaModel.#{name.words.camelcase}\n" +
278
- (fact_type ? " // REVISIT: Here, we should use fact_roles_dump(fact_type)\n\n" : '') +
279
- absorbed_roles.map do |role|
248
+ def scala_object(title_name, id_names, id_types)
249
+ " object #{title_name} {\n" +
250
+ " def apply(" +
251
+ (id_names.zip(id_types).map do |(name, type_name)|
252
+ "#{name}: #{type_name}"
253
+ end * ', '
254
+ ) +
255
+ ")(implicit constellation: Constellation) = {\n" +
256
+
257
+ # Define the constant storage for the identifying role values:
258
+ id_names.map do |name|
259
+ " val _#{name} = #{name}"
260
+ end*"\n" +
261
+ " val _constellation = constellation\n" +
262
+ " assertEntity(new #{title_name} {\n" +
263
+ id_names.map do |name|
264
+ " val #{name} = _#{name}"
265
+ end*"\n" +
266
+ " val constellation = _constellation\n" +
267
+ " })\n" + # Ends new block and assertEntity
268
+ " }\n" + # Ends apply()
269
+ " }\n" + # Ends object{}
270
+ "\n"
271
+ end
272
+
273
+ def scala_trait(title_name, primary_supertype, pis)
274
+ s = 'override ' unless supertypes.empty?
275
+
276
+ " trait #{title_name} extends #{primary_supertype ? primary_supertype.name.words.titlecase : 'FBMModel.Entity'} {\n" +
277
+ " #{s}val objectType = metaModel.#{name.words.camelcase}\n" +
278
+ (fact_type ? " // REVISIT: Here, we should use fact_roles_dump(fact_type)\n\n" : '') +
279
+ absorbed_roles.map do |role|
280
280
  role.scala_role_definition
281
281
  end.
282
282
  compact*"\n" +
283
- " #{s}val identifier: Seq[Seq[FBMModel.Identifier[_]]] = Seq(#{
284
- pis.map do |pi|
285
- 'Seq(' +
286
- pi.role_sequence.all_role_ref_in_order.map do |id_role_ref|
287
- id_role_ref.role.object_type.name.words.camelcase
288
- end*', ' +
289
- ')'
290
- end*', '
291
- })\n" +
292
- " }\n" + # Ends trait{}
293
- "\n"
294
- end
295
-
296
- def scala_metamodel(title_name)
297
- pi = preferred_identifier
298
- # The following finds the closest non-inheritance identifier
299
- #while pi.role_sequence.all_role_ref.size == 1 and
300
- # (role = pi.role_sequence.all_role_ref.single.role).fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
301
- # pi = role.fact_type.supertype_role.object_type.preferred_identifier
302
- #end
303
- identifying_parameters =
304
- pi.role_sequence.all_role_ref_in_order.map{|rr| rr.role.object_type.name.words.camelcase }*', '
305
-
306
- supertypes_list =
307
- if supertypes.empty?
308
- 'Nil'
309
- else
310
- "List(#{supertypes.map{|s| s.name.words.camelcase}*', '})"
311
- end
312
- " val #{name.words.camelcase} = assertEntity(FBMModel.EntityType(FBMModel.DomainObjectTypeName(\"#{title_name}\"), #{supertypes_list}, Seq(#{identifying_parameters})))\n"
313
- end
314
-
315
- def scala_shared(o, supertypes, pi = nil)
316
- if supertypes
317
- primary_supertype = o && (o.identifying_supertype || o.supertypes[0])
318
- end
319
- title_name = o.name.words.titlecase
320
-
321
- id_roles, pis = *all_identifying_roles(o)
322
- id_names = id_role_names(o, id_roles)
323
- id_types = id_role_types(id_roles)
324
- identification = pi ? identified_by(o, pi) : nil
325
-
326
- # REVISIT: We don't want an object for abstract classes,
327
- # i.e. where subtypes have a disjoint mandatory constraint
328
- entity_object(title_name, id_names, id_types)
329
-
330
- entity_trait(o, title_name, primary_supertype, pis)
331
-
332
- entity_model(o, title_name)
333
- end
334
-
335
- def id_role_names id_roles
336
- id_roles.map do |role|
337
- # Ignore identification through a supertype
338
- next if role.fact_type.kind_of?(ActiveFacts::Metamodel::TypeInheritance)
339
- role.scala_preferred_role_name(self).words.camelcase
340
- end.compact
341
- end
342
-
343
- def id_role_types id_roles
344
- id_roles.map do |role|
345
- next if role.fact_type.kind_of?(ActiveFacts::Metamodel::TypeInheritance)
346
- if !role.fact_type.entity_type && role.fact_type.all_role.size == 1
347
- "Boolean"
348
- else
349
- role.object_type.name.words.titlecase
350
- end
351
- end.compact
352
- end
353
-
354
- def scala_objectification
355
- # REVISIT: This disregards any supertypes and their identifiers
283
+ " #{s}val identifier: Seq[Seq[FBMModel.Identifier[_]]] = Seq(#{
284
+ pis.map do |pi|
285
+ 'Seq(' +
286
+ pi.role_sequence.all_role_ref_in_order.map do |id_role_ref|
287
+ id_role_ref.role.object_type.name.words.camelcase
288
+ end*', ' +
289
+ ')'
290
+ end*', '
291
+ })\n" +
292
+ " }\n" + # Ends trait{}
293
+ "\n"
294
+ end
295
+
296
+ def scala_metamodel(title_name)
297
+ pi = preferred_identifier
298
+ # The following finds the closest non-inheritance identifier
299
+ #while pi.role_sequence.all_role_ref.size == 1 and
300
+ # (role = pi.role_sequence.all_role_ref.single.role).fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
301
+ # pi = role.fact_type.supertype_role.object_type.preferred_identifier
302
+ #end
303
+ identifying_parameters =
304
+ pi.role_sequence.all_role_ref_in_order.map{|rr| rr.role.object_type.name.words.camelcase }*', '
305
+
306
+ supertypes_list =
307
+ if supertypes.empty?
308
+ 'Nil'
309
+ else
310
+ "List(#{supertypes.map{|s| s.name.words.camelcase}*', '})"
311
+ end
312
+ " val #{name.words.camelcase} = assertEntity(FBMModel.EntityType(FBMModel.DomainObjectTypeName(\"#{title_name}\"), #{supertypes_list}, Seq(#{identifying_parameters})))\n"
313
+ end
314
+
315
+ def scala_shared(o, supertypes, pi = nil)
316
+ if supertypes
317
+ primary_supertype = o && (o.identifying_supertype || o.supertypes[0])
318
+ end
319
+ title_name = o.name.words.titlecase
320
+
321
+ id_roles, pis = *all_identifying_roles(o)
322
+ id_names = id_role_names(o, id_roles)
323
+ id_types = id_role_types(id_roles)
324
+ identification = pi ? identified_by(o, pi) : nil
325
+
326
+ # REVISIT: We don't want an object for abstract classes,
327
+ # i.e. where subtypes have a disjoint mandatory constraint
328
+ entity_object(title_name, id_names, id_types)
329
+
330
+ entity_trait(o, title_name, primary_supertype, pis)
331
+
332
+ entity_model(o, title_name)
333
+ end
334
+
335
+ def id_role_names id_roles
336
+ id_roles.map do |role|
337
+ # Ignore identification through a supertype
338
+ next if role.fact_type.kind_of?(ActiveFacts::Metamodel::TypeInheritance)
339
+ role.scala_preferred_role_name(self).words.camelcase
340
+ end.compact
341
+ end
342
+
343
+ def id_role_types id_roles
344
+ id_roles.map do |role|
345
+ next if role.fact_type.kind_of?(ActiveFacts::Metamodel::TypeInheritance)
346
+ if !role.fact_type.entity_type && role.fact_type.all_role.size == 1
347
+ "Boolean"
348
+ else
349
+ role.object_type.name.words.titlecase
350
+ end
351
+ end.compact
352
+ end
353
+
354
+ def scala_objectification
355
+ # REVISIT: This disregards any supertypes and their identifiers
356
356
  # primary_supertype = o && (o.identifying_supertype || o.supertypes[0])
357
357
  # secondary_supertypes = o.supertypes-[primary_supertype]
358
358
 
359
- pi = preferred_identifier
360
- id_roles = []
361
- identifying_role_refs = pi.role_sequence.all_role_ref_in_order
362
- identifying_role_refs.each do |id_role_ref|
363
- id_roles << id_role_ref.role
364
- end
365
- id_names = id_role_names id_roles
366
- id_types = id_role_types id_roles
367
-
368
- " case class #{name.words.titlecase}(#{
369
- id_names.zip(id_types).map {|(n, t)|
370
- "#{n}: #{t}"
371
- }*', '
372
- }) extends FBMModel.ObjectifiedFact {\n" +
373
- " // REVISIT: Here, we should use fact_roles_dump(fact_type)\n" +
374
- absorbed_roles.map do |role|
359
+ pi = preferred_identifier
360
+ id_roles = []
361
+ identifying_role_refs = pi.role_sequence.all_role_ref_in_order
362
+ identifying_role_refs.each do |id_role_ref|
363
+ id_roles << id_role_ref.role
364
+ end
365
+ id_names = id_role_names id_roles
366
+ id_types = id_role_types id_roles
367
+
368
+ " case class #{name.words.titlecase}(#{
369
+ id_names.zip(id_types).map {|(n, t)|
370
+ "#{n}: #{t}"
371
+ }*', '
372
+ }) extends FBMModel.ObjectifiedFact {\n" +
373
+ " // REVISIT: Here, we should use fact_roles_dump(fact_type)\n" +
374
+ absorbed_roles.map do |role|
375
375
  role.scala_role_definition
376
376
  end.
377
377
  compact*"\n" +
378
- " }"
379
- end
378
+ " }"
379
+ end
380
380
 
381
- def scala_objectification_metamodel
382
- identifying_parameters = preferred_identifier.role_sequence.all_role_ref_in_order.map{|rr| rr.role.object_type.name.words.camelcase }*', '
383
- " val #{name.words.camelcase} = assertEntity(FBMModel.ObjectifiedType(FBMModel.DomainObjectTypeName(\"#{name.words.titlecase}\"), Nil, Seq(#{identifying_parameters})))\n"
384
- end
381
+ def scala_objectification_metamodel
382
+ identifying_parameters = preferred_identifier.role_sequence.all_role_ref_in_order.map{|rr| rr.role.object_type.name.words.camelcase }*', '
383
+ " val #{name.words.camelcase} = assertEntity(FBMModel.ObjectifiedType(FBMModel.DomainObjectTypeName(\"#{name.words.titlecase}\"), Nil, Seq(#{identifying_parameters})))\n"
384
+ end
385
385
  end
386
386
 
387
387
  module FactType
@@ -415,28 +415,28 @@ END
415
415
 
416
416
  # An objectified fact type has internal roles that are always "has_one":
417
417
  def fact_roles
418
- raise "Fact #{describe} type is not objectified" unless entity_type
418
+ raise "Fact #{describe} type is not objectified" unless entity_type
419
419
  all_role.sort_by do |role|
420
- role.scala_preferred_role_name(entity_type)
421
- end.
422
- map do |role|
423
- role_name = role.scala_preferred_role_name(entity_type)
424
- one_to_one = role.all_role_ref.detect{|rr|
425
- rr.role_sequence.all_role_ref.size == 1 &&
426
- rr.role_sequence.all_presence_constraint.detect{|pc|
427
- pc.max_frequency == 1
428
- }
429
- }
430
- counterpart_role_method = (one_to_one ? "" : "all_") +
431
- entity_type.oo_default_role_name +
432
- (role_name != role.object_type.oo_default_role_name ? "_as_#{role_name}" : '')
433
- role.as_binary(role_name, role.object_type, true, one_to_one, nil, nil, counterpart_role_method)
434
- end.
435
- join('')
436
- end
420
+ role.scala_preferred_role_name(entity_type)
421
+ end.
422
+ map do |role|
423
+ role_name = role.scala_preferred_role_name(entity_type)
424
+ one_to_one = role.all_role_ref.detect{|rr|
425
+ rr.role_sequence.all_role_ref.size == 1 &&
426
+ rr.role_sequence.all_presence_constraint.detect{|pc|
427
+ pc.max_frequency == 1
428
+ }
429
+ }
430
+ counterpart_role_method = (one_to_one ? "" : "all_") +
431
+ entity_type.oo_default_role_name +
432
+ (role_name != role.object_type.oo_default_role_name ? "_as_#{role_name}" : '')
433
+ role.as_binary(role_name, role.object_type, true, one_to_one, nil, nil, counterpart_role_method)
434
+ end.
435
+ join('')
436
+ end
437
437
  end
438
438
 
439
- include ActiveFacts::TraitInjector # Must be last in this module, after all submodules have been defined
439
+ include ActiveFacts::TraitInjector # Must be last in this module, after all submodules have been defined
440
440
  end
441
441
  end
442
442
  end