ro-bundle 0.1.0 → 0.2.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.
- checksums.yaml +5 -13
- data/.ruby-gemset +0 -1
- data/.ruby-version +1 -2
- data/.travis.yml +9 -1
- data/Licence.rdoc +1 -1
- data/ReadMe.rdoc +8 -7
- data/bin/dir2ro +3 -2
- data/bin/ro-bundle-info +2 -2
- data/bin/verify-ro-bundle +2 -2
- data/bin/zip2ro +2 -2
- data/lib/ro-bundle.rb +3 -2
- data/lib/ro-bundle/exceptions.rb +0 -14
- data/lib/ro-bundle/file.rb +28 -20
- data/lib/ro-bundle/ro/agent.rb +1 -1
- data/lib/ro-bundle/ro/aggregate.rb +46 -38
- data/lib/ro-bundle/ro/annotation.rb +58 -20
- data/lib/ro-bundle/ro/manifest-entry.rb +52 -0
- data/lib/ro-bundle/ro/manifest.rb +76 -38
- data/lib/ro-bundle/ro/provenance.rb +78 -11
- data/lib/ro-bundle/ro/proxy.rb +80 -0
- data/lib/ro-bundle/util.rb +1 -1
- data/lib/ro-bundle/version.rb +1 -1
- data/ro-bundle.gemspec +6 -5
- data/test/data/HelloAnyone.robundle +0 -0
- data/test/data/example3-manifest.json +7 -7
- data/test/data/example6-manifest.json +17 -0
- data/test/helpers/fake_provenance.rb +4 -1
- data/test/tc_add_annotation.rb +47 -44
- data/test/tc_aggregate.rb +70 -65
- data/test/tc_annotation.rb +70 -11
- data/test/tc_create.rb +30 -12
- data/test/tc_manifest.rb +25 -2
- data/test/tc_provenance.rb +75 -0
- data/test/tc_proxy.rb +56 -0
- data/test/tc_read.rb +4 -4
- data/test/tc_remove.rb +8 -5
- data/test/tc_util.rb +2 -1
- data/test/ts_ro_bundle.rb +3 -1
- metadata +51 -31
@@ -1,5 +1,5 @@
|
|
1
1
|
#------------------------------------------------------------------------------
|
2
|
-
# Copyright (c) 2014 The University of Manchester, UK.
|
2
|
+
# Copyright (c) 2014, 2015 The University of Manchester, UK.
|
3
3
|
#
|
4
4
|
# BSD Licenced. See LICENCE.rdoc for details.
|
5
5
|
#
|
@@ -10,8 +10,7 @@
|
|
10
10
|
module ROBundle
|
11
11
|
|
12
12
|
# A class to represent an Annotation in a Research Object.
|
13
|
-
class Annotation
|
14
|
-
include Provenance
|
13
|
+
class Annotation < ManifestEntry
|
15
14
|
|
16
15
|
# :call-seq:
|
17
16
|
# new(target, content = nil)
|
@@ -24,25 +23,67 @@ module ROBundle
|
|
24
23
|
# An annotation id is a UUID prefixed with "urn:uuid" as per
|
25
24
|
# {RFC4122}[http://www.ietf.org/rfc/rfc4122.txt].
|
26
25
|
def initialize(object, content = nil)
|
26
|
+
super()
|
27
|
+
|
27
28
|
if object.instance_of?(Hash)
|
28
29
|
@structure = object
|
30
|
+
@structure[:about] = [*@structure[:about]]
|
29
31
|
init_provenance_defaults(@structure)
|
30
32
|
else
|
31
33
|
@structure = {}
|
32
|
-
@structure[:about] = object
|
33
|
-
@structure[:
|
34
|
+
@structure[:about] = [*object]
|
35
|
+
@structure[:uri] = UUID.generate(:urn)
|
34
36
|
@structure[:content] = content
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
38
40
|
# :call-seq:
|
39
|
-
# target
|
41
|
+
# annotates?(target) -> true or false
|
42
|
+
#
|
43
|
+
# Does this annotation object annotate the supplied target?
|
44
|
+
def annotates?(target)
|
45
|
+
@structure[:about].include?(target)
|
46
|
+
end
|
47
|
+
|
48
|
+
# :call-seq:
|
49
|
+
# target -> String or Array
|
50
|
+
#
|
51
|
+
# The identifier(s) for the annotated resource. This is considered the
|
52
|
+
# target of the annotation, that is the resource (or resources) the
|
53
|
+
# annotation content is "somewhat about".
|
40
54
|
#
|
41
|
-
# The
|
42
|
-
# of the annotation, that is the resource the annotation content is
|
43
|
-
# "somewhat about".
|
55
|
+
# The target can either be a singleton or a list of targets.
|
44
56
|
def target
|
45
|
-
@structure[:about]
|
57
|
+
about = @structure[:about]
|
58
|
+
about.length == 1 ? about[0] : about.dup
|
59
|
+
end
|
60
|
+
|
61
|
+
# :call-seq:
|
62
|
+
# add_target(new_target, ...) -> added target(s)
|
63
|
+
#
|
64
|
+
# Add a new target, or targets, to this annotation.
|
65
|
+
#
|
66
|
+
# The target(s) added are returned.
|
67
|
+
def add_target(add)
|
68
|
+
@structure[:about] += [*add]
|
69
|
+
|
70
|
+
@edited = true
|
71
|
+
add
|
72
|
+
end
|
73
|
+
|
74
|
+
# :call-seq:
|
75
|
+
# remove_target(target) -> target or nil
|
76
|
+
#
|
77
|
+
# Remove a target from this annotation. An annotation must always have a
|
78
|
+
# target so this method will do nothing if it already has only one target.
|
79
|
+
#
|
80
|
+
# If the target can be removed then it is returned, otherwise nil is
|
81
|
+
# returned.
|
82
|
+
def remove_target(remove)
|
83
|
+
return if @structure[:about].length == 1
|
84
|
+
|
85
|
+
@edited = true
|
86
|
+
@structure[:about].delete(remove)
|
46
87
|
end
|
47
88
|
|
48
89
|
# :call-seq:
|
@@ -58,15 +99,16 @@ module ROBundle
|
|
58
99
|
#
|
59
100
|
# Set the content of this annotation.
|
60
101
|
def content=(new_content)
|
102
|
+
@edited = true
|
61
103
|
@structure[:content] = new_content
|
62
104
|
end
|
63
105
|
|
64
106
|
# :call-seq:
|
65
|
-
#
|
107
|
+
# uri -> String in the form of a urn:uuid URI.
|
66
108
|
#
|
67
109
|
# Return the annotation id of this Annotation.
|
68
|
-
def
|
69
|
-
@structure[:
|
110
|
+
def uri
|
111
|
+
@structure[:uri]
|
70
112
|
end
|
71
113
|
|
72
114
|
# :call-seq:
|
@@ -75,13 +117,9 @@ module ROBundle
|
|
75
117
|
# Write this Annotation out as a json string. Takes the same options as
|
76
118
|
# JSON#generate.
|
77
119
|
def to_json(*a)
|
78
|
-
Util.clean_json(@structure)
|
79
|
-
|
80
|
-
|
81
|
-
private
|
82
|
-
|
83
|
-
def structure
|
84
|
-
@structure
|
120
|
+
cleaned = Util.clean_json(@structure)
|
121
|
+
cleaned[:about] = target
|
122
|
+
JSON.generate(cleaned,*a)
|
85
123
|
end
|
86
124
|
|
87
125
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2014 The University of Manchester, UK.
|
3
|
+
#
|
4
|
+
# BSD Licenced. See LICENCE.rdoc for details.
|
5
|
+
#
|
6
|
+
# Author: Robert Haines
|
7
|
+
#------------------------------------------------------------------------------
|
8
|
+
|
9
|
+
#
|
10
|
+
module ROBundle
|
11
|
+
|
12
|
+
# This is the bass class of things which can appear in the manifest:
|
13
|
+
# * Aggregate
|
14
|
+
# * Annotation
|
15
|
+
# * Proxy
|
16
|
+
class ManifestEntry
|
17
|
+
include Provenance
|
18
|
+
|
19
|
+
# :call-seq:
|
20
|
+
# new
|
21
|
+
#
|
22
|
+
# Create a new ManifestEntry with an empty structure and the +edited+ flag
|
23
|
+
# set to false.
|
24
|
+
def initialize
|
25
|
+
@structure = {}
|
26
|
+
@edited = false
|
27
|
+
end
|
28
|
+
|
29
|
+
# :call-seq:
|
30
|
+
# edited? -> true or false
|
31
|
+
#
|
32
|
+
# Has this ManifestEntry been edited?
|
33
|
+
def edited?
|
34
|
+
@edited
|
35
|
+
end
|
36
|
+
|
37
|
+
# :stopdoc:
|
38
|
+
# For internal use only!
|
39
|
+
def stored
|
40
|
+
@edited = false
|
41
|
+
end
|
42
|
+
# :startdoc:
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def structure
|
47
|
+
@structure
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -24,9 +24,19 @@ module ROBundle
|
|
24
24
|
def initialize
|
25
25
|
super(FILE_NAME, :required => true)
|
26
26
|
|
27
|
+
@structure = nil
|
28
|
+
@initialized = false
|
27
29
|
@edited = false
|
28
30
|
end
|
29
31
|
|
32
|
+
# :call-seq:
|
33
|
+
# initialized? -> true or false
|
34
|
+
#
|
35
|
+
# Has this manifest been initialized?
|
36
|
+
def initialized?
|
37
|
+
@initialized
|
38
|
+
end
|
39
|
+
|
30
40
|
# :call-seq:
|
31
41
|
# context -> List of context URIs
|
32
42
|
#
|
@@ -93,7 +103,7 @@ module ROBundle
|
|
93
103
|
#
|
94
104
|
# Return a list of all the aggregated resources in this Research Object.
|
95
105
|
def aggregates
|
96
|
-
structure[:aggregates]
|
106
|
+
structure[:aggregates]
|
97
107
|
end
|
98
108
|
|
99
109
|
# :call-seq:
|
@@ -134,12 +144,9 @@ module ROBundle
|
|
134
144
|
|
135
145
|
if object.is_a?(Aggregate)
|
136
146
|
removed = structure[:aggregates].delete(object)
|
137
|
-
|
138
|
-
unless removed.nil?
|
139
|
-
removed = removed.file.nil? ? removed.uri : removed.file
|
140
|
-
end
|
147
|
+
removed = removed.uri unless removed.nil?
|
141
148
|
else
|
142
|
-
removed =
|
149
|
+
removed = remove_aggregate_by_uri(object)
|
143
150
|
end
|
144
151
|
|
145
152
|
unless removed.nil?
|
@@ -165,7 +172,7 @@ module ROBundle
|
|
165
172
|
# If the supplied Annotation object is already registered then it is
|
166
173
|
# the annotation itself we are annotating!
|
167
174
|
if container.annotation?(object)
|
168
|
-
object = Annotation.new(object.
|
175
|
+
object = Annotation.new(object.uri, content)
|
169
176
|
end
|
170
177
|
else
|
171
178
|
object = Annotation.new(object, content)
|
@@ -200,7 +207,7 @@ module ROBundle
|
|
200
207
|
end
|
201
208
|
|
202
209
|
removed.each do |ann|
|
203
|
-
id = ann.
|
210
|
+
id = ann.uri
|
204
211
|
remove_annotation(id) unless id.nil?
|
205
212
|
end
|
206
213
|
|
@@ -212,7 +219,7 @@ module ROBundle
|
|
212
219
|
#
|
213
220
|
# Return a list of all the annotations in this Research Object.
|
214
221
|
def annotations
|
215
|
-
structure[:annotations]
|
222
|
+
structure[:annotations]
|
216
223
|
end
|
217
224
|
|
218
225
|
# :call-seq:
|
@@ -220,7 +227,11 @@ module ROBundle
|
|
220
227
|
#
|
221
228
|
# Has this manifest been altered in any way?
|
222
229
|
def edited?
|
223
|
-
@
|
230
|
+
if @structure.nil?
|
231
|
+
@edited
|
232
|
+
else
|
233
|
+
@edited || edited(aggregates) || edited(annotations)
|
234
|
+
end
|
224
235
|
end
|
225
236
|
|
226
237
|
# :call-seq:
|
@@ -229,8 +240,39 @@ module ROBundle
|
|
229
240
|
# Write this Manifest out as a json string. Takes the same options as
|
230
241
|
# JSON#generate.
|
231
242
|
def to_json(*a)
|
232
|
-
Util.clean_json(structure)
|
243
|
+
JSON.generate(Util.clean_json(structure),*a)
|
244
|
+
end
|
245
|
+
|
246
|
+
# :call-seq:
|
247
|
+
# write
|
248
|
+
#
|
249
|
+
# Write this manifest into the RO Bundle, overwriting the old version.
|
250
|
+
def write
|
251
|
+
container.file.open(full_name, "w") do |m|
|
252
|
+
m.puts JSON.pretty_generate(self)
|
253
|
+
end
|
254
|
+
|
255
|
+
stored
|
256
|
+
end
|
257
|
+
|
258
|
+
# :stopdoc:
|
259
|
+
# For internal use only!
|
260
|
+
def init(struct = {})
|
261
|
+
init_default_context(struct)
|
262
|
+
init_default_id(struct)
|
263
|
+
init_provenance_defaults(struct)
|
264
|
+
struct[:history] = [*struct.fetch(:history, [])]
|
265
|
+
struct[:aggregates] = [*struct.fetch(:aggregates, [])].map do |agg|
|
266
|
+
Aggregate.new(agg)
|
267
|
+
end
|
268
|
+
struct[:annotations] = [*struct.fetch(:annotations, [])].map do |ann|
|
269
|
+
Annotation.new(ann)
|
270
|
+
end
|
271
|
+
|
272
|
+
@initialized = true
|
273
|
+
@structure = struct
|
233
274
|
end
|
275
|
+
# :startdoc:
|
234
276
|
|
235
277
|
protected
|
236
278
|
|
@@ -250,12 +292,17 @@ module ROBundle
|
|
250
292
|
|
251
293
|
private
|
252
294
|
|
295
|
+
def stored
|
296
|
+
@edited = false
|
297
|
+
(aggregates + annotations).each { |a| a.stored }
|
298
|
+
end
|
299
|
+
|
253
300
|
# The internal structure of this class cannot be setup at construction
|
254
301
|
# time in the initializer as there is no route to its data on disk at that
|
255
302
|
# point. Once loaded, parts of the structure are converted to local
|
256
303
|
# objects where appropriate.
|
257
304
|
def structure
|
258
|
-
return @structure if
|
305
|
+
return @structure if initialized?
|
259
306
|
|
260
307
|
begin
|
261
308
|
struct ||= JSON.parse(contents, :symbolize_names => true)
|
@@ -263,22 +310,7 @@ module ROBundle
|
|
263
310
|
struct = {}
|
264
311
|
end
|
265
312
|
|
266
|
-
|
267
|
-
end
|
268
|
-
|
269
|
-
def init_defaults(struct)
|
270
|
-
init_default_context(struct)
|
271
|
-
init_default_id(struct)
|
272
|
-
init_provenance_defaults(struct)
|
273
|
-
struct[:history] = [*struct.fetch(:history, [])]
|
274
|
-
struct[:aggregates] = [*struct.fetch(:aggregates, [])].map do |agg|
|
275
|
-
Aggregate.new(agg)
|
276
|
-
end
|
277
|
-
struct[:annotations] = [*struct.fetch(:annotations, [])].map do |ann|
|
278
|
-
Annotation.new(ann)
|
279
|
-
end
|
280
|
-
|
281
|
-
struct
|
313
|
+
init(struct)
|
282
314
|
end
|
283
315
|
|
284
316
|
def init_default_context(struct)
|
@@ -303,14 +335,10 @@ module ROBundle
|
|
303
335
|
struct
|
304
336
|
end
|
305
337
|
|
306
|
-
def
|
307
|
-
aggregates.each do |agg|
|
308
|
-
if
|
309
|
-
return structure[:aggregates].delete(agg).uri
|
310
|
-
else
|
311
|
-
if object == agg.file || object == agg.file_entry
|
312
|
-
return structure[:aggregates].delete(agg).file
|
313
|
-
end
|
338
|
+
def remove_aggregate_by_uri(object)
|
339
|
+
structure[:aggregates].each do |agg|
|
340
|
+
if object == agg.uri || object == agg.file_entry
|
341
|
+
return structure[:aggregates].delete(agg).uri
|
314
342
|
end
|
315
343
|
end
|
316
344
|
|
@@ -321,8 +349,10 @@ module ROBundle
|
|
321
349
|
def remove_annotation_by_field(object)
|
322
350
|
removed = []
|
323
351
|
|
324
|
-
|
325
|
-
|
352
|
+
# Need to dup the list here so we don't break it when deleting things.
|
353
|
+
# We can't use delete_if because we want to know what we've deleted!
|
354
|
+
structure[:annotations].dup.each do |ann|
|
355
|
+
if ann.uri == object ||
|
326
356
|
ann.target == object ||
|
327
357
|
ann.content == object
|
328
358
|
|
@@ -333,6 +363,14 @@ module ROBundle
|
|
333
363
|
removed
|
334
364
|
end
|
335
365
|
|
366
|
+
def edited(resource)
|
367
|
+
resource.each do |res|
|
368
|
+
return true if res.edited?
|
369
|
+
end
|
370
|
+
|
371
|
+
false
|
372
|
+
end
|
373
|
+
|
336
374
|
end
|
337
375
|
|
338
376
|
end
|
@@ -10,8 +10,7 @@
|
|
10
10
|
module ROBundle
|
11
11
|
|
12
12
|
# This module is a mixin for Research Object
|
13
|
-
# {provenance}[
|
14
|
-
# information.
|
13
|
+
# {provenance}[https://w3id.org/bundle/#provenance] information.
|
15
14
|
#
|
16
15
|
# To use this module simply provide an (optionally private) method named
|
17
16
|
# 'structure' which returns the internal fields of the object as a Hash.
|
@@ -21,16 +20,19 @@ module ROBundle
|
|
21
20
|
# * <tt>:authoredOn</tt>
|
22
21
|
# * <tt>:createdBy</tt>
|
23
22
|
# * <tt>:createdOn</tt>
|
23
|
+
# * <tt>:retrievedBy</tt>
|
24
|
+
# * <tt>:retrievedFrom</tt>
|
25
|
+
# * <tt>:retrievedOn</tt>
|
24
26
|
module Provenance
|
25
27
|
|
26
28
|
# :call-seq:
|
27
29
|
# add_author(author) -> Agent
|
28
30
|
#
|
29
|
-
# Add an author to the list of authors for this
|
31
|
+
# Add an author to the list of authors for this resource. The
|
30
32
|
# supplied parameter can either be an Agent or the name of an author as a
|
31
33
|
# String.
|
32
34
|
#
|
33
|
-
# The Agent object
|
35
|
+
# The Agent object that is added is returned.
|
34
36
|
def add_author(author)
|
35
37
|
unless author.is_a?(Agent)
|
36
38
|
author = Agent.new(author.to_s)
|
@@ -44,7 +46,7 @@ module ROBundle
|
|
44
46
|
# :call-seq:
|
45
47
|
# authored_by -> Agents
|
46
48
|
#
|
47
|
-
# Return the list of Agents that authored this
|
49
|
+
# Return the list of Agents that authored this resource.
|
48
50
|
def authored_by
|
49
51
|
structure.fetch(:authoredBy, []).dup
|
50
52
|
end
|
@@ -52,7 +54,7 @@ module ROBundle
|
|
52
54
|
# :call-seq:
|
53
55
|
# authored_on -> Time
|
54
56
|
#
|
55
|
-
# Return the time that this
|
57
|
+
# Return the time that this resource was edited as a Time object, or
|
56
58
|
# +nil+ if not present in the manifest.
|
57
59
|
def authored_on
|
58
60
|
Util.parse_time(structure[:authoredOn])
|
@@ -61,7 +63,7 @@ module ROBundle
|
|
61
63
|
# :call-seq:
|
62
64
|
# authored_on = new_time
|
63
65
|
#
|
64
|
-
# Set a new authoredOn time for this
|
66
|
+
# Set a new authoredOn time for this resource. Anything that Ruby can
|
65
67
|
# interpret as a time is accepted and converted to ISO8601 format on
|
66
68
|
# serialization.
|
67
69
|
def authored_on=(new_time)
|
@@ -72,7 +74,7 @@ module ROBundle
|
|
72
74
|
# :call-seq:
|
73
75
|
# created_by -> Agent
|
74
76
|
#
|
75
|
-
# Return the Agent that created this
|
77
|
+
# Return the Agent that created this resource.
|
76
78
|
def created_by
|
77
79
|
structure[:createdBy]
|
78
80
|
end
|
@@ -80,7 +82,7 @@ module ROBundle
|
|
80
82
|
# :call-seq:
|
81
83
|
# created_by = new_creator
|
82
84
|
#
|
83
|
-
# Set the Agent that has created this
|
85
|
+
# Set the Agent that has created this resource. Anything passed to this
|
84
86
|
# method that is not an Agent will be converted to an Agent before setting
|
85
87
|
# the value.
|
86
88
|
def created_by=(new_creator)
|
@@ -95,7 +97,7 @@ module ROBundle
|
|
95
97
|
# :call-seq:
|
96
98
|
# created_on -> Time
|
97
99
|
#
|
98
|
-
# Return the time that this
|
100
|
+
# Return the time that this resource was created as a Time object, or
|
99
101
|
# +nil+ if not present in the manifest.
|
100
102
|
def created_on
|
101
103
|
Util.parse_time(structure[:createdOn])
|
@@ -104,7 +106,7 @@ module ROBundle
|
|
104
106
|
# :call-seq:
|
105
107
|
# created_on = new_time
|
106
108
|
#
|
107
|
-
# Set a new createdOn time for this
|
109
|
+
# Set a new createdOn time for this resource. Anything that Ruby can
|
108
110
|
# interpret as a time is accepted and converted to ISO8601 format on
|
109
111
|
# serialization.
|
110
112
|
def created_on=(new_time)
|
@@ -128,6 +130,69 @@ module ROBundle
|
|
128
130
|
end
|
129
131
|
end
|
130
132
|
|
133
|
+
# :call-seq:
|
134
|
+
# retrieved_by -> Agent
|
135
|
+
#
|
136
|
+
# Return the Agent that retrieved this resource.
|
137
|
+
def retrieved_by
|
138
|
+
structure[:retrievedBy]
|
139
|
+
end
|
140
|
+
|
141
|
+
# :call-seq:
|
142
|
+
# retrieved_by = new_retrievor
|
143
|
+
#
|
144
|
+
# Set the Agent that has retrieved this resource. Anything passed to this
|
145
|
+
# method that is not an Agent will be converted to an Agent before setting
|
146
|
+
# the value.
|
147
|
+
def retrieved_by=(new_retrievor)
|
148
|
+
unless new_retrievor.instance_of?(Agent)
|
149
|
+
new_retrievor = Agent.new(new_retrievor.to_s)
|
150
|
+
end
|
151
|
+
|
152
|
+
@edited = true
|
153
|
+
structure[:retrievedBy] = new_retrievor
|
154
|
+
end
|
155
|
+
|
156
|
+
# :call-seq:
|
157
|
+
# retrieved_from -> String URI
|
158
|
+
#
|
159
|
+
# Return the URI from which this resource was retrieved.
|
160
|
+
def retrieved_from
|
161
|
+
structure[:retrievedFrom]
|
162
|
+
end
|
163
|
+
|
164
|
+
# :call-seq:
|
165
|
+
# retrieved_from = uri
|
166
|
+
#
|
167
|
+
# Set the URI from which this resource was retrieved. If a URI object is
|
168
|
+
# given it is converted to a String first.
|
169
|
+
def retrieved_from=(uri)
|
170
|
+
return unless Util.is_absolute_uri?(uri)
|
171
|
+
|
172
|
+
@edited = true
|
173
|
+
structure[:retrievedFrom] = uri.to_s
|
174
|
+
end
|
175
|
+
|
176
|
+
# :call-seq:
|
177
|
+
# retrieved_on -> Time
|
178
|
+
#
|
179
|
+
# Return the time that this resource was retrieved as a Time object, or
|
180
|
+
# +nil+ if not present in the manifest.
|
181
|
+
def retrieved_on
|
182
|
+
Util.parse_time(structure[:retrievedOn])
|
183
|
+
end
|
184
|
+
|
185
|
+
# :call-seq:
|
186
|
+
# retrieved_on = new_time
|
187
|
+
#
|
188
|
+
# Set a new retrievedOn time for this resource. Anything that Ruby can
|
189
|
+
# interpret as a time is accepted and converted to ISO8601 format on
|
190
|
+
# serialization.
|
191
|
+
def retrieved_on=(new_time)
|
192
|
+
@edited = true
|
193
|
+
set_time(:retrievedOn, new_time)
|
194
|
+
end
|
195
|
+
|
131
196
|
private
|
132
197
|
|
133
198
|
def init_provenance_defaults(struct)
|
@@ -136,6 +201,8 @@ module ROBundle
|
|
136
201
|
struct[:authoredBy] = [*struct.fetch(:authoredBy, [])].map do |agent|
|
137
202
|
Agent.new(agent)
|
138
203
|
end
|
204
|
+
retrievor = struct[:retrievedBy]
|
205
|
+
struct[:retrievedBy] = Agent.new(retrievor) unless retrievor.nil?
|
139
206
|
|
140
207
|
struct
|
141
208
|
end
|