activefacts-generators 1.8.0 → 1.8.1

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: f40edd413e3910347f03b39b1fd1cd36513c15a8
4
- data.tar.gz: 0ace4f714d8e1ba990a3d8f81fdf6ac50ec812dd
3
+ metadata.gz: 1b8cf08b3a5a39113eb4e04697ee25b4f4abdb4f
4
+ data.tar.gz: aeed8fc142836d0d79321eff69c97b38d016dc45
5
5
  SHA512:
6
- metadata.gz: 641e9a5ce19aa07e807cde79708ed740ab1b810c913255fe94580fcec9660bdae247f5e49325b39193b3ed2c69e803873730be884c05c82e940eaf5c65b5454b
7
- data.tar.gz: 99448103bb436f51228565c94ddc7dd8103f2a014aa4a76bbabdf7844972c97a10fcf0af429f25c16afb1d43a71fd63c29f63f559ea6d1128957c1d952c87a6a
6
+ metadata.gz: 13ce57f363db35fce13e217a916d17661fcfcd6349c0345d1873d0832a45fff625a5f656eb36cd8e758fb53d93df025234feade6defd6839ce50a9d2c9069f4f
7
+ data.tar.gz: b3a5c20cb3b066cb77774d88e1b55d3c95053672c079decf4f7f00b79a05e5da89a0c62d46a25a0b6f2ed13c58fe2a9aa1cabcfa0c178702f220db89a59f1e15
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "activefacts-generators"
7
- spec.version = "1.8.0"
7
+ spec.version = "1.8.1"
8
8
  spec.authors = ["Clifford Heath"]
9
9
  spec.email = ["clifford.heath@gmail.com"]
10
10
 
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.add_development_dependency "rake", "~> 10.0"
21
21
  spec.add_development_dependency "rspec", "~> 3.3"
22
22
 
23
- spec.add_runtime_dependency "activefacts-metamodel", ">= 1.8", "~> 1.8.0"
24
- spec.add_runtime_dependency "activefacts-rmap", ">= 1.8", "~> 1.8.0"
23
+ spec.add_runtime_dependency "activefacts-metamodel", ">= 1.8", "~> 1"
24
+ spec.add_runtime_dependency "activefacts-rmap", ">= 1.8", "~> 1"
25
25
  spec.add_runtime_dependency "activesupport", ">= 4.2", "~> 4.2.4"
26
26
  end
