activefacts 1.6.0 → 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 (169) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +14 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +60 -0
  8. data/Rakefile +3 -80
  9. data/activefacts.gemspec +36 -0
  10. data/bin/afgen +4 -2
  11. data/bin/cql +5 -1
  12. data/lib/activefacts.rb +3 -12
  13. data/lib/activefacts/{vocabulary/query_evaluator.rb → query/evaluator.rb} +0 -0
  14. data/lib/activefacts/version.rb +2 -2
  15. metadata +48 -296
  16. data/History.txt +0 -4
  17. data/LICENSE +0 -19
  18. data/Manifest.txt +0 -165
  19. data/README.rdoc +0 -81
  20. data/css/offline.css +0 -3
  21. data/css/orm2.css +0 -124
  22. data/css/print.css +0 -8
  23. data/css/style-print.css +0 -357
  24. data/css/style.css +0 -387
  25. data/download.html +0 -110
  26. data/examples/CQL/Address.cql +0 -44
  27. data/examples/CQL/Blog.cql +0 -54
  28. data/examples/CQL/CompanyDirectorEmployee.cql +0 -56
  29. data/examples/CQL/Death.cql +0 -17
  30. data/examples/CQL/Diplomacy.cql +0 -48
  31. data/examples/CQL/Genealogy.cql +0 -98
  32. data/examples/CQL/Insurance.cql +0 -320
  33. data/examples/CQL/Marriage.cql +0 -18
  34. data/examples/CQL/Metamodel.cql +0 -493
  35. data/examples/CQL/Monogamy.cql +0 -24
  36. data/examples/CQL/MultiInheritance.cql +0 -22
  37. data/examples/CQL/NonRoleId.cql +0 -14
  38. data/examples/CQL/OddIdentifier.cql +0 -18
  39. data/examples/CQL/OilSupply.cql +0 -53
  40. data/examples/CQL/OneToOnes.cql +0 -17
  41. data/examples/CQL/Orienteering.cql +0 -111
  42. data/examples/CQL/PersonPlaysGame.cql +0 -18
  43. data/examples/CQL/RedundantDependency.cql +0 -34
  44. data/examples/CQL/SchoolActivities.cql +0 -33
  45. data/examples/CQL/SeparateSubtype.cql +0 -30
  46. data/examples/CQL/ServiceDirector.cql +0 -276
  47. data/examples/CQL/SimplestUnary.cql +0 -12
  48. data/examples/CQL/Supervision.cql +0 -34
  49. data/examples/CQL/WaiterTips.cql +0 -33
  50. data/examples/CQL/Warehousing.cql +0 -101
  51. data/examples/CQL/WindowInRoomInBldg.cql +0 -28
  52. data/examples/CQL/unit.cql +0 -474
  53. data/examples/index.html +0 -420
  54. data/examples/intro.html +0 -327
  55. data/examples/local.css +0 -24
  56. data/index.html +0 -111
  57. data/lib/activefacts/cql.rb +0 -35
  58. data/lib/activefacts/cql/CQLParser.treetop +0 -158
  59. data/lib/activefacts/cql/Context.treetop +0 -48
  60. data/lib/activefacts/cql/Expressions.treetop +0 -67
  61. data/lib/activefacts/cql/FactTypes.treetop +0 -358
  62. data/lib/activefacts/cql/Language/English.treetop +0 -315
  63. data/lib/activefacts/cql/LexicalRules.treetop +0 -253
  64. data/lib/activefacts/cql/ObjectTypes.treetop +0 -210
  65. data/lib/activefacts/cql/Rakefile +0 -14
  66. data/lib/activefacts/cql/Terms.treetop +0 -183
  67. data/lib/activefacts/cql/ValueTypes.treetop +0 -202
  68. data/lib/activefacts/cql/compiler.rb +0 -156
  69. data/lib/activefacts/cql/compiler/clause.rb +0 -1137
  70. data/lib/activefacts/cql/compiler/constraint.rb +0 -581
  71. data/lib/activefacts/cql/compiler/entity_type.rb +0 -457
  72. data/lib/activefacts/cql/compiler/expression.rb +0 -443
  73. data/lib/activefacts/cql/compiler/fact.rb +0 -390
  74. data/lib/activefacts/cql/compiler/fact_type.rb +0 -421
  75. data/lib/activefacts/cql/compiler/query.rb +0 -106
  76. data/lib/activefacts/cql/compiler/shared.rb +0 -161
  77. data/lib/activefacts/cql/compiler/value_type.rb +0 -174
  78. data/lib/activefacts/cql/nodes.rb +0 -49
  79. data/lib/activefacts/cql/parser.rb +0 -241
  80. data/lib/activefacts/dependency_analyser.rb +0 -182
  81. data/lib/activefacts/generate/absorption.rb +0 -70
  82. data/lib/activefacts/generate/composition.rb +0 -118
  83. data/lib/activefacts/generate/cql.rb +0 -714
  84. data/lib/activefacts/generate/dm.rb +0 -279
  85. data/lib/activefacts/generate/help.rb +0 -64
  86. data/lib/activefacts/generate/helpers/inject.rb +0 -16
  87. data/lib/activefacts/generate/helpers/oo.rb +0 -162
  88. data/lib/activefacts/generate/helpers/ordered.rb +0 -605
  89. data/lib/activefacts/generate/helpers/rails.rb +0 -57
  90. data/lib/activefacts/generate/html/glossary.rb +0 -461
  91. data/lib/activefacts/generate/json.rb +0 -337
  92. data/lib/activefacts/generate/null.rb +0 -32
  93. data/lib/activefacts/generate/rails/models.rb +0 -246
  94. data/lib/activefacts/generate/rails/schema.rb +0 -216
  95. data/lib/activefacts/generate/records.rb +0 -46
  96. data/lib/activefacts/generate/ruby.rb +0 -133
  97. data/lib/activefacts/generate/sql/mysql.rb +0 -280
  98. data/lib/activefacts/generate/sql/server.rb +0 -273
  99. data/lib/activefacts/generate/stats.rb +0 -69
  100. data/lib/activefacts/generate/text.rb +0 -27
  101. data/lib/activefacts/generate/topics.rb +0 -265
  102. data/lib/activefacts/generate/traits/datavault.rb +0 -241
  103. data/lib/activefacts/generate/traits/oo.rb +0 -73
  104. data/lib/activefacts/generate/traits/ordered.rb +0 -33
  105. data/lib/activefacts/generate/traits/ruby.rb +0 -210
  106. data/lib/activefacts/generate/transform/datavault.rb +0 -266
  107. data/lib/activefacts/generate/transform/surrogate.rb +0 -214
  108. data/lib/activefacts/generate/version.rb +0 -26
  109. data/lib/activefacts/input/cql.rb +0 -43
  110. data/lib/activefacts/input/orm.rb +0 -1636
  111. data/lib/activefacts/mapping/rails.rb +0 -132
  112. data/lib/activefacts/persistence.rb +0 -15
  113. data/lib/activefacts/persistence/columns.rb +0 -446
  114. data/lib/activefacts/persistence/foreignkey.rb +0 -187
  115. data/lib/activefacts/persistence/index.rb +0 -240
  116. data/lib/activefacts/persistence/object_type.rb +0 -198
  117. data/lib/activefacts/persistence/reference.rb +0 -434
  118. data/lib/activefacts/persistence/tables.rb +0 -380
  119. data/lib/activefacts/registry.rb +0 -11
  120. data/lib/activefacts/support.rb +0 -132
  121. data/lib/activefacts/vocabulary.rb +0 -9
  122. data/lib/activefacts/vocabulary/extensions.rb +0 -1348
  123. data/lib/activefacts/vocabulary/metamodel.rb +0 -570
  124. data/lib/activefacts/vocabulary/verbaliser.rb +0 -804
  125. data/script/txt2html +0 -71
  126. data/spec/absorption_spec.rb +0 -95
  127. data/spec/cql/comparison_spec.rb +0 -89
  128. data/spec/cql/context_spec.rb +0 -94
  129. data/spec/cql/contractions_spec.rb +0 -224
  130. data/spec/cql/deontic_spec.rb +0 -88
  131. data/spec/cql/entity_type_spec.rb +0 -320
  132. data/spec/cql/expressions_spec.rb +0 -66
  133. data/spec/cql/fact_type_matching_spec.rb +0 -338
  134. data/spec/cql/french_spec.rb +0 -21
  135. data/spec/cql/parser/bad_literals_spec.rb +0 -86
  136. data/spec/cql/parser/constraints_spec.rb +0 -19
  137. data/spec/cql/parser/entity_types_spec.rb +0 -106
  138. data/spec/cql/parser/expressions_spec.rb +0 -199
  139. data/spec/cql/parser/fact_types_spec.rb +0 -44
  140. data/spec/cql/parser/literals_spec.rb +0 -312
  141. data/spec/cql/parser/pragmas_spec.rb +0 -89
  142. data/spec/cql/parser/value_types_spec.rb +0 -42
  143. data/spec/cql/role_matching_spec.rb +0 -148
  144. data/spec/cql/samples_spec.rb +0 -244
  145. data/spec/cql_cql_spec.rb +0 -73
  146. data/spec/cql_dm_spec.rb +0 -136
  147. data/spec/cql_mysql_spec.rb +0 -69
  148. data/spec/cql_parse_spec.rb +0 -34
  149. data/spec/cql_ruby_spec.rb +0 -73
  150. data/spec/cql_sql_spec.rb +0 -72
  151. data/spec/cql_symbol_tables_spec.rb +0 -261
  152. data/spec/cqldump_spec.rb +0 -170
  153. data/spec/helpers/array_matcher.rb +0 -23
  154. data/spec/helpers/ctrl_c_support.rb +0 -52
  155. data/spec/helpers/diff_matcher.rb +0 -39
  156. data/spec/helpers/file_matcher.rb +0 -34
  157. data/spec/helpers/parse_to_ast_matcher.rb +0 -80
  158. data/spec/helpers/string_matcher.rb +0 -30
  159. data/spec/helpers/test_parser.rb +0 -15
  160. data/spec/norma_cql_spec.rb +0 -66
  161. data/spec/norma_ruby_spec.rb +0 -62
  162. data/spec/norma_ruby_sql_spec.rb +0 -107
  163. data/spec/norma_sql_spec.rb +0 -57
  164. data/spec/norma_tables_spec.rb +0 -95
  165. data/spec/ruby_api_spec.rb +0 -23
  166. data/spec/spec_helper.rb +0 -35
  167. data/spec/transform_surrogate_spec.rb +0 -59
  168. data/status.html +0 -138
  169. data/why.html +0 -60
