aspire 0.1.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 +7 -0
- data/.gitignore +59 -0
- data/.rbenv-gemsets +1 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Dockerfile +20 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +851 -0
- data/Rakefile +10 -0
- data/aspire.gemspec +40 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/entrypoint.sh +11 -0
- data/exe/build-cache +13 -0
- data/lib/aspire.rb +11 -0
- data/lib/aspire/api.rb +2 -0
- data/lib/aspire/api/base.rb +198 -0
- data/lib/aspire/api/json.rb +195 -0
- data/lib/aspire/api/linked_data.rb +214 -0
- data/lib/aspire/caching.rb +4 -0
- data/lib/aspire/caching/builder.rb +356 -0
- data/lib/aspire/caching/cache.rb +365 -0
- data/lib/aspire/caching/cache_entry.rb +296 -0
- data/lib/aspire/caching/cache_logger.rb +63 -0
- data/lib/aspire/caching/util.rb +210 -0
- data/lib/aspire/cli/cache_builder.rb +123 -0
- data/lib/aspire/cli/command.rb +20 -0
- data/lib/aspire/enumerator/base.rb +29 -0
- data/lib/aspire/enumerator/json_enumerator.rb +130 -0
- data/lib/aspire/enumerator/linked_data_uri_enumerator.rb +32 -0
- data/lib/aspire/enumerator/report_enumerator.rb +64 -0
- data/lib/aspire/exceptions.rb +36 -0
- data/lib/aspire/object.rb +7 -0
- data/lib/aspire/object/base.rb +155 -0
- data/lib/aspire/object/digitisation.rb +43 -0
- data/lib/aspire/object/factory.rb +87 -0
- data/lib/aspire/object/list.rb +590 -0
- data/lib/aspire/object/module.rb +36 -0
- data/lib/aspire/object/resource.rb +371 -0
- data/lib/aspire/object/time_period.rb +47 -0
- data/lib/aspire/object/user.rb +46 -0
- data/lib/aspire/properties.rb +20 -0
- data/lib/aspire/user_lookup.rb +103 -0
- data/lib/aspire/util.rb +185 -0
- data/lib/aspire/version.rb +3 -0
- data/lib/retry.rb +197 -0
- metadata +274 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'aspire/object/list'
|
2
|
+
require 'aspire/object/module'
|
3
|
+
require 'aspire/object/resource'
|
4
|
+
require 'aspire/util'
|
5
|
+
|
6
|
+
module Aspire
|
7
|
+
module Object
|
8
|
+
# A factory returning reading list objects given the object's URI
|
9
|
+
class Factory
|
10
|
+
include Aspire::Util
|
11
|
+
|
12
|
+
# @!attribute [rw] cache
|
13
|
+
# @return [Aspire::Caching::Cache] the cache for retrieving data
|
14
|
+
attr_accessor :cache
|
15
|
+
|
16
|
+
# @!attribute [rw] users
|
17
|
+
# @return [Hash<String, Aspire::Object::User>] a hash of user profiles
|
18
|
+
# indexed by URI
|
19
|
+
attr_accessor :users
|
20
|
+
|
21
|
+
# Initialises a new Factory instance
|
22
|
+
# @param cache [Aspire::Caching::Cache] the cache for retrieving data
|
23
|
+
# @param users [Hash<String, Aspire::Object::User>] a hash of user
|
24
|
+
# profiles indexed by URI
|
25
|
+
# @return [void]
|
26
|
+
def initialize(cache, users = nil)
|
27
|
+
self.cache = cache
|
28
|
+
self.users = users || {}
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns a new API list object (Aspire::Object::ListBase subclass) given
|
32
|
+
# its URI
|
33
|
+
# @param uri [String] the URI of the object
|
34
|
+
# @param parent [Aspire::Object::ListBase] this object's parent object
|
35
|
+
# @param json [Hash] the parsed JSON API data for the object
|
36
|
+
# @param ld [Hash] the parsed linked data API data for the object
|
37
|
+
# @return [Aspire::Object::ListBase] the list object
|
38
|
+
def get(uri = nil, parent = nil, json: nil, ld: nil)
|
39
|
+
return nil if uri.nil? || uri.empty?
|
40
|
+
get_exceptions(uri, parent, json: json, ld: ld) ||
|
41
|
+
get_linked_data(uri, parent, json: json, ld: ld)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# Returns a new object from sources other than the linked data API
|
47
|
+
# @param uri [String] the URI of the object
|
48
|
+
# @param parent [Aspire::Object::ListBase] this object's parent object
|
49
|
+
# @param json [Hash] the parsed JSON API data for the object
|
50
|
+
# @param ld [Hash] the parsed linked data API data for the object
|
51
|
+
# @return [Aspire::Object::ListBase, nil] the list object or nil if not
|
52
|
+
# available
|
53
|
+
def get_exceptions(uri = nil, parent = nil, json: nil, ld: nil)
|
54
|
+
# Get item data from the parent list's JSON API data
|
55
|
+
return ListItem.new(uri, self, parent) if item?(uri)
|
56
|
+
# Get resource data from the JSON API
|
57
|
+
if resource?(uri) && !json.nil?
|
58
|
+
return Resource.new(uri, self, json: json, ld: ld)
|
59
|
+
end
|
60
|
+
# Get user data from the users lookup table
|
61
|
+
# - normalise the URI to the form used by the linked data API
|
62
|
+
return users[cache.linked_data_url(uri), self] if user?(uri)
|
63
|
+
# Otherwise no exceptions
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns a new object from the linked data API
|
68
|
+
# @param uri [String] the URI of the object
|
69
|
+
# @param parent [Aspire::Object::ListBase] this object's parent object
|
70
|
+
# @param json [Hash] the parsed JSON API data for the object
|
71
|
+
# @param ld [Hash] the parsed linked data API data for the object
|
72
|
+
# @return [Aspire::Object::ListBase, nil] the list object or nil if not
|
73
|
+
# available
|
74
|
+
def get_linked_data(uri, parent = nil, json: nil, ld: nil)
|
75
|
+
# Call #linked_data to determine whether uri is present in ld
|
76
|
+
ld = linked_data(uri, ld) || cache.read(uri)
|
77
|
+
return List.new(uri, self, parent, json: json, ld: ld) if list?(uri)
|
78
|
+
return Module.new(uri, self, json: json, ld: ld) if module?(uri)
|
79
|
+
return Resource.new(uri, self, json: json, ld: ld) if resource?(uri)
|
80
|
+
if section?(uri)
|
81
|
+
return ListSection.new(uri, self, parent, json: json, ld: ld)
|
82
|
+
end
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,590 @@
|
|
1
|
+
require 'aspire/object/base'
|
2
|
+
require 'aspire/properties'
|
3
|
+
|
4
|
+
module Aspire
|
5
|
+
module Object
|
6
|
+
# The abstract base class of reading list objects (items, lists, sections)
|
7
|
+
class ListBase < Aspire::Object::Base
|
8
|
+
# The Aspire linked data API returns properties of the form
|
9
|
+
# "#{KEY_PREFIX}_n" where n is a 1-based numeric index denoting the
|
10
|
+
# display order of the property.
|
11
|
+
KEY_PREFIX = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'.freeze
|
12
|
+
|
13
|
+
# @!attribute [rw] entries
|
14
|
+
# @return [Array<Aspire::Object::ListBase>] the ordered list of child
|
15
|
+
# objects
|
16
|
+
attr_accessor :entries
|
17
|
+
|
18
|
+
# @!attribute [rw] parent
|
19
|
+
# @return [Aspire::Object::ListBase] the parent reading list object of
|
20
|
+
# this object
|
21
|
+
attr_accessor :parent
|
22
|
+
|
23
|
+
# Initialises a new ListBase instance
|
24
|
+
# @param uri [String] the reading list object URI (item/list/section)
|
25
|
+
# @param factory [Aspire::Object::Factory] a factory returning ListBase
|
26
|
+
# subclass instances
|
27
|
+
# @param parent [Aspire::Object::ListBase] the parent reading list object
|
28
|
+
# of this object
|
29
|
+
# @param json [Hash] the parsed JSON data from the Aspire JSON API
|
30
|
+
# @param ld [Hash] the parsed JSON data from the Aspire linked data API
|
31
|
+
# @return [void]
|
32
|
+
def initialize(uri, factory, parent = nil, json: nil, ld: nil)
|
33
|
+
super(uri, factory)
|
34
|
+
self.parent = parent
|
35
|
+
self.entries = get_entries(ld: ld)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Iterates over the child reading list objects in display order
|
39
|
+
# @yield [entry] passes the child reading list object to the block
|
40
|
+
# @yieldparam entry [Aspire::Object::ListBase] the reading list object
|
41
|
+
def each(&block)
|
42
|
+
entries.each(&block)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Iterates over the child list items in display order (depth-first tree
|
46
|
+
# traversal)
|
47
|
+
# @yield [entry] passes the list item to the block
|
48
|
+
# @yieldparam entry [Aspire::Object::ListItem] the reading list item
|
49
|
+
# @return [void]
|
50
|
+
def each_item(&block)
|
51
|
+
each do |entry|
|
52
|
+
if entry.is_a?(ListItem)
|
53
|
+
# Pass the list item to the block
|
54
|
+
yield(entry) if block_given?
|
55
|
+
else
|
56
|
+
# Iterate the entry's list items
|
57
|
+
entry.each_item(&block)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
|
63
|
+
# Iterates over the child list sections in display order (depth-first tree
|
64
|
+
# traversal)
|
65
|
+
# @yield [entry] passes the list section to the block
|
66
|
+
# @yieldparam entry [Aspire::Object::ListSection] the reading list section
|
67
|
+
# @return [void]
|
68
|
+
def each_section(&block)
|
69
|
+
each do |entry|
|
70
|
+
if entry.is_a?(List)
|
71
|
+
# Iterate the list's sections
|
72
|
+
entry.each_section(&block)
|
73
|
+
elsif entry.is_a?(ListSection)
|
74
|
+
# Pass the list section to the block
|
75
|
+
yield(entry) if block_given?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
nil
|
79
|
+
end
|
80
|
+
|
81
|
+
# Returns a list of child reading list objects in display order
|
82
|
+
# @param ld [Hash] the parsed JSON data from the Aspire linked data API
|
83
|
+
# @return [Array<Aspire::Object::ListBase>] the ordered list of child
|
84
|
+
# objects
|
85
|
+
def get_entries(ld: nil)
|
86
|
+
entries = []
|
87
|
+
data = linked_data(uri, ld)
|
88
|
+
return entries unless data
|
89
|
+
data.each { |key, value| get_ordered_entry(key, value, entries, ld) }
|
90
|
+
entries
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns the child items of this object in display order
|
94
|
+
# @return [Array<Aspire::Object::ListItem>] the child list items
|
95
|
+
def items
|
96
|
+
result = []
|
97
|
+
each_item { |item| result.push(item) }
|
98
|
+
result
|
99
|
+
end
|
100
|
+
|
101
|
+
# Returns the number of items in the list
|
102
|
+
# @param item_type [Symbol] selects the list entry type to count
|
103
|
+
# :entry = top-level item or section
|
104
|
+
# :item = list item (default)
|
105
|
+
# :section = top-level section
|
106
|
+
# @return [Integer] the number of list entry instances
|
107
|
+
def length(item_type = nil)
|
108
|
+
item_type ||= :item
|
109
|
+
# Return the number of top-level entries (items and sections)
|
110
|
+
return entries.length if item_type == :entry
|
111
|
+
# Return the sum of the number of list items in each entry
|
112
|
+
if item_type == :item
|
113
|
+
entries.reduce(0) { |count, entry| count + entry.length(:item) }
|
114
|
+
end
|
115
|
+
# Return the number of top-level sections
|
116
|
+
return sections.length if item_type == :section
|
117
|
+
# Otherwise return 0 for unknown item types
|
118
|
+
0
|
119
|
+
end
|
120
|
+
|
121
|
+
# Returns the parent list of this object
|
122
|
+
# @return [Aspire::Object::List] the parent reading list
|
123
|
+
def parent_list
|
124
|
+
parent_lists[0]
|
125
|
+
end
|
126
|
+
|
127
|
+
# Returns the ancestor lists of this object (nearest ancestor first)
|
128
|
+
# @return [Array<Aspire::Object::List>] the ancestor reading lists
|
129
|
+
def parent_lists
|
130
|
+
parents(List)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Returns the parent section of this object
|
134
|
+
# @return [Aspire::Object::ListSection] the parent reading list section
|
135
|
+
def parent_section
|
136
|
+
parent_sections[0]
|
137
|
+
end
|
138
|
+
|
139
|
+
# Returns the ancestor sections of this object (nearest ancestor first)
|
140
|
+
# @return [Array<Aspire::Object::ListSection>] the ancestor reading list
|
141
|
+
# sections
|
142
|
+
def parent_sections
|
143
|
+
parents(ListSection)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Returns a list of ancestor reading list objects of this object (nearest
|
147
|
+
# ancestor first)
|
148
|
+
# Positional parameters are the reading list classes to include in the
|
149
|
+
# result. If no classes are specified, all classes are included.
|
150
|
+
# @yield [ancestor] passes the ancestor to the block
|
151
|
+
# @yieldparam ancestor [Aspire::Object::ListBase] the reading list object
|
152
|
+
# @yieldreturn [Boolean] if true, include in the ancestor list, otherwise
|
153
|
+
# ignore
|
154
|
+
def parents(*classes, &block)
|
155
|
+
result = []
|
156
|
+
ancestor = parent
|
157
|
+
until ancestor.nil?
|
158
|
+
result.push(ancestor) if parents_include?(ancestor, *classes, &block)
|
159
|
+
ancestor = ancestor.parent
|
160
|
+
end
|
161
|
+
result
|
162
|
+
end
|
163
|
+
|
164
|
+
# Returns true if ancestor should be included as a parent, false otherwise
|
165
|
+
# @param ancestor [Aspire::Object::ListBase] the reading list object
|
166
|
+
# Remaining positional parameters are the reading list classes to include
|
167
|
+
# in the result. If no classes are specified, all classes are included.
|
168
|
+
# @yield [ancestor] passes the ancestor to the block
|
169
|
+
# @yieldparam ancestor [Aspire::Object::ListBase]
|
170
|
+
# the reading list object
|
171
|
+
# @yieldreturn [Boolean] if true, include in the ancestor list, otherwise
|
172
|
+
# ignore
|
173
|
+
def parents_include?(ancestor, *classes)
|
174
|
+
# Filter ancestors by class
|
175
|
+
if classes.nil? || classes.empty? || classes.include?(ancestor.class)
|
176
|
+
# The ancestor is allowed by class, but may be disallowed by a code
|
177
|
+
# block which returns false. If the code block returns true or is not
|
178
|
+
# given, the ancestor is included.
|
179
|
+
return block_given? && !yield(ancestor) ? false : true
|
180
|
+
end
|
181
|
+
# Otherwise the ancestor is not allowed by class
|
182
|
+
false
|
183
|
+
end
|
184
|
+
|
185
|
+
# Returns the child sections of this object
|
186
|
+
# @return [Array<Aspire::Object::ListSection>] the child list sections
|
187
|
+
def sections
|
188
|
+
entries.select { |e| e.is_a?(ListSection) }
|
189
|
+
end
|
190
|
+
|
191
|
+
private
|
192
|
+
|
193
|
+
# Adds a child object to the entries array if key is an ordered property
|
194
|
+
# @param key [String] the property name URI
|
195
|
+
# @param value [Hash] the property value hash
|
196
|
+
# @param entries [Array<Aspire::Object::ListBase>] the ordered list of
|
197
|
+
# child objects
|
198
|
+
# @param ld [Hash] the parsed JSON data from the Aspire linked data API
|
199
|
+
# @return [Aspire::Object::ListBase] the list object
|
200
|
+
def get_ordered_entry(key, value, entries, ld)
|
201
|
+
prefix, index = key.split('_')
|
202
|
+
return nil unless prefix == KEY_PREFIX
|
203
|
+
uri = value[0]['value']
|
204
|
+
entries[index.to_i - 1] = factory.get(uri, self, ld: ld)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# Represents a reading list in the Aspire API
|
209
|
+
class List < ListBase
|
210
|
+
include Aspire::Properties
|
211
|
+
|
212
|
+
# @!attribute [rw] created
|
213
|
+
# @return [DateTime] the creation timestamp of the list
|
214
|
+
attr_accessor :created
|
215
|
+
|
216
|
+
# @!attribute [rw] creator
|
217
|
+
# @return [Array<Aspire::Object::User>] the reading list creators
|
218
|
+
attr_accessor :creator
|
219
|
+
|
220
|
+
# @!attribute [rw] description
|
221
|
+
# @return [String] the description of the list
|
222
|
+
attr_accessor :description
|
223
|
+
|
224
|
+
# @!attribute [rw] items
|
225
|
+
# @return [Hash<String, Aspire::Object::ListItem>] a hash of ListItems
|
226
|
+
# indexed by item URI
|
227
|
+
attr_accessor :items
|
228
|
+
|
229
|
+
# @!attribute [rw] last_published
|
230
|
+
# @return [DateTime] the timestamp of the most recent list publication
|
231
|
+
attr_accessor :last_published
|
232
|
+
|
233
|
+
# @!attribute [rw] last_updated
|
234
|
+
# @return [DateTime] the timestamp of the most recent list update
|
235
|
+
attr_accessor :last_updated
|
236
|
+
|
237
|
+
# @!attribute [rw] modules
|
238
|
+
# @return [Array<Aspire::Object::Module>] the modules referencing this
|
239
|
+
# list
|
240
|
+
attr_accessor :modules
|
241
|
+
|
242
|
+
# @!attribute [rw] name
|
243
|
+
# @return [String] the reading list name
|
244
|
+
attr_accessor :name
|
245
|
+
|
246
|
+
# @!attribute [rw] owner
|
247
|
+
# @return [Aspire::Object::User] the list owner
|
248
|
+
attr_accessor :owner
|
249
|
+
|
250
|
+
# @!attribute [rw] publisher
|
251
|
+
# @return [Aspire::Object::User] the list publisher
|
252
|
+
attr_accessor :publisher
|
253
|
+
|
254
|
+
# @!attribute [rw] time_period
|
255
|
+
# @return [Aspire::Object::TimePeriod] the period covered by the list
|
256
|
+
attr_accessor :time_period
|
257
|
+
|
258
|
+
# Initialises a new List instance
|
259
|
+
# @param uri [String] the URI of the object
|
260
|
+
# @param factory [Aspire::Object::Factory] a factory returning ListBase
|
261
|
+
# subclass instances
|
262
|
+
# @param parent [Aspire::Object::ListBase] this object's parent object
|
263
|
+
# @param json [Hash] the parsed JSON data from the Aspire JSON API
|
264
|
+
# @param ld [Hash] the parsed JSON data from the Aspire linked data API
|
265
|
+
# @return [void]
|
266
|
+
def initialize(uri, factory, parent = nil, json: nil, ld: nil)
|
267
|
+
# Set properties from the Reading Lists JSON API
|
268
|
+
# - this must be called before the superclass constructor so that item
|
269
|
+
# details are available
|
270
|
+
init_json_data(uri, factory, json)
|
271
|
+
# Initialise the superclass
|
272
|
+
super(uri, factory, parent, json: json, ld: ld)
|
273
|
+
# Set properties from the linked data API data
|
274
|
+
init_linked_data(ld)
|
275
|
+
end
|
276
|
+
|
277
|
+
# Returns the number of items in the list
|
278
|
+
# @see (Aspire::Object::ListBase#length)
|
279
|
+
def length(item_type = nil)
|
280
|
+
item_type ||= :item
|
281
|
+
# The item length of a list is the length of the items property,
|
282
|
+
# avoiding the need to sum list entry lengths
|
283
|
+
item_type == :item ? items.length : super(item_type)
|
284
|
+
end
|
285
|
+
|
286
|
+
# Returns a string representation of the List instance (the name)
|
287
|
+
# @return [String] the string representation of the List instance
|
288
|
+
def to_s
|
289
|
+
name || super
|
290
|
+
end
|
291
|
+
|
292
|
+
private
|
293
|
+
|
294
|
+
# Retrieves the list details and history from the Aspire JSON API
|
295
|
+
# @param uri [String] the URI of the object
|
296
|
+
# @param factory [Aspire::Object::Factory] a factory returning ListBase
|
297
|
+
# subclass instances
|
298
|
+
# @param json [Hash] the parsed JSON data from the Aspire JSON API
|
299
|
+
# @return [void]
|
300
|
+
def init_json_data(uri, factory, json = nil)
|
301
|
+
init_json_defaults
|
302
|
+
# Get the list details
|
303
|
+
json ||= factory.cache.read(uri, json: true)
|
304
|
+
if json
|
305
|
+
self.name = json['name']
|
306
|
+
init_json_items(json['items'])
|
307
|
+
init_json_modules(json['modules'], factory)
|
308
|
+
init_json_time_period(json['timePeriod'], factory)
|
309
|
+
end
|
310
|
+
# Return the parsed JSON data from the Aspire list details JSON API
|
311
|
+
json
|
312
|
+
end
|
313
|
+
|
314
|
+
# Sets the property defaults for JSON API fields
|
315
|
+
# @return [void]
|
316
|
+
def init_json_defaults
|
317
|
+
# Default values
|
318
|
+
self.modules = nil
|
319
|
+
self.name = nil
|
320
|
+
self.time_period = nil
|
321
|
+
end
|
322
|
+
|
323
|
+
# Builds a mapping from item URI to JSON data for items from the JSON API
|
324
|
+
# @param items [Array<Hash>] the parsed JSON data for the items array
|
325
|
+
# @return [void]
|
326
|
+
def init_json_items(items)
|
327
|
+
# A hash mapping item URI to item
|
328
|
+
self.items = {}
|
329
|
+
return unless items
|
330
|
+
items.each { |item| self.items[item['uri']] = item }
|
331
|
+
end
|
332
|
+
|
333
|
+
# Builds a list of Module instances for modules from the JSON API
|
334
|
+
# @param mods [Array<Hash>] the parsed JSON data for the modules array
|
335
|
+
# @param factory [Aspire::Object::Factory] a factory returning ListBase
|
336
|
+
# subclass instances
|
337
|
+
# @return [void]
|
338
|
+
def init_json_modules(mods, factory)
|
339
|
+
return unless mods
|
340
|
+
self.modules = mods.map { |m| Module.new(m['uri'], factory, json: m) }
|
341
|
+
end
|
342
|
+
|
343
|
+
# Sets the time period for the list from the JSON API
|
344
|
+
# @param period [Array<Hash>] the parsed JSON data for the time period
|
345
|
+
# @param factory [Aspire::Object::Factory] a factory returning ListBase
|
346
|
+
# subclass instances
|
347
|
+
# @return [void]
|
348
|
+
def init_json_time_period(period, factory)
|
349
|
+
self.time_period = if period
|
350
|
+
TimePeriod.new(period['uri'], factory,
|
351
|
+
json: period)
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
# Sets reading list properties from the Aspire linked data API
|
356
|
+
# @return [void]
|
357
|
+
def init_linked_data(ld = nil)
|
358
|
+
list_data = linked_data(uri, ld)
|
359
|
+
init_linked_data_creator(list_data, ld)
|
360
|
+
init_linked_data_modules(list_data, ld)
|
361
|
+
init_linked_data_owner(list_data, ld)
|
362
|
+
init_linked_data_publisher(list_data, ld)
|
363
|
+
self.created = get_date(CREATED, list_data)
|
364
|
+
self.description = get_property(DESCRIPTION, list_data)
|
365
|
+
self.last_published = get_date(LAST_PUBLISHED, list_data)
|
366
|
+
self.last_updated = get_date(LAST_UPDATED, list_data)
|
367
|
+
self.name = get_property(NAME, list_data) unless name
|
368
|
+
end
|
369
|
+
|
370
|
+
# Sets the reading list creator
|
371
|
+
# @param list_data [Hash] the parsed JSON data for the list from the
|
372
|
+
# Aspire linked data API
|
373
|
+
# @param ld [Hash] the parsed JSON data from the Aspire linked data API
|
374
|
+
# @return [void]
|
375
|
+
def init_linked_data_creator(list_data, ld)
|
376
|
+
has_creator = get_property(HAS_CREATOR, list_data, single: false) || []
|
377
|
+
self.creator = has_creator.map { |u| factory.get(u, ld: ld) }
|
378
|
+
end
|
379
|
+
|
380
|
+
# Sets the list modules
|
381
|
+
# @param list_data [Hash] the parsed JSON data for the list from the
|
382
|
+
# Aspire linked data API
|
383
|
+
# @param ld [Hash] the parsed JSON data from the Aspire linked data API
|
384
|
+
# @return [void]
|
385
|
+
def init_linked_data_modules(list_data, ld)
|
386
|
+
return unless modules.nil?
|
387
|
+
mods = get_property(USED_BY, list_data, single: false) || []
|
388
|
+
self.modules = mods.map { |u| factory.get(u, ld: ld) } if mods
|
389
|
+
end
|
390
|
+
|
391
|
+
# Sets the list owner
|
392
|
+
# @param list_data [Hash] the parsed JSON data for the list from the
|
393
|
+
# Aspire linked data API
|
394
|
+
# @param ld [Hash] the parsed JSON data from the Aspire linked data API
|
395
|
+
# @return [void]
|
396
|
+
def init_linked_data_owner(list_data, ld)
|
397
|
+
has_owner = get_property(HAS_OWNER, list_data, single: false) || []
|
398
|
+
self.owner = has_owner.map { |u| factory.get(u, ld: ld) }
|
399
|
+
end
|
400
|
+
|
401
|
+
# Sets the list publisher
|
402
|
+
# @param list_data [Hash] the parsed JSON data for the list from the
|
403
|
+
# Aspire linked data API
|
404
|
+
# @param ld [Hash] the parsed JSON data from the Aspire linked data API
|
405
|
+
# @return [void]
|
406
|
+
def init_linked_data_publisher(list_data, ld)
|
407
|
+
published_by = get_property(PUBLISHED_BY, list_data)
|
408
|
+
self.publisher = factory.get(published_by, ld: ld)
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
# Represents a reading list item (citation) in the Aspire API
|
413
|
+
class ListItem < ListBase
|
414
|
+
# @!attribute [rw] digitisation
|
415
|
+
# @return [Aspire::Object::Digitisation]
|
416
|
+
# the digitisation details for the item
|
417
|
+
attr_accessor :digitisation
|
418
|
+
|
419
|
+
# @!attribute [rw] importance
|
420
|
+
# @return [String] the importance of the item
|
421
|
+
attr_accessor :importance
|
422
|
+
|
423
|
+
# @!attribute [rw] library_note
|
424
|
+
# @return [String] the internal library note for the item
|
425
|
+
attr_accessor :library_note
|
426
|
+
|
427
|
+
# @!attribute [rw] local_control_number
|
428
|
+
# @return [String] the identifier of the resource in the local library
|
429
|
+
# management system
|
430
|
+
attr_accessor :local_control_number
|
431
|
+
|
432
|
+
# @!attribute [rw] note
|
433
|
+
# @return [String] the public note for the item
|
434
|
+
attr_accessor :note
|
435
|
+
|
436
|
+
# @!attribute [rw] resource
|
437
|
+
# @return [Aspire::Object::Resource] the resource for
|
438
|
+
# the item
|
439
|
+
attr_accessor :resource
|
440
|
+
|
441
|
+
# @!attribute [rw] student_note
|
442
|
+
# @return [String] the public note for the item
|
443
|
+
attr_accessor :student_note
|
444
|
+
|
445
|
+
# @!attribute [rw] title
|
446
|
+
# @return [String] the title of the item
|
447
|
+
attr_accessor :title
|
448
|
+
|
449
|
+
# Initialises a new ListItem instance
|
450
|
+
# @param uri [String] the reading list object URI (item/list/section)
|
451
|
+
# @param factory [Aspire::Object::Factory]
|
452
|
+
# a factory returning ReadingListBase subclass instances
|
453
|
+
# @param parent [Aspire::Object::ListBase]
|
454
|
+
# the parent reading list object of this object
|
455
|
+
# @param json [Hash] the parsed JSON data from the Aspire JSON API
|
456
|
+
# @param ld [Hash] the parsed JSON data from the Aspire linked data API
|
457
|
+
# @return [void]
|
458
|
+
def initialize(uri, factory, parent = nil, json: nil, ld: nil)
|
459
|
+
super(uri, factory, parent, json: json, ld: ld)
|
460
|
+
json ||= init_list_items
|
461
|
+
init_digitisation(json)
|
462
|
+
init_resource(json)
|
463
|
+
self.importance = get_property('importance', json)
|
464
|
+
self.library_note = get_property('libraryNote', json)
|
465
|
+
self.local_control_number = get_property('lcn', json)
|
466
|
+
self.note = get_property('note', json)
|
467
|
+
self.student_note = get_property('studentNote', json)
|
468
|
+
self.title = get_property('title', json)
|
469
|
+
end
|
470
|
+
|
471
|
+
# Returns the length of the list item
|
472
|
+
# @see (Aspire::Object::ListBase#length)
|
473
|
+
def length(item_type = nil)
|
474
|
+
item_type ||= :item
|
475
|
+
# List items return an item length of 1 to enable summation of
|
476
|
+
# list/section lengths
|
477
|
+
item_type == :item ? 1 : super(item_type)
|
478
|
+
end
|
479
|
+
|
480
|
+
# Returns the public (student or general) note
|
481
|
+
# @return [String] the student note or general note
|
482
|
+
def public_note
|
483
|
+
student_note || note
|
484
|
+
end
|
485
|
+
|
486
|
+
# Returns the resource title or public note if no resource is available
|
487
|
+
# @param alt [Symbol] the alternative if no resource is available
|
488
|
+
# :library_note or :private_note = the library note
|
489
|
+
# :note = the student note, or the library note if no student note is
|
490
|
+
# available
|
491
|
+
# :public_note, :student_note = the student note
|
492
|
+
# :uri = the list item URI
|
493
|
+
# @return [String] the resource title or alternative
|
494
|
+
def title(alt = nil)
|
495
|
+
# Return the resource title if available
|
496
|
+
return resource.title || @title if resource
|
497
|
+
# Otherwise return the specified alternative
|
498
|
+
title_alt(alt)
|
499
|
+
end
|
500
|
+
|
501
|
+
# Returns a string representation of the ListItem instance (the citation
|
502
|
+
# title or note)
|
503
|
+
# @return [String] the string representation of the ListItem instance
|
504
|
+
def to_s
|
505
|
+
title(:public_note).to_s
|
506
|
+
end
|
507
|
+
|
508
|
+
private
|
509
|
+
|
510
|
+
# Returns the digitisation request JSON data if available, nil if not
|
511
|
+
# @param json [Hash] the JSON API data
|
512
|
+
# @return [void]
|
513
|
+
def init_digitisation(json)
|
514
|
+
dig_json = json ? json['digitisation'] : nil
|
515
|
+
dig_ld = nil
|
516
|
+
self.digitisation = if dig_json || dig_ld
|
517
|
+
Digitisation.new(json: dig_json, ld: dig_ld)
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
# Returns the list of JSON API list items from the parent list
|
522
|
+
# @return [Array<Hash>] the list items, or nil if none are available
|
523
|
+
def init_list_items
|
524
|
+
owner = parent_list
|
525
|
+
owner && owner.items ? owner.items[uri] : nil
|
526
|
+
end
|
527
|
+
|
528
|
+
# Sets the resource
|
529
|
+
# @param json [Hash] the parsed JSON resource data
|
530
|
+
# @return nil
|
531
|
+
def init_resource(json)
|
532
|
+
res_json = json ? json['resource'] : nil
|
533
|
+
if res_json.is_a?(Array)
|
534
|
+
res_json = res_json.empty? ? nil : res_json[0]
|
535
|
+
puts("WARNING: used first resource of #{res_json}") if res_json
|
536
|
+
end
|
537
|
+
self.resource = factory.get(res_json['uri'], json: res_json) if res_json
|
538
|
+
# resource_json = json ? json['resource'] : nil
|
539
|
+
# resource_uri = get_property('http://purl.org/vocab/resourcelist/schema#resource', item_ld)
|
540
|
+
# resource = resource_json # || resource_uri ? factory.get(resource_uri, json: resource_json, ld: ld) : nil
|
541
|
+
end
|
542
|
+
|
543
|
+
# Returns the alternative resource title
|
544
|
+
# @param (see #title)
|
545
|
+
# @return [String] the alternative to the resource title
|
546
|
+
def title_alt(alt)
|
547
|
+
return library_note if %w[library_note private_note].include?(alt)
|
548
|
+
return public_note || library_note if alt == :note
|
549
|
+
return public_note if %w[public_note student_note].include?(alt)
|
550
|
+
return uri if alt == :uri
|
551
|
+
nil
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
555
|
+
# Represents a reading list section in the Aspire API
|
556
|
+
class ListSection < ListBase
|
557
|
+
include Aspire::Properties
|
558
|
+
|
559
|
+
# @!attribute [rw] description
|
560
|
+
# @return [String] the reading list section description
|
561
|
+
attr_accessor :description
|
562
|
+
|
563
|
+
# @!attribute [rw] name
|
564
|
+
# @return [String] the reading list section name
|
565
|
+
attr_accessor :name
|
566
|
+
|
567
|
+
# Initialises a new ListSection instance
|
568
|
+
# @param uri [String] the URI of the object
|
569
|
+
# @param factory [Aspire::Object::Factory] a factory returning ListBase
|
570
|
+
# subclass instances
|
571
|
+
# @param parent [Aspire::Object::ListBase] this object's parent object
|
572
|
+
# @param json [Hash] the parsed JSON data from the Aspire JSON API
|
573
|
+
# @param ld [Hash] the parsed JSON data from the Aspire linked data API
|
574
|
+
# @return [void]
|
575
|
+
def initialize(uri, factory, parent = nil, json: nil, ld: nil)
|
576
|
+
super(uri, factory, parent, json: json, ld: ld)
|
577
|
+
section_ld = linked_data(uri, ld)
|
578
|
+
self.description = get_property(DESCRIPTION, section_ld)
|
579
|
+
self.name = get_property(NAME, section_ld)
|
580
|
+
end
|
581
|
+
|
582
|
+
# Returns a string representation of the ListSection instance (the section
|
583
|
+
# name)
|
584
|
+
# @return [String] the string representation of the ListSection instance
|
585
|
+
def to_s
|
586
|
+
name || super
|
587
|
+
end
|
588
|
+
end
|
589
|
+
end
|
590
|
+
end
|