rof 1.0.7 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +9 -7
  3. data/LICENSE +201 -16
  4. data/Rakefile +46 -0
  5. data/bin/csv_to_rof +1 -2
  6. data/bin/fedora_to_rof +7 -1
  7. data/bin/jsonld_to_rof +26 -0
  8. data/bin/osf_to_rof +6 -2
  9. data/bin/rof +5 -19
  10. data/lib/rof.rb +2 -6
  11. data/lib/rof/access.rb +1 -1
  12. data/lib/rof/cli.rb +104 -67
  13. data/lib/rof/compare_rof.rb +68 -39
  14. data/lib/rof/filter.rb +21 -0
  15. data/lib/rof/filters.rb +38 -0
  16. data/lib/rof/filters/bendo.rb +15 -17
  17. data/lib/rof/filters/date_stamp.rb +5 -4
  18. data/lib/rof/filters/file_to_url.rb +5 -3
  19. data/lib/rof/filters/label.rb +9 -7
  20. data/lib/rof/filters/work.rb +7 -5
  21. data/lib/rof/ingest.rb +5 -0
  22. data/lib/rof/osf_context.rb +2 -2
  23. data/lib/rof/rdf_context.rb +2 -0
  24. data/lib/rof/translator.rb +18 -0
  25. data/lib/rof/translators.rb +23 -0
  26. data/lib/rof/{translate_csv.rb → translators/csv_to_rof.rb} +4 -3
  27. data/lib/rof/translators/fedora_to_rof.rb +244 -0
  28. data/lib/rof/translators/jsonld_to_rof.rb +112 -0
  29. data/lib/rof/translators/jsonld_to_rof/accumulator.rb +175 -0
  30. data/lib/rof/translators/jsonld_to_rof/predicate_handler.rb +223 -0
  31. data/lib/rof/translators/jsonld_to_rof/predicate_object_handler.rb +125 -0
  32. data/lib/rof/translators/jsonld_to_rof/statement_handler.rb +91 -0
  33. data/lib/rof/translators/osf_to_rof.rb +191 -0
  34. data/lib/rof/utility.rb +44 -1
  35. data/lib/rof/version.rb +1 -1
  36. data/rof.gemspec +10 -2
  37. data/spec/coverage_helper.rb +17 -0
  38. data/spec/fixtures/for_utility_load_items_from_json_file/multiple_items.json +8 -0
  39. data/spec/fixtures/for_utility_load_items_from_json_file/parse_error.json +3 -0
  40. data/spec/fixtures/for_utility_load_items_from_json_file/single_item.json +3 -0
  41. data/spec/fixtures/jsonld_to_rof/0g354f18610.jsonld +113 -0
  42. data/spec/fixtures/jsonld_to_rof/0g354f18610.rof +96 -0
  43. data/spec/fixtures/jsonld_to_rof/2j62s467216.jsonld +113 -0
  44. data/spec/fixtures/jsonld_to_rof/2j62s467216.rof +93 -0
  45. data/spec/fixtures/jsonld_to_rof/2v23vt16z2z.jsonld +70 -0
  46. data/spec/fixtures/jsonld_to_rof/2v23vt16z2z.rof +87 -0
  47. data/spec/fixtures/jsonld_to_rof/cr56n01253w.jsonld +84 -0
  48. data/spec/fixtures/jsonld_to_rof/cr56n01253w.rof +95 -0
  49. data/spec/fixtures/jsonld_to_rof/h989r21069m.jsonld +84 -0
  50. data/spec/fixtures/jsonld_to_rof/h989r21069m.rof +98 -0
  51. data/spec/fixtures/jsonld_to_rof/js956d59913.jsonld +79 -0
  52. data/spec/fixtures/jsonld_to_rof/js956d59913.rof +89 -0
  53. data/spec/fixtures/jsonld_to_rof/m039k358q5c.jsonld +80 -0
  54. data/spec/fixtures/jsonld_to_rof/m039k358q5c.rof +64 -0
  55. data/spec/fixtures/jsonld_to_rof/nk322b9161g.jsonld +89 -0
  56. data/spec/fixtures/jsonld_to_rof/nk322b9161g.rof +69 -0
  57. data/spec/fixtures/jsonld_to_rof/p8418k7430d.jsonld +84 -0
  58. data/spec/fixtures/jsonld_to_rof/p8418k7430d.rof +67 -0
  59. data/spec/fixtures/jsonld_to_rof/xg94hm53h0c.jsonld +98 -0
  60. data/spec/fixtures/jsonld_to_rof/xg94hm53h0c.rof +110 -0
  61. data/spec/fixtures/jsonld_to_rof/zk51vd69n1r.jsonld +94 -0
  62. data/spec/fixtures/jsonld_to_rof/zk51vd69n1r.rof +121 -0
  63. data/spec/fixtures/osf/phz6b.tar.gz +0 -0
  64. data/spec/lib/rof/access_spec.rb +30 -23
  65. data/spec/lib/rof/cli_spec.rb +83 -60
  66. data/spec/lib/rof/compare_rof_spec.rb +35 -24
  67. data/spec/lib/rof/filter_spec.rb +10 -0
  68. data/spec/lib/rof/filters/bendo_spec.rb +42 -0
  69. data/spec/lib/rof/filters/date_stamp_spec.rb +9 -5
  70. data/spec/lib/rof/filters/file_to_url_spec.rb +7 -3
  71. data/spec/lib/rof/filters/label_spec.rb +121 -77
  72. data/spec/lib/rof/filters/work_spec.rb +7 -4
  73. data/spec/lib/rof/filters_spec.rb +14 -0
  74. data/spec/lib/rof/translator_spec.rb +15 -0
  75. data/spec/lib/rof/{translate_csv_spec.rb → translators/csv_to_rof_spec.rb} +14 -14
  76. data/spec/lib/rof/translators/fedora_to_rof_spec.rb +64 -0
  77. data/spec/lib/rof/translators/jsonld_to_rof/accumulator_spec.rb +121 -0
  78. data/spec/lib/rof/translators/jsonld_to_rof/predicate_handler_spec.rb +73 -0
  79. data/spec/lib/rof/translators/jsonld_to_rof/predicate_object_handler_spec.rb +48 -0
  80. data/spec/lib/rof/translators/jsonld_to_rof/statement_handler_spec.rb +40 -0
  81. data/spec/lib/rof/translators/jsonld_to_rof_spec.rb +120 -0
  82. data/spec/lib/rof/{osf_to_rof_spec.rb → translators/osf_to_rof_spec.rb} +55 -25
  83. data/spec/lib/rof/translators_spec.rb +14 -0
  84. data/spec/lib/rof/utility_spec.rb +47 -1
  85. data/spec/spec_helper.rb +1 -1
  86. data/spec/support/an_rof_filter.rb +10 -0
  87. metadata +186 -15
  88. data/lib/rof/get_from_fedora.rb +0 -211
  89. data/lib/rof/osf_to_rof.rb +0 -123
  90. data/spec/lib/rof/get_from_fedora_spec.rb +0 -22
