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,427 @@
1
+ require 'assit'
2
+ require 'semantic_naming'
3
+ require 'active_rdf'
4
+ require 'fileutils'
5
+
6
+ module TaliaCore
7
+
8
+ # The TaliaCore initializer is responsible for setting up the Talia core
9
+ # system, e.g. making the neccessary connections, setting up the
10
+ # basic namespaces, etc.
11
+ #
12
+ # The basic mechanism works like the Rails initializer: Options can be
13
+ # added to the Hash in a block that is passed to the run method of the
14
+ # intializers.
15
+ #
16
+ # There are two settings that can be made before the configuration is started:
17
+ #
18
+ # <tt>environmemnt</tt> is used to define the environment. This is used to
19
+ # select the configuration options from the files. This option will default
20
+ # to <tt>ENV['RAILS_ENV']</tt> if Talia runs in Rails. Otherwise the default
21
+ # will be "development".
22
+ #
23
+ # <tt>talia_root</tt> is the root directory for the Talia installation. If
24
+ # unset, the will default to <tt>RAILS_ROOT</tt> in Rails and to the current
25
+ # directory if Talia is used as a standalone module. This will be used to find
26
+ # the configuration and data files.
27
+ #
28
+ # Usually these options need only to be set if running Talia standalone. In
29
+ # this case, assign <tt>TaliaCore::Initializer.talia_root</tt> and/or
30
+ # <tt>TaliaCore::Initializer.environment</tt> before running the
31
+ # configuration.
32
+ #
33
+ # The options may also be stored in a configuration file; the name of
34
+ # the file is passed to the initializer.
35
+ #
36
+ # = Example config
37
+ #
38
+ # # If working with Rails, this code goes to the environment.rb
39
+ #
40
+ # # Set the root directory (optional, for Rails it's automatic)
41
+ # TaliaCore::Initializer.talia_root = "/my_directory/my_talia_root/"
42
+ # # Set the environment (optional, automatic for rails)
43
+ # TaliaCore::Initializer.environment = "development"
44
+ #
45
+ # # Run the initializer, giving a config file
46
+ # # See the example config files for options
47
+ # TaliaCore::Initializer.run("talia_core.yml") do |config|
48
+ # # Give more confi options. These will overwrite the ones from the
49
+ # # config file
50
+ # config['standalone_db'] = "true"
51
+ # end
52
+ class Initializer
53
+
54
+ # Is used to set the root directory manually. Must be written before
55
+ # the configuration is run.
56
+ cattr_writer :talia_root
57
+
58
+ # Is used to manually set the environment. Must be written before
59
+ # the configuration is run.
60
+ cattr_writer :environment
61
+
62
+ # Indicates if the system has been initialized
63
+ cattr_reader :initialized
64
+ @@initialized ||= false
65
+
66
+ # Indicates if the initialization was started,
67
+ # but not finished
68
+ cattr_reader :init_started
69
+ @@init_started ||= false
70
+
71
+ class << self
72
+
73
+ # Runs the initialization. You can pass a block to this method, which
74
+ # is run with one parameter: A hash containing the configuration.
75
+ #
76
+ # If a configuration file is given, the contents will be read before the
77
+ # block is called, the block values will overwrite the settings from the
78
+ # file.
79
+ #
80
+ # For now, the values are documented in the code below and in the default
81
+ # configuration file.
82
+ def run(config_file = nil, &initializer)
83
+ raise(SystemInitializationError, "System cannot be initialized twice") if(@@initialized || @@init_started)
84
+
85
+ @@init_started = true
86
+
87
+ # Set the talia root first
88
+ set_talia_root
89
+
90
+ # Set the environmnet
91
+ set_environment
92
+
93
+ # Load the config file if one is given
94
+ if(config_file)
95
+ config_file_path = File.join(TALIA_ROOT, 'config', "#{config_file}.yml")
96
+ @config = YAML::load(File.open(config_file_path))
97
+ else
98
+ # Create the default configuration
99
+ @config = create_default_config()
100
+ end
101
+
102
+ # Start logging
103
+ set_logger # Set the logger
104
+ talia_logger.info("TaliaCore initializing with environmnet #{@environment}")
105
+
106
+ # Call the user code
107
+ initializer.call(@config) if(initializer)
108
+
109
+ # Initialize the database connection
110
+ config_db
111
+
112
+ # Initialize the ActiveRDF connection
113
+ config_rdf
114
+
115
+ # Configure the namespaces
116
+ config_namespaces
117
+
118
+ # Configure the data directory
119
+ config_data_directory
120
+
121
+ # Configure the iip root directory
122
+ config_iip_root_directory
123
+
124
+ # Configure the ontologies
125
+ load_ontologies
126
+
127
+ # Load the Ruby Core extensions
128
+ load_core_ext
129
+
130
+ # register the default mime types
131
+ register_mime_types
132
+
133
+ # set the $ASSERT flag
134
+ if(@config["assert"])
135
+ $ASSERT = true
136
+ end
137
+
138
+ @@initialized = true
139
+
140
+ # Set the environment to the configuration
141
+ @config["environment"] = @@environment
142
+
143
+
144
+ # Make the configuration available as a constant
145
+ TaliaCore.const_set(:CONFIG, @config)
146
+
147
+ talia_logger.info("TaliaCore initialization complete")
148
+ end
149
+
150
+ def talia_logger
151
+ @logger
152
+ end
153
+
154
+ protected
155
+
156
+ # Creates the default values for the config hash
157
+ def create_default_config
158
+ config = Hash.new
159
+
160
+ # The name of the local node
161
+ config["local_uri"] = "http://test.dummy/"
162
+
163
+ # The "default" namespace
164
+ config["default_namespace_uri"] = "http://default.dummy/"
165
+
166
+ # Connect options for ActiveRDF
167
+ # Defaults to in-memory RDFLite
168
+ config["rdf_connection"] = {
169
+ :type => :rdflite
170
+ }
171
+
172
+ # Indicates if the DB backend (ActiveRecord) is
173
+ # used "standalone", which means "outside" a
174
+ # rails application.
175
+ # For the standalone case, the Talia
176
+ # initializer will make the database connections.
177
+ # Otherwise, Rails will handle that.
178
+ config["standalone_db"] = false
179
+
180
+ # Configuration for standalone database connection
181
+ config["db_connection"] = nil
182
+
183
+ # Additional namespaces that will be registered at
184
+ # startup. If present, this is expected to be a Hash with
185
+ # :shortcut => URI pairs
186
+ config["namespaces"] = nil
187
+
188
+ # Whether to set the $ASSERT flag that activates the simple assertions
189
+ config["assert"] = true
190
+
191
+ # Where to find the data directory which will be contain the data
192
+ config["data_directory_location"] = File.join(TALIA_ROOT, 'data')
193
+
194
+ return config
195
+ end
196
+
197
+
198
+ # Creates a logger if no logger is defined
199
+ # At the moment, this just creates a logger to the default director
200
+ def set_logger
201
+ @logger ||= if(defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER)
202
+ RAILS_DEFAULT_LOGGER
203
+ else
204
+ log_name = @config['standalone_log'] || File.join(TALIA_ROOT, 'log', "talia_core_#{@environment}.log")
205
+ log_level = @config['standalone_log_level'] ? Logger.const_get(@config['standalone_log_level']) : default_log_level
206
+ FileUtils.makedirs(File.dirname(log_name))
207
+ logger = Logger.new(log_name)
208
+ logger.level = log_level
209
+ logger
210
+ end
211
+ end
212
+
213
+ # Get the default log level for the standalone log
214
+ def default_log_level
215
+ case(@environment)
216
+ when 'development', 'test':
217
+ Logger::DEBUG
218
+ else
219
+ Logger::WARN
220
+ end
221
+ end
222
+
223
+ # Set the Talia root directory first. Use the configured directory
224
+ # if given, otherwise go for the RAILS_ROOT/current directory.
225
+ def set_talia_root
226
+ root = if(@@talia_root)
227
+ @@talia_root
228
+ elsif(defined?(RAILS_ROOT))
229
+ RAILS_ROOT
230
+ else
231
+ '.'
232
+ end
233
+ # Use the full path for the root
234
+ Object.const_set(:TALIA_ROOT, File.expand_path(root))
235
+ end
236
+
237
+ # Set the environmet to be used for config selection
238
+ def set_environment
239
+ if(@@environment)
240
+ @environment = @@environment
241
+ elsif(ENV['RAILS_ENV'])
242
+ @environment = ENV['RAILS_ENV']
243
+ else
244
+ @environment = "development"
245
+ end
246
+ @@environment = @environment
247
+ end
248
+
249
+ # Gets connection options from a file. The default_opts are the ones
250
+ # that will be used if no file is given. If both file and default are given,
251
+ # the method will overwrite the defaults.
252
+ def connection_opts(default_opts, config_file)
253
+ options = default_opts
254
+
255
+ # First check for the file
256
+ if(config_file)
257
+ if(default_opts)
258
+ talia_logger.warn("Database options will be overwritten by config file values.")
259
+ end
260
+
261
+ config_path = File.join(TALIA_ROOT, 'config', "#{config_file}.yml")
262
+ options = YAML::load(File.open(config_path))[@environment]
263
+ end
264
+
265
+ options
266
+ end
267
+
268
+ # The connection options for the standalone database connection
269
+ def db_connection_opts
270
+ connection_opts(@config["db_connection"], @config["db_file"])
271
+ end
272
+
273
+
274
+ # Configure the database connection
275
+ def config_db
276
+ # Initialize the database connection
277
+ if(@config["standalone_db"])
278
+ talia_logger.info("TaliaCore using standalone database")
279
+
280
+ ActiveRecord::Base.configurations['talia'] = db_connection_opts
281
+ ActiveRecord::Base.establish_connection(:talia)
282
+ ActiveRecord::Base.logger = talia_logger
283
+ else
284
+ talia_logger.info("TaliaCore using exisiting database connection.")
285
+ unless(ActiveRecord::Base.logger)
286
+ talia_logger.info("ActiveRecord logger not active, setting it to Talia logger")
287
+ ActiveRecord::Base.logger = talia_logger
288
+ end
289
+ end
290
+ end
291
+
292
+ # Get the RDF configuration options
293
+ def rdf_connection_opts
294
+ options = connection_opts(@config["rdf_connection"], @config["rdf_connection_file"])
295
+ # Make the keys into symbols, as needed by ActiveRDF
296
+ rdf_cfg = Hash.new
297
+ options.each { |key, value| rdf_cfg[key.to_sym] = value }
298
+
299
+ rdf_cfg
300
+ end
301
+
302
+ # Configure the RDF connection
303
+ def config_rdf
304
+ # Logginging goes to standard talia logger
305
+ ActiveRdfLogger.logger = talia_logger
306
+
307
+ ConnectionPool.add_data_source(rdf_connection_opts)
308
+ end
309
+
310
+ # Configure the namespaces
311
+ def config_namespaces
312
+ # Register the local name
313
+ N::Namespace.shortcut(:local, @config["local_uri"])
314
+ talia_logger.info("Local Domain: #{N::LOCAL}")
315
+
316
+ # Register the default name
317
+ N::Namespace.shortcut(:default, @config["default_namespace_uri"])
318
+ talia_logger.debug("Default Domain: #{N::DEFAULT}")
319
+
320
+ # Register namespace for database dupes
321
+ N::Namespace.shortcut(:talia, "http://talia.discovery-project.eu/wiki/TaliaInternal#")
322
+
323
+ # Register additional namespaces
324
+ if(@config["namespaces"])
325
+ assit_kind_of(Hash, @config["namespaces"])
326
+ @config["namespaces"].each_pair do |shortcut, uri|
327
+ N::Namespace.shortcut(shortcut, uri)
328
+ end
329
+ end
330
+ end
331
+
332
+ # Configure the data directory
333
+ def config_data_directory
334
+ data_directory = if(@config['data_directory_location'])
335
+ # Replace the data directory location variables
336
+ @config["data_directory_location"].gsub(/TALIA_ROOT/, TALIA_ROOT)
337
+ else
338
+ File.join(TALIA_ROOT, 'data')
339
+ end
340
+
341
+ @config['data_directory_location'] = data_directory
342
+ end
343
+
344
+ # Configure the data directory
345
+ def config_iip_root_directory
346
+ data_directory = if(@config['iip_root_directory_location'])
347
+ # Replace the iip root directory location variables
348
+ @config["iip_root_directory_location"].gsub(/TALIA_ROOT/, TALIA_ROOT)
349
+ else
350
+ File.join(TALIA_ROOT, 'iip_root')
351
+ end
352
+
353
+ @config['iip_root_directory_location'] = data_directory
354
+ end
355
+
356
+ # Autoload ontologies, if configured
357
+ def load_ontologies
358
+ return unless(@config['auto_ontologies'] && !['false', 'no'].include?(@config['auto_ontologies'].downcase))
359
+ onto_dir = File.join(TALIA_ROOT, @config['auto_ontologies'])
360
+ raise(SystemInitializationError, "Cannot find configured ontology dir #{onto_dir}") unless(File.directory?(onto_dir))
361
+ adapter = ConnectionPool.write_adapter
362
+ raise(SystemInitializationError, "Ontology autoloading without a context-aware adapter deletes all RDF data. This is only allowed in testing, please load the ontology manually.") unless(adapter.supports_context? || (@environment == 'testing'))
363
+ raise(SystemInitializationError, "Ontology autoloading requires 'load' capability on the adapter.") unless(adapter.respond_to?(:load))
364
+
365
+ # Clear out the RDF
366
+ if(adapter.supports_context?)
367
+ TaliaCore::RdfImport.clear_file_contexts
368
+ else
369
+ adapter.respond_to?(:clear) ? adapter.clear : TaliaUtil::Util::flush_rdf
370
+ end
371
+
372
+ loaded_ontos = []
373
+
374
+ Dir.foreach(onto_dir) do |file|
375
+ if(file =~ /\.owl$|\.rdf$|\.rdfs$/)
376
+ file = File.expand_path(File.join(onto_dir, file))
377
+ adapter.supports_context? ? TaliaCore::RdfImport.import_file(file, 'rdfxml', :auto) : TaliaCore::RdfImport.import_file(file, 'rdfxml')
378
+ loaded_ontos << File.basename(file)
379
+ end
380
+ end
381
+
382
+ klasses, updated = TaliaUtil::RdfUpdate::rdfs_from_owl
383
+
384
+ puts "Ontologies autoloaded: #{loaded_ontos.join(', ')} (#{updated} of #{klasses} updated)"
385
+ end
386
+
387
+ def load_core_ext
388
+ path_to_core_ext = File.join(TALIA_ROOT, 'vendor', 'plugins', 'talia_core', 'lib', 'core_ext')
389
+ Dir[path_to_core_ext + '/**/*.rb'].each { |f| require f}
390
+ end
391
+
392
+ # Register the default mime types
393
+ def register_mime_types
394
+
395
+ # Add new mime types for use in respond_to blocks:
396
+ # Mime::Type.register "text/richtext", :rtf
397
+ # Mime::Type.register_alias "text/html", :iphone
398
+ Mime::Type.register "application/rdf+xml", :rdf
399
+
400
+ # The are used for serving "static" widget content by mime type
401
+ Mime::Type.register "image/gif", :gif, [], %w( gif )
402
+ Mime::Type.register "image/jpeg", :jpeg, [], %w( jpeg jpg jpe jfif pjpeg pjp )
403
+ Mime::Type.register "image/png", :png, [], %w( png )
404
+ Mime::Type.register "image/tiff", :tiff, [], %w( tiff tif )
405
+ Mime::Type.register "image/bmp", :bmp, [], %w( bmp )
406
+ Mime::Type.register "video/isivideo", :isivideo, [], %w( fvi )
407
+ Mime::Type.register "video/mpeg", :mpeg, [], %w( mpeg mpg mpe mpv vbs mpegv )
408
+ Mime::Type.register "video/x-mpeg2", :xmpeg2, [], %w( mpv2 mp2v )
409
+ Mime::Type.register "video/msvideo", :msvideo, [], %w( avi )
410
+ Mime::Type.register "video/quicktime", :quicktime, [], %w( qt mov moov )
411
+ Mime::Type.register "video/vivo", :vivo, [], %w( viv vivo )
412
+ Mime::Type.register "video/wavelet", :wavelet, [], %w( wv )
413
+ Mime::Type.register "video/x-sgi-movie", :xsgimovie, [], %w( movie )
414
+ Mime::Type.register "application/pdf", :pdf, [], %w( pdf )
415
+ %w( hnml tei tei-p4 tei-p5 gml wittei).each do |type|
416
+ Mime::Type.register "application/xml+#{type}", type.gsub(/-/, '_').to_sym, [], [ type ]
417
+ end
418
+ end
419
+
420
+ end
421
+ end
422
+
423
+ # Add logger to the module
424
+ def self.logger
425
+ Initializer.talia_logger
426
+ end
427
+ end
@@ -0,0 +1,228 @@
1
+ module TaliaCore
2
+
3
+ # This class provides an ordering on the related sources. It will load the
4
+ # related elements into an array. All changes made to the OrderedSource will
5
+ # reflect on the Array, and will only be persisted to the store on save.
6
+ #
7
+ # The collection is contained in the ordered_objects - if you ever use that
8
+ # accessor all "ordering" relations for the object will be completely overwritten
9
+ # on saving. (You can still assign the predicates manually as long as the
10
+ # ordered_objects accesssor is not called before saving.)
11
+ class OrderedSource < ActiveSource
12
+
13
+ attr_reader :current_index
14
+
15
+ before_save :rewrite_order_relations
16
+
17
+ # Initialize SeqContainer
18
+ def self.new(uri)
19
+ @resource = super(uri)
20
+ # @resource.save!
21
+ # @resource.types << RDF::Seq.uri
22
+ # @resource
23
+ end
24
+
25
+ # Returns all elements (not the relations) in an ordered array. Unlike the
26
+ # ordered_objects accessor this will not include nil elements and the
27
+ # index will not have a 1:1 relation to the position of the elment.
28
+ #
29
+ # The ordering of the elements will be preserved, though.
30
+ def elements
31
+ # execute query
32
+ ordered_objects.compact
33
+ end
34
+
35
+ # Returns the first element of the collection
36
+ def first
37
+ ordered_objects.find { |el| !el.nil? }
38
+ end
39
+
40
+ # return the item at position index.
41
+ #
42
+ # * index: int
43
+ # * return value: TaliaCore::ActiveSource
44
+ def at(index)
45
+ @current_index = index
46
+ ordered_objects.at(index)
47
+ end
48
+
49
+ # return next item
50
+ # * current_element: int or string. Current element. If nil, the index is the last integer used with at method
51
+ def next(current_element = nil)
52
+ set_current_index_for(current_element)
53
+
54
+ # if current element is nil, next must return first value
55
+ @current_index ||= 0
56
+
57
+ if (@current_index < (size - 1))
58
+ return at(@current_index + 1) # TODO: Current is not increased, is this intentional? Do we need this method at all?
59
+ else
60
+ raise "Last item reached"
61
+ end
62
+ end
63
+
64
+ # return previous item
65
+ # * current_element: int or string. Current element. If nil, the index is the last integer used with at method
66
+ def previous(current_element = nil)
67
+ set_current_index_for(current_element)
68
+
69
+ # if current element is nil, next must return first value
70
+ @current_index = (size + 1) if @current_index.nil?
71
+
72
+ if (@current_index > 1) # TODO: This assumes a one-base array, not really useful
73
+ return at(@current_index - 1) # TODO: See above
74
+ else
75
+ raise "First item reached"
76
+ end
77
+ end
78
+
79
+ # Return the "size" of the collection. This is actually the maximum position
80
+ # index that is used. The value is cached internally and will be increased
81
+ # on insert_at (only if inserting at a value larger at the current size) and
82
+ # on the add operation. If elements are added in another way, the count
83
+ # may be off, but in that case it would be off anyway. Delete will decrease
84
+ # the size by 1, if the index removed equals the size (this is a rough guess
85
+ # which may be off!)
86
+ # The cached counter will be reset on saving.
87
+ def size
88
+ ordered_objects.size
89
+ end
90
+
91
+ # Inserts an element at the given index.
92
+ def insert_at(index, object)
93
+ write_for_index(ordered_objects, index, object)
94
+ end
95
+
96
+ # Add new item to ordered source. This will add the object after the last
97
+ # element. ATTENTION: If you add on an empty collection, it will start at
98
+ # index 1 (One), for backwards compatability
99
+ def add(object)
100
+ position = (size > 0) ? size : 1
101
+ insert_at(position, object)
102
+ end
103
+
104
+ # remove an existing object to ordered source. This will reorder the
105
+ # existing positions if deleting from the middle! If you don't want
106
+ # that use insert_at(index, nil)
107
+ def delete(index)
108
+ ordered_objects.delete_at(index)
109
+ end
110
+
111
+ # remove all existing object to ordered source
112
+ # TODO: This will not reliably delete all elements, since the size
113
+ # value is not reliable
114
+ def delete_all
115
+ @ordered_objects = []
116
+ end
117
+
118
+ # replace item as position index with object
119
+ # * index: int
120
+ # * object: TaliaCore::ActiveSource
121
+ def replace(index, object)
122
+ replace_for_index(ordered_objects, index, object)
123
+ end
124
+
125
+ # Find the position index of the given object. This will always find the
126
+ # first occurence
127
+ def find_position_by_object(object)
128
+ ordered_objects.index(object)
129
+ end
130
+
131
+ # return string for index
132
+ def index_to_predicate(index)
133
+ self.class.index_to_predicate(index)
134
+ end
135
+
136
+ # return index of predicate
137
+ def predicate_to_index(predicate)
138
+ self.class.predicate_to_index(predicate)
139
+ end
140
+
141
+ # Returns all the objects that are ordered in an array where the array
142
+ # index equals the position of the object in the ordered set. The array
143
+ # is zero-based, position that don't have an object attached will be set to
144
+ # nil.
145
+ def ordered_objects
146
+ return @ordered_objects if(@ordered_objects)
147
+ relations = query
148
+ # Let's assume the follwing is a sane assumption ;-)
149
+ # Even if a one-base collection comes in, we need to push just one element
150
+ @ordered_objects = Array.new(relations.size)
151
+ # Now add the elements so that the relation property is reflected
152
+ # on the position in the array
153
+ relations.each do |rel|
154
+ index = rel.rel_order
155
+ write_for_index(@ordered_objects, index, rel.object)
156
+ end
157
+
158
+ @ordered_objects
159
+ end
160
+
161
+ # return string for index
162
+ def self.index_to_predicate(index)
163
+ 'http://www.w3.org/1999/02/22-rdf-syntax-ns#_' << ("%06d" % index.to_i)
164
+ end
165
+
166
+ # return index of predicate
167
+ def self.predicate_to_index(predicate)
168
+ predicate.sub('http://www.w3.org/1999/02/22-rdf-syntax-ns#_', '').to_i
169
+ end
170
+
171
+ private
172
+
173
+ # Set the current index for the given element, which can be a number, a
174
+ # predicate string or an object contained in the collection. Passing nil
175
+ # causes it to do nothing.
176
+ def set_current_index_for(current_element)
177
+ return unless(current_element)
178
+
179
+ case current_element
180
+ when Fixnum then @current_index = current_element
181
+ when String then @current_index = predicate_to_index(current_element)
182
+ when TaliaCore::ActiveSource
183
+ # find semantic relation
184
+ pos = find_position_by_object(current_element)
185
+ # if no relations is found
186
+ raise "Object isn't in current OrderedSource" if pos.nil?
187
+ # else we have a position
188
+ @current_index = pos
189
+ else
190
+ raise "Class #{current_element.class} not supported"
191
+ end
192
+ end
193
+
194
+ # This will be called before saving and will completely rewrite the relations
195
+ # that make up the ordered store, based on the internal array
196
+ def rewrite_order_relations
197
+ return unless(@ordered_objects) # If this is nil, the relations weren't loaded in the first place
198
+ objects = ordered_objects # Fetch them before deleting
199
+ # Now destroy the existing elements
200
+ SemanticRelation.destroy_all(['subject_id = ? AND rel_order IS NOT NULL', self.id])
201
+ # rewrite from the relations array
202
+ objects.each_index do |index|
203
+ if(obj = objects.at(index)) # Check if there's a value to handle
204
+ # Create a new relation with an order
205
+ self[index_to_predicate(index)].add_with_order(obj, index)
206
+ end
207
+ end
208
+ end
209
+
210
+ # Helper to "grow" an array to the given index. Unless replace is true, it
211
+ # will raise an error if the element already exists.
212
+ def write_for_index(arr, index, value, replace = false)
213
+ raise(RuntimeError, "Duplicate element found on index #{index}") if(arr.at(index) && !replace)
214
+ arr[index] = value
215
+ end
216
+
217
+ def replace_for_index(arr, index, value)
218
+ write_for_index(arr, index, value, true)
219
+ end
220
+
221
+ # execute query and return the result
222
+ def query(scope = :all)
223
+ # execute query
224
+ self.semantic_relations.find(scope, :conditions => 'rel_order IS NOT NULL', :order => :rel_order)
225
+ end
226
+
227
+ end
228
+ end
@@ -0,0 +1,13 @@
1
+ module ActionController # :nodoc:
2
+ module RecordIdentifier
3
+ def singular_class_name(record_or_class)
4
+ class_from_record_or_class(record_or_class).underscore.tr('/', '_')
5
+ end
6
+
7
+ private
8
+ def class_from_record_or_class(record_or_class)
9
+ klass = record_or_class.is_a?(Class) ? record_or_class : record_or_class.class
10
+ klass.to_s.demodulize
11
+ end
12
+ end
13
+ end
@@ -0,0 +1 @@
1
+ Dir[File.dirname(__FILE__) + "/action_controller/*.rb"].sort.each { |file| require(file) }
@@ -0,0 +1 @@
1
+ Dir[File.dirname(__FILE__) + "/actionpack/*.rb"].sort.each { |file| require(file) }
@@ -0,0 +1 @@
1
+ Dir[File.dirname(__FILE__) + "/rails_ext/*.rb"].sort.each { |file| require(file) }