activefacts 1.6.0 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
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