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,273 +0,0 @@
1
- #
2
- # ActiveFacts Generators.
3
- # Generate SQL for SQL Server from an ActiveFacts vocabulary.
4
- #
5
- # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
6
- #
7
- require 'activefacts/vocabulary'
8
- require 'activefacts/persistence'
9
-
10
- module ActiveFacts
11
- module Generate
12
- module SQL #:nodoc:
13
- # Generate SQL for SQL Server for an ActiveFacts vocabulary.
14
- # Invoke as
15
- # afgen --sql/server[=options] <file>.cql
16
- # Options are comma or space separated:
17
- # * delay_fks Leave all foreign keys until the end, not just those that contain forward-references
18
- class SERVER
19
- private
20
- include Persistence
21
- ColumnNameMax = 40
22
-
23
- RESERVED_WORDS = %w{
24
- ADD ALL ALTER AND ANY AS ASC AUTHORIZATION BACKUP BEGIN BETWEEN
25
- BREAK BROWSE BULK BY CASCADE CASE CHECK CHECKPOINT CLOSE CLUSTERED
26
- COALESCE COLLATE COLUMN COMMIT COMPUTE CONSTRAINT CONTAINS CONTAINSTABLE
27
- CONTINUE CONVERT CREATE CROSS CURRENT CURRENT_DATE CURRENT_TIME
28
- CURRENT_TIMESTAMP CURRENT_USER CURSOR DATABASE DBCC DEALLOCATE
29
- DECLARE DEFAULT DELETE DENY DESC DISK DISTINCT DISTRIBUTED DOUBLE
30
- DROP DUMMY DUMP ELSE END ERRLVL ESCAPE EXCEPT EXEC EXECUTE EXISTS
31
- EXIT FETCH FILE FILLFACTOR FOR FOREIGN FREETEXT FREETEXTTABLE FROM
32
- FULL FUNCTION GOTO GRANT GROUP HAVING HOLDLOCK IDENTITY IDENTITYCOL
33
- IDENTITY_INSERT IF IN INDEX INNER INSERT INTERSECT INTO IS JOIN KEY
34
- KILL LEFT LIKE LINENO LOAD NATIONAL NOCHECK NONCLUSTERED NOT NULL
35
- NULLIF OF OFF OFFSETS ON OPEN OPENDATASOURCE OPENQUERY OPENROWSET
36
- OPENXML OPTION OR ORDER OUTER OVER PERCENT PLAN PRECISION PRIMARY
37
- PRINT PROC PROCEDURE PUBLIC RAISERROR READ READTEXT RECONFIGURE
38
- REFERENCES REPLICATION RESTORE RESTRICT RETURN REVOKE RIGHT ROLLBACK
39
- ROWCOUNT ROWGUIDCOL RULE SAVE SCHEMA SELECT SESSION_USER SET SETUSER
40
- SHUTDOWN SOME STATISTICS SYSTEM_USER TABLE TEXTSIZE THEN TO TOP
41
- TRAN TRANSACTION TRIGGER TRUNCATE TSEQUAL UNION UNIQUE UPDATE
42
- UPDATETEXT USE USER VALUES VARYING VIEW WAITFOR WHEN WHERE WHILE
43
- WITH WRITETEXT
44
- }.inject({}){ |h,w| h[w] = true; h }
45
-
46
- def initialize(vocabulary, *options)
47
- @vocabulary = vocabulary
48
- @vocabulary = @vocabulary.Vocabulary.values[0] if ActiveFacts::API::Constellation === @vocabulary
49
- @delay_fks = options.include? "delay_fks"
50
- @underscore = options.include?("underscore") ? "_" : ""
51
- end
52
-
53
- def puts s
54
- @out.puts s
55
- end
56
-
57
- def go s
58
- puts s
59
- puts "GO\n\n"
60
- end
61
-
62
- def escape s
63
- # Escape SQL keywords and non-identifiers
64
- s = s[0...120]
65
- if s =~ /[^A-Za-z0-9_]/ || RESERVED_WORDS[s.upcase]
66
- "[#{s}]"
67
- else
68
- s
69
- end
70
- end
71
-
72
- # Return SQL type and (modified?) length for the passed base type
73
- def normalise_type(type, length)
74
- sql_type = case type
75
- when /^Auto ?Counter$/
76
- 'int'
77
-
78
- when /^Unsigned ?Integer$/,
79
- /^Signed ?Integer$/,
80
- /^Unsigned ?Small ?Integer$/,
81
- /^Signed ?Small ?Integer$/,
82
- /^Unsigned ?Tiny ?Integer$/
83
- s = case
84
- when length <= 8
85
- 'tinyint'
86
- when length <= 16
87
- 'smallint'
88
- when length <= 32
89
- 'int'
90
- else
91
- 'bigint'
92
- end
93
- length = nil
94
- s
95
-
96
- when /^Decimal$/
97
- 'decimal'
98
-
99
- when /^Fixed ?Length ?Text$/, /^Char$/
100
- 'char'
101
- when /^Variable ?Length ?Text$/, /^String$/
102
- 'varchar'
103
- when /^Large ?Length ?Text$/, /^Text$/
104
- 'text'
105
-
106
- when /^Date ?And ?Time$/, /^Date ?Time$/
107
- 'datetime'
108
- when /^Date$/
109
- 'datetime' # SQLSVR 2K5: 'date'
110
- when /^Time$/
111
- 'datetime' # SQLSVR 2K5: 'time'
112
- when /^Auto ?Time ?Stamp$/
113
- 'timestamp'
114
-
115
- when /^Guid$/
116
- 'uniqueidentifier'
117
- when /^Money$/
118
- 'decimal'
119
- when /^Picture ?Raw ?Data$/, /^Image$/
120
- 'image'
121
- when /^Variable ?Length ?Raw ?Data$/, /^Blob$/
122
- 'varbinary'
123
- when /^BIT$/
124
- 'bit'
125
- else type # raise "SQL type unknown for standard type #{type}"
126
- end
127
- [sql_type, length]
128
- end
129
-
130
- public
131
- def generate(out = $>) #:nodoc:
132
- @out = out
133
- #go "CREATE SCHEMA #{@vocabulary.name}"
134
-
135
- tables_emitted = {}
136
- delayed_foreign_keys = []
137
-
138
- @vocabulary.tables.each do |table|
139
- puts "CREATE TABLE #{escape table.name.gsub(' ',@underscore)} ("
140
-
141
- pk = table.identifier_columns
142
- identity_column = pk[0] if pk[0].is_auto_assigned
143
-
144
- fk_refs = table.references_from.select{|ref| ref.is_simple_reference }
145
- fk_columns = table.columns.select do |column|
146
- column.references[0].is_simple_reference
147
- end
148
-
149
- # We sort the columns here, not in the persistence layer, because it affects
150
- # the ordering of columns in an index :-(.
151
- columns = table.columns.sort_by { |column| column.name(@underscore) }.map do |column|
152
- name = escape column.name(@underscore)
153
- padding = " "*(name.size >= ColumnNameMax ? 1 : ColumnNameMax-name.size)
154
- type, params, constraints = column.type
155
- constraints = [] if (fk_columns.include?(column)) # Don't enforce VT constraints on FK columns
156
- length = params[:length]
157
- length &&= length.to_i
158
- scale = params[:scale]
159
- scale &&= scale.to_i
160
- type, length = normalise_type(type, length)
161
- sql_type = "#{type}#{
162
- if !length
163
- ""
164
- else
165
- "(" + length.to_s + (scale ? ", #{scale}" : "") + ")"
166
- end
167
- }"
168
- # Emit IDENTITY for auto-assigned columns, unless it's assigned at assert:
169
- identity = column == identity_column && column.references[-1].to.transaction_phase != 'assert' ? " IDENTITY" : ""
170
- null = (column.is_mandatory ? "NOT " : "") + "NULL"
171
- check = check_clause(name, constraints)
172
- comment = column.comment
173
- [ "-- #{comment}", "#{name}#{padding}#{sql_type}#{identity} #{null}#{check}" ]
174
- end.flatten
175
-
176
- pk_def = (pk.detect{|column| !column.is_mandatory} ? "UNIQUE(" : "PRIMARY KEY(") +
177
- pk.map{|column| escape column.name(@underscore)}*", " +
178
- ")"
179
-
180
- inline_fks = []
181
- table.foreign_keys.each do |fk|
182
- fk_text = "FOREIGN KEY (" +
183
- fk.from_columns.map{|column| column.name(@underscore)}*", " +
184
- ") REFERENCES #{escape fk.to.name.gsub(' ',@underscore)} (" +
185
- fk.to_columns.map{|column| column.name(@underscore)}*", " +
186
- ")"
187
- if !@delay_fks and # We don't want to delay all Fks
188
- (tables_emitted[fk.to] or # The target table has been emitted
189
- fk.to == table && !fk.to_columns.detect{|column| !column.is_mandatory}) # The reference columns already have the required indexes
190
- inline_fks << fk_text
191
- else
192
- delayed_foreign_keys << ("ALTER TABLE #{escape fk.from.name.gsub(' ',@underscore)}\n\tADD " + fk_text)
193
- end
194
- end
195
-
196
- indices = table.indices
197
- inline_indices = []
198
- delayed_indices = []
199
- indices.each do |index|
200
- next if index.over == table && index.is_primary # Already did the primary keys
201
- abbreviated_column_names = index.abbreviated_column_names(@underscore)*""
202
- column_names = index.column_names(@underscore)
203
- column_name_list = column_names.map{|n| escape(n)}*", "
204
- if index.columns.all?{|column| column.is_mandatory}
205
- inline_indices << "UNIQUE(#{column_name_list})"
206
- else
207
- view_name = escape "#{index.view_name}_#{abbreviated_column_names}"
208
- delayed_indices <<
209
- %Q{CREATE VIEW dbo.#{view_name} (#{column_name_list}) WITH SCHEMABINDING AS
210
- \tSELECT #{column_name_list} FROM dbo.#{escape index.on.name.gsub(' ',@underscore)}
211
- \tWHERE\t#{
212
- index.columns.
213
- select{|column| !column.is_mandatory }.
214
- map{|column|
215
- escape(column.name(@underscore)) + " IS NOT NULL"
216
- }*"\n\t AND\t"
217
- }
218
- GO
219
-
220
- CREATE UNIQUE CLUSTERED INDEX #{escape index.name} ON dbo.#{view_name}(#{index.columns.map{|column| column.name(@underscore)}*", "})
221
- }
222
- end
223
- end
224
-
225
- tables_emitted[table] = true
226
-
227
- puts("\t" + (columns + [pk_def] + inline_indices + inline_fks)*",\n\t")
228
- go ")"
229
- delayed_indices.each {|index_text|
230
- go index_text
231
- }
232
- end
233
-
234
- delayed_foreign_keys.each do |fk|
235
- go fk
236
- end
237
- end
238
-
239
- private
240
- def sql_value(value)
241
- value.is_literal_string ? sql_string(value.literal) : value.literal
242
- end
243
-
244
- def sql_string(str)
245
- "'" + str.gsub(/'/,"''") + "'"
246
- end
247
-
248
- def check_clause(column_name, constraints)
249
- return "" if constraints.empty?
250
- # REVISIT: Merge all constraints (later; now just use the first)
251
- " CHECK(" +
252
- constraints[0].all_allowed_range_sorted.map do |ar|
253
- vr = ar.value_range
254
- min = vr.minimum_bound
255
- max = vr.maximum_bound
256
- if (min && max && max.value.literal == min.value.literal)
257
- "#{column_name} = #{sql_value(min.value)}"
258
- else
259
- inequalities = [
260
- min && "#{column_name} >#{min.is_inclusive ? "=" : ""} #{sql_value(min.value)}",
261
- max && "#{column_name} <#{max.is_inclusive ? "=" : ""} #{sql_value(max.value)}"
262
- ].compact
263
- inequalities.size > 1 ? "(" + inequalities*" AND " + ")" : inequalities[0]
264
- end
265
- end*" OR " +
266
- ")"
267
- end
268
- end
269
- end
270
- end
271
- end
272
-
273
- ActiveFacts::Registry.generator('sql/server', ActiveFacts::Generate::SQL::SERVER)
@@ -1,69 +0,0 @@
1
- #
2
- # ActiveFacts Generators.
3
- # Generate metamodel statistics fora compiled vocabulary
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 a text verbalisation of the metamodel constellation created for an ActiveFacts vocabulary.
12
- # Invoke as
13
- # afgen --text <file>.cql
14
- class Statistics
15
- private
16
- def initialize(vocabulary)
17
- @vocabulary = vocabulary
18
- @vocabulary = @vocabulary.Vocabulary.values[0] if ActiveFacts::API::Constellation === @vocabulary
19
- end
20
-
21
- public
22
- def generate(out = $>)
23
- constellation = @vocabulary.constellation
24
- object_types = constellation.ObjectType.values
25
- fact_types = constellation.FactType.values
26
-
27
- # All metamodel object types:
28
- object_count = 0
29
- populated_object_type_count = 0
30
- fact_types_processed = {}
31
- fact_count = 0
32
- role_played_count = 0
33
- constellation.vocabulary.object_type.map do |object_type_name, object_type|
34
- objects = constellation.send(object_type_name)
35
- next unless objects.size > 0
36
- puts "\t#{object_type_name}: #{objects.size} instances (which play #{object_type.all_role.size} roles)"
37
- populated_object_type_count += 1
38
- object_count += objects.size
39
-
40
- #puts "#{object_type_name} has #{object_type.all_role.size} roles"
41
- object_type.all_role.each do |name, role|
42
- next unless role.unique
43
- next if fact_types_processed[role.fact_type]
44
- next if role.fact_type.is_a?(ActiveFacts::API::TypeInheritanceFactType)
45
- role_population_count =
46
- objects.values.inject(0) do |count, object|
47
- count += 1 if object.send(role.name) != nil
48
- count
49
- end
50
- puts "\t\t#{object_type_name}.#{role.name} has #{role_population_count} instances" if role_population_count > 0
51
- fact_count += role_population_count
52
- role_played_count += role_population_count*role.fact_type.all_role.size
53
-
54
- fact_types_processed[role.fact_type] = true
55
- end
56
-
57
- end
58
- puts "#{@vocabulary.name} has"
59
- puts "\t#{object_types.size} object types"
60
- puts "\t#{fact_types.size} fact types"
61
- puts "\tcompiles to #{object_count} objects in total, of #{populated_object_type_count} metamodel types"
62
- puts "\tcompiles to #{fact_count} facts in total, of #{fact_types_processed.size} metamodel fact types"
63
- puts "\tcompiles to #{role_played_count} role instances in total"
64
- end
65
- end
66
- end
67
- end
68
-
69
- ActiveFacts::Registry.generator('records', ActiveFacts::Generate::Statistics)
@@ -1,27 +0,0 @@
1
- #
2
- # ActiveFacts Generators.
3
- # Generate text output (verbalise the meta-vocabulary) for ActiveFacts vocabularies.
4
- #
5
- # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
6
- #
7
- module ActiveFacts
8
- module Generate
9
- # Generate a text verbalisation of the metamodel constellation created for an ActiveFacts vocabulary.
10
- # Invoke as
11
- # afgen --text <file>.cql
12
- class TEXT
13
- private
14
- def initialize(vocabulary)
15
- @vocabulary = vocabulary
16
- @vocabulary = @vocabulary.Vocabulary.values[0] if ActiveFacts::API::Constellation === @vocabulary
17
- end
18
-
19
- public
20
- def generate(out = $>)
21
- out.puts @vocabulary.constellation.verbalise
22
- end
23
- end
24
- end
25
- end
26
-
27
- ActiveFacts::Registry.generator('text', ActiveFacts::Generate::TEXT)
@@ -1,265 +0,0 @@
1
- #
2
- # ActiveFacts Generators.
3
- # Generate metamodel topic hierarchy (topologically sorted) for a compiled vocabulary
4
- #
5
- # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
6
- #
7
- require 'activefacts/dependency_analyser'
8
- require 'activefacts/persistence'
9
-
10
- module ActiveFacts
11
- module Generate
12
- # Generate a topic hierarchy of the metamodel constellation created for an ActiveFacts vocabulary.
13
- # Invoke as
14
- # afgen --topics <file>.cql
15
- class Topics
16
- private
17
- def initialize(vocabulary)
18
- @vocabulary = vocabulary
19
- @vocabulary = @vocabulary.Vocabulary.values[0] if ActiveFacts::API::Constellation === @vocabulary
20
- end
21
-
22
- public
23
- def generate(out = $>)
24
- @constellation = @vocabulary.constellation
25
-
26
- @concepts = @constellation.Concept.values.select do |c|
27
- !c.embodied_as.is_a?(ActiveFacts::Metamodel::Role) &&
28
- !c.implication_rule
29
- end
30
-
31
- @concept_deps = ActiveFacts::DependencyAnalyser.new(@concepts) {|c| c.precursors }
32
-
33
- # list_concepts(@concept_deps)
34
- # list_precursors(@concept_deps)
35
- # list_followers(@concept_deps)
36
- # list_chasers(@concept_deps)
37
- # list_ranks(@concept_deps)
38
-
39
- # @constellation.Topic.values.each do |topic|
40
- # puts "#{topic.topic_name} depends on #{topic.precursors.map(&:topic_name)*', '}"
41
- # end
42
-
43
- # analyse_topic_sequence
44
-
45
- list_groups_by_rank @concept_deps
46
-
47
- end
48
-
49
- def list_concepts concept_deps
50
- puts "Concepts are"
51
- concept_deps.each do |concept|
52
- puts "\t#{concept.describe}"
53
- end
54
- puts
55
- end
56
-
57
- def list_precursors(concept_deps)
58
- puts "Precursors are"
59
- concept_deps.each do |concept|
60
- next unless (p = concept_deps.precursors(concept)).size > 0
61
- puts "#{concept.describe}:"
62
- p.each do |precursor|
63
- puts "\t#{precursor.describe}"
64
- end
65
- end
66
- end
67
-
68
- def list_followers(concept_deps)
69
- puts "Followers are:"
70
- concept_deps.each do |concept|
71
- next unless (f = concept_deps.followers(concept)).size > 0
72
- puts "#{concept.describe}:"
73
- f.each do |follower|
74
- puts "\t#{follower.describe}"
75
- end
76
- end
77
- end
78
-
79
- def list_chasers(concept_deps)
80
- puts "Chasers are:"
81
- concept_deps.each do |concept|
82
- next unless (f = concept_deps.chasers(concept)).size > 0
83
- puts "#{concept.describe}:"
84
- f.each do |follower|
85
- puts "\t#{follower.describe}"
86
- end
87
- end
88
- end
89
-
90
- def list_ranks(concept_deps)
91
- puts "Ranks are:"
92
- page_rank = concept_deps.page_rank
93
- page_rank.keys.sort_by{|k| -page_rank[k]}.each do |concept|
94
- puts("%8.4f\t%s" % [page_rank[concept], concept.describe])
95
- end
96
- end
97
-
98
- def analyse_topic_sequence
99
- if @constellation.Topic.size == 1
100
- @topics = @constellation.Topic.values.first
101
- else
102
- puts "=== Analysing existing topics ==="
103
- @topic_analyser = ActiveFacts::DependencyAnalyser.new(@constellation.Topic.values) do |topic|
104
- topic.precursors
105
- end
106
-
107
- @topics = []
108
- failed_topics = @topic_analyser.tsort { |topic|
109
- @topics << topic
110
- puts "#{topic.topic_name} including #{topic.all_concept.size} concepts"
111
- }
112
- if failed_topics
113
- puts "Topological sort of topics is impossible"
114
-
115
- # REVISIT: The strategy here should be to look at the structure of the dependency loop
116
- # involving the highest-rank topic. Choose the loop member that has fewest dependencies
117
- # involving individual concepts, and dump that (it will need to flip topic to dump
118
- # those dependencies). That should break the loop in a minimal way, so we can continue.
119
-
120
- failed_topics.each do |topic, precursor_topics|
121
- puts "#{topic.topic_name} depends on:"
122
- precursor_topics.each do |precursor_topic|
123
- puts "\t#{precursor_topic.topic_name} because of:"
124
-
125
- blocking_concept =
126
- precursor_topic.all_concept.select{|concept|
127
- concept.precursors.detect{|cp|
128
- cp.topic == precursor_topic
129
- }
130
- }
131
-
132
- blocking_concept.each do |concept|
133
- puts "\t\t#{concept.describe} (depends on #{concept.precursors.map(&:topic).uniq.map(&:topic_name).sort.inspect})"
134
- end
135
- end
136
- end
137
- return
138
- end
139
- end
140
- end
141
-
142
- def list_groups_by_rank concept_deps
143
- puts "=== Concepts listed in Ranking Order with chasers ==="
144
- # List the highest-ranked items that have no un-listed precursors.
145
- # After each listed item, list the chasers *transitively* before
146
- # choosing the next highest ranked item.
147
- @listed = {}
148
-
149
- start = Time.now
150
- @page_rank = concept_deps.page_rank # Get the page_rank
151
- # puts "done in #{Time.now-start}"
152
-
153
- @ranked = @page_rank.keys.sort_by{|k| -@page_rank[k]} # Sort decreasing
154
- @topic = nil
155
- until @listed.size >= @ranked.size
156
- vt = nil # Capture the first listable ValueType, which we'll choose if we must
157
- chosen = @ranked.detect do |concept|
158
- next if @listed[concept]
159
-
160
- unlisted_precursors =
161
- concept_deps.precursors_transitive(concept).
162
- reject do |precursor|
163
- is_value_type_concept(precursor) or
164
- precursor == concept or
165
- @listed[precursor] or
166
- is_value_type_concept(precursor)
167
- end
168
- next if unlisted_precursors.size > 0 # Still has precursors
169
- vt ||= concept
170
- next if is_value_type_concept(concept)
171
- concept
172
- end
173
- chosen ||= vt # Choose a value type if there's no other
174
-
175
- @cluster = []
176
-
177
- descend concept_deps, chosen
178
-
179
- cluster_ranks = @cluster.sort_by{|c| -@page_rank[c]}
180
- head = cluster_ranks.detect{|c| c.object_type} || cluster_ranks.first
181
- puts "/*\n * #{head.object_type ? head.object_type.name : head.describe}\n */"
182
- @cluster.each do |concept|
183
- puts '*'*10+" TOPIC #{@topic = concept.topic.topic_name}" if @topic != concept.topic.topic_name
184
- puts concept.describe
185
- end
186
- puts # Put a line between sections
187
- end
188
- end
189
-
190
- # Descend the concept, also the items that are necessarily dumped with concept, so we don't select them again
191
- def descend(concept_deps, concept, tab = '')
192
- @causation ||= []
193
- @cluster ||= []
194
- return if @listed[concept] || @causation.include?(concept) # Recursion prevention
195
- begin
196
- @causation << concept # Reversed by the "ensure" below.
197
-
198
- concept_deps.precursors(concept).each do |precursor|
199
- descend(concept_deps, precursor, tab) unless @listed[precursor] || precursor == concept
200
- end
201
-
202
- #puts tab+concept.describe
203
- @listed[concept] = true
204
- @cluster << concept
205
-
206
- body = concept.embodied_as
207
- case body
208
- when ActiveFacts::Metamodel::FactType
209
- body.internal_presence_constraints.each do |pc|
210
- # puts "Listing #{pc.concept.describe} as internal_presence_constraint of #{concept.describe}"
211
- descend(concept_deps, pc.concept, tab+"\t")
212
- end
213
- if body.entity_type
214
- # puts "Listing #{body.entity_type.concept.describe} as objectification of #{concept.describe}"
215
- descend(concept_deps, body.entity_type.concept, tab+"\t")
216
- end
217
- body.all_role.each do |role|
218
- role.all_ring_constraint.each do |rc|
219
- # puts "Listing #{rc.concept.describe} as ring_constraint of #{concept.describe}"
220
- descend(concept_deps, rc.concept, tab+"\t")
221
- end
222
- end
223
- when ActiveFacts::Metamodel::EntityType
224
- body.preferred_identifier.role_sequence.all_role_ref.each do |rr|
225
- # puts "Listing #{rr.role.fact_type.concept.describe} as existential fact of #{concept.describe}"
226
- descend(concept_deps, rr.role.fact_type.concept, tab+"\t")
227
- end
228
- descend(concept_deps, body.preferred_identifier.concept, tab+"\t")
229
- when ActiveFacts::Metamodel::ValueType
230
- if body.value_constraint
231
- # puts "Listing #{body.value_constraint.concept.describe} as value constraint of #{concept.describe}"
232
- descend(concept_deps, body.value_constraint.concept, tab+"\t")
233
- end
234
- end
235
-
236
- # Follow up with unlisted chasers (that have no remaining precursors) in order of decreasing importance:
237
- chasers =
238
- concept_deps.followers(concept).reject do |follower|
239
- @listed[follower] or
240
- is_value_type_concept(follower) or
241
- concept_deps.precursors(follower).detect{|p| !@listed[p] && !is_value_type_concept(p) } or
242
- # Exclude subtypes of entity types from the followers:
243
- concept.object_type && concept.object_type.is_a?(ActiveFacts::Metamodel::EntityType) && concept.object_type.subtypes.include?(follower.object_type)
244
- end.
245
- sort_by{|nc| -@page_rank[nc]}
246
-
247
- chasers.each do |chaser|
248
- # puts "**** Listing #{chaser.describe} as chaser of #{concept.describe}"
249
- descend(concept_deps, chaser, tab)
250
- end
251
-
252
- ensure
253
- @causation.pop
254
- end
255
- end
256
-
257
- def is_value_type_concept concept
258
- o = concept.object_type and o.is_a?(ActiveFacts::Metamodel::ValueType)
259
- end
260
-
261
- end
262
- end
263
- end
264
-
265
- ActiveFacts::Registry.generator('topics', ActiveFacts::Generate::Topics)