@@ -3,90 +3,119 @@ require 'rdf/ntriples'
3
3
  require 'rdf/rdfxml'
4
4
  require 'rof/rdf_context'
5
5
  require 'rdf/isomorphic'
6
+ require 'active_support/core_ext/array/wrap'
6
7
 
7
8
  module ROF
8
9
  class CompareRof
9
10
 
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)
11
+ # Compare two ROF objects; we'll call one fedora_rof and the other bendo_rof
12
+ # @return 0 if no errors; otherwise there are errors
13
+ def self.fedora_vs_bendo(fedora_rof, bendo_rof, _output = nil, options = {})
14
+ new(Array.wrap(fedora_rof)[0], Array.wrap(bendo_rof)[0], options).error_count
15
+ end
13
16
 
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
17
+ def initialize(fedora, bendo, options = {})
18
+ @fedora = Array.wrap(fedora).first
19
+ @bendo = Array.wrap(bendo).first
20
+ @skip_rels_ext_context = options.fetch(:skip_rels_ext_context) { false }
21
+ end
22
+ attr_reader :fedora, :bendo
23
+
24
+ def error_count
25
+ @error_count = 0
26
+ @error_count += compare_rights
27
+ @error_count += compare_rels_ext
28
+ @error_count += compare_metadata
29
+ @error_count += compare_everything_else
30
+ @error_count
21
31
  end
22
32
 
23
33
  # do rights comparison
24
34
  # return 0 if the same, >0 if different
25
- def self.compare_rights( fedora_rof, bendo_rof, output )
35
+ def compare_rights
26
36
 
27
37
  error_count =0
28
38
 
29
39
  # Use same comparison scheme on all rights
30
40
  [ 'read' , 'read-groups', 'edit', 'edit-groups', 'edit-users', 'embargo-date'].each do |attribute|