@@ -0,0 +1,184 @@
1
+ #
2
+ # ActiveFacts Generators.
3
+ # Generate a Scala module for the ActiveFacts API from an ActiveFacts vocabulary.
4
+ #
5
+ # Copyright (c) 2013 Clifford Heath. Read the LICENSE file.
6
+ #
7
+ require 'activefacts'
8
+ require 'activefacts/metamodel'
9
+ require 'activefacts/generators/helpers/oo'
10
+ require 'activefacts/generators/traits/scala'
11
+ require 'activefacts/registry'
12
+
13
+ module ActiveFacts
14
+ module Generators
15
+ # Generate Scala module containing classes for an ActiveFacts vocabulary.
16
+ # Invoke as
17
+ # afgen --scala[=options] <file>.cql
18
+ # Options are comma or space separated:
19
+ # * help list available options
20
+
21
+ class Scala < Helpers::OO
22
+
23
+ def initialize(vocabulary, *options)
24
+ super
25
+ @constraints_used = {}
26
+ @fact_types_dumped = {}
27
+ end
28
+
29
+ private
30
+
31
+ def set_option(option)
32
+ @mapping = false
33
+ case option
34
+ when 'help', '?'
35
+ $stderr.puts "Usage:\t\tafgen --scala[=option,option] input_file.cql\n"+
36
+ "\t\tmeta\t\tModify the mapping to suit a metamodel"
37
+ exit 0
38
+ when /^meta/
39
+ @is_metamodel = true
40
+ else super
41
+ end
42
+ end
43
+
44
+ def fact_type_name(fact_type)
45
+ fact_type.default_reading.words
46
+ end
47
+
48
+ def vocabulary_start
49
+ puts @vocabulary.scala_prelude
50
+
51
+ @metamodel = @vocabulary.scala_prelude_metamodel
52
+ end
53
+
54
+ def vocabulary_end
55
+ puts @vocabulary.scala_finale
56
+ puts "#{@metamodel}\n}\n"
57
+ end
58
+
59
+ def data_type_dump(o)
60
+ end
61
+
62
+ def value_type_dump(o, super_type_name, facets)
63
+ puts o.scala_definition(super_type_name, facets)
64
+
65
+ @metamodel << o.scala_metamodel(super_type_name, facets)
66
+ end
67
+
68
+ def id_role_names o, id_roles
69
+ id_roles.map do |role|
70
+ # Ignore identification through a supertype
71
+ next if role.fact_type.kind_of?(ActiveFacts::Metamodel::TypeInheritance)
72
+ role.preferred_role_name(o).words.camelcase
73
+ end.compact
74
+ end
75
+
76
+ def id_role_types id_roles
77
+ id_roles.map do |role|
78
+ next if role.fact_type.kind_of?(ActiveFacts::Metamodel::TypeInheritance)
79
+ if !role.fact_type.entity_type && role.fact_type.all_role.size == 1
80
+ "Boolean"
81
+ else
82
+ role.object_type.name.words.titlecase
83
+ end
84
+ end.compact
85
+ end
86
+
87
+ def all_identifying_roles(o)
88
+ pis = []
89
+ # This places the subtype identifying roles before the supertype's. Reverse the list to change this.
90
+ id_roles = []
91
+ o.supertypes_transitive.each do |supertype|
92
+ pi = supertype.preferred_identifier
93
+ next if pis.include?(pi) # Seen this identifier already?
94
+ pis << pi
95
+ identifying_role_refs = pi.role_sequence.all_role_ref_in_order
96
+ identifying_role_refs.each do |id_role_ref|
97
+ # Have we seen this role in another identifier?
98
+ next if id_roles.detect{|idr| idr == id_role_ref.role }
99
+ id_roles << id_role_ref.role
100
+ end
101
+ end
102
+ [id_roles, pis]
103
+ end
104
+
105
+ def entity_object(o, title_name, id_names, id_types)
106
+ puts o.scala_object(title_name, id_names, id_types)
107
+ end
108
+
109
+ def entity_trait(o, title_name, primary_supertype, pis)
110
+ puts o.scala_trait(title_name, primary_supertype, pis)
111
+ end
112
+
113
+ def entity_model(o, title_name)
114
+ @metamodel << o.scala_metamodel(title_name)
115
+ end
116
+
117
+ def non_subtype_dump(o, pi)
118
+ subtype_dump(o, nil, pi)
119
+ end
120
+
121
+ def subtype_dump(o, supertypes, pi = nil)
122
+ if supertypes
123
+ primary_supertype = o && (o.identifying_supertype || o.supertypes[0])
124
+ end
125
+ title_name = o.name.words.titlecase
126
+
127
+ id_roles, pis = *all_identifying_roles(o)
128
+ id_names = id_role_names(o, id_roles)
129
+ id_types = id_role_types(id_roles)
130
+ identification = pi ? identified_by(o, pi) : nil
131
+
132
+ # REVISIT: We don't want an object for abstract classes,
133
+ # i.e. where subtypes have a disjoint mandatory constraint
134
+ entity_object(o, title_name, id_names, id_types)
135
+
136
+ entity_trait(o, title_name, primary_supertype, pis)
137
+
138
+ entity_model(o, title_name)
139
+
140
+ @constraints_used[pi] = true if pi
141
+ end
142
+
143
+ def identified_by_roles_and_facts(entity_type, identifying_role_refs, identifying_facts)
144
+ identifying_role_refs.map do |role_ref|
145
+ [ role_ref.role.scala_preferred_role_name(entity_type),
146
+ entity_type.name.words.titlecase
147
+ ]
148
+ end
149
+ end
150
+
151
+ def skip_fact_type(f)
152
+ f.is_a?(ActiveFacts::Metamodel::TypeInheritance)
153
+ end
154
+
155
+ # Dump one fact type.
156
+ def fact_type_dump(fact_type, name)
157
+ @fact_types_dumped[fact_type] = true
158
+ return objectified_fact_type_dump(fact_type.entity_type) if fact_type.entity_type
159
+
160
+ puts fact_type.scala_definition
161
+
162
+ @metamodel << fact_type.scala_metamodel
163
+ end
164
+
165
+ def objectified_fact_type_dump o
166
+ puts o.scala_objectification
167
+ @metamodel << o.scala_objectification_metamodel
168
+ end
169
+
170
+ def unary_dump(role, role_name)
171
+ scala_role_name = role_name.words.camelcase
172
+ puts " val #{scala_role_name}: Boolean"
173
+ end
174
+
175
+ def role_dump(role)
176
+ puts role.scala_role_definition
177
+ end
178
+
179
+ end
180
+ end
181
+ end
182
+
183
+ ActiveFacts::Registry.generator('scala', ActiveFacts::Generators::Scala)
184
+
@@ -0,0 +1,442 @@
1
+ #
2
+ # ActiveFacts Generators.
3
+ #
4
+ # Metamodel Traits for mapping to Scala
5
+ #
6
+ # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
7
+ #
8
+ module ActiveFacts
9
+ module Generators
10
+ module ScalaTraits
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
37
+ end
38
+
39
+ module ObjectType
40
+ # Map the ObjectType name to a Scala class name
41
+ def scala_type_name
42
+ oo_type_name
43
+ end
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
49
+
50
+ def absorbed_roles
51
+ all_role.
52
+ select do |role|
53
+ role.fact_type.all_role.size <= 2 &&
54
+ !role.fact_type.is_a?(ActiveFacts::Metamodel::LinkFactType)
55
+ end.
56
+ sort_by do |role|
57
+ r = role.fact_type.all_role.select{|r2| r2 != role}[0] || role
58
+ r.scala_preferred_role_name(self) + ':' + role.scala_preferred_role_name(r.object_type)
59
+ end
60
+ end
61
+ end
62
+
63
+ module Role
64
+ def scala_preferred_role_name(is_for = nil, &name_builder)
65
+ # REVISIT: Modify this to suit Scala
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
71
+
72
+ name_builder ||= proc {|names| names.map(&:downcase)*'_' } # Make snake_case by default
73
+
74
+ # Handle an objectified unary role:
75
+ if is_for && fact_type.entity_type == is_for && fact_type.all_role.size == 1
76
+ return name_builder.call(object_type.name.words)
77
+ end
78
+
79
+ # trace "Looking for preferred_role_name of #{describe_fact_type(fact_type, self)}"
80
+ reading = fact_type.preferred_reading
81
+ preferred_role_ref = reading.role_sequence.all_role_ref.detect{|reading_rr|
82
+ reading_rr.role == self
83
+ }
84
+
85
+ if fact_type.all_role.size == 1
86
+ return name_builder.call(
87
+ role_name ?
88
+ role_name.snakewords :
89
+ reading.text.gsub(/ *\{0\} */,' ').gsub(/[- ]+/,'_').words
90
+ )
91
+ end
92
+
93
+ if role_name && role_name != ""
94
+ role_words = [role_name]
95
+ else
96
+ role_words = []
97
+
98
+ la = preferred_role_ref.leading_adjective
99
+ role_words += la.words.snakewords if la && la != ""
100
+
101
+ role_words += object_type.name.words.snakewords
102
+
103
+ ta = preferred_role_ref.trailing_adjective
104
+ role_words += ta.words.snakewords if ta && ta != ""
105
+ end
106
+
107
+ # n = role_words.map{|w| w.gsub(/([a-z])([A-Z]+)/,'\1_\2').downcase}*"_"
108
+ n = role_words*'_'
109
+ # trace "\tresult=#{n}"
110
+ return name_builder.call(n.gsub(' ','_').split(/_/))
111
+ end
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"
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
+ })
172
+ }
173
+ END
174
+ else
175
+ <<"END"
176
+ /*
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
+ })
183
+ }
184
+ */
185
+ END
186
+ end
187
+ end
188
+ end
189
+
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|
219
+ role.scala_role_definition
220
+ end.
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
245
+ end
246
+
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|
280
+ role.scala_role_definition
281
+ end.
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
356
+ # primary_supertype = o && (o.identifying_supertype || o.supertypes[0])
357
+ # secondary_supertypes = o.supertypes-[primary_supertype]
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|
375
+ role.scala_role_definition
376
+ end.
377
+ compact*"\n" +
378
+ " }"
379
+ end
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
385
+ end
386
+
387
+ module FactType
388
+ def scala_name
389
+ default_reading.words
390
+ end
391
+
392
+ def scala_definition
393
+ # Dump a non-objectified fact type
394
+ name_words = scala_name
395
+ role_names = preferred_reading.role_sequence.all_role_ref_in_order.map do |rr|
396
+ rr.role.scala_preferred_role_name.words.camelcase
397
+ end
398
+ role_types = preferred_reading.role_sequence.all_role_ref_in_order.map do |rr|
399
+ rr.role.object_type.name.words.camelcase
400
+ end
401
+
402
+ " case class #{name_words.titlecase}(#{role_names.zip(role_types).map{|n, t| n+': '+t}*', '})(implicit val constellation: Constellation) extends FBMModel.BinaryFact {\n" +
403
+ " def factType = metaModel.#{name_words.camelcase}\n" +
404
+ " def rolePlayers = (#{role_names*', '})\n" +
405
+ " }\n\n"
406
+ end
407
+
408
+ def scala_metamodel
409
+ name_words = scala_name
410
+ role_names = preferred_reading.role_sequence.all_role_ref_in_order.map do |rr|
411
+ rr.role.scala_preferred_role_name.words.camelcase
412
+ end
413
+ " val #{name_words.camelcase} = assertEntity(FBMModel.BinaryFactType(FBMModel.FactTypeName(\"#{name_words.titlecase}\"), (#{role_names*', '})))\n"
414
+ end
415
+
416
+ # An objectified fact type has internal roles that are always "has_one":
417
+ def fact_roles
418
+ raise "Fact #{describe} type is not objectified" unless entity_type
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
437
+ end
438
+
439
+ include ActiveFacts::TraitInjector # Must be last in this module, after all submodules have been defined
440
+ end
441
+ end
442
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activefacts-generators
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 1.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clifford Heath
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-04 00:00:00.000000000 Z
11
+ date: 2015-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -67,7 +67,7 @@ dependencies:
67
67
  version: '1.8'
