activefacts-generators 1.7.1

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.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +10 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +30 -0
  8. data/Rakefile +6 -0
  9. data/activefacts-generators.gemspec +26 -0
  10. data/lib/activefacts/dependency_analyser.rb +182 -0
  11. data/lib/activefacts/generators/absorption.rb +71 -0
  12. data/lib/activefacts/generators/composition.rb +119 -0
  13. data/lib/activefacts/generators/cql.rb +715 -0
  14. data/lib/activefacts/generators/diagrams/json.rb +340 -0
  15. data/lib/activefacts/generators/help.rb +64 -0
  16. data/lib/activefacts/generators/helpers/inject.rb +16 -0
  17. data/lib/activefacts/generators/helpers/oo.rb +162 -0
  18. data/lib/activefacts/generators/helpers/ordered.rb +605 -0
  19. data/lib/activefacts/generators/helpers/rails.rb +57 -0
  20. data/lib/activefacts/generators/html/glossary.rb +462 -0
  21. data/lib/activefacts/generators/metadata/json.rb +204 -0
  22. data/lib/activefacts/generators/null.rb +32 -0
  23. data/lib/activefacts/generators/rails/models.rb +247 -0
  24. data/lib/activefacts/generators/rails/schema.rb +217 -0
  25. data/lib/activefacts/generators/ruby.rb +134 -0
  26. data/lib/activefacts/generators/sql/mysql.rb +281 -0
  27. data/lib/activefacts/generators/sql/server.rb +274 -0
  28. data/lib/activefacts/generators/stats.rb +70 -0
  29. data/lib/activefacts/generators/text.rb +29 -0
  30. data/lib/activefacts/generators/traits/datavault.rb +241 -0
  31. data/lib/activefacts/generators/traits/oo.rb +73 -0
  32. data/lib/activefacts/generators/traits/ordered.rb +33 -0
  33. data/lib/activefacts/generators/traits/ruby.rb +210 -0
  34. data/lib/activefacts/generators/transform/datavault.rb +303 -0
  35. data/lib/activefacts/generators/transform/surrogate.rb +215 -0
  36. data/lib/activefacts/registry.rb +11 -0
  37. 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