31
- error_count += rights_equal(attribute, fedora_rof, bendo_rof)
41
+ error_count += rights_equal(attribute)
32
42
  break if error_count != 0
33
43
  end
34
44
 
35
45
  error_count
36
46
  end
37
47
 
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, [])
48
+ private
42
49
 
43
- f_rights = f_rights.sort if f_rights.respond_to?(:"sort")
44
- b_rights = b_rights.sort if b_rights.respond_to?(:"sort")
50
+ # compare array or element for equivalence
51
+ def rights_equal(rights_attr)
52
+ f_rights = Array.wrap(fedora.fetch('rights', {}).fetch(rights_attr, [])).sort
53
+ b_rights = Array.wrap(bendo.fetch('rights', {}).fetch(rights_attr, [])).sort
45
54
 
46
55
  return 0 if f_rights == b_rights
47
56
  1
48
57
  end
49
58
 
59
+ public
60
+
50
61
  # convert RELS-EXT sections to RDF::graph and compater w/ rdf-isomorphic
51
- def self.compare_rels_ext(fedora, bendo)
62
+ def compare_rels_ext
52
63
  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)
64
+ # Because Sipity's RELS-EXT context was out of whack, I need a switch to skip comparing
65
+ # the @context of the rels-ext document
66
+ bendo_rdf = jsonld_to_rdf(bendo.fetch('rels-ext', {}), ROF::RelsExtRefContext, @skip_rels_ext_context)
67
+ fedora_rdf = jsonld_to_rdf(fedora.fetch('rels-ext', {}), ROF::RelsExtRefContext, @skip_rels_ext_context)
55
68
  error_count +=1 if ! bendo_rdf.isomorphic_with? fedora_rdf
56
69
  error_count
57
70
  end
58
-
59
- def self.jsonld_to_rdf(doc, default_context)
60
- doc["@context"] = default_context unless doc.has_key?("@context")
71
+
72
+ private
73
+
74
+ def jsonld_to_rdf(doc, default_context, skip_context = false)
75
+ if skip_context
76
+ doc.delete('@context')
77
+ else
78
+ doc["@context"] ||= default_context
79
+ end
61
80
  RDF::Graph.new << JSON::LD::API.toRdf(doc)
62
81
  end
63
82
 
83
+ public
84
+
64
85
  # convert metadata sections to RDF::graph and compater w/ rdf-isomorphic
65
- def self.compare_metadata(fedora, bendo)
86
+ def compare_metadata
66
87
  error_count = 0
67
- bendo_rdf = jsonld_to_rdf(bendo['metadata'], ROF::RdfContext)
68
- fedora_rdf = jsonld_to_rdf(fedora['metadata'], ROF::RdfContext)
88
+ bendo_rdf = jsonld_to_rdf(bendo.fetch('metadata', {}), ROF::RdfContext)
89
+ fedora_rdf = jsonld_to_rdf(fedora.fetch('metadata', {}), ROF::RdfContext)
69
90
  error_count +=1 if ! bendo_rdf.isomorphic_with? fedora_rdf
70
91
  error_count
71
92
  end
72
93
 
73
94
  # compare what remains
74
- def self.compare_everything_else( fedora, bendo, output)
95
+ def compare_everything_else
75
96
  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
97
+ exclude_keys = ['rights', 'rels-ext', 'metadata', 'thumbnail-file']
98
+ all_keys_to_check = (bendo.keys + fedora.keys - exclude_keys).uniq
99
+ all_keys_to_check.each do |key|
100
+ bendo_value = bendo.fetch(key, nil)
101
+ fedora_value = fedora.fetch(key, nil)
102
+ # Treat an empty hash and an empty array as equal
103
+ next if bendo_value.empty? && fedora_value.empty?
104
+ next if normalize_value(bendo_value) == normalize_value(fedora_value)
105
+ error_count += 1
106
+ break
107
+ end
80
108
  error_count
81
109
  end
82
110
 
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
111
+ private
112
+
113
+ # Because sometimes we have carriage returns and line breaks but we really don't care
114
+ # @todo Do we care about line breaks?
115
+ def normalize_value(values)
116
+ Array.wrap(values).map do |value|
117
+ value.is_a?(String) ? value.gsub("\n", "") : value
118
+ end
90
119
  end
91
120
  end
92
121
  end
