talia_core 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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) }