activefacts-generators 1.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +1 -0
- data/.travis.yml +4 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +30 -0
- data/Rakefile +6 -0
- data/activefacts-generators.gemspec +26 -0
- data/lib/activefacts/dependency_analyser.rb +182 -0
- data/lib/activefacts/generators/absorption.rb +71 -0
- data/lib/activefacts/generators/composition.rb +119 -0
- data/lib/activefacts/generators/cql.rb +715 -0
- data/lib/activefacts/generators/diagrams/json.rb +340 -0
- data/lib/activefacts/generators/help.rb +64 -0
- data/lib/activefacts/generators/helpers/inject.rb +16 -0
- data/lib/activefacts/generators/helpers/oo.rb +162 -0
- data/lib/activefacts/generators/helpers/ordered.rb +605 -0
- data/lib/activefacts/generators/helpers/rails.rb +57 -0
- data/lib/activefacts/generators/html/glossary.rb +462 -0
- data/lib/activefacts/generators/metadata/json.rb +204 -0
- data/lib/activefacts/generators/null.rb +32 -0
- data/lib/activefacts/generators/rails/models.rb +247 -0
- data/lib/activefacts/generators/rails/schema.rb +217 -0
- data/lib/activefacts/generators/ruby.rb +134 -0
- data/lib/activefacts/generators/sql/mysql.rb +281 -0
- data/lib/activefacts/generators/sql/server.rb +274 -0
- data/lib/activefacts/generators/stats.rb +70 -0
- data/lib/activefacts/generators/text.rb +29 -0
- data/lib/activefacts/generators/traits/datavault.rb +241 -0
- data/lib/activefacts/generators/traits/oo.rb +73 -0
- data/lib/activefacts/generators/traits/ordered.rb +33 -0
- data/lib/activefacts/generators/traits/ruby.rb +210 -0
- data/lib/activefacts/generators/transform/datavault.rb +303 -0
- data/lib/activefacts/generators/transform/surrogate.rb +215 -0
- data/lib/activefacts/registry.rb +11 -0
- metadata +176 -0
@@ -0,0 +1,340 @@
|
|
1
|
+
#
|
2
|
+
# ActiveFacts Generators.
|
3
|
+
# Generate json output from a vocabulary, for loading into APRIMO
|
4
|
+
#
|
5
|
+
# Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
|
6
|
+
#
|
7
|
+
require 'json'
|
8
|
+
require 'digest/sha1'
|
9
|
+
require 'activefacts/registry'
|
10
|
+
|
11
|
+
module ActiveFacts
|
12
|
+
module Generators
|
13
|
+
module Diagrams
|
14
|
+
# Generate json output from a vocabulary, for loading into APRIMO.
|
15
|
+
# Invoke as
|
16
|
+
# afgen --diagrams/json <file>.cql=diagrams
|
17
|
+
class JSON
|
18
|
+
private
|
19
|
+
def initialize(vocabulary)
|
20
|
+
@vocabulary = vocabulary
|
21
|
+
@vocabulary = @vocabulary.Vocabulary.values[0] if ActiveFacts::API::Constellation === @vocabulary
|
22
|
+
end
|
23
|
+
|
24
|
+
def puts(*a)
|
25
|
+
@out.puts *a
|
26
|
+
end
|
27
|
+
|
28
|
+
public
|
29
|
+
def generate(out = $>)
|
30
|
+
@out = out
|
31
|
+
uuids = {}
|
32
|
+
|
33
|
+
puts "{ model: '#{@vocabulary.name}',\n" +
|
34
|
+
"diagrams: [\n#{
|
35
|
+
@vocabulary.all_diagram.sort_by{|o| o.name.gsub(/ /,'')}.map do |d|
|
36
|
+
j = {:uuid => (uuids[d] ||= uuid_from_id(d)), :name => d.name}
|
37
|
+
" #{j.to_json}"
|
38
|
+
end*",\n"
|
39
|
+
}\n ],"
|
40
|
+
|
41
|
+
object_types = @vocabulary.all_object_type.sort_by{|o| o.name.gsub(/ /,'')}
|
42
|
+
puts " object_types: [\n#{
|
43
|
+
object_types.sort_by{|o|o.identifying_role_values.inspect}.map do |o|
|
44
|
+
uuids[o] ||= uuid_from_id(o)
|
45
|
+
ref_mode = nil
|
46
|
+
if o.is_a?(ActiveFacts::Metamodel::EntityType) and
|
47
|
+
p = o.preferred_identifier and
|
48
|
+
(rrs = p.role_sequence.all_role_ref).size == 1 and
|
49
|
+
(r = rrs.single.role).fact_type != o.fact_type and
|
50
|
+
r.object_type.is_a?(ActiveFacts::Metamodel::ValueType) and
|
51
|
+
!r.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
|
52
|
+
ref_mode = "#{r.object_type.name}"
|
53
|
+
ref_mode.sub!(%r{#{o.name} *}, '.')
|
54
|
+
end
|
55
|
+
j = {
|
56
|
+
:uuid => uuids[o],
|
57
|
+
:name => o.name,
|
58
|
+
:shapes => o.all_object_type_shape.sort_by{|s| [s.location.x, s.location.y]}.map do |shape|
|
59
|
+
x = { :diagram => uuids[shape.orm_diagram],
|
60
|
+
:is_expanded => shape.is_expanded,
|
61
|
+
:uuid => uuid_from_id(shape),
|
62
|
+
:x => shape.location.x,
|
63
|
+
:y => shape.location.y
|
64
|
+
}
|
65
|
+
x[:is_expanded] = true if ref_mode && shape.is_expanded # Don't show the reference mode
|
66
|
+
x
|
67
|
+
end
|
68
|
+
}
|
69
|
+
j[:ref_mode] = ref_mode if ref_mode
|
70
|
+
j[:independent] = true if o.is_independent
|
71
|
+
|
72
|
+
if o.is_a?(ActiveFacts::Metamodel::EntityType)
|
73
|
+
# Entity Type may be objectified, and may have supertypes:
|
74
|
+
if o.fact_type
|
75
|
+
uuid = (uuids[o.fact_type] ||= uuid_from_id(o.fact_type))
|
76
|
+
j[:objectifies] = uuid
|
77
|
+
j[:implicit] = true if o.concept.implication_rule
|
78
|
+
end
|
79
|
+
if o.all_type_inheritance_as_subtype.size > 0
|
80
|
+
j[:supertypes] = o.
|
81
|
+
all_type_inheritance_as_subtype.
|
82
|
+
sort_by{|ti| ti.provides_identification ? 0 : 1}.
|
83
|
+
map{|ti|
|
84
|
+
[ uuids[ti.supertype] ||= uuid_from_id(ti.supertype),
|
85
|
+
uuids[ti.supertype_role] = uuid_from_id(ti.supertype_role)
|
86
|
+
]
|
87
|
+
}
|
88
|
+
end
|
89
|
+
else
|
90
|
+
# ValueType usually has a supertype:
|
91
|
+
if (o.supertype)
|
92
|
+
j[:supertype] = (uuids[o.supertype] ||= uuid_from_id(o.supertype))
|
93
|
+
end
|
94
|
+
end
|
95
|
+
# REVISIT: Place a ValueConstraint and shape
|
96
|
+
" #{j.to_json}"
|
97
|
+
end*",\n"
|
98
|
+
}\n ],"
|
99
|
+
|
100
|
+
fact_types = @vocabulary.constellation.
|
101
|
+
FactType.values.
|
102
|
+
reject{|ft|
|
103
|
+
ActiveFacts::Metamodel::LinkFactType === ft || ActiveFacts::Metamodel::TypeInheritance === ft
|
104
|
+
}
|
105
|
+
puts " fact_types: [\n#{
|
106
|
+
fact_types.sort_by{|f| f.identifying_role_values.inspect}.map do |f|
|
107
|
+
uuids[f] ||= uuid_from_id(f)
|
108
|
+
j = {:uuid => uuids[f]}
|
109
|
+
|
110
|
+
if f.entity_type
|
111
|
+
j[:objectified_as] = uuids[f.entity_type]
|
112
|
+
end
|
113
|
+
|
114
|
+
# Emit roles
|
115
|
+
roles = f.all_role.sort_by{|r| r.ordinal }
|
116
|
+
j[:roles] = roles.map do |role|
|
117
|
+
uuid = (uuids[role] ||= uuid_from_id(role))
|
118
|
+
# REVISIT: Internal Mandatory Constraints
|
119
|
+
# REVISIT: Place a ValueConstraint and shape
|
120
|
+
# REVISIT: Place a RoleName shape
|
121
|
+
{:uuid => uuid, :player => uuids[role.object_type]}
|
122
|
+
# N.B. The object_type shape to which this role is attached is not in the meta-model
|
123
|
+
# Attach to the closest instance on this diagram (if any)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Emit readings. Each is a [role_order, text] pair
|
127
|
+
j[:readings] = f.all_reading.map do |r|
|
128
|
+
role_refs = r.role_sequence.all_role_ref_in_order
|
129
|
+
[
|
130
|
+
role_order(uuids, role_refs.map{|rr| rr.role}, roles),
|
131
|
+
r.text.gsub(/\{([0-9])\}/) do |insert|
|
132
|
+
role_ref = role_refs[$1.to_i]
|
133
|
+
la = role_ref.leading_adjective
|
134
|
+
la = nil if la == ''
|
135
|
+
ta = role_ref.trailing_adjective
|
136
|
+
ta = nil if ta == ''
|
137
|
+
(la ? la+'-' : '') +
|
138
|
+
(la && la.index(' ') ? ' ' : '') +
|
139
|
+
insert +
|
140
|
+
(ta && ta.index(' ') ? ' ' : '') +
|
141
|
+
(ta ? '-'+ta : '')
|
142
|
+
end
|
143
|
+
]
|
144
|
+
end.sort_by{|(ro,text)| ro }.map do |(ro,text)|
|
145
|
+
[ ro, text ]
|
146
|
+
end
|
147
|
+
|
148
|
+
# Emit shapes
|
149
|
+
j[:shapes] = f.all_fact_type_shape.sort_by{|s| [s.location.x, s.location.y]}.map do |shape|
|
150
|
+
sj = {
|
151
|
+
:diagram => uuids[shape.orm_diagram],
|
152
|
+
:uuid => uuid_from_id(shape),
|
153
|
+
:x => shape.location.x,
|
154
|
+
:y => shape.location.y
|
155
|
+
}
|
156
|
+
|
157
|
+
# Add the role_order, if specified
|
158
|
+
if shape.all_role_display.size > 0
|
159
|
+
if shape.all_role_display.size != roles.size
|
160
|
+
raise "Invalid RoleDisplay for #{f.default_reading} in #{shape.orm_diagram.name} diagram"
|
161
|
+
end
|
162
|
+
ro = role_order(
|
163
|
+
uuids,
|
164
|
+
shape.all_role_display.sort_by{|rd| rd.ordinal }.map{|rd| rd.role },
|
165
|
+
roles
|
166
|
+
)
|
167
|
+
sj[:role_order] = ro if ro
|
168
|
+
end
|
169
|
+
|
170
|
+
# REVISIT: Place the ReadingShape
|
171
|
+
|
172
|
+
# Emit the location of the name, if objectified
|
173
|
+
if n = shape.objectified_fact_type_name_shape
|
174
|
+
sj[:name_shape] = {:x => n.location.x, :y => n.location.y}
|
175
|
+
end
|
176
|
+
sj
|
177
|
+
end
|
178
|
+
|
179
|
+
# Emit Internal Presence Constraints
|
180
|
+
f.internal_presence_constraints.to_a.sort_by{|ipc, z|
|
181
|
+
[ipc.is_preferred_identifier ? 0 : 1, ipc.is_mandatory ? 0 : 1, ipc.min_frequency || 0, ipc.max_frequency || 1_000]
|
182
|
+
}.each do |ipc|
|
183
|
+
uuid = (uuids[ipc] ||= uuid_from_id(ipc))
|
184
|
+
|
185
|
+
constraint = {
|
186
|
+
:uuid => uuid,
|
187
|
+
:min => ipc.min_frequency,
|
188
|
+
:max => ipc.max_frequency,
|
189
|
+
:is_preferred => ipc.is_preferred_identifier,
|
190
|
+
:mandatory => ipc.is_mandatory
|
191
|
+
}
|
192
|
+
|
193
|
+
# Get the role (or excluded role, for a UC)
|
194
|
+
roles = ipc.role_sequence.all_role_ref_in_order.map{|r| r.role}
|
195
|
+
if roles.size > 1 || (!ipc.is_mandatory && ipc.max_frequency == 1)
|
196
|
+
# This can be only a uniqueness constraint. Record the missing role, if any
|
197
|
+
role = (f.all_role.to_a - roles)[0]
|
198
|
+
constraint[:uniqueExcept] = uuids[role]
|
199
|
+
else
|
200
|
+
# An internal mandatory or frequency constraint applies to only one role.
|
201
|
+
# If it's also unique (max == 1), that applies on the counterpart role.
|
202
|
+
# You can also have a mandatory frequency constraint, but that applies on this role.
|
203
|
+
constraint[:role] = uuids[roles[0]]
|
204
|
+
end
|
205
|
+
(j[:constraints] ||= []) << constraint
|
206
|
+
end
|
207
|
+
|
208
|
+
# Add ring constraints
|
209
|
+
f.all_role_in_order.
|
210
|
+
map{|r| r.all_ring_constraint.to_a+r.all_ring_constraint_as_other_role.to_a }.
|
211
|
+
flatten.uniq.each do |ring|
|
212
|
+
(j[:constraints] ||= []) << {
|
213
|
+
:uuid => (uuids[ring] ||= uuid_from_id(ring)),
|
214
|
+
:shapes => ring.all_constraint_shape.sort_by{|s| [s.location.x, s.location.y]}.map do |shape|
|
215
|
+
{ :diagram => uuids[shape.orm_diagram],
|
216
|
+
:uuid => uuid_from_id(shape),
|
217
|
+
:x => shape.location.x,
|
218
|
+
:y => shape.location.y
|
219
|
+
}
|
220
|
+
end,
|
221
|
+
:ringKind => ring.ring_type,
|
222
|
+
:roles => [uuids[ring.role], uuids[ring.other_role]]
|
223
|
+
# REVISIT: Deontic, enforcement
|
224
|
+
}
|
225
|
+
end
|
226
|
+
|
227
|
+
# REVISIT: RotationSetting
|
228
|
+
|
229
|
+
" #{j.to_json}"
|
230
|
+
end*",\n"
|
231
|
+
}\n ],"
|
232
|
+
|
233
|
+
constraints = @vocabulary.constellation.
|
234
|
+
Constraint.values
|
235
|
+
puts " constraints: [\n#{
|
236
|
+
constraints.sort_by{|c|c.identifying_role_values.inspect}.select{|c| !uuids[c]}.map do |c|
|
237
|
+
uuid = uuids[c] ||= uuid_from_id(c)
|
238
|
+
j = {
|
239
|
+
:uuid => uuid,
|
240
|
+
:type => c.class.basename,
|
241
|
+
:shapes => c.all_constraint_shape.sort_by{|s| [s.location.x, s.location.y]}.map do |shape|
|
242
|
+
{ :diagram => uuids[shape.orm_diagram],
|
243
|
+
:uuid => uuid_from_id(shape),
|
244
|
+
:x => shape.location.x,
|
245
|
+
:y => shape.location.y
|
246
|
+
}
|
247
|
+
end
|
248
|
+
}
|
249
|
+
|
250
|
+
if (c.enforcement)
|
251
|
+
# REVISIT: Deontic constraint
|
252
|
+
end
|
253
|
+
if (c.concept.all_context_note_as_relevant_concept.size > 0)
|
254
|
+
# REVISIT: Context Notes
|
255
|
+
end
|
256
|
+
|
257
|
+
case c
|
258
|
+
when ActiveFacts::Metamodel::PresenceConstraint
|
259
|
+
j[:min_frequency] = c.min_frequency
|
260
|
+
j[:max_frequency] = c.max_frequency
|
261
|
+
j[:is_mandatory] = c.is_mandatory
|
262
|
+
j[:is_preferred_identifier] = c.is_preferred_identifier
|
263
|
+
rss = [c.role_sequence.all_role_ref_in_order.map(&:role)]
|
264
|
+
|
265
|
+
# Ignore internal presence constraints on TypeInheritance fact types
|
266
|
+
next nil if !c.role_sequence.all_role_ref.
|
267
|
+
detect{|rr|
|
268
|
+
!rr.role.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
|
269
|
+
}
|
270
|
+
|
271
|
+
when ActiveFacts::Metamodel::RingConstraint
|
272
|
+
next nil # These are emitted with the corresponding fact type
|
273
|
+
|
274
|
+
when ActiveFacts::Metamodel::SetComparisonConstraint
|
275
|
+
rss = c.
|
276
|
+
all_set_comparison_roles.sort_by{|scr| scr.ordinal}.
|
277
|
+
map{|scr| scr.role_sequence.all_role_ref_in_order.map(&:role) }
|
278
|
+
if (ActiveFacts::Metamodel::SetExclusionConstraint === c)
|
279
|
+
j[:is_mandatory] = c.is_mandatory
|
280
|
+
end
|
281
|
+
|
282
|
+
when ActiveFacts::Metamodel::SubsetConstraint
|
283
|
+
rss = [c.subset_role_sequence, c.superset_role_sequence].
|
284
|
+
map{|rs| rs.all_role_ref_in_order.map(&:role) }
|
285
|
+
|
286
|
+
when ActiveFacts::Metamodel::ValueConstraint
|
287
|
+
next nil # REVISIT: Should have been handled elsewhere
|
288
|
+
if (c.role)
|
289
|
+
# Should have been handled as role.role_value_constraint
|
290
|
+
elsif (c.value_type)
|
291
|
+
# Should have been handled as object_type.value_constraint
|
292
|
+
end
|
293
|
+
j[:allowed_ranges] = c.all_allowed_range.map{|ar|
|
294
|
+
[ ar.value_range.minimum_bound, ar.value_range.maximum_bound ].
|
295
|
+
map{|b| [b.value.literal, b.value.unit.name, b.is_inclusive] }
|
296
|
+
}
|
297
|
+
|
298
|
+
else
|
299
|
+
raise "REVISIT: Constraint type not yet dumped to JSON"
|
300
|
+
end
|
301
|
+
|
302
|
+
# rss contains the constrained role sequences; map to uuids
|
303
|
+
j[:role_sequences] = rss.map{|rs|
|
304
|
+
rs.map do |role|
|
305
|
+
uuids[role]
|
306
|
+
end
|
307
|
+
}
|
308
|
+
|
309
|
+
" #{j.to_json}"
|
310
|
+
end.compact*",\n"
|
311
|
+
}\n ]"
|
312
|
+
|
313
|
+
puts "}"
|
314
|
+
end
|
315
|
+
|
316
|
+
def role_order(uuids, roles, order)
|
317
|
+
if (roles.size > 9)
|
318
|
+
roles.map{|r| uuids[r] }
|
319
|
+
else
|
320
|
+
roles.map{|r| order.index(r).to_s }*''
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
def uuid_from_id o
|
325
|
+
irvs = o.identifying_role_values.inspect
|
326
|
+
d = Digest::SHA1.digest irvs
|
327
|
+
# $stderr.puts "#{o.class.basename}: #{irvs}"
|
328
|
+
d[0,4].unpack("H8")[0]+'-'+
|
329
|
+
d[4,2].unpack("H4")[0]+'-'+
|
330
|
+
d[6,2].unpack("H4")[0]+'-'+
|
331
|
+
d[8,2].unpack("H4")[0]+'-'+
|
332
|
+
d[10,6].unpack("H6")[0]
|
333
|
+
end
|
334
|
+
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
ActiveFacts::Registry.generator('diagrams/json', ActiveFacts::Generators::Diagrams::JSON)
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#
|
2
|
+
# ActiveFacts Generators.
|
3
|
+
# Provides help for afgen - from afgen --help
|
4
|
+
#
|
5
|
+
# Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
|
6
|
+
#
|
7
|
+
require 'activefacts/registry'
|
8
|
+
|
9
|
+
module ActiveFacts
|
10
|
+
module Generators
|
11
|
+
# Generate nothing from an ActiveFacts vocabulary. This is useful to check the file can be read ok.
|
12
|
+
# Invoke as
|
13
|
+
# afgen --null <file>.cql
|
14
|
+
class HELP
|
15
|
+
private
|
16
|
+
def initialize(vocabulary, *options)
|
17
|
+
generators = $:.
|
18
|
+
map{|path|
|
19
|
+
Dir[path+"/activefacts/generators/**/*.rb"].
|
20
|
+
reject{|p|
|
21
|
+
p =~ %r{/(transform|helpers)/}
|
22
|
+
}.
|
23
|
+
map{|p|
|
24
|
+
p.sub(%r{.*/activefacts/generators/}, '').sub(/\.rb/,'')
|
25
|
+
}
|
26
|
+
}
|
27
|
+
transformers = $:.
|
28
|
+
map{|path|
|
29
|
+
Dir[path+"/activefacts/generators/transform/**/*.rb"].
|
30
|
+
map{|p|
|
31
|
+
p.sub(%r{.*/activefacts/generators/}, '').sub(/\.rb/,'')
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
puts %Q{
|
36
|
+
Usage: afgen [ --transformer[=options] ... ] [ --generator[=options] ... ] file.inp[=options]
|
37
|
+
options are comma-separated lists. Use =help to get more information.
|
38
|
+
|
39
|
+
Available generators are:
|
40
|
+
#{generators.flatten.uniq.sort.join("\n\t")
|
41
|
+
}
|
42
|
+
|
43
|
+
Available transformers are:
|
44
|
+
#{transformers.flatten.uniq.sort.join("\n\t")
|
45
|
+
}
|
46
|
+
|
47
|
+
inp is the name of a file input handler. Available input handlers are:
|
48
|
+
#{$:.map{|path|
|
49
|
+
Dir[path+"/activefacts/input/**.rb"].map{|p|
|
50
|
+
p.sub(%r{.*/}, '').sub(/\.rb/,'')
|
51
|
+
}
|
52
|
+
}.flatten.uniq.sort.join("\n\t")
|
53
|
+
}
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
public
|
58
|
+
def generate(out = $>)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
ActiveFacts::Registry.generator('help', ActiveFacts::Generators::HELP)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'activefacts/metamodel'
|
2
|
+
|
3
|
+
module ActiveFacts
|
4
|
+
module TraitInjector
|
5
|
+
def self.included other
|
6
|
+
overlap = Metamodel.constants & other.constants
|
7
|
+
overlap.each do |const|
|
8
|
+
mix_into = Metamodel.const_get(const)
|
9
|
+
mix_in = other.const_get(const)
|
10
|
+
mix_into.instance_exec {
|
11
|
+
include(mix_in)
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
#
|
2
|
+
# ActiveFacts Generators.
|
3
|
+
# Base class for generators of class libraries in any object-oriented language that supports the ActiveFacts API.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
|
6
|
+
#
|
7
|
+
require 'activefacts/metamodel'
|
8
|
+
require 'activefacts/generators/helpers/ordered'
|
9
|
+
require 'activefacts/generators/traits/oo'
|
10
|
+
|
11
|
+
module ActiveFacts
|
12
|
+
module Generators
|
13
|
+
|
14
|
+
module Helpers
|
15
|
+
# Base class for generators of object-oriented class libraries for an ActiveFacts vocabulary.
|
16
|
+
class OO < OrderedDumper #:nodoc:
|
17
|
+
def constraints_dump
|
18
|
+
# Stub, not needed.
|
19
|
+
end
|
20
|
+
|
21
|
+
def value_type_banner
|
22
|
+
end
|
23
|
+
|
24
|
+
def value_type_end
|
25
|
+
end
|
26
|
+
|
27
|
+
def entity_type_dump(o)
|
28
|
+
o.ordered_dumped!
|
29
|
+
pi = o.preferred_identifier
|
30
|
+
|
31
|
+
supers = o.supertypes
|
32
|
+
if (supers.size > 0)
|
33
|
+
# Ignore identification by a supertype:
|
34
|
+
pi = nil if pi && pi.role_sequence.all_role_ref.detect{|rr| rr.role.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance) }
|
35
|
+
subtype_dump(o, supers, pi)
|
36
|
+
else
|
37
|
+
non_subtype_dump(o, pi)
|
38
|
+
end
|
39
|
+
pi.ordered_dumped! if pi
|
40
|
+
end
|
41
|
+
|
42
|
+
# Dump the roles for an object type (excluding the roles of a fact type which is objectified)
|
43
|
+
def roles_dump(o)
|
44
|
+
o.all_role.
|
45
|
+
select{|role|
|
46
|
+
role.fact_type.all_role.size <= 2 &&
|
47
|
+
!role.fact_type.is_a?(ActiveFacts::Metamodel::LinkFactType)
|
48
|
+
}.
|
49
|
+
sort_by{|role|
|
50
|
+
other_role = role.fact_type.all_role.select{|r2| r2 != role}[0] || role
|
51
|
+
other_role.preferred_role_name(o) + ':' + role.preferred_role_name(other_role.object_type)
|
52
|
+
}.each{|role|
|
53
|
+
role_dump(role)
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def role_dump(role)
|
58
|
+
fact_type = role.fact_type
|
59
|
+
if fact_type.all_role.size == 1
|
60
|
+
unary_dump(role, role.preferred_role_name)
|
61
|
+
return
|
62
|
+
end
|
63
|
+
return if role.fact_type.entity_type
|
64
|
+
|
65
|
+
if fact_type.all_role.size != 2
|
66
|
+
# Shouldn't come here, except perhaps for an invalid model
|
67
|
+
return # ternaries and higher are always objectified
|
68
|
+
end
|
69
|
+
|
70
|
+
# REVISIT: TypeInheritance
|
71
|
+
if fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
|
72
|
+
# trace "Ignoring role #{role} in #{fact_type}, subtype fact type"
|
73
|
+
# REVISIT: What about secondary subtypes?
|
74
|
+
# REVISIT: What about dumping the relational mapping when using separate tables?
|
75
|
+
return
|
76
|
+
end
|
77
|
+
|
78
|
+
return unless role.is_functional
|
79
|
+
|
80
|
+
other_role = fact_type.all_role.select{|r| r != role}[0]
|
81
|
+
other_role_name = other_role.preferred_role_name
|
82
|
+
other_player = other_role.object_type
|
83
|
+
|
84
|
+
# It's a one_to_one if there's a uniqueness constraint on the other role:
|
85
|
+
one_to_one = other_role.is_functional
|
86
|
+
return if one_to_one &&
|
87
|
+
!other_role.object_type.ordered_dumped
|
88
|
+
|
89
|
+
# Find role name:
|
90
|
+
role_method = role.preferred_role_name
|
91
|
+
other_role_method = one_to_one ? role_method : "all_"+role_method
|
92
|
+
# puts "---"+role.role_name if role.role_name
|
93
|
+
if other_role_name != other_player.oo_default_role_name and
|
94
|
+
role_method == role.object_type.oo_default_role_name
|
95
|
+
# debugger
|
96
|
+
other_role_method += "_as_#{other_role_name}"
|
97
|
+
end
|
98
|
+
|
99
|
+
role_name = role_method
|
100
|
+
role_name = nil if role_name == role.object_type.oo_default_role_name
|
101
|
+
|
102
|
+
b = role.ruby_role_definition
|
103
|
+
puts b
|
104
|
+
|
105
|
+
# binary_dump(role, other_role_name, other_player, role.is_mandatory, one_to_one, nil, role_name, other_role_method)
|
106
|
+
end
|
107
|
+
|
108
|
+
def skip_fact_type(f)
|
109
|
+
# REVISIT: There might be constraints we have to merge into the nested entity or subtype. These will come up as un-handled constraints.
|
110
|
+
!f.entity_type ||
|
111
|
+
f.is_a?(ActiveFacts::Metamodel::TypeInheritance)
|
112
|
+
end
|
113
|
+
|
114
|
+
# An objectified fact type has internal roles that are always "has_one":
|
115
|
+
def fact_roles_dump(fact_type)
|
116
|
+
fact_type.all_role.sort_by{|role|
|
117
|
+
role.preferred_role_name(fact_type.entity_type)
|
118
|
+
}.each{|role|
|
119
|
+
role_name = role.preferred_role_name(fact_type.entity_type)
|
120
|
+
one_to_one = role.is_unique
|
121
|
+
as = role_name != role.object_type.oo_default_role_name ? "_as_#{role_name}" : ""
|
122
|
+
# debugger if as != ''
|
123
|
+
raise "Fact #{fact_type.describe} type is not objectified" unless fact_type.entity_type
|
124
|
+
other_role_method = (one_to_one ? "" : "all_") +
|
125
|
+
fact_type.entity_type.oo_default_role_name +
|
126
|
+
as
|
127
|
+
binary_dump(role, role_name, role.object_type, true, one_to_one, nil, nil, other_role_method)
|
128
|
+
}
|
129
|
+
end
|
130
|
+
|
131
|
+
def entity_type_banner
|
132
|
+
end
|
133
|
+
|
134
|
+
def entity_type_group_end
|
135
|
+
end
|
136
|
+
|
137
|
+
def append_ring_to_reading(reading, ring)
|
138
|
+
# REVISIT: trace "Should override append_ring_to_reading"
|
139
|
+
end
|
140
|
+
|
141
|
+
def fact_type_banner
|
142
|
+
end
|
143
|
+
|
144
|
+
def fact_type_end
|
145
|
+
end
|
146
|
+
|
147
|
+
def constraint_banner
|
148
|
+
# trace "Should override constraint_banner"
|
149
|
+
end
|
150
|
+
|
151
|
+
def constraint_end
|
152
|
+
# trace "Should override constraint_end"
|
153
|
+
end
|
154
|
+
|
155
|
+
def constraint_dump(c)
|
156
|
+
# trace "Should override constraint_dump"
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|