talia_core 0.4.0

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 (119) hide show
  1. data/README.rdoc +41 -0
  2. data/bin/talia +33 -0
  3. data/lib/JXslt/jxslt.rb +60 -0
  4. data/lib/acts_as_roled.rb +11 -0
  5. data/lib/core_ext/platform.rb +9 -0
  6. data/lib/core_ext/string.rb +6 -0
  7. data/lib/core_ext.rb +1 -0
  8. data/lib/custom_template.rb +4 -0
  9. data/lib/loader_helper.rb +62 -0
  10. data/lib/mysql.rb +1214 -0
  11. data/lib/progressbar.rb +236 -0
  12. data/lib/role.rb +12 -0
  13. data/lib/talia_cl/command_line.rb +39 -0
  14. data/lib/talia_cl/commands/standalone/cl_options.rb +9 -0
  15. data/lib/talia_cl/commands/standalone/standalone_generate.rb +75 -0
  16. data/lib/talia_cl/commands/standalone.rb +25 -0
  17. data/lib/talia_cl/commands/talia_console/cl_options.rb +55 -0
  18. data/lib/talia_cl/commands/talia_console/console_commands.rb +37 -0
  19. data/lib/talia_cl/commands/talia_console/talia_commands.rb +131 -0
  20. data/lib/talia_cl/commands/talia_console.rb +47 -0
  21. data/lib/talia_cl/core_commands.rb +11 -0
  22. data/lib/talia_cl.rb +47 -0
  23. data/lib/talia_core/active_source.rb +372 -0
  24. data/lib/talia_core/active_source_parts/class_methods.rb +378 -0
  25. data/lib/talia_core/active_source_parts/predicate_handler.rb +89 -0
  26. data/lib/talia_core/active_source_parts/rdf.rb +131 -0
  27. data/lib/talia_core/active_source_parts/sql_helper.rb +36 -0
  28. data/lib/talia_core/active_source_parts/xml/base_builder.rb +47 -0
  29. data/lib/talia_core/active_source_parts/xml/generic_reader.rb +363 -0
  30. data/lib/talia_core/active_source_parts/xml/rdf_builder.rb +88 -0
  31. data/lib/talia_core/active_source_parts/xml/source_builder.rb +73 -0
  32. data/lib/talia_core/active_source_parts/xml/source_reader.rb +20 -0
  33. data/lib/talia_core/agent.rb +14 -0
  34. data/lib/talia_core/background_jobs/job.rb +82 -0
  35. data/lib/talia_core/background_jobs/progress_job.rb +68 -0
  36. data/lib/talia_core/collection.rb +13 -0
  37. data/lib/talia_core/data_types/data_loader.rb +92 -0
  38. data/lib/talia_core/data_types/data_record.rb +105 -0
  39. data/lib/talia_core/data_types/delayed_copier.rb +76 -0
  40. data/lib/talia_core/data_types/file_record.rb +59 -0
  41. data/lib/talia_core/data_types/file_store.rb +306 -0
  42. data/lib/talia_core/data_types/iip_data.rb +153 -0
  43. data/lib/talia_core/data_types/iip_loader.rb +127 -0
  44. data/lib/talia_core/data_types/image_data.rb +32 -0
  45. data/lib/talia_core/data_types/media_link.rb +19 -0
  46. data/lib/talia_core/data_types/mime_mapping.rb +45 -0
  47. data/lib/talia_core/data_types/path_helpers.rb +77 -0
  48. data/lib/talia_core/data_types/pdf_data.rb +42 -0
  49. data/lib/talia_core/data_types/simple_text.rb +36 -0
  50. data/lib/talia_core/data_types/temp_file_handling.rb +85 -0
  51. data/lib/talia_core/data_types/xml_data.rb +169 -0
  52. data/lib/talia_core/dc_resource.rb +20 -0
  53. data/lib/talia_core/dummy_handler.rb +34 -0
  54. data/lib/talia_core/dummy_source.rb +20 -0
  55. data/lib/talia_core/errors.rb +25 -0
  56. data/lib/talia_core/initializer.rb +427 -0
  57. data/lib/talia_core/ordered_source.rb +228 -0
  58. data/lib/talia_core/rails_ext/actionpack/action_controller/record_identifier.rb +13 -0
  59. data/lib/talia_core/rails_ext/actionpack/action_controller.rb +1 -0
  60. data/lib/talia_core/rails_ext/actionpack.rb +1 -0
  61. data/lib/talia_core/rails_ext.rb +1 -0
  62. data/lib/talia_core/rdf_import.rb +90 -0
  63. data/lib/talia_core/rdf_resource.rb +159 -0
  64. data/lib/talia_core/semantic_collection_item.rb +93 -0
  65. data/lib/talia_core/semantic_collection_wrapper.rb +324 -0
  66. data/lib/talia_core/semantic_property.rb +7 -0
  67. data/lib/talia_core/semantic_relation.rb +67 -0
  68. data/lib/talia_core/source.rb +323 -0
  69. data/lib/talia_core/source_transfer_object.rb +38 -0
  70. data/lib/talia_core/workflow/base.rb +15 -0
  71. data/lib/talia_core/workflow/publication_workflow.rb +62 -0
  72. data/lib/talia_core/workflow.rb +300 -0
  73. data/lib/talia_core.rb +9 -0
  74. data/lib/talia_dependencies.rb +12 -0
  75. data/lib/talia_util/bar_progressor.rb +15 -0
  76. data/lib/talia_util/configuration/config_file.rb +48 -0
  77. data/lib/talia_util/configuration/database_config.rb +40 -0
  78. data/lib/talia_util/configuration/mysql_database_setup.rb +104 -0
  79. data/lib/talia_util/data_import.rb +91 -0
  80. data/lib/talia_util/image_conversions.rb +82 -0
  81. data/lib/talia_util/import_job_helper.rb +132 -0
  82. data/lib/talia_util/io_helper.rb +54 -0
  83. data/lib/talia_util/progressable.rb +38 -0
  84. data/lib/talia_util/progressbar.rb +236 -0
  85. data/lib/talia_util/rdf_update.rb +80 -0
  86. data/lib/talia_util/some_sigla.xml +1960 -0
  87. data/lib/talia_util/test_helpers.rb +151 -0
  88. data/lib/talia_util/util.rb +226 -0
  89. data/lib/talia_util/yaml_import.rb +80 -0
  90. data/lib/talia_util.rb +13 -0
  91. data/lib/user.rb +116 -0
  92. data/lib/version.rb +15 -0
  93. data/test/core_ext/string_test.rb +11 -0
  94. data/test/custom_template_test.rb +8 -0
  95. data/test/talia_core/active_source_predicate_test.rb +54 -0
  96. data/test/talia_core/active_source_rdf_test.rb +89 -0
  97. data/test/talia_core/active_source_test.rb +631 -0
  98. data/test/talia_core/data_types/data_loader_test.rb +123 -0
  99. data/test/talia_core/data_types/data_record_test.rb +40 -0
  100. data/test/talia_core/data_types/file_record_test.rb +171 -0
  101. data/test/talia_core/data_types/iip_data_test.rb +130 -0
  102. data/test/talia_core/data_types/image_data_test.rb +88 -0
  103. data/test/talia_core/data_types/pdf_data_test.rb +68 -0
  104. data/test/talia_core/data_types/xml_data_test.rb +134 -0
  105. data/test/talia_core/generic_xml_test.rb +83 -0
  106. data/test/talia_core/initializer_test.rb +36 -0
  107. data/test/talia_core/ordered_source_test.rb +398 -0
  108. data/test/talia_core/rdf_resource_test.rb +115 -0
  109. data/test/talia_core/semantic_collection_item_test.rb +129 -0
  110. data/test/talia_core/source_reader_test.rb +33 -0
  111. data/test/talia_core/source_test.rb +484 -0
  112. data/test/talia_core/source_transfer_object_test.rb +24 -0
  113. data/test/talia_core/workflow/publication_workflow_test.rb +242 -0
  114. data/test/talia_core/workflow/user_class_for_workflow.rb +35 -0
  115. data/test/talia_core/workflow/workflow_base_test.rb +21 -0
  116. data/test/talia_core/workflow_test.rb +19 -0
  117. data/test/talia_util/import_job_helper_test.rb +46 -0
  118. data/test/test_helper.rb +68 -0
  119. metadata +262 -0