@@ -0,0 +1,21 @@
1
+ module ROF
2
+ # A placeholder implementation for an ROF::Filter.
3
+ # @see ROF::Filters
4
+ class Filter
5
+ # @param [Hash] options - a hash with symbol keys; used to configure the instantiation of the filter
6
+ def initialize(options = {})
7
+ end
8
+
9
+ # Performs operations on the given obj_list. This can be things like:
10
+ #
11
+ # * Adding new keys to the inner Hash
12
+ # * Converting placeholder values with calculated values (@see ROF::Filters::Label)
13
+ # * Other changes
14
+ #
15
+ # @param [Array<Hash>] obj_list - An Array of Hash objects
16
+ # @return [Array<Hash>] a changed version of the given
17
+ def process(obj_list)
18
+ raise NotImplementedError
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ Dir.glob(File.expand_path('../filters/*.rb', __FILE__)).each do |filename|
2
+ require filename
3
+ end
4
+
5
+ module ROF
6
+ # A container class for all ROF filters. What is an ROF filter? @see ROF::Filters.for
7
+ # @see ROF::Filter for abstract definition
8
+ module Filters
9
+ class UnknownFilterError < RuntimeError
10
+ def initialize(filter_name, available_filters)
11
+ super(%(Unable to find filter "#{filter_name}". Available filter names are: #{available_filters.inspect}))
12
+ end
13
+ end
14
+ AVAILABLE_FILTERS = {
15
+ "bendo" => ROF::Filters::Bendo,
16
+ "datestamp" => ROF::Filters::DateStamp,
17
+ "file-to-url" => ROF::Filters::FileToUrl,
18
+ "label" => ROF::Filters::Label,
19
+ "work" => ROF::Filters::Work,
20
+ }
21
+ # @api public
22
+ #
23
+ # @param [String] filter_name - the named filter you want to instantiate
24
+ # @param [Hash] options - a hash (with symbol keys) that is used for configuring the instantiating of the filter
25
+ # @return [ROF::Filter]
26
+ # @raise ROF::Filters::UnknownFilterError if the given filter name is not registered
27
+ # @see ./spec/support/an_rof_filter.rb
28
+ # @see ROF::Filter
29
+ def self.for(filter_name, options = {})
30
+ begin
31
+ filter = AVAILABLE_FILTERS.fetch(filter_name)
32
+ rescue KeyError
33
+ raise UnknownFilterError.new(filter_name, AVAILABLE_FILTERS.keys)
34
+ end
35
+ filter.new(options)
36
+ end
37
+ end
38
+ end
@@ -1,30 +1,28 @@
1
- require 'date'
2
-
1
+ require 'rof/filter'
3
2
  module ROF
4
3
  module Filters
5
4
 
6
5
  # If bendo server is set , add it into datasreams that contain an URl referencing bendo
7
- #
8
- class Bendo
9
- def initialize(bendo=nil)
10
- @bendo = bendo
6
+ class Bendo < ROF::Filter
7
+ def initialize(options = {})
8
+ @bendo = options.fetch(:bendo_info)
11
9
  end
12
10
 
13
- def process(obj_list, _fname)
14
-
15
- ends_meta = Regexp.new('(.+)-meta')
16
-
17
- # for *-meta objects containing "URL", sub in bendo string if provided
18
-
11
+ # for *-meta objects containing "URL", sub in bendo string if provided
12
+ def process(obj_list)
13
+ # NOTE: This was refactored to short-circuit the loop. A side-effect is that the code
14
+ # is now returning the same object as was passed in. The previous behavior was that a
15
+ # new object_list was created via the #map! method.
16
+ return obj_list unless @bendo
17
+ key_name_ends_in_meta_regexp = Regexp.new('(.+)-meta')
19
18
  obj_list.map! do |obj|
20
- obj.map do |name, value|
21
- if name =~ ends_meta
22
- if obj[name]["URL"] && @bendo
23
- obj[name]["URL"] = obj[name]["URL"].sub("bendo:",@bendo)
19
+ obj.map do |key_name, value|
20
+ if key_name =~ key_name_ends_in_meta_regexp
21
+ if obj[key_name]["URL"]
22
+ obj[key_name]["URL"] = obj[key_name]["URL"].sub("bendo:", @bendo)
24
23
  end
25
24
  end
26
25
  end
27
- # print object
28
26
  obj
29
27
  end
30
28
  end
@@ -1,3 +1,4 @@
1
+ require 'rof/filter'
1
2
  require 'date'
2
3
 
3
4
  module ROF
@@ -5,9 +6,9 @@ module ROF
5
6
  # Set the upload date to be the date given, provided it doesn't already exist.
6
7
  # Also set the date modified to be the date given.
7
8
  # If not given, the date used defaults to the local time on the computer.
8
- class DateStamp
9
- def initialize(date=nil)
10
- @today = date || Date::today
9
+ class DateStamp < ROF::Filter
10
+ def initialize(options = {})
11
+ @today = options.fetch(:as_of) { Date::today }
11
12
  @today_s = if @today.is_a?(Date)
12
13
  @today.strftime('%FZ')
13
14
  else
@@ -15,7 +16,7 @@ module ROF
15
16
  end
16
17
  end
17
18
 
18
- def process(obj_list, _fname)
19
+ def process(obj_list)
19
20
  obj_list.map! do |obj|
20
21
  if obj["metadata"].nil?
21
22
  obj["metadata"] = {
@@ -1,3 +1,5 @@
1
+ require 'rof/filter'
2
+
1
3
  module ROF
2
4
  module Filters
3
5
  # Convert any content datastream files into a bendo URL, and alter the rof
@@ -5,11 +7,11 @@ module ROF
5
7
  # will only exist for items having a bendo-item id set. The URL generated
6
8
  # supposes the file keeps the same relative path the item originally had in
7
9
  # the rof file.
8
- class FileToUrl
9
- def initialize()
10
+ class FileToUrl < ROF::Filter
11
+ def initialize(options = {})
10
12
  end
11
13
 
12
- def process(obj_list, _fname)
14
+ def process(obj_list)
13
15
  obj_list.map! do |obj|
14
16
  bendo_item = obj['bendo-item']
15
17
  content_file = obj['content-file']
@@ -1,3 +1,4 @@
1
+ require 'rof/filter'
1
2
  require 'noids_client'
2
3
 
3
4
  module ROF
@@ -5,7 +6,7 @@ module ROF
5
6
  # Class Label locates in-place labels of the form
6
7
  # "$(label_name)" in the ROF file, assigns each
7
8
  # label a pid, then replaces the label with that pid.
8
- class Label
9
+ class Label < ROF::Filter
9
10
  class MissingLabel < RuntimeError
10
11
  end
11
12
 
@@ -21,14 +22,15 @@ module ROF
21
22
  # Use :id_list to pass in a ruby object responding to #shift and #empty? to generate
22
23
  # ids. This is usually a list, to facilitate testing.
23
24
  #
24
- # If prefix is not nil, then "#{prefix}:" is prepended to
25
+ # If prefix is not nil, then "<prefix>:" is prepended to
25
26
  # every identifier.
26
- def initialize(prefix, options)
27
+ def initialize(options = {})
28
+ prefix = options.fetch(:prefix, nil)
27
29
  @id_list = case
28
30
  when options[:id_list]
29
31
  options[:id_list]
30
32
  when options[:noid_server]
31
- NoidsPool.new(options[:noid_server], options[:pool_name])
33
+ NoidsPool.new(options[:noid_server], options.fetch(:pool_name))
32
34
  else
33
35
  raise NoPool
34
36
  end
@@ -39,7 +41,7 @@ module ROF
39
41
 
40
42
  # mutate obj_list by assigning labels and resolving labels where needed
41
43
  # Every fobject will be assigned an pid and a bendo_item
42
- def process(obj_list, _fname)
44
+ def process(obj_list)
43
45
  labels = {}
44
46
 
45
47
  # Use two passes. First assign ids, and then resolve labels
@@ -136,8 +138,8 @@ module ROF
136
138
 
137
139
  # Encapsulates connection to Noids Server
138
140
  class NoidsPool
139
- def initialize(noids_server, pool_name)
140
- @pool = NoidsClient::Connection.new(noids_server).get_pool(pool_name)
141
+ def initialize(noids_server_url, pool_name)
142
+ @pool = NoidsClient::Connection.new(noids_server_url).get_pool(pool_name)
141
143
  end
142
144
 
143
145
  def shift
@@ -1,5 +1,5 @@
1
1
  require 'mime-types'
2
-
2
+ require 'rof/filter'
3
3
  module ROF
4
4
  module Filters
5
5
  # Expand objects of type "Work(-(.+))?" into a
@@ -8,17 +8,19 @@ module ROF
8
8
  # adds a depositor
9
9
  # turns original object into an fobject/$1
10
10
  # and copies the access to each fobject.
11
- class Work
11
+ class Work < ROF::Filter
12
12
  class NoFile < RuntimeError
13
13
  end
14
14
 
15
- def initialize
15
+ def initialize(options = {})
16
+ @file_name = options.fetch(:file_name)
16
17
  @utility = ROF::Utility.new
17
18
  end
19
+ attr_reader :file_name
18
20
 
19
21
  # wade through object list
20
- def process(obj_list, filename)
21
- @utility.set_workdir(filename)
22
+ def process(obj_list)
23
+ @utility.set_workdir(file_name)
22
24
  obj_list.map! { |x| process_one_work(x) }
23
25
  obj_list.flatten!
24
26
  end
@@ -20,6 +20,11 @@ module ROF
20
20
  # Otherwise fedora is a Rubydora::Reporitory object (for now...)
21
21
  # Returns a list of ingested datastreams, if everything is okay.
22
22
  # Otherwise raises an exception depending on the error.
23
+ # @param [Hash] item - has string based keys
24
+ # @param [#find_or_initialize, nil] fedora - when nil then we verify that item is in the proper format; otherwise we ingest or update
25
+ # @param [Array] search_paths
26
+ # @param [nil, String] bendo - when nil, no attempts to substitute the bendo URL
27
+ # @return [Array<String>] List of ingested data streams; Implies everything ingested ok.
23
28
  def self.Ingest(item, fedora=nil, search_paths=[], bendo=nil)
24
29
  raise NotFobjectError if item["type"] != "fobject"
25
30
  raise TooManyIdentitiesError if item.key?("id") && item.key?("pid")
@@ -1,5 +1,4 @@
1
1
  module ROF
2
-
3
2
  OsfPrefixList = {
4
3
  'dcterms' => 'http://purl.org/dc/terms/',
5
4
  'osf-model' => 'http://www.dataconservancy.org/osf-business-object-model#'
@@ -14,6 +13,7 @@ module ROF
14
13
  'hasContributor' => 'http://www.dataconservancy.org/osf-business-object-model#hasContributor',
15
14
  'isBibliographic' => 'http://www.dataconservancy.org/osf-business-object-model#isBibliographic',
16
15
  'hasFullName' => 'http://www.dataconservancy.org/osf-business-object-model#hasFullName',
17
- 'hasUser' => 'http://www.dataconservancy.org/osf-business-object-model#hasUser'
16
+ 'hasUser' => 'http://www.dataconservancy.org/osf-business-object-model#hasUser',
17
+ 'registeredFrom' => 'http://www.dataconservancy.org/osf-business-object-model#registeredFrom'
18
18
  }.freeze
19
19
  end
@@ -11,6 +11,7 @@ module ROF
11
11
  'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#',
12
12
  'ths' => 'http://id.loc.gov/vocabulary/relators/',
13
13
  'vracore' => 'http://purl.org/vra/',
14
+ 'pav' => 'http://purl.org/pav/',
14
15
 
15
16
  'dc:dateSubmitted' => {
16
17
  '@type' => 'http://www.w3.org/2001/XMLSchema#date'
@@ -26,6 +27,7 @@ module ROF
26
27
  RelsExtRefContext = {
27
28
  '@vocab' => 'info:fedora/fedora-system:def/relations-external#',
28
29
  'fedora-model' => 'info:fedora/fedora-system:def/model#',
30
+ 'pav' => 'http://purl.org/pav/',
29
31
  'hydra' => 'http://projecthydra.org/ns/relations#',
30
32
  'hasModel' => { '@id' => 'fedora-model:hasModel', '@type' => '@id' },
31
33
  'hasEditor' => { '@id' => 'hydra:hasEditor', '@type' => '@id' },
@@ -0,0 +1,18 @@
1
+ module ROF
2
+ # A translator is responsible for converting the input into the given output.
3
+ # The input and output need not be the same type (e.g. CSV to Hash)
4
+ #
5
+ # @todo This is a work in progress; I will be normalizing the .call behavior.
6
+ #
7
+ # @see ROF::Translators::CsvToRof
8
+ # @see ROF::Translators::FedoraToRof
9
+ # @see ROF::Translators::OsfToRof
10
+ class Translator
11
+ # @param [Object] input - the thing that will be processed
12
+ # @param [Hash] config - a Hash with symbol keys
13
+ # @return [Hash] often times a Hash that can be serialized into JSON
14
+ def self.call(input, config = {})
15
+ raise NotImplementedError
16
+ end
17
+ end
18
+ end