68
68
  - - "~>"
69
69
  - !ruby/object:Gem::Version
70
- version: 1.8.0
70
+ version: '1'
71
71
  type: :runtime
72
72
  prerelease: false
73
73
  version_requirements: !ruby/object:Gem::Requirement
@@ -77,7 +77,7 @@ dependencies:
77
77
  version: '1.8'
78
78
  - - "~>"
79
79
  - !ruby/object:Gem::Version
80
- version: 1.8.0
80
+ version: '1'
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: activefacts-rmap
83
83
  requirement: !ruby/object:Gem::Requirement
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: '1.8'
88
88
  - - "~>"
89
89
  - !ruby/object:Gem::Version
90
- version: 1.8.0
90
+ version: '1'
91
91
  type: :runtime
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
@@ -97,7 +97,7 @@ dependencies:
97
97
  version: '1.8'
98
98
  - - "~>"
99
99
  - !ruby/object:Gem::Version
100
- version: 1.8.0
100
+ version: '1'
101
101
  - !ruby/object:Gem::Dependency
102
102
  name: activesupport
103
103
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +150,7 @@ files:
150
150
  - lib/activefacts/generators/rails/models.rb
151
151
  - lib/activefacts/generators/rails/schema.rb
152
152
  - lib/activefacts/generators/ruby.rb
153
+ - lib/activefacts/generators/scala.rb
153
154
  - lib/activefacts/generators/sql/mysql.rb
154
155
  - lib/activefacts/generators/sql/server.rb
155
156
  - lib/activefacts/generators/stats.rb
@@ -158,6 +159,7 @@ files:
158
159
  - lib/activefacts/generators/traits/oo.rb
159
160
  - lib/activefacts/generators/traits/ordered.rb
160
161
  - lib/activefacts/generators/traits/ruby.rb
162
+ - lib/activefacts/generators/traits/scala.rb
161
163
  - lib/activefacts/generators/transform/datavault.rb
162
164
  - lib/activefacts/generators/transform/surrogate.rb
163
165
  - lib/activefacts/registry.rb