rof 0.0.1.pre → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +12 -2
- data/Gemfile +1 -0
- data/README.md +87 -0
- data/bin/.ruby-version +1 -0
- data/bin/csv_to_rof +26 -0
- data/bin/fedora_to_rof +57 -0
- data/bin/osf_to_rof +40 -0
- data/bin/rof +78 -0
- data/bulk-ingest.md +242 -0
- data/labels.md +111 -0
- data/lib/rof.rb +20 -1
- data/lib/rof/access.rb +57 -0
- data/lib/rof/cli.rb +122 -0
- data/lib/rof/collection.rb +109 -0
- data/lib/rof/compare_rof.rb +92 -0
- data/lib/rof/filters/bendo.rb +33 -0
- data/lib/rof/filters/date_stamp.rb +36 -0
- data/lib/rof/filters/file_to_url.rb +27 -0
- data/lib/rof/filters/label.rb +153 -0
- data/lib/rof/filters/work.rb +111 -0
- data/lib/rof/get_from_fedora.rb +196 -0
- data/lib/rof/ingest.rb +204 -0
- data/lib/rof/ingesters/rels_ext_ingester.rb +78 -0
- data/lib/rof/ingesters/rights_metadata_ingester.rb +68 -0
- data/lib/rof/osf_context.rb +19 -0
- data/lib/rof/osf_to_rof.rb +122 -0
- data/lib/rof/rdf_context.rb +36 -0
- data/lib/rof/translate_csv.rb +112 -0
- data/lib/rof/utility.rb +84 -0
- data/lib/rof/version.rb +2 -2
- data/rof.gemspec +17 -0
- data/spec/fixtures/a.json +4 -0
- data/spec/fixtures/label.json +20 -0
- data/spec/fixtures/osf/b6psa.tar.gz +0 -0
- data/spec/fixtures/rof/dev0012829m.rof +45 -0
- data/spec/fixtures/vcr_tests/fedora_to_rof1.yml +5274 -0
- data/spec/fixtures/vecnet-citation.json +73 -0
- data/spec/lib/rof/access_spec.rb +36 -0
- data/spec/lib/rof/cli_spec.rb +66 -0
- data/spec/lib/rof/collection_spec.rb +90 -0
- data/spec/lib/rof/compare_rof_spec.rb +263 -0
- data/spec/lib/rof/filters/date_stamp_spec.rb +90 -0
- data/spec/lib/rof/filters/file_to_url_spec.rb +70 -0
- data/spec/lib/rof/filters/label_spec.rb +94 -0
- data/spec/lib/rof/filters/work_spec.rb +87 -0
- data/spec/lib/rof/ingest_spec.rb +117 -0
- data/spec/lib/rof/ingesters/rels_ext_ingester_spec.rb +62 -0
- data/spec/lib/rof/ingesters/rights_metadata_ingester_spec.rb +114 -0
- data/spec/lib/rof/osf_to_rof_spec.rb +76 -0
- data/spec/lib/rof/translate_csv_spec.rb +109 -0
- data/spec/lib/rof/utility_spec.rb +64 -0
- data/spec/lib/rof_spec.rb +14 -0
- data/spec/spec_helper.rb +11 -11
- metadata +283 -18
data/labels.md
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
# Pid Assigner Filter (aka Labels)
|
2
|
+
|
3
|
+
This filter will assign pids to objects which don't have one, and provides a labeling system so items without pids and still be linked together using RELS-EXT relationships.
|
4
|
+
|
5
|
+
More thought is needed on how to provide linking in RDF since RDF requires a full URI for subjects and objects.
|
6
|
+
|
7
|
+
## Parameters
|
8
|
+
|
9
|
+
The filter requires the following parameters to work
|
10
|
+
|
11
|
+
- A namespace to use
|
12
|
+
- A server and pool of a noids service to use
|
13
|
+
|
14
|
+
## Output
|
15
|
+
|
16
|
+
The service does two things: it assigns identifiers to objects, and it provides identifiers for linking in the RELS-EXT section.
|
17
|
+
The filter uses the following rules to assign identifiers to objects:
|
18
|
+
|
19
|
+
1. Any item not of type `fobject` is skipped.
|
20
|
+
|
21
|
+
1. Any item of type `fobject` which does not have a `pid` field will be assigned one using the provided namespace and an identifier generated by the noids service.
|
22
|
+
|
23
|
+
1. Any item of type `fobject` which has a label in its `pid` field will be assigned an pid using the provided namespace and an identifier generated by the noids service. The label will be **defined** to be the generated identifier.
|
24
|
+
|
25
|
+
1. Any item of type `fobject` which otherwise has a `pid` is skipped.
|
26
|
+
|
27
|
+
The filter uses the following rules to provide for linking in the RELS-EXT section:
|
28
|
+
|
29
|
+
1. Any item not of type `fobject` is skipped.
|
30
|
+
|
31
|
+
1. Any item of type `fobject` with no `rels-ext` section is skipped.
|
32
|
+
|
33
|
+
1. Any item of type `fobject` with a `rels-ext` section has all identifiers which are labels **substituted** with the pid assigned to the label. It is an error to use a label which cannot be resolved. See Resolution.
|
34
|
+
|
35
|
+
## Labels
|
36
|
+
|
37
|
+
A label has the same textual form whether it is used to assign a pid or to reference an assigned pid.
|
38
|
+
A label begins with a dollar sign and an open parenthesis, contains a label name, and ends with a close parenthesis.
|
39
|
+
For example, `$(label-name)`
|
40
|
+
A label name may contain any character except close parenthesis `)`.
|
41
|
+
Labels which end with the following strings are reserved:
|
42
|
+
|
43
|
+
-noid
|
44
|
+
-ns
|
45
|
+
-info
|
46
|
+
|
47
|
+
These suffixes are reserved for future use as providing alternate forms of an identifier.
|
48
|
+
|
49
|
+
I see the replacement of labels in text blocks as a possible way to adapt this to use in the `descMetadata` field, e.g.
|
50
|
+
|
51
|
+
https://curate.nd.edu/show/$(label-noid)
|
52
|
+
|
53
|
+
## Resolution
|
54
|
+
|
55
|
+
Identifiers do not need to be defined before they are referenced; they merely need to be defined eventually.
|
56
|
+
This property allows for complicated object constellations such as cycles, and even self-references.
|
57
|
+
It also makes it easier to create input files since ROF creators do not need to make sure objects which define a label are listed before any references to that label.
|
58
|
+
|
59
|
+
## Example
|
60
|
+
|
61
|
+
The following code shows how a list of objects with labels is transformed.
|
62
|
+
The input is
|
63
|
+
|
64
|
+
```
|
65
|
+
[
|
66
|
+
{
|
67
|
+
"type" : "fobject",
|
68
|
+
"pid" : "$(first)"
|
69
|
+
},
|
70
|
+
{
|
71
|
+
"type" : "fobject",
|
72
|
+
"rels-ext" : {
|
73
|
+
"memberOf" : ["$(first)", "$(second)"]
|
74
|
+
}
|
75
|
+
},
|
76
|
+
{
|
77
|
+
"type" : "fobject",
|
78
|
+
"pid" : "$(second)"
|
79
|
+
}
|
80
|
+
]
|
81
|
+
```
|
82
|
+
|
83
|
+
Results in the following output after applying the filter.
|
84
|
+
|
85
|
+
```
|
86
|
+
[
|
87
|
+
{
|
88
|
+
"type": "fobject",
|
89
|
+
"pid": "temp:001"
|
90
|
+
},
|
91
|
+
{
|
92
|
+
"type": "fobject",
|
93
|
+
"rels-ext": {
|
94
|
+
"memberOf": [
|
95
|
+
"temp:001",
|
96
|
+
"temp:003"
|
97
|
+
]
|
98
|
+
},
|
99
|
+
"pid": "temp:002"
|
100
|
+
},
|
101
|
+
{
|
102
|
+
"type": "fobject",
|
103
|
+
"pid": "temp:003"
|
104
|
+
}
|
105
|
+
]
|
106
|
+
```
|
107
|
+
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
|
data/lib/rof.rb
CHANGED
@@ -1,5 +1,24 @@
|
|
1
|
+
require "rof/ingest"
|
1
2
|
require "rof/version"
|
3
|
+
require "rof/cli"
|
4
|
+
require "rof/access"
|
5
|
+
require "rof/collection"
|
6
|
+
require "rof/utility"
|
7
|
+
require "rof/rdf_context"
|
8
|
+
require "rof/translate_csv"
|
9
|
+
require "rof/filters/date_stamp"
|
10
|
+
require "rof/filters/file_to_url"
|
11
|
+
require "rof/filters/label"
|
12
|
+
require "rof/filters/work"
|
13
|
+
require "rof/filters/bendo"
|
2
14
|
|
3
15
|
module ROF
|
16
|
+
end
|
4
17
|
|
5
|
-
|
18
|
+
# work around Rubydora expecting a logger
|
19
|
+
unless defined?(logger)
|
20
|
+
def logger
|
21
|
+
require 'logger'
|
22
|
+
@logger ||= Logger.new(STDOUT)
|
23
|
+
end
|
24
|
+
end
|
data/lib/rof/access.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module ROF
|
2
|
+
# provide translation between access strings and the ROF access hash
|
3
|
+
# e.g. ("public", owner=dbrower) --> {read-groups: "public", edit: "dbrower"}
|
4
|
+
class Access
|
5
|
+
class DecodeError < RuntimeError
|
6
|
+
end
|
7
|
+
|
8
|
+
# convert from a string to a hash
|
9
|
+
def self.decode(access_string, owner=nil)
|
10
|
+
result = {}
|
11
|
+
access_string.split(";").each do |clause|
|
12
|
+
t = self.decode_clause(clause, owner)
|
13
|
+
t.each do |k,v|
|
14
|
+
if v.is_a?(Array)
|
15
|
+
result[k] = (result.fetch(k, []) + v).uniq
|
16
|
+
else
|
17
|
+
result[k] = v
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
result
|
23
|
+
end
|
24
|
+
|
25
|
+
# convert from a hash to a string
|
26
|
+
# simple because we do not try to recover "public", et al.
|
27
|
+
def self.encode(access_hash)
|
28
|
+
result = []
|
29
|
+
access_hash.each do |k,v|
|
30
|
+
xk = k.gsub("-groups", "group").gsub("embargo-date","embargo")
|
31
|
+
xv = v.join(',') if v.is_a?(Array)
|
32
|
+
result << "#{xk}=#{xv}"
|
33
|
+
end
|
34
|
+
result.join(";")
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.decode_clause(access, owner)
|
38
|
+
case access
|
39
|
+
when "public"
|
40
|
+
{"read-groups" => ["public"], "edit" => [owner]}
|
41
|
+
when "restricted"
|
42
|
+
{"read-groups" => ["registered"], "edit" => [owner]}
|
43
|
+
when "private"
|
44
|
+
{"edit" => [owner]}
|
45
|
+
when /^embargo=(.+)/
|
46
|
+
{"embargo-date" => $1}
|
47
|
+
when /^(read|readgroup|edit|editgroup|discover|discovergroup)=(.+)/
|
48
|
+
which = $1
|
49
|
+
who = $2.split(",")
|
50
|
+
xwhich = which.gsub("group", "-groups")
|
51
|
+
Hash[xwhich, who]
|
52
|
+
else
|
53
|
+
raise DecodeError
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/rof/cli.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'rof/compare_rof'
|
3
|
+
require 'json'
|
4
|
+
require 'rubydora'
|
5
|
+
require 'rof/ingest'
|
6
|
+
require 'rof/collection'
|
7
|
+
require 'rof/get_from_fedora'
|
8
|
+
require 'rof/osf_to_rof'
|
9
|
+
module ROF
|
10
|
+
module CLI
|
11
|
+
# Ingest the file `fname` that is a level 0 rof file. It may contain any
|
12
|
+
# number of fedora objects; they will be delt with in the order they appear
|
13
|
+
# in the file. Any external files (except fname) are searched for using the
|
14
|
+
# `search_path` array of directories. If `fedora` is present, it is a hash
|
15
|
+
# having the keys `url`, `user`, and `password`. Omitting `fedora` has the
|
16
|
+
# effect of verifying the format of `fname`.
|
17
|
+
#
|
18
|
+
# All output is sent to `outfile`.
|
19
|
+
#
|
20
|
+
# Returns the number of errors.
|
21
|
+
def self.ingest_file(fname, search_paths = [], outfile = STDOUT, fedora = nil, bendo = nil)
|
22
|
+
items = load_items_from_file(fname, outfile)
|
23
|
+
ingest_array(items, search_paths, outfile, fedora, bendo)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.ingest_array(items, search_paths = [], outfile = STDOUT, fedora = nil, bendo = nil)
|
27
|
+
need_close = false
|
28
|
+
if outfile.nil?
|
29
|
+
outfile = File.open('/dev/null', 'w')
|
30
|
+
need_close = true
|
31
|
+
end
|
32
|
+
fedora = Rubydora.connect(fedora) if fedora
|
33
|
+
item_count = 1
|
34
|
+
error_count = 0
|
35
|
+
verb = fedora.nil? ? 'Verifying' : 'Ingesting'
|
36
|
+
overall_benchmark = Benchmark.measure do
|
37
|
+
items.each do |item|
|
38
|
+
begin
|
39
|
+
outfile.write("#{item_count}. #{verb} #{item['pid']} ...")
|
40
|
+
item_count += 1
|
41
|
+
individual_benchmark = Benchmark.measure do
|
42
|
+
ROF.Ingest(item, fedora, search_paths, bendo)
|
43
|
+
end
|
44
|
+
outfile.write("ok. %0.3fs\n" % individual_benchmark.real)
|
45
|
+
rescue Exception => e
|
46
|
+
error_count += 1
|
47
|
+
outfile.write("error. #{e}\n")
|
48
|
+
# TODO(dbrower): add option to toggle displaying backtraces
|
49
|
+
if e.backtrace
|
50
|
+
outfile.write(e.backtrace.join("\n\t"))
|
51
|
+
outfile.write("\n")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
outfile.write("Total time %0.3fs\n" % overall_benchmark.real)
|
57
|
+
outfile.write("#{error_count} errors\n")
|
58
|
+
error_count
|
59
|
+
ensure
|
60
|
+
outfile.close if outfile && need_close
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.filter_file(filter, fname, outfile = STDOUT)
|
64
|
+
items = load_items_from_file(fname, STDERR)
|
65
|
+
filter_array(filter, items, fname, outfile)
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.filter_array(filter, items, fname, outfile = STDOUT)
|
69
|
+
# filter will transform the items array in place
|
70
|
+
result = filter.process(items, fname)
|
71
|
+
outfile.write(JSON.pretty_generate(result))
|
72
|
+
end
|
73
|
+
|
74
|
+
# retrieve fedora object and convert to ROF
|
75
|
+
def self.convert_to_rof(pids, fedora = nil, outfile = STDOUT, config = {})
|
76
|
+
need_close = false
|
77
|
+
# use outfile is_a String
|
78
|
+
if outfile.is_a?(String)
|
79
|
+
outfile = File.open(outfile, 'w')
|
80
|
+
need_close = true
|
81
|
+
end
|
82
|
+
|
83
|
+
# wrap the objects inside a JSON list
|
84
|
+
result = []
|
85
|
+
pids.each do |pid|
|
86
|
+
result << ROF::FedoraToRof.GetFromFedora(pid, fedora, config)
|
87
|
+
end
|
88
|
+
outfile.write(JSON.pretty_generate(result))
|
89
|
+
ensure
|
90
|
+
outfile.close if outfile && need_close
|
91
|
+
end
|
92
|
+
|
93
|
+
# convert OSF archive tar.gz to rof file
|
94
|
+
def self.osf_to_rof(config, outfile = STDOUT)
|
95
|
+
osf_projects = load_items_from_file(config['project_file'], outfile) if config.key?('project_file')
|
96
|
+
rof_data = ROF::OsfToRof.osf_to_rof(config, osf_projects[0])
|
97
|
+
outfile.write(JSON.pretty_generate(rof_data))
|
98
|
+
end
|
99
|
+
|
100
|
+
# compare two rofs
|
101
|
+
def self.compare_files(file1, file2, outfile = STDOUT, _fedora, _bendo)
|
102
|
+
fedora_rof = load_items_from_file(file1, outfile)
|
103
|
+
bendo_rof = load_items_from_file(file2, outfile)
|
104
|
+
|
105
|
+
ROF::CompareRof.fedora_vs_bendo(fedora_rof, bendo_rof, outfile)
|
106
|
+
end
|
107
|
+
|
108
|
+
protected
|
109
|
+
|
110
|
+
def self.load_items_from_file(fname, outfile)
|
111
|
+
items = nil
|
112
|
+
File.open(fname, 'r:UTF-8') do |f|
|
113
|
+
items = JSON.parse(f.read)
|
114
|
+
end
|
115
|
+
items = [items] unless items.is_a? Array
|
116
|
+
items
|
117
|
+
rescue JSON::ParserError => e
|
118
|
+
outfile.puts("Error reading #{fname}:#{e}")
|
119
|
+
exit!(1)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'mime-types'
|
2
|
+
|
3
|
+
module ROF
|
4
|
+
# Called from ROF::Work.process_one_work
|
5
|
+
# Can assume type fobject, af-model Collection
|
6
|
+
class Collection
|
7
|
+
class NoFile < RuntimeError
|
8
|
+
end
|
9
|
+
def self.process_one_collection(input_obj, utility)
|
10
|
+
# set the required fields
|
11
|
+
result = set_required_fields(input_obj, utility)
|
12
|
+
result = make_images(result, input_obj, utility)
|
13
|
+
result
|
14
|
+
end
|
15
|
+
|
16
|
+
# Set the fields that must be there
|
17
|
+
def self.set_required_fields(obj, utility)
|
18
|
+
result = {}
|
19
|
+
result['type'] = 'fobject'
|
20
|
+
result['af-model'] = 'Collection'
|
21
|
+
result['rights'] = obj['rights']
|
22
|
+
result['metadata'] = obj['metadata']
|
23
|
+
result['pid'] = obj.fetch('pid', utility.next_label)
|
24
|
+
result['rels-ext'] = obj.fetch('rels-ext', {})
|
25
|
+
result['properties'] = ROF::Utility.prop_ds(obj['owner'])
|
26
|
+
result['properties-meta'] = { 'mime-type' => 'text/xml' }
|
27
|
+
result
|
28
|
+
end
|
29
|
+
|
30
|
+
# If collection included a file, create launch image and thumbnaile
|
31
|
+
def self.make_images(subtotal, obj, utility)
|
32
|
+
return subtotal if obj['files'].nil?
|
33
|
+
|
34
|
+
# verify source image is present in job dir
|
35
|
+
image_source = File.join(utility.workdir, obj['files'][0])
|
36
|
+
|
37
|
+
# attempt to create a launch page image and thumbnail
|
38
|
+
# exit if either fails
|
39
|
+
unless File.exist?(image_source)
|
40
|
+
STDERR.print("ROF:Collection.make_images: file ", image_source, " does not exist.\n")
|
41
|
+
raise NoFile
|
42
|
+
end
|
43
|
+
create_images(subtotal, image_source)
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.create_images(obj, image_source)
|
47
|
+
launch_img = make_launch(image_source)
|
48
|
+
thumb_img = make_thumb(image_source)
|
49
|
+
raise NoFile if launch_img.nil? || thumb_img.nil?
|
50
|
+
obj['content-file'] = File.basename(launch_img)
|
51
|
+
obj['content-meta'] = { 'mime-type' => find_file_mime(launch_img) }
|
52
|
+
obj['thumbnail-file'] = File.basename(thumb_img)
|
53
|
+
obj['thumbnail-meta'] = { 'mime-type' => find_file_mime(thumb_img) }
|
54
|
+
obj
|
55
|
+
end
|
56
|
+
|
57
|
+
# make collections launch page image
|
58
|
+
def self.make_launch(src_image)
|
59
|
+
options = ' -resize 350x350 '
|
60
|
+
|
61
|
+
dest_image = mk_dest_img_name(src_image, '-launch')
|
62
|
+
unless run_convert(src_image, dest_image, options)
|
63
|
+
STDERR.print("ROF:Collection.mk_launch: failed on file ", src_image, ".\n")
|
64
|
+
return nil
|
65
|
+
end
|
66
|
+
dest_image
|
67
|
+
end
|
68
|
+
|
69
|
+
# make thumbnail
|
70
|
+
def self.make_thumb(src_image)
|
71
|
+
options = ' -resize 256x256 '
|
72
|
+
|
73
|
+
dest_image = mk_dest_img_name(src_image, '-thumb')
|
74
|
+
unless run_convert(src_image, dest_image, options)
|
75
|
+
STDERR.print("ROF:Collection.mk_thumb: failed on file ", src_image, ".\n")
|
76
|
+
return nil
|
77
|
+
end
|
78
|
+
dest_image
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.run_convert(src_image, dest_image, options)
|
82
|
+
command = set_convert_path + ' ' + src_image + options + ' ' + dest_image
|
83
|
+
Kernel.system(command)
|
84
|
+
end
|
85
|
+
|
86
|
+
# figure out where ImageMagick is installed
|
87
|
+
# (assumes brew path on MacOS, binary RPM path on Linux).
|
88
|
+
def self.set_convert_path
|
89
|
+
host_os = RbConfig::CONFIG['sitearch']
|
90
|
+
|
91
|
+
return '/usr/local/bin/convert' if host_os.include? 'darwin'
|
92
|
+
'/usr/bin/convert'
|
93
|
+
end
|
94
|
+
|
95
|
+
# given source image, create destination name for conversion
|
96
|
+
# keep same mime type - use dumb mime type determination
|
97
|
+
def self.mk_dest_img_name(src_img, dest_name)
|
98
|
+
dest_part = src_img.split('.')
|
99
|
+
dest_img = dest_part[0] + dest_name
|
100
|
+
dest_img = dest_img + '.' + dest_part[1] if dest_part.length == 2
|
101
|
+
dest_img
|
102
|
+
end
|
103
|
+
|
104
|
+
# extract file extension and determine mime/type.
|
105
|
+
def self.find_file_mime(filename)
|
106
|
+
MIME::Types.of(filename).first.content_type
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'rdf/ntriples'
|
3
|
+
require 'rdf/rdfxml'
|
4
|
+
require 'rof/rdf_context'
|
5
|
+
require 'rdf/isomorphic'
|
6
|
+
|
7
|
+
module ROF
|
8
|
+
class CompareRof
|
9
|
+
|
10
|
+
# compare fedora rof to bendo_rof
|
11
|
+
# return true in equivalent, false if not
|
12
|
+
def self.fedora_vs_bendo( fedora_rof, bendo_rof, output)
|
13
|
+
|
14
|
+
error_count = 0
|
15
|
+
# dereferencing an array of one element with [0]. Oh, the horror of it.
|
16
|
+
error_count += compare_rights( fedora_rof[0], bendo_rof[0], output)
|
17
|
+
error_count += compare_rels_ext(fedora_rof[0], bendo_rof[0])
|
18
|
+
error_count += compare_metadata(fedora_rof[0], bendo_rof[0])
|
19
|
+
error_count += compare_everything_else(fedora_rof[0], bendo_rof[0], output)
|
20
|
+
error_count
|
21
|
+
end
|
22
|
+
|
23
|
+
# do rights comparison
|
24
|
+
# return 0 if the same, >0 if different
|
25
|
+
def self.compare_rights( fedora_rof, bendo_rof, output )
|
26
|
+
|
27
|
+
error_count =0
|
28
|
+
|
29
|
+
# Use same comparison scheme on all rights
|
30
|
+
[ 'read' , 'read-groups', 'edit', 'edit-groups', 'edit-users', 'embargo-date'].each do |attribute|
|
31
|
+
error_count += rights_equal(attribute, fedora_rof, bendo_rof)
|
32
|
+
break if error_count != 0
|
33
|
+
end
|
34
|
+
|
35
|
+
error_count
|
36
|
+
end
|
37
|
+
|
38
|
+
# compare array or element for equivalence
|
39
|
+
def self.rights_equal(rights_attr, fedora, bendo)
|
40
|
+
f_rights = fedora.fetch('rights', {}).fetch(rights_attr, [])
|
41
|
+
b_rights = bendo.fetch('rights', {}).fetch(rights_attr, [])
|
42
|
+
|
43
|
+
f_rights = f_rights.sort if f_rights.respond_to?(:"sort")
|
44
|
+
b_rights = b_rights.sort if b_rights.respond_to?(:"sort")
|
45
|
+
|
46
|
+
return 0 if f_rights == b_rights
|
47
|
+
1
|
48
|
+
end
|
49
|
+
|
50
|
+
# convert RELS-EXT sections to RDF::graph and compater w/ rdf-isomorphic
|
51
|
+
def self.compare_rels_ext(fedora, bendo)
|
52
|
+
error_count = 0
|
53
|
+
bendo_rdf = jsonld_to_rdf(bendo['rels-ext'], ROF::RelsExtRefContext)
|
54
|
+
fedora_rdf = jsonld_to_rdf(fedora['rels-ext'], ROF::RelsExtRefContext)
|
55
|
+
error_count +=1 if ! bendo_rdf.isomorphic_with? fedora_rdf
|
56
|
+
error_count
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.jsonld_to_rdf(doc, default_context)
|
60
|
+
doc["@context"] = default_context unless doc.has_key?("@context")
|
61
|
+
RDF::Graph.new << JSON::LD::API.toRdf(doc)
|
62
|
+
end
|
63
|
+
|
64
|
+
# convert metadata sections to RDF::graph and compater w/ rdf-isomorphic
|
65
|
+
def self.compare_metadata(fedora, bendo)
|
66
|
+
error_count = 0
|
67
|
+
bendo_rdf = jsonld_to_rdf(bendo['metadata'], ROF::RdfContext)
|
68
|
+
fedora_rdf = jsonld_to_rdf(fedora['metadata'], ROF::RdfContext)
|
69
|
+
error_count +=1 if ! bendo_rdf.isomorphic_with? fedora_rdf
|
70
|
+
error_count
|
71
|
+
end
|
72
|
+
|
73
|
+
# compare what remains
|
74
|
+
def self.compare_everything_else( fedora, bendo, output)
|
75
|
+
error_count =0
|
76
|
+
fedora = remove_others(fedora)
|
77
|
+
bendo = remove_others(bendo)
|
78
|
+
# comparsion using builtin equivalency operation
|
79
|
+
error_count = 1 if bendo != fedora
|
80
|
+
error_count
|
81
|
+
end
|
82
|
+
|
83
|
+
# remove elements we've dealt with already
|
84
|
+
def self.remove_others( rof_object)
|
85
|
+
rof_object.delete('rights')
|
86
|
+
rof_object.delete('rels-ext')
|
87
|
+
rof_object.delete('metadata')
|
88
|
+
rof_object.delete('thumbnail-file')
|
89
|
+
rof_object
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|