activefacts-generators 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +10 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +30 -0
  8. data/Rakefile +6 -0
  9. data/activefacts-generators.gemspec +26 -0
  10. data/lib/activefacts/dependency_analyser.rb +182 -0
  11. data/lib/activefacts/generators/absorption.rb +71 -0
  12. data/lib/activefacts/generators/composition.rb +119 -0
  13. data/lib/activefacts/generators/cql.rb +715 -0
  14. data/lib/activefacts/generators/diagrams/json.rb +340 -0
  15. data/lib/activefacts/generators/help.rb +64 -0
  16. data/lib/activefacts/generators/helpers/inject.rb +16 -0
  17. data/lib/activefacts/generators/helpers/oo.rb +162 -0
  18. data/lib/activefacts/generators/helpers/ordered.rb +605 -0
  19. data/lib/activefacts/generators/helpers/rails.rb +57 -0
  20. data/lib/activefacts/generators/html/glossary.rb +462 -0
  21. data/lib/activefacts/generators/metadata/json.rb +204 -0
  22. data/lib/activefacts/generators/null.rb +32 -0
  23. data/lib/activefacts/generators/rails/models.rb +247 -0
  24. data/lib/activefacts/generators/rails/schema.rb +217 -0
  25. data/lib/activefacts/generators/ruby.rb +134 -0
  26. data/lib/activefacts/generators/sql/mysql.rb +281 -0
  27. data/lib/activefacts/generators/sql/server.rb +274 -0
  28. data/lib/activefacts/generators/stats.rb +70 -0
  29. data/lib/activefacts/generators/text.rb +29 -0
  30. data/lib/activefacts/generators/traits/datavault.rb +241 -0
  31. data/lib/activefacts/generators/traits/oo.rb +73 -0
  32. data/lib/activefacts/generators/traits/ordered.rb +33 -0
  33. data/lib/activefacts/generators/traits/ruby.rb +210 -0
  34. data/lib/activefacts/generators/transform/datavault.rb +303 -0
  35. data/lib/activefacts/generators/transform/surrogate.rb +215 -0
  36. data/lib/activefacts/registry.rb +11 -0
  37. metadata +176 -0
