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,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)