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,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