libis-tools 0.9.1
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.
- checksums.yaml +7 -0
- data/.coveralls.yml +2 -0
- data/.gitignore +16 -0
- data/.rspec +2 -0
- data/.travis.yml +37 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +289 -0
- data/Rakefile +6 -0
- data/lib/libis-tools.rb +1 -0
- data/lib/libis/tools.rb +16 -0
- data/lib/libis/tools/assert.rb +41 -0
- data/lib/libis/tools/checksum.rb +84 -0
- data/lib/libis/tools/command.rb +40 -0
- data/lib/libis/tools/config.rb +160 -0
- data/lib/libis/tools/dc_record.rb +47 -0
- data/lib/libis/tools/extend/empty.rb +7 -0
- data/lib/libis/tools/extend/hash.rb +107 -0
- data/lib/libis/tools/extend/ostruct.rb +3 -0
- data/lib/libis/tools/extend/string.rb +85 -0
- data/lib/libis/tools/extend/struct.rb +29 -0
- data/lib/libis/tools/logger.rb +71 -0
- data/lib/libis/tools/mets_file.rb +575 -0
- data/lib/libis/tools/parameter.rb +172 -0
- data/lib/libis/tools/sharepoint_mapping.rb +118 -0
- data/lib/libis/tools/sharepoint_record.rb +260 -0
- data/lib/libis/tools/version.rb +5 -0
- data/lib/libis/tools/xml_document.rb +574 -0
- data/libis-tools.gemspec +39 -0
- data/spec/assert_spec.rb +65 -0
- data/spec/checksum_spec.rb +132 -0
- data/spec/command_spec.rb +68 -0
- data/spec/config_spec.rb +86 -0
- data/spec/data/test.data +9 -0
- data/spec/data/test.xml +8 -0
- data/spec/data/test.yml +1 -0
- data/spec/logger_spec.rb +107 -0
- data/spec/parameter_container_spec.rb +83 -0
- data/spec/parameter_spec.rb +139 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/test.xsd +20 -0
- data/spec/xmldocument_spec.rb +413 -0
- data/test/test_helper.rb +7 -0
- data/test/webservices/test_ca_item_info.rb +59 -0
- data/test/webservices/test_ca_search.rb +35 -0
- metadata +244 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'digest'
|
4
|
+
|
5
|
+
module Libis
|
6
|
+
module Tools
|
7
|
+
|
8
|
+
# Common interface for checksum calculations.
|
9
|
+
#
|
10
|
+
# Supported checksum algortihms are MD5, RMD160 (not on JRuby), SHA-1, SHA-2 (256, 384 and 512-bit versions).
|
11
|
+
# All methods are available on the class and on the instance. The instance has to be initialized with a checksum
|
12
|
+
# algorithm and therefore the instance methods do not have to specify the checksum type.
|
13
|
+
#
|
14
|
+
class Checksum
|
15
|
+
if defined? JRUBY_VERSION
|
16
|
+
CHECKSUM_TYPES = [:MD5, :SHA1, :SHA256, :SHA384, :SHA512]
|
17
|
+
else
|
18
|
+
CHECKSUM_TYPES = [:MD5, :RMD160, :SHA1, :SHA256, :SHA384, :SHA512]
|
19
|
+
end
|
20
|
+
|
21
|
+
# Create instance for a given checksum algorithm.
|
22
|
+
#
|
23
|
+
# @param [Symbol] type checksum algorithm; one of {#CHECKSUM_TYPES}
|
24
|
+
def initialize(type)
|
25
|
+
@hasher = self.class.get_hasher(type)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Calculate binary digest of a file.
|
29
|
+
#
|
30
|
+
# @param [String] file_path_or_string path of the file to calculate the digest for
|
31
|
+
def digest(file_path_or_string)
|
32
|
+
@hasher.file(file_path_or_string).digest!
|
33
|
+
end
|
34
|
+
|
35
|
+
# Calculate the hexadecimal digest of a file.
|
36
|
+
# @param (see #digest)
|
37
|
+
def hexdigest(file_path_or_string)
|
38
|
+
@hasher.file(file_path_or_string).hexdigest!
|
39
|
+
end
|
40
|
+
|
41
|
+
# Calculate the base64 digest of a file.
|
42
|
+
# @param (see #digest)
|
43
|
+
def base64digest(file_path_or_string)
|
44
|
+
@hasher.file(file_path_or_string).base64digest!
|
45
|
+
end
|
46
|
+
|
47
|
+
# Calculate the binary digest of a file.
|
48
|
+
# @param (see #digest)
|
49
|
+
# @param (see #initialize)
|
50
|
+
def self.digest(file_path_or_string, type)
|
51
|
+
new(type).digest(file_path_or_string)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Calculate the hexadecimal digest of a file.
|
55
|
+
# @param (see #digest)
|
56
|
+
# @param (see #initialize)
|
57
|
+
def self.hexdigest(file_path_or_string, type)
|
58
|
+
new(type).hexdigest(file_path_or_string)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Calculate the base64 digest of a file.
|
62
|
+
# @param (see #digest)
|
63
|
+
# @param (see #initialize)
|
64
|
+
def self.base64digest(file_path_or_string, type)
|
65
|
+
new(type).base64digest(file_path_or_string)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Instatiate a Digest instance for access to low-level functionality
|
69
|
+
# @param (see #initialize)
|
70
|
+
def self.get_hasher(type)
|
71
|
+
raise RuntimeError, "Checksum type '#{type}' not supported." unless CHECKSUM_TYPES.include? type
|
72
|
+
Digest(type).new
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def hashit(file_path_or_string)
|
78
|
+
@hasher.file(file_path_or_string)
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'open3'
|
3
|
+
|
4
|
+
module Libis
|
5
|
+
module Tools
|
6
|
+
|
7
|
+
module Command
|
8
|
+
|
9
|
+
# Run an external program and return status, stdout and stderr.
|
10
|
+
#
|
11
|
+
#
|
12
|
+
# @param [String] cmd program name
|
13
|
+
# @param [Array<String>] opts optional list of command line arguments
|
14
|
+
# @return [Hash] a Hash with:
|
15
|
+
# * +:status+ : the exit status of the command
|
16
|
+
# * +:out+ : the stdout output of the command
|
17
|
+
# * +:err+ : the stderr output of the command
|
18
|
+
def self.run(cmd, *opts)
|
19
|
+
result = {}
|
20
|
+
begin
|
21
|
+
Open3.popen3(cmd, *opts) do |_, output, error, thread|
|
22
|
+
output = output.read
|
23
|
+
error = error.read
|
24
|
+
result[:out] = output.split("\n").map(&:chomp)
|
25
|
+
result[:err] = error.split("\n").map(&:chomp)
|
26
|
+
result[:status] = thread.value.exitstatus rescue nil
|
27
|
+
end
|
28
|
+
|
29
|
+
rescue Exception
|
30
|
+
# ignored
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
result
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'singleton'
|
3
|
+
require 'set'
|
4
|
+
require 'yaml'
|
5
|
+
require 'erb'
|
6
|
+
require 'logger'
|
7
|
+
require 'backports'
|
8
|
+
|
9
|
+
require 'libis/tools/extend/hash'
|
10
|
+
|
11
|
+
module Libis
|
12
|
+
module Tools
|
13
|
+
|
14
|
+
# The Config class is a convenience method for easy configuration maintenance and loading.
|
15
|
+
# It supports code defaults, loading configurations from multiple YAML files containing ERB statements.
|
16
|
+
# The Config class follows the Singleton pattern and behaves like a Hash/OpenStruct/HashWithIndifferentAccess.
|
17
|
+
# It also initializes a default Logger instance.
|
18
|
+
# The class also stores a system-wide {::Logger} instance that will be used by {::Libis::Tools::Logger}.
|
19
|
+
#
|
20
|
+
# The parameters can be accessed by getter/setter method or using the Hash syntax:
|
21
|
+
#
|
22
|
+
# require 'libis/tools/config'
|
23
|
+
# cfg = ::Libis::Tools::Config
|
24
|
+
# cfg['my_value'] = 10
|
25
|
+
# p cfg.instance.my_value # => 10
|
26
|
+
# cfg.instance.my_text = 'abc'
|
27
|
+
# p cfg[:my_text] # => 'abc'
|
28
|
+
# p cfg.logger.warn('message') # => W, [2015-03-16T12:51:01.180548 #28935] WARN -- : message
|
29
|
+
#
|
30
|
+
class Config
|
31
|
+
include Singleton
|
32
|
+
|
33
|
+
class << self
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# For each configuration parameter, the value can be accessed via the class or the Singleton instance.
|
38
|
+
def method_missing(name, *args, &block)
|
39
|
+
instance.send(name, *args, &block)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
# Load configuration parameters from a YAML file or Hash.
|
45
|
+
#
|
46
|
+
# The YAML file can contain ERB syntax values that will be evaluated at loading time. Multiple files can be
|
47
|
+
# loaded. Instead of a YAML file, a Hash can be passed. The file paths and Hashes are memorised and loaded again
|
48
|
+
# by the {#reload} methods.
|
49
|
+
# @param [String,Hash] file_or_hash
|
50
|
+
def <<(file_or_hash)
|
51
|
+
return if file_or_hash.nil?
|
52
|
+
hash = case file_or_hash
|
53
|
+
when Hash
|
54
|
+
@sources << file_or_hash
|
55
|
+
file_or_hash
|
56
|
+
when String
|
57
|
+
return unless File.exist?(file_or_hash)
|
58
|
+
@sources << File.absolute_path(file_or_hash)
|
59
|
+
data = ERB.new(open(file_or_hash).read).result
|
60
|
+
# noinspection RubyResolve
|
61
|
+
YAML.load(data).to_hash rescue {}
|
62
|
+
else
|
63
|
+
{}
|
64
|
+
end
|
65
|
+
@data.merge! hash.key_symbols_to_strings recursive: true
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
# Load all files and Hashes again. Will not reset the configuration parameters. Parameters set directly on the
|
70
|
+
# configuration are kept intact unless they also exist in the files or hashes in which case they will be overwritten.
|
71
|
+
def reload
|
72
|
+
sources = @sources.dup
|
73
|
+
@sources.clear
|
74
|
+
sources.each { |f| self << f }
|
75
|
+
self
|
76
|
+
end
|
77
|
+
|
78
|
+
# Load all files and Hashes again. All configuration parameters are first deleted which means that any parameters
|
79
|
+
# added directly (not via file or hash) will no longer be available. Parameters set explicitly that also exist in
|
80
|
+
# the files or hashes will be reset to the values in those files and hashes.
|
81
|
+
def reload!
|
82
|
+
@data.clear
|
83
|
+
reload
|
84
|
+
end
|
85
|
+
|
86
|
+
# Get the value of a parameter.
|
87
|
+
# @param [String, Symbol] name parameter name
|
88
|
+
# @return [Object] parameter value; nil if the parameter does not exist
|
89
|
+
def [](name)
|
90
|
+
@data.fetch(name.to_s) rescue nil
|
91
|
+
end
|
92
|
+
|
93
|
+
# Set the value of a parameter.
|
94
|
+
# If the parameter does not yet exist, it will be created.
|
95
|
+
# @param (see #[])
|
96
|
+
# @param [Object] value the new value for the parameter
|
97
|
+
# @return [Object] parameter value
|
98
|
+
def []=(name, value)
|
99
|
+
@data.store(name.to_s, value)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Return the ::Logger instance.
|
103
|
+
def logger
|
104
|
+
@logger
|
105
|
+
end
|
106
|
+
|
107
|
+
# Set the ::Logger instance.
|
108
|
+
# @param [::Logger] my_logger new logger instance
|
109
|
+
def logger=(my_logger)
|
110
|
+
@logger = my_logger
|
111
|
+
end
|
112
|
+
|
113
|
+
# Set the ::Logger instance's formatter.
|
114
|
+
# If the supplied formatter is missing or nil, a default formatter will be applied. The default formatter prints
|
115
|
+
# log lines like this:
|
116
|
+
#
|
117
|
+
# <first char of severity>, [<timestamp>#<process-id>] <severity> -- <program_name> : <message>
|
118
|
+
#
|
119
|
+
# @param [Proc] formatter the formatter procedure or nil for default formatter
|
120
|
+
def set_log_formatter(formatter = nil)
|
121
|
+
logger.formatter = formatter || proc do |severity, time, progname, msg|
|
122
|
+
"%s, [%s#%d] %5s -- %s: %s\n" % [severity[0..0],
|
123
|
+
(time.strftime('%Y-%m-%dT%H:%M:%S.') << '%06d ' % time.usec),
|
124
|
+
$$, severity, progname, msg]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def method_missing(name, *args)
|
131
|
+
key = name.to_s
|
132
|
+
if name.to_s =~ /^(.*)(=)$/
|
133
|
+
key = $1
|
134
|
+
end
|
135
|
+
if @data.has_key?(key)
|
136
|
+
if key =~/^\w+$/ # not all key names are safe to use as method names
|
137
|
+
self.instance_eval <<-END
|
138
|
+
def #{key}
|
139
|
+
self['#{key}']
|
140
|
+
end
|
141
|
+
def #{name}=(value)
|
142
|
+
self['#{name}'] = value
|
143
|
+
end
|
144
|
+
END
|
145
|
+
end
|
146
|
+
end
|
147
|
+
($2.nil? || $2.empty?) ? (@data.fetch(key) rescue nil) : @data.store(key, args.first)
|
148
|
+
end
|
149
|
+
|
150
|
+
def initialize
|
151
|
+
@data = Hash.new
|
152
|
+
@sources = Array.new
|
153
|
+
@logger = ::Logger.new(STDOUT)
|
154
|
+
set_log_formatter
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require_relative 'xml_document'
|
4
|
+
|
5
|
+
module Libis
|
6
|
+
module Tools
|
7
|
+
|
8
|
+
class DCRecord < XmlDocument
|
9
|
+
|
10
|
+
# noinspection RubyResolve
|
11
|
+
def initialize(doc = nil)
|
12
|
+
super('utf-8')
|
13
|
+
case doc
|
14
|
+
when NilClass
|
15
|
+
build do |xml|
|
16
|
+
xml[:dc].record('xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
17
|
+
'xmlns:dc' => 'http://purl.org/dc/elements/1.1/',
|
18
|
+
'xmlns:dcterms' => 'http://purl.org/dc/terms/') {
|
19
|
+
yield xml if block_given?
|
20
|
+
}
|
21
|
+
end
|
22
|
+
when ::Libis::Tools::XmlDocument
|
23
|
+
@document = doc.document.dup
|
24
|
+
when String
|
25
|
+
if File.exist?(doc)
|
26
|
+
# noinspection RubyResolve
|
27
|
+
load(doc)
|
28
|
+
else
|
29
|
+
parse(doc)
|
30
|
+
end
|
31
|
+
when Hash
|
32
|
+
self.from_hash(doc)
|
33
|
+
when IO
|
34
|
+
self.parse(doc.read)
|
35
|
+
else
|
36
|
+
raise ArgumentError, "Invalid argument: #{doc.inspect}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def add(tag, value = nil, attributes = {})
|
41
|
+
add_node(tag, value, root, attributes)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'backports/rails/hash'
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
|
5
|
+
def cleanup
|
6
|
+
self.delete_if { |_,v| v.nil? || (v.respond_to?(:empty?) ? v.empty? : false) }
|
7
|
+
end unless method_defined? :cleanup
|
8
|
+
|
9
|
+
def recursive_cleanup
|
10
|
+
delete_proc = Proc.new do |_, v|
|
11
|
+
v.delete_if(&delete_proc) if v.kind_of?(Hash)
|
12
|
+
v.nil? || (v.respond_to?(:empty?) ? v.empty? : false)
|
13
|
+
end
|
14
|
+
self.delete_if &delete_proc
|
15
|
+
end unless method_defined? :recursive_cleanup
|
16
|
+
|
17
|
+
def recursive_merge(other_hash)
|
18
|
+
self.merge(other_hash) do |_, old_val, new_val|
|
19
|
+
if old_val.is_a? Hash
|
20
|
+
old_val.recursive_merge new_val
|
21
|
+
else
|
22
|
+
new_val
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end unless method_defined? :recursive_merge
|
26
|
+
|
27
|
+
def recursive_merge!(other_hash)
|
28
|
+
self.merge!(other_hash) do |_, old_val, new_val|
|
29
|
+
if old_val.is_a? Hash
|
30
|
+
old_val.recursive_merge new_val
|
31
|
+
else
|
32
|
+
new_val
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end unless method_defined? :recursive_merge!
|
36
|
+
|
37
|
+
def key_strings_to_symbols(opts = {})
|
38
|
+
opts = {resursive: false, upcase: false, downcase: false}.merge opts
|
39
|
+
|
40
|
+
r = Hash.new
|
41
|
+
self.each_pair do |k,v|
|
42
|
+
|
43
|
+
k = k.to_s if k.kind_of? Symbol
|
44
|
+
if k.kind_of? String
|
45
|
+
k = k.downcase if opts[:downcase]
|
46
|
+
k = k.upcase if opts[:upcase]
|
47
|
+
k = k.to_sym
|
48
|
+
end
|
49
|
+
|
50
|
+
if opts[:recursive]
|
51
|
+
case v
|
52
|
+
when Hash
|
53
|
+
v = v.key_strings_to_symbols opts
|
54
|
+
when Array
|
55
|
+
# noinspection RubyResolve
|
56
|
+
v = v.collect { |a| (a.kind_of? Hash) ? a.key_strings_to_symbols(opts) : Marshal.load(Marshal.dump(a)) }
|
57
|
+
else
|
58
|
+
# noinspection RubyResolve
|
59
|
+
v = Marshal.load(Marshal.dump(v))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
r[k] = v
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
r
|
68
|
+
end unless method_defined? :key_strings_to_symbols
|
69
|
+
|
70
|
+
def key_symbols_to_strings!(opts = {})
|
71
|
+
self.replace self.key_symbols_to_strings opts
|
72
|
+
end unless method_defined? :key_symbols_to_strings!
|
73
|
+
|
74
|
+
def key_symbols_to_strings(opts = {})
|
75
|
+
opts = {resursive: false, upcase: false, downcase: false}.merge opts
|
76
|
+
|
77
|
+
r = Hash.new
|
78
|
+
self.each_pair do |k,v|
|
79
|
+
|
80
|
+
k = k.to_sym if k.kind_of? String
|
81
|
+
if k.kind_of? Symbol
|
82
|
+
k = k.to_s
|
83
|
+
k = k.downcase if opts[:downcase]
|
84
|
+
k = k.upcase if opts[:upcase]
|
85
|
+
end
|
86
|
+
|
87
|
+
if opts[:recursive]
|
88
|
+
case v
|
89
|
+
when Hash
|
90
|
+
v = v.key_symbols_to_strings(opts)
|
91
|
+
when Array
|
92
|
+
# noinspection RubyResolve
|
93
|
+
v = v.collect { |a| (a.kind_of? Hash) ? a.key_symbols_to_strings(opts) : Marshal.load(Marshal.dump(a)) }
|
94
|
+
else
|
95
|
+
# noinspection RubyResolve
|
96
|
+
v = Marshal.load(Marshal.dump(v))
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
r[k] = v
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
r
|
105
|
+
end unless method_defined? :key_symbols_to_strings
|
106
|
+
|
107
|
+
end
|