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,82 @@
1
+ module TaliaUtil
2
+
3
+ # Helper class that provides an interface to convert images, create
4
+ # thumbnails and pyramid images. This provides a central point from which to
5
+ # call external conversion tools.
6
+ #
7
+ # Since it calls the command line, it should be compatible both with JRuby
8
+ # and plain Ruby.
9
+ class ImageConversions
10
+
11
+ class << self
12
+
13
+ # Returns the command that is used for converting images
14
+ def vips_command
15
+ @vips_command ||= if(defined?(TaliaCore))
16
+ TaliaCore::CONFIG['vips_command'] || '/opt/local/bin/vips'
17
+ elsif(defined?(VIPS_COMMAND))
18
+ VIPS_COMMAND
19
+ else
20
+ raise(ArgumentError('Unconfigured vips command. If not in Talia, set VIPS_COMMAND'))
21
+ end
22
+ end
23
+
24
+ # Returns the command that is used for converting thumbnails
25
+ def convert_command
26
+ @convert_command ||= if(defined?(TaliaCore))
27
+ TaliaCore::CONFIG['convert_command'] || '/opt/local/bin/convert'
28
+ elsif(defined?(CONVERT_COMMAND))
29
+ CONVERT_COMMAND
30
+ else
31
+ raise(ArgumentError('Unconfigured convert command. If not in Talia, set CONVERT_COMMAND'))
32
+ end
33
+ end
34
+
35
+ # Returns the options for the thumbnail
36
+ def thumb_options
37
+ @thumb_options ||= if(defined?(TaliaCore))
38
+ TaliaCore::CONFIG['thumb_options'] || { 'width' => '80', 'height' => '120' }
39
+ elsif(defined?(THUMB_OPTIONS))
40
+ THUMB_OPTIONS
41
+ else
42
+ raise(ArgumentError('Unconfigured thumbnail options. If not in Talia, set THUMB_OPTIONS'))
43
+ end
44
+ end
45
+
46
+ # Create the thumbnail by running the configured creation command.
47
+ def create_thumb(source, destination)
48
+ thumbnail_size = "#{thumb_options['width']}x#{thumb_options['height']}"
49
+ thumbnail_command = "#{convert_command} \"#{source}\" -quality 85 -thumbnail \"#{thumbnail_size}>\" -background transparent -gravity center -extent #{thumbnail_size} \"#{destination}\""
50
+ execute_command(thumbnail_command, destination)
51
+ end
52
+
53
+ # Creates the pyramid image for IIP by running the configured system
54
+ # command. This automatically creates the file in the correct location
55
+ # (IIP root)
56
+ def create_pyramid(source, destination)
57
+ pyramid_command = "#{vips_command} im_vips2tiff \"#{source}\" \"#{destination}\":jpeg:85,tile:256x256,pyramid"
58
+ execute_command(pyramid_command, destination)
59
+ end
60
+
61
+ # Transforms the given image into a PNG image. Note that the .png suffix
62
+ # will automatically added to the destination name
63
+ def to_png(source, destination)
64
+ destination = "#{destination}.png" unless(File.extname(destination) == '.png')
65
+ convert_line = "#{convert_command} \"#{source}\" \"#{destination}\""
66
+ execute_command(convert_line, destination)
67
+ end
68
+
69
+ private
70
+
71
+ # Executes the given command and raises an error if not successful.
72
+ # The error will also be raised if a file is given and does not exist.
73
+ def execute_command(command, file_to_exist = nil)
74
+ system_result = system(command)
75
+ # check if successful
76
+ raise(IOError, "Command #{command} failed (#{$?}).") unless ((file_to_exist && File.exists?(file_to_exist)) || !system_result)
77
+ end
78
+
79
+ end
80
+ end
81
+ end
82
+
@@ -0,0 +1,132 @@
1
+ require 'hpricot'
2
+
3
+ module TaliaUtil
4
+
5
+ # Helper methods that will be used during import job runs.
6
+ # The import jobs may use the following environment parameters:
7
+ #
8
+ # [*base_url*] - The base URL or directory. This will be prefixed to all urls, or if it is
9
+ # a local directory, it will be made the current directory during the import
10
+ # [*index*] - If given, the importer will try to read this document. While this will still
11
+ # support the old-style "hyper" format with sigla, it should usually contain a
12
+ # main element called "index" followed by "url" entries.
13
+ # [*xml*] - URL of an XML file to import. This is incompatible with the "index" option.
14
+ # If neither "xml" nor "index" are given, the class will try to read the XML data from
15
+ # STDIN
16
+ # [*importer*] - Name of the importer class to be used for the data. Uses the default class if not given
17
+ # [*reset_store*] - If this is set, the data store will be cleared before the import
18
+ # [*user*] - Username for HTTP authentication, if required
19
+ # [*pass*] - Password for HTTP authentication, if required
20
+ # [*callback*] - Name of a class. If given, the import will call the #before_import and #after_import
21
+ # methods on an object of that class. The call will receive a block which may be
22
+ # yielded to for each progress step and which can receive the overall number of
23
+ # steps
24
+ # [*extension*] - Only used with index files; file extension to use
25
+ class ImportJobHelper
26
+
27
+ include IoHelper
28
+
29
+ attr_reader :importer, :credentials, :index_data, :xml_data, :reset, :callback, :base_url, :message_stream, :progressor
30
+
31
+ # The message_stream will be used for printing progress messages
32
+ def initialize(message_stream = STDOUT, progressor = TaliaCore::BackgroundJobs::Job)
33
+ @progressor = progressor
34
+ @message_stream = message_stream
35
+ @importer = ENV['importer'] || 'TaliaCore::ActiveSourceParts::Xml::SourceReader'
36
+ @credentials = { :http_basic_authentication => [ENV['user'], ENV['pass']] } unless(ENV['user'].blank?)
37
+ assit(!(ENV['xml'] && ENV['index']), 'Not both xml and index parameters allowed')
38
+ @reset = ['yes', 'true'].include?(ENV['reset_store'].downcase) if(ENV['reset_store'])
39
+
40
+ @base_url = ENV['base_url'].blank? ? '' : ENV['base_url']
41
+ if(base_url && File.directory?(base_url))
42
+ message_stream.puts "Setting directory to #{base_url}"
43
+ FileUtils.cd(base_url)
44
+ end
45
+
46
+ init_data
47
+
48
+ @callback = ENV['callback'].classify.constantize.new unless(ENV['callback'].blank?)
49
+
50
+ message_stream.puts "Registered callback (#{callback.class.name}) - (#{callback.respond_to?(:before_import)}|#{callback.respond_to?(:after_import)})" if(callback)
51
+
52
+ callback.progressor = progressor if(callback && callback.respond_to?(:'progressor='))
53
+ end
54
+
55
+ def init_data
56
+ if(ENV['index'].blank?)
57
+ @xml_data = if(ENV['xml'].blank?)
58
+ STDIN.read
59
+ else
60
+ xml_url = ENV['xml']
61
+ xml_url = base_url + xml_url unless(File.exists?(xml_url))
62
+ open_generic(xml_url, credentials) { |io| io.read }
63
+ end
64
+ else
65
+ index = make_url_from(ENV['index'])
66
+ @index_data = open_generic(index, credentials) { |io| io.read }
67
+ end
68
+ end
69
+
70
+ def do_import
71
+ if(reset)
72
+ TaliaUtil::Util.full_reset
73
+ puts "Data Store has been completely reset"
74
+ end
75
+ errors = []
76
+ run_callback(:before_import)
77
+ if(index_data)
78
+ import_from_index(errors)
79
+ else
80
+ puts "Importing from single data file."
81
+ TaliaCore::ActiveSource.create_from_xml(xml_data, :progressor => progressor, :reader => importer, :errors => errors)
82
+ end
83
+ if(errors.size > 0)
84
+ puts "WARNING: #{errors.size} errors during import:"
85
+ errors.each { |e| puts e }
86
+ end
87
+ run_callback(:after_import)
88
+ end
89
+
90
+ def import_from_index(errors)
91
+ doc = Hpricot.XML(index_data)
92
+ hyper_format = (doc.root.name == 'sigla')
93
+ elements = hyper_format ? (doc/:siglum) : (doc/:url)
94
+ puts "Import from Index file, #{elements.size} elements"
95
+ # Read the Attributes from the urls
96
+ source_attributes = []
97
+ my_importer = importer.classify.constantize
98
+ progressor.run_with_progress('Reading w/ index', elements.size) do |prog|
99
+ elements.each do |element|
100
+ url = make_url_from("#{element.inner_text}#{ENV['extension']}")
101
+ begin
102
+ open_generic(url, credentials) do |io|
103
+ this_attribs = my_importer.sources_from(io)
104
+ source_attributes = source_attributes + this_attribs
105
+ end
106
+ rescue Exception => e
107
+ message_stream.puts "Problem importing #{url} (#{e.message})"
108
+ message_stream.puts e.backtrace
109
+ end
110
+ prog.inc
111
+ end
112
+ end
113
+ # Write the data
114
+ TaliaCore::ActiveSource.progressor = progressor
115
+ TaliaCore::ActiveSource.create_multi_from(source_attributes, :errors => errors)
116
+ end
117
+
118
+ def make_url_from(url)
119
+ return url if(File.exist?(url))
120
+ "#{base_url}#{url}"
121
+ end
122
+
123
+ def run_callback(name)
124
+ if(callback && callback.respond_to?(name))
125
+ puts "Running callback #{name}"
126
+ callback.send(name)
127
+ end
128
+ end
129
+
130
+
131
+ end # End class
132
+ end
@@ -0,0 +1,54 @@
1
+ require 'open-uri'
2
+
3
+ module TaliaUtil
4
+
5
+ # Import data files into the Talia store. This can be used to bootstrap
6
+ # simple installations
7
+ module IoHelper
8
+
9
+ # Generic "open" method for files and urls. This won't choke on file:// URLs and
10
+ # will do some extra escaping on the URL.
11
+ #
12
+ # See open_from_url for an explanation of the options
13
+ def open_generic(url, options = {})
14
+ url = file_url(url)
15
+ # Even though open-uri would also open local files, we avoid to mangle
16
+ # the URL in open_from_url
17
+ if(File.exist?(url))
18
+ File.open(url) { |io| yield(io) }
19
+ else
20
+ open_from_url(url, options) { |io| yield(io) }
21
+ end
22
+ end
23
+
24
+ # Opens the given (web) URL, using URL encoding and necessary substitutions.
25
+ # The user must pass a block which will receive the io object from
26
+ # the url.
27
+ #
28
+ # The options may contain the http authentication information and such. See
29
+ # the documentation for open-uri for more information. Example for options:
30
+ #
31
+ # :http_basic_authentication => [login, password]
32
+ def open_from_url(url, options = {})
33
+ url = URI.encode(url)
34
+ url.gsub!(/\[/, '%5B') # URI class doesn't like unescaped brackets
35
+ url.gsub!(/\]/, '%5D')
36
+ open_args = [ url ]
37
+ open_args << options if(options)
38
+
39
+ begin
40
+ open(*open_args) do |io|
41
+ yield(io)
42
+ end
43
+ rescue Exception => e
44
+ raise(IOError, "Error loading #{url} (when file: #{url}, open_args: [#{open_args.join(', ')}]) #{e}")
45
+ end
46
+ end
47
+
48
+ # Get the "file url" for the given url, stripping a possible file:// from the front
49
+ def file_url(uri)
50
+ uri.gsub(/\Afile:\/\//, '')
51
+ end
52
+
53
+ end # End modules
54
+ end
@@ -0,0 +1,38 @@
1
+ module TaliaUtil
2
+
3
+ # Mix-in for a class that wishes to use decoupled progress meters.
4
+ module Progressable
5
+
6
+ # This is the object that will receive the progress messages
7
+ def progressor
8
+ @progressor
9
+ end
10
+
11
+ # Set the progressor class. The progress class should simply respond to
12
+ # a #run_with_progress(message, size, &block) class
13
+ def progressor=(progr)
14
+ raise(ArgumentError, "Illegal progressor") unless((progr == nil) || progr.respond_to?(:run_with_progress))
15
+ @progressor = progr
16
+ end
17
+
18
+ # Runs some block with a progress meter. The containing block will be
19
+ # passed an object on which #inc can be called to increase the meter.
20
+ #
21
+ # If no progressor object is passed in manually, the one configured
22
+ # in the class is used
23
+ def run_with_progress(message, size, progr = nil, &block)
24
+ if(progr_object = (progr || progressor))
25
+ progr_object.run_with_progress(message, size, &block)
26
+ else
27
+ dummy_prog = Object.new
28
+ class << dummy_prog
29
+ def inc
30
+ end
31
+ end
32
+ block.call(dummy_prog)
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,236 @@
1
+ #
2
+ # Ruby/ProgressBar - a text progress bar library
3
+ #
4
+ # Copyright (C) 2001-2005 Satoru Takabayashi <satoru@namazu.org>
5
+ # All rights reserved.
6
+ # This is free software with ABSOLUTELY NO WARRANTY.
7
+ #
8
+ # You can redistribute it and/or modify it under the terms
9
+ # of Ruby's license.
10
+ #
11
+
12
+ class ProgressBar # :nodoc:
13
+ VERSION = "0.9"
14
+
15
+ def initialize (title, total, out = STDERR)
16
+ @title = title
17
+ @total = total
18
+ @out = out
19
+ @terminal_width = 80
20
+ @bar_mark = "o"
21
+ @current = 0
22
+ @previous = 0
23
+ @finished_p = false
24
+ @start_time = Time.now
25
+ @previous_time = @start_time
26
+ @title_width = 14
27
+ @format = "%-#{@title_width}s %3d%% %s %s"
28
+ @format_arguments = [:title, :percentage, :bar, :stat]
29
+ clear
30
+ show
31
+ end
32
+ attr_reader :title
33
+ attr_reader :current
34
+ attr_reader :total
35
+ attr_accessor :start_time
36
+
37
+ private
38
+ def fmt_bar
39
+ bar_width = do_percentage * @terminal_width / 100
40
+ sprintf("|%s%s|",
41
+ @bar_mark * bar_width,
42
+ " " * (@terminal_width - bar_width))
43
+ end
44
+
45
+ def fmt_percentage
46
+ do_percentage
47
+ end
48
+
49
+ def fmt_stat
50
+ if @finished_p then elapsed else eta end
51
+ end
52
+
53
+ def fmt_stat_for_file_transfer
54
+ if @finished_p then
55
+ sprintf("%s %s %s", bytes, transfer_rate, elapsed)
56
+ else
57
+ sprintf("%s %s %s", bytes, transfer_rate, eta)
58
+ end
59
+ end
60
+
61
+ def fmt_title
62
+ @title[0,(@title_width - 1)] + ":"
63
+ end
64
+
65
+ def convert_bytes (bytes)
66
+ if bytes < 1024
67
+ sprintf("%6dB", bytes)
68
+ elsif bytes < 1024 * 1000 # 1000kb
69
+ sprintf("%5.1fKB", bytes.to_f / 1024)
70
+ elsif bytes < 1024 * 1024 * 1000 # 1000mb
71
+ sprintf("%5.1fMB", bytes.to_f / 1024 / 1024)
72
+ else
73
+ sprintf("%5.1fGB", bytes.to_f / 1024 / 1024 / 1024)
74
+ end
75
+ end
76
+
77
+ def transfer_rate
78
+ bytes_per_second = @current.to_f / (Time.now - @start_time)
79
+ sprintf("%s/s", convert_bytes(bytes_per_second))
80
+ end
81
+
82
+ def bytes
83
+ convert_bytes(@current)
84
+ end
85
+
86
+ def format_time (t)
87
+ t = t.to_i
88
+ sec = t % 60
89
+ min = (t / 60) % 60
90
+ hour = t / 3600
91
+ sprintf("%02d:%02d:%02d", hour, min, sec);
92
+ end
93
+
94
+ # ETA stands for Estimated Time of Arrival.
95
+ def eta
96
+ if @current == 0
97
+ "ETA: --:--:--"
98
+ else
99
+ elapsed = Time.now - @start_time
100
+ eta = elapsed * @total / @current - elapsed;
101
+ sprintf("ETA: %s", format_time(eta))
102
+ end
103
+ end
104
+
105
+ def elapsed
106
+ elapsed = Time.now - @start_time
107
+ sprintf("Time: %s", format_time(elapsed))
108
+ end
109
+
110
+ def eol
111
+ if @finished_p then "\n" else "\r" end
112
+ end
113
+
114
+ def do_percentage
115
+ if @total.zero?
116
+ 100
117
+ else
118
+ @current * 100 / @total
119
+ end
120
+ end
121
+
122
+ def get_width
123
+ # FIXME: I don't know how portable it is.
124
+ default_width = 80
125
+ begin
126
+ tiocgwinsz = 0x5413
127
+ data = [0, 0, 0, 0].pack("SSSS")
128
+ if @out.ioctl(tiocgwinsz, data) >= 0 then
129
+ rows, cols, xpixels, ypixels = data.unpack("SSSS")
130
+ if cols >= 0 then cols else default_width end
131
+ else
132
+ default_width
133
+ end
134
+ rescue Exception
135
+ default_width
136
+ end
137
+ end
138
+
139
+ def show
140
+ arguments = @format_arguments.map {|method|
141
+ method = sprintf("fmt_%s", method)
142
+ send(method)
143
+ }
144
+ line = sprintf(@format, *arguments)
145
+
146
+ width = get_width
147
+ if line.length == width - 1
148
+ @out.print(line + eol)
149
+ @out.flush
150
+ elsif line.length >= width
151
+ @terminal_width = [@terminal_width - (line.length - width + 1), 0].max
152
+ if @terminal_width == 0 then @out.print(line + eol) else show end
153
+ else # line.length < width - 1
154
+ @terminal_width += width - line.length + 1
155
+ show
156
+ end
157
+ @previous_time = Time.now
158
+ end
159
+
160
+ def show_if_needed
161
+ if @total.zero?
162
+ cur_percentage = 100
163
+ prev_percentage = 0
164
+ else
165
+ cur_percentage = (@current * 100 / @total).to_i
166
+ prev_percentage = (@previous * 100 / @total).to_i
167
+ end
168
+
169
+ # Use "!=" instead of ">" to support negative changes
170
+ if cur_percentage != prev_percentage ||
171
+ Time.now - @previous_time >= 1 || @finished_p
172
+ show
173
+ end
174
+ end
175
+
176
+ public
177
+ def clear
178
+ @out.print "\r"
179
+ @out.print(" " * (get_width - 1))
180
+ @out.print "\r"
181
+ end
182
+
183
+ def finish
184
+ @current = @total
185
+ @finished_p = true
186
+ show
187
+ end
188
+
189
+ def finished?
190
+ @finished_p
191
+ end
192
+
193
+ def file_transfer_mode
194
+ @format_arguments = [:title, :percentage, :bar, :stat_for_file_transfer]
195
+ end
196
+
197
+ def format= (format)
198
+ @format = format
199
+ end
200
+
201
+ def format_arguments= (arguments)
202
+ @format_arguments = arguments
203
+ end
204
+
205
+ def halt
206
+ @finished_p = true
207
+ show
208
+ end
209
+
210
+ def inc (step = 1)
211
+ @current += step
212
+ @current = @total if @current > @total
213
+ show_if_needed
214
+ @previous = @current
215
+ end
216
+
217
+ def set (count)
218
+ if count < 0 || count > @total
219
+ raise "invalid count: #{count} (total: #{@total})"
220
+ end
221
+ @current = count
222
+ show_if_needed
223
+ @previous = @current
224
+ end
225
+
226
+ def inspect
227
+ "#<ProgressBar:#{@current}/#{@total}>"
228
+ end
229
+ end
230
+
231
+ class ReversedProgressBar < ProgressBar
232
+ def do_percentage
233
+ 100 - super
234
+ end
235
+ end
236
+
@@ -0,0 +1,80 @@
1
+ module TaliaUtil
2
+
3
+ # Some methods to update the RDF store. There is no real inferencing, just
4
+ # some hardcoded rules that help to provide basic functionality with simple
5
+ # RDF stores.
6
+ class RdfUpdate
7
+
8
+ class << self
9
+
10
+ # This is the wrapper for rdfs_from_owl for the rake task
11
+ def owl_to_rdfs
12
+ puts "Checking for OWL classes."
13
+ # Register the namespaces for ActiveRDF
14
+ Namespace.register(:rdfs, N::RDFS.to_s)
15
+ Namespace.register(:owl, N::OWL.to_s)
16
+ progress = nil
17
+ size, modified, blanks = rdfs_from_owl do |size|
18
+ progress ||= begin
19
+ puts "#{size} OWL classes found, adding rdfs:Class type for each."
20
+ ProgressBar.new("Updating RDF database", size)
21
+ end
22
+ progress.inc
23
+ end
24
+
25
+ progress.finish if(progress)
26
+ puts "Finished updating. Updated #{modified} of #{size} classes. #{blanks} blank nodes were ignored."
27
+
28
+ end
29
+
30
+ # This checks for owl:Classes and adds and rdfs:Class triple to them. This
31
+ # doesn't check if the triple already exists, and thus may cause duplicates.
32
+ # You can pass a block that will be called with the overall size
33
+ # as a parameter.
34
+ #
35
+ # It returns the overall size, the number of modified elements and the
36
+ # number of blank nodes
37
+ def rdfs_from_owl
38
+ # Remove previous auto rdfs triples
39
+ FederationManager.clear(N::TALIA.auto_rdfs.context)
40
+
41
+ # Get all OWL classes
42
+ qry = Query.new(N::URI).distinct.select(:klass, :type)
43
+ qry.where(:klass, N::RDF::type, N::OWL + 'Class')
44
+ qry.where(:klass, N::RDF::type, :type)
45
+ classes_with_types = qry.execute
46
+ modified = 0
47
+ blanks = 0
48
+
49
+ class_hash = {}
50
+
51
+ # We have a list of all combinations of klass elements with their types
52
+ # The next step is to find all things where a RDFS.Class type already
53
+ # exists
54
+ classes_with_types.each do |class_with_type|
55
+ if(class_with_type.first.is_a?(RDFS::BNode))
56
+ blanks = blanks + 1
57
+ next
58
+ end
59
+
60
+ klass, type = class_with_type
61
+
62
+ class_hash[klass.to_s] ||= :no_rdfs_class
63
+ class_hash[klass.to_s] = :has_rdfs_class if(type == N::RDFS.Class)
64
+ end
65
+
66
+ # Now go through all klasses and add the missing triples
67
+ class_hash.each do |klass, status|
68
+ if(status == :has_rdfs_class)
69
+ modified = modified + 1
70
+ FederationManager.add(N::URI.new(klass), N::RDF.type, N::RDFS.Class, N::TALIA.auto_rdfs_context)
71
+ end
72
+ yield(class_hash.size) if(block_given?)
73
+ end
74
+
75
+ return [class_hash.size, modified, blanks]
76
+ end
77
+
78
+ end
79
+ end
80
+ end