@@ -1,279 +0,0 @@
1
- #
2
- # ActiveFacts Generators.
3
- # Generate Ruby code for Data Mapper from an ActiveFacts vocabulary.
4
- #
5
- # A testing strategy:
6
- # Generate and load a set of models
7
- # call DataMapper::finalize to check they're consistent
8
- # call DataMapper::Spec.cleanup_models to delete them again
9
- #
10
- # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
11
- #
12
- require 'activefacts/vocabulary'
13
- require 'activefacts/persistence'
14
- require 'activefacts/generate/helpers/oo'
15
-
16
- module ActiveFacts
17
- module Generate
18
- class DM < Helpers::OO #:nodoc:
19
- # Generate SQL for DataMapper for an ActiveFacts vocabulary.
20
- # Invoke as
21
- # afgen --dm[=options] <file>.cql
22
- # Options:
23
- # dir=<mixins directory>
24
- # Example:
25
- # afgen --dm=dir=app/mixins MyApp.cql
26
- include Persistence
27
-
28
- def initialize(vocabulary, *options)
29
- @vocabulary = vocabulary
30
- @vocabulary = @vocabulary.Vocabulary.values[0] if ActiveFacts::API::Constellation === @vocabulary
31
- @mixins = options.grep(/^dir=/)[-1]
32
- @mixins && @mixins.sub!(/^dir=/,'')
33
- end
34
-
35
- def puts s
36
- @out.puts s
37
- end
38
-
39
- def model_file(name)
40
- @mixins+'/'+name.gsub(/\s/,'')+'.rb'
41
- end
42
-
43
- def class_name(name)
44
- name.gsub(/\s/,'')
45
- end
46
-
47
- def column_name(column)
48
- column.name('_').snakecase
49
- end
50
-
51
- def symbol_name(name)
52
- name.gsub(/\s/,'_').snakecase
53
- end
54
-
55
- def new_output(name)
56
- return unless @mixins
57
- @out.flush
58
- @out = File.open(model_file(name), "w")
59
- puts "require 'datamapper'\n\n"
60
- end
61
-
62
- def key_fields(ref, reverse = false)
63
- # Compute and return child_key and parent_key if necessary
64
- fk = ref.from.foreign_keys.detect{|k| k.jump_reference == ref}
65
- unless fk
66
- debugger
67
- raise "foreign key not found for #{ref}"
68
- end
69
- child_key = fk.from_columns.map{|c| column_name(c)}
70
- parent_key = fk.to_columns.map{|c| column_name(c)}
71
- if child_key != parent_key
72
- c, p = *(reverse ? ['parent', 'child'] : ['child', 'parent'])
73
- ", :#{c}_key => [:#{child_key*', :'}], :#{p}_key => [:#{parent_key*', :'}]"
74
- else
75
- ''
76
- end
77
- end
78
-
79
- public
80
-
81
- def generate(out = $>) #:nodoc:
82
- @out = out
83
-
84
- # Calculate the relational absorption:
85
- tables = @vocabulary.tables
86
-
87
- # Figure out which ObjectType will be models (tables and their subtypes)
88
- models =
89
- @vocabulary.all_object_type.sort_by{|o| o.name}.select do |o|
90
- next false if o.name =~ /_?ImplicitBooleanValueType/
91
- o.is_table || (o.absorbed_via && o.absorbed_via.role_type == :supertype)
92
- end
93
- is_model = models.inject({}) { |h, m| h[m] = true; h }
94
-
95
- puts "require 'dm-core'"
96
- puts "require 'dm-constraints'"
97
- puts "\n"
98
-
99
- # Dump tables until all done, subtypes before supertypes:
100
- until models.empty?
101
- # Choose another object type that we can dump now:
102
- o = models.detect do |o|
103
- next true if o.is_table
104
- next true if a = o.absorbed_via and a.role_type == :supertype and supertype = a.from and !models.include?(supertype)
105
- false
106
- end
107
- models.delete(o)
108
-
109
- supertype = (a = o.absorbed_via and a.role_type == :supertype) ? supertype = a.from : nil
110
- if o.is_a?(ActiveFacts::Metamodel::EntityType)
111
- if secondary_supertypes = o.supertypes-[supertype] and
112
- secondary_supertypes.size > 0 and
113
- secondary_supertypes.detect do |sst|
114
- sst_ref_facts = sst.preferred_identifier.role_sequence.all_role_ref.map{|rr| rr.role.fact_type}.uniq
115
- non_identifying_inheritable_references =
116
- sst.references_from.reject do |ref|
117
- sst_ref_facts.include?(ref.fact_type)
118
- end
119
- non_identifying_inheritable_references.size > 0
120
- end
121
- raise "Cannot map classes like #{o.name} with roles inherited from external supertypes (#{secondary_supertypes.map{|t|t.name}*", "})"
122
- end
123
- pi = o.preferred_identifier
124
- identifying_role_refs = pi.role_sequence.all_role_ref.sort_by{|role_ref| role_ref.ordinal}
125
- identifying_facts = ([o.fact_type]+identifying_role_refs.map{|rr| rr.role.fact_type }).compact.uniq
126
- else
127
- identifying_facts = []
128
- end
129
-
130
- # REVISIT: STI fails where the base class is absorbed into another table, like Incident in Insurance for example.
131
- # In this case you get the subtype fields absorbed and should not get an STI model.
132
-
133
- puts "class #{class_name(o.name)}#{supertype ? " < #{class_name(supertype.name)}" : ''}"
134
- puts " include DataMapper::Resource\n\n" unless supertype
135
-
136
- columns = o.columns
137
- o.references_from.sort_by{|r| r.to_s}.each do |ref|
138
- # A (set of) columns
139
- if !columns
140
- # absorbed subtypes didn't have columns populated
141
- columns = o.all_columns({})
142
- end
143
-
144
- next if [:subtype, :supertype].include?(ref.role_type)
145
- # debugger if ref_columns.detect{|c| [:subtype, :supertype].include?(c.references[0].role_type)}
146
- ref_columns = columns.select{|c| c.references[0] == ref }
147
- # puts " \# #{ref.reading}:"
148
- ref_columns.sort_by{|column| column_name(column)}.each do |column|
149
- type, params, constraints = column.type
150
- length = params[:length]
151
- length &&= length.to_i
152
- scale = params[:scale]
153
- scale &&= scale.to_i
154
- type, length = normalise_type(type, length)
155
- key = identifying_facts.include?(column.references[0].fact_type) ||
156
- (identifying_facts.empty? && ref.is_self_value)
157
- cname = column_name(column)
158
- required = column.is_mandatory && !key ? ", :required => true" : "" # Key fields are implicitly required
159
- if type == 'Serial'
160
- if !key || o.preferred_identifier.role_sequence.all_role_ref.size != 1
161
- type = 'Integer'
162
- else
163
- key = false # This is implicit
164
- end
165
- end
166
- $stderr.puts "Warning: non-mandatory key field #{o.name}.#{column.name} is forced to mandatory" if !column.is_mandatory && key
167
- puts " property :#{column_name(column)}, #{type}#{length ? ", :length => "+length.to_s : ''}#{required}#{key ? ', :key => true' : ''}\t\# #{column.comment}"
168
- end
169
-
170
- if is_model[ref.to]
171
- # An association
172
- reverse = false
173
- association_type =
174
- case ref.role_type
175
- when :one_one
176
- reverse = true
177
- "has 1,"
178
- when :one_many, :many_one
179
- "belongs_to"
180
- when :supertype
181
- next
182
- when :subtype
183
- next
184
- else
185
- raise "role type #{ref.role_type} not handled"
186
- end
187
-
188
- association_name = (ref.to_names*'_')
189
- model_name = association_name != ref.to.name ? model_name = ", '#{class_name(ref.to.name)}'" : ''
190
- comment = o.fact_type ? "#{association_name} is involved in #{o.name}" : ref.reading
191
- keys = key_fields(ref, reverse)
192
- puts " #{association_type} :#{association_name.downcase}#{model_name}#{keys}\t\# #{comment}"
193
- end
194
- end
195
-
196
- # Emit the "has n," associations
197
- # REVISIT: Need to use ActiveSupport to pluralise these names, or disable inflexion somehow.
198
- o.references_to.sort_by{|r| [r.to_s, (r.from_role||r.to_role).ordinal] }.each do |ref|
199
- next unless is_model[ref.from]
200
- constraint = ''
201
- association_type =
202
- case ref.role_type
203
- when :one_one
204
- "has 1,"
205
- when :many_one, :one_many
206
- constraint = ', :constraint => :destroy' # REVISIT: Check mandatory, and use nullify?
207
- "has n,"
208
- else
209
- next
210
- end
211
- prr = ref.fact_type.preferred_reading.role_sequence.all_role_ref.detect{|rr| rr.role == ref.to_role}
212
- association_name = (ref.from_names*'_')
213
- if prr && (prr.role.role_name || prr.leading_adjective || prr.trailing_adjective)
214
- association_name += "_as_"+symbol_name(ref.to_names*'_')
215
- end
216
- model_name = association_name != ref.from.name ? model_name = ", '#{class_name(ref.from.name)}'" : ''
217
- comment = o.is_a?(ActiveFacts::Metamodel::EntityType) && o.fact_type ? "#{association_name} is involved in #{o.name}" : ref.reading
218
- keys = key_fields(ref)
219
-
220
- puts " #{association_type} :#{association_name.downcase}#{model_name}#{keys}\t\# #{comment}"
221
- end
222
- puts "end\n\n"
223
- end
224
- end
225
-
226
-
227
- # Return DataMapper type and (modified?) length for the passed base type
228
- def normalise_type(type, length)
229
- dm_type = case type
230
- when /^Auto ?Counter$/
231
- 'Serial'
232
-
233
- when /^Unsigned ?Integer$/,
234
- /^Signed ?Integer$/,
235
- /^Unsigned ?Small ?Integer$/,
236
- /^Signed ?Small ?Integer$/,
237
- /^Unsigned ?Tiny ?Integer$/
238
- length = nil
239
- 'Integer'
240
-
241
- when /^Decimal$/
242
- 'Decimal'
243
-
244
- when /^Fixed ?Length ?Text$/, /^Char$/
245
- 'String'
246
- when /^Variable ?Length ?Text$/, /^String$/
247
- 'String'
248
- when /^Large ?Length ?Text$/, /^Text$/
249
- 'Text'
250
-
251
- when /^Date ?And ?Time$/, /^Date ?Time$/
252
- 'DateTime'
253
- when /^Date$/
254
- 'DateTime'
255
- when /^Time$/
256
- 'DateTime'
257
- when /^Auto ?Time ?Stamp$/
258
- 'DateTime'
259
-
260
- when /^Money$/
261
- 'Decimal'
262
- when /^Picture ?Raw ?Data$/, /^Image$/
263
- 'String'
264
- when /^Variable ?Length ?Raw ?Data$/, /^Blob$/
265
- 'String'
266
- when /^BIT$/
267
- 'Boolean'
268
- else
269
- # raise "DataMapper type unknown for standard type #{type}"
270
- type
271
- end
272
- [dm_type, length]
273
- end
274
-
275
- end
276
- end
277
- end
278
-
279
- ActiveFacts::Registry.generator('dm', ActiveFacts::Generate::DM)
@@ -1,64 +0,0 @@
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/persistence'
8
-
9
- module ActiveFacts
10
- module Generate
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/generate/**/*.rb"].
20
- reject{|p|
21
- p =~ %r{/(transform|helpers)/}
22
- }.
23
- map{|p|
24
- p.sub(%r{.*/activefacts/generate/}, '').sub(/\.rb/,'')
25
- }
26
- }
27
- transformers = $:.
28
- map{|path|
29
- Dir[path+"/activefacts/generate/transform/**/*.rb"].
30
- map{|p|
31
- p.sub(%r{.*/activefacts/generate/}, '').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::Generate::HELP)
@@ -1,16 +0,0 @@
1
- require 'activefacts/vocabulary'
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
@@ -1,162 +0,0 @@
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/vocabulary'
8
- require 'activefacts/generate/helpers/ordered'
9
- require 'activefacts/generate/traits/oo'
10
-
11
- module ActiveFacts
12
- module Generate
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