@@ -0,0 +1,300 @@
1
+ module TaliaCore #:nodoc:
2
+ module Workflow #:nodoc:
3
+ class InvalidState < Exception #:nodoc:
4
+ end
5
+ class NoInitialState < Exception #:nodoc:
6
+ end
7
+ class NoAuthorizedException < Exception #:nodoc:
8
+ end
9
+
10
+
11
+ def self.included(base) #:nodoc:
12
+ base.extend WorkflowMacro
13
+ end
14
+
15
+ module SupportingClasses
16
+ class State
17
+ attr_reader :name
18
+
19
+ def initialize(name, opts)
20
+ @name, @opts = name, opts
21
+ end
22
+
23
+ def entering(record)
24
+ enteract = @opts[:enter]
25
+ record.send(:run_transition_action, enteract) if enteract
26
+ end
27
+
28
+ def entered(record)
29
+ afteractions = @opts[:after]
30
+ return unless afteractions
31
+ Array(afteractions).each do |afteract|
32
+ record.send(:run_transition_action, afteract)
33
+ end
34
+ end
35
+
36
+ def exited(record)
37
+ exitact = @opts[:exit]
38
+ record.send(:run_transition_action, exitact) if exitact
39
+ end
40
+ end
41
+
42
+ class StateTransition
43
+ attr_reader :from, :to, :opts
44
+
45
+ def initialize(opts)
46
+ @from, @to, @guard = opts[:from], opts[:to], opts[:guard]
47
+ @opts = opts
48
+ end
49
+
50
+ def guard(obj, args)
51
+ @guard ? obj.send(:run_transition_action, @guard, args) : true
52
+ end
53
+
54
+ def on_transition(obj, args = nil)
55
+ action = @opts[:on_transition]
56
+ obj.send(:run_transition_action, action, args) if action
57
+ end
58
+
59
+ def perform(record, args = nil)
60
+ return false unless guard(record, args)
61
+ loopback = record.current_state == to
62
+ states = record.class.read_inheritable_attribute(:states)
63
+ next_state = states[to]
64
+ old_state = states[record.current_state]
65
+
66
+ # permform action
67
+ on_transition(record, args)
68
+
69
+ next_state.entering(record) unless loopback
70
+
71
+ record.update_attribute(record.class.state_column, to.to_s)
72
+
73
+ next_state.entered(record) unless loopback
74
+ old_state.exited(record) unless loopback
75
+ true
76
+ end
77
+
78
+ def ==(obj)
79
+ @from == obj.from && @to == obj.to
80
+ end
81
+ end
82
+
83
+ class Event
84
+ attr_reader :name
85
+ attr_reader :transitions
86
+ attr_reader :opts
87
+
88
+ def initialize(name, opts, transition_table, &block)
89
+ @name = name.to_sym
90
+ @transitions = transition_table[@name] = []
91
+ instance_eval(&block) if block
92
+ @opts = opts
93
+ @opts.freeze
94
+ @transitions.freeze
95
+ freeze
96
+ end
97
+
98
+ def next_states(record)
99
+ @transitions.select { |t| t.from == record.current_state }
100
+ end
101
+
102
+ def fire(record, user, args = nil)
103
+ # check user role
104
+ unless @opts[:require_role].nil?
105
+ raise NoAuthorizedException unless user.authorized_as?(@opts[:require_role])
106
+ end
107
+
108
+ # perform transition
109
+ next_states(record).each do |transition|
110
+ break true if transition.perform(record, args)
111
+ end
112
+ end
113
+
114
+ def transitions(trans_opts)
115
+ Array(trans_opts[:from]).each do |s|
116
+ @transitions << SupportingClasses::StateTransition.new(trans_opts.merge({:from => s.to_sym}))
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ module WorkflowMacro
123
+ # Configuration options are
124
+ #
125
+ # * +column+ - specifies the column name to use for keeping the state (default: state)
126
+ # * +property+ - specifies the column name to use for keeping the property of current state (default: state_properties)
127
+ # * +initial+ - specifies an initial state for newly created objects (required)
128
+ def workflow_machine(opts)
129
+ self.extend(ClassMethods)
130
+ raise NoInitialState unless opts[:initial]
131
+
132
+ write_inheritable_attribute :states, {}
133
+ write_inheritable_attribute :initial_state, opts[:initial]
134
+ write_inheritable_attribute :initial_state_properties, opts[:initial_properties] || {}
135
+ write_inheritable_attribute :transition_table, {}
136
+ write_inheritable_attribute :event_table, {}
137
+ write_inheritable_attribute :state_column, opts[:column] || 'state'
138
+ write_inheritable_attribute :state_properties_column, opts[:properties] || 'state_properties'
139
+
140
+ class_inheritable_reader :initial_state
141
+ class_inheritable_reader :initial_state_properties
142
+ class_inheritable_reader :state_column
143
+ class_inheritable_reader :state_properties_column
144
+ class_inheritable_reader :transition_table
145
+ class_inheritable_reader :event_table
146
+
147
+ self.send(:include, TaliaCore::Workflow::InstanceMethods)
148
+
149
+ before_create :set_initial_state, :set_initial_state_properties
150
+ after_create :run_initial_state_actions
151
+ end
152
+ end
153
+
154
+ module InstanceMethods
155
+ def state_properties
156
+ Marshal.load(self.send(self.class.state_properties_column))
157
+ end
158
+
159
+ def state_properties=(value)
160
+ write_attribute self.class.state_properties_column, Marshal.dump(value)
161
+ end
162
+
163
+ def set_initial_state #:nodoc:
164
+ write_attribute self.class.state_column, self.class.initial_state.to_s
165
+ end
166
+
167
+ def set_initial_state_properties #:nodoc:
168
+ write_attribute self.class.state_properties_column, Marshal.dump(self.class.initial_state_properties)
169
+ end
170
+
171
+ def run_initial_state_actions
172
+ initial = self.class.read_inheritable_attribute(:states)[self.class.initial_state.to_sym]
173
+ initial.entering(self)
174
+ initial.entered(self)
175
+ end
176
+
177
+ # Returns the current state the object is in, as a Ruby symbol.
178
+ def current_state
179
+ self.send(self.class.state_column).to_sym
180
+ end
181
+
182
+ # Returns what the next state for a given event would be, as a Ruby symbol.
183
+ def next_state_for_event(event)
184
+ ns = next_states_for_event(event)
185
+ ns.empty? ? nil : ns.first.to
186
+ end
187
+
188
+ def next_states_for_event(event)
189
+ self.class.read_inheritable_attribute(:transition_table)[event.to_sym].select do |s|
190
+ s.from == current_state
191
+ end
192
+ end
193
+
194
+ def run_transition_action(action, args = nil)
195
+ Symbol === action ? self.method(action).call(args) : action.call(self)
196
+ end
197
+ private :run_transition_action
198
+ end
199
+
200
+ module ClassMethods
201
+ # Returns an array of all known states.
202
+ def states
203
+ read_inheritable_attribute(:states).keys
204
+ end
205
+
206
+ # Define an event. This takes a block which describes all valid transitions
207
+ # for this event.
208
+ #
209
+ # Example:
210
+ #
211
+ # class Order < ActiveRecord::Base
212
+ # acts_as_state_machine :initial => :open
213
+ #
214
+ # state :open
215
+ # state :closed
216
+ #
217
+ # event :close_order do
218
+ # transitions :to => :closed, :from => :open
219
+ # end
220
+ # end
221
+ #
222
+ # +transitions+ takes a hash where <tt>:to</tt> is the state to transition
223
+ # to and <tt>:from</tt> is a state (or Array of states) from which this
224
+ # event can be fired.
225
+ #
226
+ # This creates an instance method used for firing the event. The method
227
+ # created is the name of the event followed by an exclamation point (!).
228
+ # Example: <tt>order.close_order!</tt>.
229
+ def event(event, opts={}, &block)
230
+ tt = read_inheritable_attribute(:transition_table)
231
+
232
+ et = read_inheritable_attribute(:event_table)
233
+ e = et[event.to_sym] = SupportingClasses::Event.new(event, opts, tt, &block)
234
+ define_method("#{event.to_s}!") { |user, *args| e.fire(self, user, args) }
235
+ end
236
+
237
+ # Define a state of the system. +state+ can take an optional Proc object
238
+ # which will be executed every time the system transitions into that
239
+ # state. The proc will be passed the current object.
240
+ #
241
+ # Example:
242
+ #
243
+ # class Order < ActiveRecord::Base
244
+ # acts_as_state_machine :initial => :open
245
+ #
246
+ # state :open
247
+ # state :closed, Proc.new { |o| Mailer.send_notice(o) }
248
+ # end
249
+ def state(name, opts={})
250
+ state = SupportingClasses::State.new(name.to_sym, opts)
251
+ read_inheritable_attribute(:states)[name.to_sym] = state
252
+
253
+ define_method("#{state.name}?") { current_state == state.name }
254
+ end
255
+
256
+ # Wraps ActiveRecord::Base.find to conveniently find all records in
257
+ # a given state. Options:
258
+ #
259
+ # * +number+ - This is just :first or :all from ActiveRecord +find+
260
+ # * +state+ - The state to find
261
+ # * +args+ - The rest of the args are passed down to ActiveRecord +find+
262
+ def find_in_state(number, state, *args)
263
+ with_state_scope state do
264
+ find(number, *args)
265
+ end
266
+ end
267
+
268
+ # Wraps ActiveRecord::Base.count to conveniently count all records in
269
+ # a given state. Options:
270
+ #
271
+ # * +state+ - The state to find
272
+ # * +args+ - The rest of the args are passed down to ActiveRecord +find+
273
+ def count_in_state(state, *args)
274
+ with_state_scope state do
275
+ count(*args)
276
+ end
277
+ end
278
+
279
+ # Wraps ActiveRecord::Base.calculate to conveniently calculate all records in
280
+ # a given state. Options:
281
+ #
282
+ # * +state+ - The state to find
283
+ # * +args+ - The rest of the args are passed down to ActiveRecord +calculate+
284
+ def calculate_in_state(state, *args)
285
+ with_state_scope state do
286
+ calculate(*args)
287
+ end
288
+ end
289
+
290
+ protected
291
+ def with_state_scope(state)
292
+ raise InvalidState unless states.include?(state)
293
+
294
+ with_scope :find => {:conditions => ["#{table_name}.#{state_column} = ?", state.to_s]} do
295
+ yield if block_given?
296
+ end
297
+ end
298
+ end
299
+ end
300
+ end
data/lib/talia_core.rb ADDED
@@ -0,0 +1,9 @@
1
+ # TaliaCore loader
2
+ require File.dirname(__FILE__) + '/talia_dependencies'
3
+
4
+ TLoad::force_rails_parts unless(defined?(ActiveRecord))
5
+
6
+ # Load local things
7
+ require 'talia_core/errors'
8
+ require 'talia_core/rails_ext'
9
+ require 'talia_core/initializer'
@@ -0,0 +1,12 @@
1
+ # TaliaCore loader
2
+ require File.dirname(__FILE__) + '/loader_helper'
3
+
4
+ # This is also needed for local loading
5
+ RAILS_GEM_VERSION = '2.3.4' unless defined? RAILS_GEM_VERSION
6
+
7
+ # Stuff we may need to load from sources/uninstalled versions
8
+ TLoad::require_module("assit", "assit", "/../../assit") unless(defined?(assit))
9
+ TLoad::require_module("activerdf", "active_rdf", "/../../ActiveRDF")
10
+ TLoad::require_module("semantic_naming", "semantic_naming", "/../../semantic_naming")
11
+
12
+ require 'version'
@@ -0,0 +1,15 @@
1
+ require File.join(File.dirname(__FILE__), 'progressbar')
2
+
3
+ module TaliaUtil
4
+
5
+ # Helper class for command-line progress bars as progressor objects
6
+ class BarProgressor
7
+
8
+ def self.run_with_progress(message, size)
9
+ progress = ProgressBar.new(message, size)
10
+ yield(progress)
11
+ progress.finish
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,48 @@
1
+ require 'yaml'
2
+
3
+ module TaliaUtil
4
+ module Configuration
5
+
6
+ # This is an object representation of a configuration file, the elements
7
+ # of the file can be directly accessed using dynamic getters/setters on the
8
+ # the class.
9
+ class ConfigFile
10
+
11
+ # Initialize from the given template
12
+ def initialize(template)
13
+ @config_doc = YAML::load_file(template)
14
+ end
15
+
16
+ # Write the configuration to the given file
17
+ def write(file)
18
+ open(file, 'w') { |io| io.puts(@config_doc.to_yaml) }
19
+ end
20
+
21
+ def [](id)
22
+ @config_doc[id]
23
+ end
24
+
25
+ # Automatically creates "accessors" for the config properties.
26
+ def method_missing(method, *params)
27
+ method = method.to_s
28
+ assign = method[-1..-1] == '=' # True if last char is a =
29
+
30
+ result = nil
31
+
32
+ if(assign)
33
+ return super if(params.size != 1)
34
+ result = @config_doc[method[0..-2]] = params[0]
35
+ else
36
+ return super if(params.size != 0)
37
+ result = @config_doc[method]
38
+ end
39
+
40
+ result
41
+ end
42
+
43
+
44
+
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,40 @@
1
+ require File.dirname(__FILE__) + '/config_file'
2
+
3
+ module TaliaUtil
4
+ module Configuration
5
+
6
+ # This contains some special methods for database config files
7
+ class DatabaseConfig < ConfigFile
8
+
9
+ def initialize(template)
10
+ @environments = ['test', 'development', 'production']
11
+ super
12
+ end
13
+
14
+ # Set the credentials for all environments
15
+ def set_credentials(db_user, db_pass)
16
+ @environments.each do |env|
17
+ @config_doc[env]['username'] = db_user
18
+ @config_doc[env]['password'] = db_pass
19
+ end
20
+ end
21
+
22
+ # Sets the database adapter for all environments
23
+ def set_adapter(db_adapter)
24
+ @environments.each { |env| @config_doc[env]['adapter'] = db_adapter }
25
+ end
26
+
27
+ # Sets the database names based on the given application name
28
+ def set_database_names(app_name)
29
+ @environments.each { |env| @config_doc[env]['database'] = "#{app_name}_#{env}" }
30
+ end
31
+
32
+ # Sets the socket file for the db
33
+ def set_socket(socket)
34
+ @environments.each { |env| @config_doc[env]['socket'] = socket }
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,104 @@
1
+ require 'active_record'
2
+
3
+ module TaliaUtil
4
+ module Configuration
5
+
6
+ # This contains some methods to set mysql databases on a production system
7
+ # from scratch. Setting the root password will apply immediately, the SQL
8
+ # operations will be cached and applied in one go.
9
+ class MysqlDatabaseSetup
10
+
11
+ def initialize
12
+ @sql_statements = []
13
+ end
14
+
15
+ attr_accessor :host
16
+ attr_accessor :app_name
17
+ attr_accessor :sock
18
+ attr_accessor :db_prefix # Prefix for having multiple databases on one install
19
+
20
+ # Set the root user/pw
21
+ def root_credentials(root_user = 'root', root_pw = nil)
22
+ @root_user = root_user
23
+ @root_pw = root_pw
24
+ end
25
+
26
+ # Set the normal user/pw
27
+ def rails_credentials(rails_user, rails_pw)
28
+ @rails_user = rails_user
29
+ @rails_pw = rails_pw
30
+ end
31
+
32
+
33
+ # Assign a new root password
34
+ def assign_root_pw(new_root_pw)
35
+ success = mysqladmin("password #{new_root_pw}")
36
+ @root_pw = new_root_pw if(success)
37
+ success
38
+ end
39
+
40
+ # Create the given database and set the permssions on it
41
+ def create_database(database)
42
+ raise(ArgumentError, "Credentials incomplete") unless(@rails_user && @rails_pw)
43
+ @sql_statements << "CREATE DATABASE #{database};"
44
+ @sql_statements << "GRANT ALL ON #{database}.* TO '#{@rails_user}'@'#{@host || 'localhost'}' IDENTIFIED BY '#{@rails_pw}'"
45
+ end
46
+
47
+ # Creates the default databases for the application. You can call back a
48
+ # block for each db to do something depending on the success of the
49
+ # operation
50
+ def create_default_databases
51
+ raise(ArgumentError, "App name not set") unless(@app_name)
52
+ %w(production test development).each do |db_suffix|
53
+ db_name = "#{db_prefix}#{@app_name}_#{db_suffix}"
54
+ create_database(db_name)
55
+ end
56
+ end
57
+
58
+ # Executes all stored statements
59
+ def execute
60
+ execute_as_root do |connection|
61
+ connection.transaction do
62
+ @sql_statements.each do |statement|
63
+ connection.execute(statement)
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ private
70
+
71
+ # Call the mysqladmin command (as root)
72
+ def mysqladmin(command)
73
+ if(@root_pw)
74
+ system("mysqladmin -u #{@root_user} #{command}")
75
+ else
76
+ system("mysqladmin -u #{@root_user} -p#{@root_pw} #{command}")
77
+ end
78
+ end
79
+
80
+ # Calls sql commands on the database using root credentials. The open
81
+ # database (ActiveRecord) connection will be passed. This will open
82
+ # the given database.
83
+ def execute_as_root(database = nil)
84
+ ActiveRecord::Base.establish_connection(root_con_opts(database))
85
+ yield(ActiveRecord::Base.connection)
86
+ ActiveRecord::Base.remove_connection
87
+ end
88
+
89
+ # options for root connection
90
+ def root_con_opts(database)
91
+ {
92
+ :adapter => "mysql",
93
+ :host => @host || "localhost",
94
+ :username => @root_user,
95
+ :password => @root_pw,
96
+ :database => database,
97
+ :socket => @sock || '/tmp/mysql.sock'
98
+ }
99
+ end
100
+
101
+ end
102
+
103
+ end
104
+ end
@@ -0,0 +1,91 @@
1
+ require 'fileutils'
2
+
3
+ module TaliaUtil
4
+
5
+ # Import data files into the Talia store. This can be used to bootstrap
6
+ # simple installations
7
+ class DataImport
8
+
9
+ class << self
10
+
11
+ # Import files with the given type. This is a simple import feature,
12
+ # it's assumed that the file (without extension is named like the
13
+ # Source it should be assigned to.
14
+ def import(files, type)
15
+
16
+ # First get the class for the data type and the directory
17
+ data_klass = get_data_class(type)
18
+ replace = ENV['replace_files'] && (ENV['replace_files'] == "yes")
19
+
20
+ progress = ProgressBar.new("Importing #{data_klass}", files.size)
21
+ not_found = []
22
+ created = 0
23
+
24
+ files.each do |file|
25
+ # Get the basename without extension and additions. This strips off
26
+ # everything after the first point or - character. Examples:
27
+ # book.html
28
+ # book-picture.jpg
29
+ # => Will all be assigned to "book"
30
+ name = File.basename(file).gsub(/[-|\.].+$/, '')
31
+ if(TaliaCore::Source.exists?(name))
32
+ src = TaliaCore::Source.find(name)
33
+
34
+ # Get the filename with extension
35
+ file_name = File.basename(file)
36
+
37
+ # Create the record if necessary
38
+ unless(data = src.data_records.find_by_location(file_name))
39
+ data = data_klass.new
40
+ File.open(file) do |io|
41
+ data.create_from_data(file_name, io)
42
+ end
43
+ src.data_records << data
44
+ src.save!
45
+ data.save!
46
+ created += 1
47
+ end
48
+ else
49
+ not_found << file
50
+ end
51
+ progress.inc
52
+ end
53
+
54
+ progress.finish
55
+ puts "Done, #{not_found.size} of #{files.size} files had no record associated."
56
+ puts "#{created} new records created."
57
+ puts "\nNot found:" unless(not_found.size == 0)
58
+ not_found.each { |file| puts file}
59
+ end
60
+
61
+
62
+ # Get the data class for the type. That does some sanity checks
63
+ def get_data_class(type)
64
+ data_klass = nil
65
+ begin
66
+ data_klass = TaliaCore::DataTypes.const_get(type)
67
+ rescue Exception => e
68
+ puts("Could get the data type #{type}: #{e}")
69
+ Util.print_options
70
+ exit(1)
71
+ end
72
+
73
+ # Do the basic check
74
+ unless(data_klass && data_klass.kind_of?(Class) && data_klass.method_defined?('data_directory'))
75
+ puts("Cannot create data class from #{type}")
76
+ exit(1)
77
+ end
78
+
79
+ # Now check if we are a subclass of the data class
80
+ my_instance = data_klass.new
81
+
82
+ unless(my_instance.kind_of?(TaliaCore::DataTypes::DataRecord))
83
+ puts("The class #{data_klass} is not a DataRecord, can't create data for it.")
84
+ exit(1)
85
+ end
86
+
87
+ data_klass
88
+ end
89
+ end
90
+ end
91
+ end