@@ -0,0 +1,215 @@
1
+ #
2
+ # ActiveFacts Schema Transform
3
+ # Transform a loaded ActiveFacts vocabulary to suit ActiveRecord
4
+ #
5
+ # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
6
+ #
7
+ require 'activefacts/metamodel'
8
+ require 'activefacts/rmap'
9
+ require 'activefacts/registry'
10
+
11
+ module ActiveFacts
12
+ module Metamodel
13
+ class ObjectType
14
+
15
+ def add_surrogate type_name = 'Auto Counter', suffix = 'ID'
16
+ # Find or assert the surrogate value type
17
+ auto_counter = vocabulary.valid_value_type_name(type_name) ||
18
+ constellation.ValueType(:vocabulary => vocabulary, :name => type_name, :concept => :new)
19
+
20
+ # Create a subtype to identify this entity type:
21
+ vt_name = self.name + ' '+suffix
22
+ my_id = @vocabulary.valid_value_type_name(vt_name) ||
23
+ constellation.ValueType(:vocabulary => vocabulary, :name => vt_name, :concept => :new, :supertype => auto_counter)
24
+
25
+ # Create a fact type
26
+ identifying_fact_type = constellation.FactType(:concept => :new)
27
+ my_role = constellation.Role(:concept => :new, :fact_type => identifying_fact_type, :ordinal => 0, :object_type => self)
28
+ @injected_surrogate_role = my_role
29
+ id_role = constellation.Role(:concept => :new, :fact_type => identifying_fact_type, :ordinal => 1, :object_type => my_id)
30
+
31
+ # Create a reading (which needs a RoleSequence)
32
+ reading = constellation.Reading(
33
+ :fact_type => identifying_fact_type,
34
+ :ordinal => 0,
35
+ :role_sequence => [:new],
36
+ :text => "{0} has {1}"
37
+ )
38
+ constellation.RoleRef(:role_sequence => reading.role_sequence, :ordinal => 0, :role => my_role)
39
+ constellation.RoleRef(:role_sequence => reading.role_sequence, :ordinal => 1, :role => id_role)
40
+
41
+ # Create two uniqueness constraints for the one-to-one. Each needs a RoleSequence (two RoleRefs)
42
+ one_id = constellation.PresenceConstraint(
43
+ :concept => :new,
44
+ :vocabulary => vocabulary,
45
+ :name => self.name+'HasOne'+suffix,
46
+ :role_sequence => [:new],
47
+ :is_mandatory => true,
48
+ :min_frequency => 1,
49
+ :max_frequency => 1,
50
+ :is_preferred_identifier => false
51
+ )
52
+ @constellation.RoleRef(:role_sequence => one_id.role_sequence, :ordinal => 0, :role => my_role)
53
+
54
+ one_me = constellation.PresenceConstraint(
55
+ :concept => :new,
56
+ :vocabulary => vocabulary,
57
+ :name => self.name+suffix+'IsOfOne'+self.name,
58
+ :role_sequence => [:new],
59
+ :is_mandatory => false,
60
+ :min_frequency => 0,
61
+ :max_frequency => 1,
62
+ :is_preferred_identifier => true
63
+ )
64
+ @constellation.RoleRef(:role_sequence => one_me.role_sequence, :ordinal => 0, :role => id_role)
65
+ end
66
+ end
67
+
68
+ class ValueType
69
+ def needs_surrogate
70
+ !is_auto_assigned
71
+ end
72
+
73
+ def inject_surrogate
74
+ trace :transform_surrogate, "Adding surrogate ID to Value Type #{name}"
75
+ add_surrogate('Auto Counter', 'ID')
76
+ end
77
+ end
78
+
79
+ class EntityType
80
+ def identifying_refs_from
81
+ pi = preferred_identifier
82
+ rrs = pi.role_sequence.all_role_ref
83
+
84
+ # REVISIT: This is actually a ref to us, not from
85
+ # if absorbed_via
86
+ # return [absorbed_via]
87
+ # end
88
+
89
+ rrs.map do |rr|
90
+ r = references_from.detect{|ref| rr.role == ref.to_role }
91
+ raise "failed to find #{name} identifying reference for #{rr.role.object_type.name} in #{references_from.inspect}" unless r
92
+ r
93
+ end
94
+ end
95
+
96
+ def needs_surrogate
97
+
98
+ # A recursive proc to replace any reference to an Entity Type by its identifying references:
99
+ trace :transform_surrogate_expansion, "Expanding key for #{name}"
100
+ substitute_identifying_refs = proc do |object|
101
+ if ref = object.absorbed_via
102
+ # This shouldn't be necessary, but see the absorbed_via comment above.
103
+ absorbed_into = ref.from
104
+ trace :transform_surrogate_expansion, "recursing to handle absorption of #{object.name} into #{absorbed_into.name}"
105
+ [substitute_identifying_refs.call(absorbed_into)]
106
+ else
107
+ irf = object.identifying_refs_from
108
+ trace :transform_surrogate_expansion, "Iterating for #{object.name} over #{irf.inspect}" do
109
+ irf.each_with_index do |ref, i|
110
+ next if ref.is_unary
111
+ next if ref.to_role.object_type.kind_of?(ActiveFacts::Metamodel::ValueType)
112
+ recurse_to = ref.to_role.object_type
113
+
114
+ trace :transform_surrogate_expansion, "#{i}: recursing to expand #{recurse_to.name} key in #{ref}" do
115
+ irf[i] = substitute_identifying_refs.call(recurse_to)
116
+ end
117
+ end
118
+ end
119
+ irf
120
+ end
121
+ end
122
+ irf = substitute_identifying_refs.call(self)
123
+
124
+ trace :transform_surrogate, "Does #{name} need a surrogate? it's identified by #{irf.inspect}" do
125
+
126
+ pk_fks = identifying_refs_from.map do |ref|
127
+ ref.to && ref.to.is_table ? ref.to : nil
128
+ end
129
+
130
+ irf.flatten!
131
+
132
+ # Multi-part identifiers are only allowed if:
133
+ # * each part is a foreign key (i.e. it's a join table),
134
+ # * there are no other columns (that might require updating) and
135
+ # * the object is not the target of a foreign key:
136
+ if irf.size >= 2
137
+ if pk_fks.include?(nil)
138
+ trace :transform_surrogate, "#{self.name} needs a surrogate because its multi-part key contains a non-table"
139
+ return true
140
+ elsif references_to.size != 0
141
+ trace :transform_surrogate, "#{self.name} is a join table between #{pk_fks.map(&:name).inspect} but is also an FK target"
142
+ return true
143
+ elsif (references_from-identifying_refs_from).size > 0
144
+ # There are other attributes to worry about
145
+ return true
146
+ else
147
+ trace :transform_surrogate, "#{self.name} is a join table between #{pk_fks.map(&:name).inspect}"
148
+ return false
149
+ end
150
+ return true
151
+ end
152
+
153
+ # Single-part key. It must be an Auto Counter, or we will add a surrogate
154
+
155
+ identifying_type = irf[0].to
156
+ if identifying_type.needs_surrogate
157
+ trace :transform_surrogate, "#{self.name} needs a surrogate because #{irf[0].to.name} is not an AutoCounter, but #{identifying_type.supertypes_transitive.map(&:name).inspect}"
158
+ return true
159
+ end
160
+
161
+ false
162
+ end
163
+ end
164
+
165
+ def inject_surrogate
166
+ trace :transform_surrogate, "Injecting a surrogate key into #{self.name}"
167
+
168
+ # Disable the preferred identifier:
169
+ pi = preferred_identifier
170
+ trace :transform_surrogate, "pi for #{name} was '#{pi.describe}'"
171
+ pi.is_preferred_identifier = false
172
+ @preferred_identifier = nil # Kill the cache
173
+
174
+ add_surrogate
175
+
176
+ trace :transform_surrogate, "pi for #{name} is now '#{preferred_identifier.describe}'"
177
+ end
178
+
179
+ end
180
+ end
181
+
182
+ module RMap
183
+ class Column
184
+ def is_injected_surrogate
185
+ references.size == 1 and
186
+ references[0].from_role == references[0].from.injected_surrogate_role
187
+ end
188
+ end
189
+ end
190
+
191
+ module Generators #:nodoc:
192
+ module Transform #:nodoc:
193
+ class Surrogate
194
+ def initialize(vocabulary, *options)
195
+ @vocabulary = vocabulary
196
+ end
197
+
198
+ def generate(out = $stdout)
199
+ @out = out
200
+ injections =
201
+ @vocabulary.tables.select do |table|
202
+ table.needs_surrogate
203
+ end
204
+ injections.each do |table|
205
+ table.inject_surrogate
206
+ end
207
+
208
+ @vocabulary.decide_tables
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end
214
+
215
+ ActiveFacts::Registry.generator('transform/surrogate', ActiveFacts::Generators::Transform::Surrogate)
@@ -0,0 +1,11 @@
1
+ module ActiveFacts
2
+ module Registry
3
+ def self.generator(name, klass)
4
+ generators[name] = klass
5
+ end
6
+
7
+ def self.generators
8
+ @@generators ||= {}
9
+ end
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,176 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activefacts-generators
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.7.1
5
+ platform: ruby
6
+ authors:
7
+ - Clifford Heath
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-10-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.10.a
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.10.a
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activefacts-metamodel
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 1.7.0
62
+ - - "~>"
63
+ - !ruby/object:Gem::Version
64
+ version: '1.7'
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: 1.7.0
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.7'
75
+ - !ruby/object:Gem::Dependency
76
+ name: activefacts-rmap
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: 1.7.0
82
+ - - "~>"
83
+ - !ruby/object:Gem::Version
84
+ version: '1.7'
85
+ type: :runtime
86
+ prerelease: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: 1.7.0
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '1.7'
95
+ - !ruby/object:Gem::Dependency
96
+ name: activesupport
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ description: Code generators for the ActiveFacts Fact Modeling suite, including the
110
+ Constellation Query Language
111
+ email:
112
+ - clifford.heath@gmail.com
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - ".gitignore"
118
+ - ".rspec"
119
+ - ".travis.yml"
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - Rakefile
124
+ - activefacts-generators.gemspec
125
+ - lib/activefacts/dependency_analyser.rb
126
+ - lib/activefacts/generators/absorption.rb
127
+ - lib/activefacts/generators/composition.rb
128
+ - lib/activefacts/generators/cql.rb
129
+ - lib/activefacts/generators/diagrams/json.rb
130
+ - lib/activefacts/generators/help.rb
131
+ - lib/activefacts/generators/helpers/inject.rb
132
+ - lib/activefacts/generators/helpers/oo.rb
133
+ - lib/activefacts/generators/helpers/ordered.rb
134
+ - lib/activefacts/generators/helpers/rails.rb
135
+ - lib/activefacts/generators/html/glossary.rb
136
+ - lib/activefacts/generators/metadata/json.rb
137
+ - lib/activefacts/generators/null.rb
138
+ - lib/activefacts/generators/rails/models.rb
139
+ - lib/activefacts/generators/rails/schema.rb
140
+ - lib/activefacts/generators/ruby.rb
141
+ - lib/activefacts/generators/sql/mysql.rb
142
+ - lib/activefacts/generators/sql/server.rb
143
+ - lib/activefacts/generators/stats.rb
144
+ - lib/activefacts/generators/text.rb
145
+ - lib/activefacts/generators/traits/datavault.rb
146
+ - lib/activefacts/generators/traits/oo.rb
147
+ - lib/activefacts/generators/traits/ordered.rb
148
+ - lib/activefacts/generators/traits/ruby.rb
149
+ - lib/activefacts/generators/transform/datavault.rb
150
+ - lib/activefacts/generators/transform/surrogate.rb
151
+ - lib/activefacts/registry.rb
152
+ homepage: http://github.com/cjheath/activefacts-generators
153
+ licenses:
154
+ - MIT
155
+ metadata: {}
156
+ post_install_message:
157
+ rdoc_options: []
158
+ require_paths:
159
+ - lib
160
+ required_ruby_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ required_rubygems_version: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - ">="
168
+ - !ruby/object:Gem::Version
169
+ version: '0'
170
+ requirements: []
171
+ rubyforge_project:
172
+ rubygems_version: 2.2.2
173
+ signing_key:
174
+ specification_version: 4
175
+ summary: Code Generators for the ActiveFacts suite
176
+ test_files: []