iiif-presentation 1.4.1 → 1.5.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 +4 -4
- data/.github/workflows/ruby.yml +8 -1
- data/.standard.yml +1 -0
- data/Gemfile +5 -5
- data/README.md +1 -1
- data/Rakefile +4 -2
- data/VERSION +1 -1
- data/bin/standardrb +16 -0
- data/iiif-presentation.gemspec +23 -23
- data/lib/iiif/hash_behaviours.rb +29 -33
- data/lib/iiif/ordered_hash.rb +33 -33
- data/lib/iiif/presentation/abstract_resource.rb +17 -22
- data/lib/iiif/presentation/annotation.rb +9 -11
- data/lib/iiif/presentation/annotation_list.rb +8 -10
- data/lib/iiif/presentation/canvas.rb +11 -13
- data/lib/iiif/presentation/collection.rb +7 -9
- data/lib/iiif/presentation/image_resource.rb +33 -35
- data/lib/iiif/presentation/layer.rb +8 -10
- data/lib/iiif/presentation/manifest.rb +9 -12
- data/lib/iiif/presentation/range.rb +8 -10
- data/lib/iiif/presentation/resource.rb +5 -7
- data/lib/iiif/presentation/sequence.rb +8 -11
- data/lib/iiif/presentation/service.rb +1 -2
- data/lib/iiif/presentation.rb +7 -7
- data/lib/iiif/service.rb +121 -102
- data/lib/iiif/v3/abstract_resource.rb +132 -144
- data/lib/iiif/v3/presentation/annotation.rb +20 -21
- data/lib/iiif/v3/presentation/annotation_collection.rb +7 -9
- data/lib/iiif/v3/presentation/annotation_page.rb +14 -15
- data/lib/iiif/v3/presentation/canvas.rb +21 -22
- data/lib/iiif/v3/presentation/choice.rb +14 -15
- data/lib/iiif/v3/presentation/collection.rb +7 -8
- data/lib/iiif/v3/presentation/image_resource.rb +21 -22
- data/lib/iiif/v3/presentation/manifest.rb +18 -19
- data/lib/iiif/v3/presentation/nav_place.rb +125 -29
- data/lib/iiif/v3/presentation/range.rb +10 -10
- data/lib/iiif/v3/presentation/resource.rb +4 -5
- data/lib/iiif/v3/presentation/sequence.rb +10 -11
- data/lib/iiif/v3/presentation/service.rb +12 -13
- data/lib/iiif/v3/presentation.rb +8 -8
- data/spec/integration/iiif/presentation/image_resource_spec.rb +54 -58
- data/spec/integration/iiif/service_spec.rb +76 -77
- data/spec/integration/iiif/v3/abstract_resource_spec.rb +73 -73
- data/spec/integration/iiif/v3/presentation/image_resource_spec.rb +53 -56
- data/spec/spec_helper.rb +56 -64
- data/spec/unit/iiif/hash_behaviours_spec.rb +384 -387
- data/spec/unit/iiif/ordered_hash_spec.rb +86 -91
- data/spec/unit/iiif/presentation/abstract_resource_spec.rb +64 -70
- data/spec/unit/iiif/presentation/annotation_list_spec.rb +1 -3
- data/spec/unit/iiif/presentation/annotation_spec.rb +1 -3
- data/spec/unit/iiif/presentation/canvas_spec.rb +11 -14
- data/spec/unit/iiif/presentation/collection_spec.rb +26 -33
- data/spec/unit/iiif/presentation/image_resource_spec.rb +4 -6
- data/spec/unit/iiif/presentation/layer_spec.rb +16 -20
- data/spec/unit/iiif/presentation/manifest_spec.rb +45 -48
- data/spec/unit/iiif/presentation/range_spec.rb +18 -22
- data/spec/unit/iiif/presentation/resource_spec.rb +3 -6
- data/spec/unit/iiif/presentation/sequence_spec.rb +58 -63
- data/spec/unit/iiif/presentation/shared_examples/abstract_resource_only_keys.rb +4 -10
- data/spec/unit/iiif/presentation/shared_examples/any_type_keys.rb +5 -9
- data/spec/unit/iiif/presentation/shared_examples/array_only_keys.rb +9 -17
- data/spec/unit/iiif/presentation/shared_examples/int_only_keys.rb +6 -14
- data/spec/unit/iiif/presentation/shared_examples/string_only_keys.rb +6 -13
- data/spec/unit/iiif/service_spec.rb +8 -13
- data/spec/unit/iiif/v3/abstract_resource_define_methods_for_spec.rb +39 -37
- data/spec/unit/iiif/v3/abstract_resource_spec.rb +128 -143
- data/spec/unit/iiif/v3/presentation/annotation_collection_spec.rb +14 -17
- data/spec/unit/iiif/v3/presentation/annotation_page_spec.rb +71 -69
- data/spec/unit/iiif/v3/presentation/annotation_spec.rb +249 -233
- data/spec/unit/iiif/v3/presentation/canvas_spec.rb +211 -193
- data/spec/unit/iiif/v3/presentation/choice_spec.rb +81 -77
- data/spec/unit/iiif/v3/presentation/collection_spec.rb +24 -29
- data/spec/unit/iiif/v3/presentation/image_resource_spec.rb +70 -71
- data/spec/unit/iiif/v3/presentation/manifest_spec.rb +248 -237
- data/spec/unit/iiif/v3/presentation/nav_place_spec.rb +249 -49
- data/spec/unit/iiif/v3/presentation/range_spec.rb +28 -29
- data/spec/unit/iiif/v3/presentation/resource_spec.rb +83 -82
- data/spec/unit/iiif/v3/presentation/sequence_spec.rb +126 -120
- data/spec/unit/iiif/v3/presentation/service_spec.rb +123 -124
- data/spec/unit/iiif/v3/presentation/shared_examples/abstract_resource_only_keys.rb +4 -8
- data/spec/unit/iiif/v3/presentation/shared_examples/any_type_keys.rb +5 -7
- data/spec/unit/iiif/v3/presentation/shared_examples/array_only_keys.rb +9 -13
- data/spec/unit/iiif/v3/presentation/shared_examples/hash_only_keys.rb +9 -13
- data/spec/unit/iiif/v3/presentation/shared_examples/int_only_keys.rb +6 -10
- data/spec/unit/iiif/v3/presentation/shared_examples/numeric_only_keys.rb +6 -10
- data/spec/unit/iiif/v3/presentation/shared_examples/string_only_keys.rb +6 -10
- data/spec/unit/iiif/v3/presentation/shared_examples/uri_only_keys.rb +9 -13
- metadata +27 -69
data/lib/iiif/service.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__),
|
|
2
|
-
require
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
1
|
+
require File.join(File.dirname(__FILE__), "hash_behaviours")
|
|
2
|
+
require "active_support/core_ext/class/subclasses"
|
|
3
|
+
require "active_support/ordered_hash"
|
|
4
|
+
require "active_support/inflector"
|
|
5
|
+
require "json"
|
|
6
6
|
|
|
7
7
|
module IIIF
|
|
8
8
|
class Service
|
|
@@ -10,24 +10,47 @@ module IIIF
|
|
|
10
10
|
|
|
11
11
|
# Anything goes! SHOULD have @id and profile, MAY have label
|
|
12
12
|
# Consider subclassing this for typical services...
|
|
13
|
-
def required_keys
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
def required_keys
|
|
14
|
+
%w[]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def any_type_keys
|
|
18
|
+
%w[]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def string_only_keys
|
|
22
|
+
%w[]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def array_only_keys
|
|
26
|
+
%w[]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def abstract_resource_only_keys
|
|
30
|
+
%w[]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def hash_only_keys
|
|
34
|
+
%w[]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def int_only_keys
|
|
38
|
+
%w[]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def numeric_only_keys
|
|
42
|
+
%w[]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def initialize(hsh = {})
|
|
23
46
|
@data = IIIF::OrderedHash[hsh]
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
47
|
+
define_methods_for_any_type_keys
|
|
48
|
+
define_methods_for_array_only_keys
|
|
49
|
+
define_methods_for_string_only_keys
|
|
50
|
+
define_methods_for_int_only_keys
|
|
51
|
+
define_methods_for_numeric_only_keys
|
|
52
|
+
define_methods_for_abstract_resource_only_keys
|
|
53
|
+
snakeize_keys
|
|
31
54
|
end
|
|
32
55
|
|
|
33
56
|
# Static methods / alternative constructors
|
|
@@ -35,21 +58,21 @@ module IIIF
|
|
|
35
58
|
# Parse from a file path, string, or existing hash
|
|
36
59
|
def parse(s)
|
|
37
60
|
ordered_hash = nil
|
|
38
|
-
if s.
|
|
61
|
+
if s.is_a?(String) && File.exist?(s)
|
|
39
62
|
ordered_hash = IIIF::OrderedHash[JSON.parse(IO.read(s))]
|
|
40
|
-
elsif s.
|
|
63
|
+
elsif s.is_a?(String) && !File.exist?(s)
|
|
41
64
|
ordered_hash = IIIF::OrderedHash[JSON.parse(s)]
|
|
42
|
-
elsif s.
|
|
65
|
+
elsif s.is_a?(Hash)
|
|
43
66
|
ordered_hash = IIIF::OrderedHash[s]
|
|
44
67
|
else
|
|
45
|
-
m =
|
|
68
|
+
m = "#parse takes a path to a file, a JSON String, or a Hash, "
|
|
46
69
|
m += "argument was a #{s.class}."
|
|
47
|
-
if s.
|
|
48
|
-
m+= "If you were trying to point to a file, does it exist?"
|
|
70
|
+
if s.is_a?(String)
|
|
71
|
+
m += "If you were trying to point to a file, does it exist?"
|
|
49
72
|
end
|
|
50
73
|
raise ArgumentError, m
|
|
51
74
|
end
|
|
52
|
-
|
|
75
|
+
IIIF::Service.from_ordered_hash(ordered_hash)
|
|
53
76
|
end
|
|
54
77
|
end
|
|
55
78
|
|
|
@@ -60,30 +83,30 @@ module IIIF
|
|
|
60
83
|
# * type check String-only values
|
|
61
84
|
# * type check Integer-only values
|
|
62
85
|
# * type check AbstractResource-only values
|
|
63
|
-
|
|
64
|
-
unless
|
|
86
|
+
required_keys.each do |k|
|
|
87
|
+
unless has_key?(k)
|
|
65
88
|
m = "A(n) #{k} is required for each #{self.class}"
|
|
66
89
|
raise IIIF::Presentation::MissingRequiredKeyError, m
|
|
67
90
|
end
|
|
68
91
|
end
|
|
69
92
|
# Viewing Direction values
|
|
70
|
-
if
|
|
71
|
-
unless
|
|
93
|
+
if has_key?("viewing_direction")
|
|
94
|
+
unless legal_viewing_direction_values.include?(self["viewing_direction"])
|
|
72
95
|
m = "viewingDirection must be one of #{legal_viewing_direction_values}"
|
|
73
96
|
raise IIIF::Presentation::IllegalValueError, m
|
|
74
97
|
end
|
|
75
98
|
end
|
|
76
99
|
# Viewing Hint values
|
|
77
|
-
if
|
|
78
|
-
unless
|
|
79
|
-
m = "viewingHint for #{self.class} must be one of #{
|
|
100
|
+
if has_key?("viewing_hint")
|
|
101
|
+
unless legal_viewing_hint_values.include?(self["viewing_hint"])
|
|
102
|
+
m = "viewingHint for #{self.class} must be one of #{legal_viewing_hint_values}."
|
|
80
103
|
raise IIIF::Presentation::IllegalValueError, m
|
|
81
104
|
end
|
|
82
105
|
end
|
|
83
106
|
# Metadata is all hashes
|
|
84
|
-
if
|
|
85
|
-
unless self[
|
|
86
|
-
m =
|
|
107
|
+
if has_key?("metadata")
|
|
108
|
+
unless self["metadata"].all? { |entry| entry.is_a?(Hash) }
|
|
109
|
+
m = "All entries in the metadata list must be a type of Hash"
|
|
87
110
|
raise IIIF::Presentation::IllegalValueError, m
|
|
88
111
|
end
|
|
89
112
|
end
|
|
@@ -92,8 +115,8 @@ module IIIF
|
|
|
92
115
|
# Options
|
|
93
116
|
# * pretty: (true|false). Should the JSON be pretty-printed? (default: false)
|
|
94
117
|
# * All options available in #to_ordered_hash
|
|
95
|
-
def to_json(opts={})
|
|
96
|
-
hsh =
|
|
118
|
+
def to_json(opts = {})
|
|
119
|
+
hsh = to_ordered_hash(opts)
|
|
97
120
|
if opts.fetch(:pretty, false)
|
|
98
121
|
JSON.pretty_generate(hsh)
|
|
99
122
|
else
|
|
@@ -105,19 +128,19 @@ module IIIF
|
|
|
105
128
|
# * force: (true|false). Skips validations.
|
|
106
129
|
# * sort_json_ld_keys: (true|false). Brings all properties starting with
|
|
107
130
|
# '@'. Default: true. to the top of the document and sorts them.
|
|
108
|
-
def to_ordered_hash(opts={})
|
|
131
|
+
def to_ordered_hash(opts = {})
|
|
109
132
|
force = opts.fetch(:force, false)
|
|
110
133
|
sort_json_ld_keys = opts.fetch(:sort_json_ld_keys, true)
|
|
111
134
|
|
|
112
135
|
unless force
|
|
113
|
-
|
|
136
|
+
validate
|
|
114
137
|
end
|
|
115
138
|
|
|
116
139
|
export_hash = IIIF::OrderedHash.new
|
|
117
140
|
|
|
118
141
|
if sort_json_ld_keys
|
|
119
|
-
|
|
120
|
-
export_hash[k] =
|
|
142
|
+
keys.select { |k| k.start_with?("@") }.sort!.each do |k|
|
|
143
|
+
export_hash[k] = data[k]
|
|
121
144
|
end
|
|
122
145
|
end
|
|
123
146
|
|
|
@@ -126,25 +149,24 @@ module IIIF
|
|
|
126
149
|
sort_json_ld_keys: sort_json_ld_keys,
|
|
127
150
|
force: force
|
|
128
151
|
}
|
|
129
|
-
|
|
130
|
-
unless sort_json_ld_keys && k.start_with?(
|
|
131
|
-
if
|
|
132
|
-
export_hash[k] =
|
|
152
|
+
keys.each do |k|
|
|
153
|
+
unless sort_json_ld_keys && k.start_with?("@")
|
|
154
|
+
if data[k].respond_to?(:to_ordered_hash) # .respond_to?(:to_ordered_hash)
|
|
155
|
+
export_hash[k] = data[k].to_ordered_hash(sub_opts)
|
|
133
156
|
|
|
134
|
-
elsif
|
|
157
|
+
elsif data[k].is_a?(Hash)
|
|
135
158
|
export_hash[k] = IIIF::OrderedHash.new
|
|
136
|
-
|
|
137
|
-
|
|
159
|
+
data[k].each do |sub_k, v|
|
|
138
160
|
if v.respond_to?(:to_ordered_hash)
|
|
139
161
|
export_hash[k][sub_k] = v.to_ordered_hash(sub_opts)
|
|
140
162
|
|
|
141
|
-
elsif v.
|
|
163
|
+
elsif v.is_a?(Array)
|
|
142
164
|
export_hash[k][sub_k] = []
|
|
143
165
|
v.each do |member|
|
|
144
|
-
if member.respond_to?(:to_ordered_hash)
|
|
145
|
-
|
|
166
|
+
export_hash[k][sub_k] << if member.respond_to?(:to_ordered_hash)
|
|
167
|
+
member.to_ordered_hash(sub_opts)
|
|
146
168
|
else
|
|
147
|
-
|
|
169
|
+
member
|
|
148
170
|
end
|
|
149
171
|
end
|
|
150
172
|
else
|
|
@@ -152,29 +174,28 @@ module IIIF
|
|
|
152
174
|
end
|
|
153
175
|
end
|
|
154
176
|
|
|
155
|
-
elsif
|
|
177
|
+
elsif data[k].is_a?(Array)
|
|
156
178
|
export_hash[k] = []
|
|
157
179
|
|
|
158
|
-
|
|
180
|
+
data[k].each do |member|
|
|
159
181
|
if member.respond_to?(:to_ordered_hash)
|
|
160
182
|
export_hash[k] << member.to_ordered_hash(sub_opts)
|
|
161
183
|
|
|
162
|
-
elsif member.
|
|
184
|
+
elsif member.is_a?(Hash)
|
|
163
185
|
hsh = IIIF::OrderedHash.new
|
|
164
186
|
export_hash[k] << hsh
|
|
165
|
-
member.each do |sub_k,v|
|
|
166
|
-
|
|
187
|
+
member.each do |sub_k, v|
|
|
167
188
|
if v.respond_to?(:to_ordered_hash)
|
|
168
189
|
hsh[sub_k] = v.to_ordered_hash(sub_opts)
|
|
169
190
|
|
|
170
|
-
elsif v.
|
|
191
|
+
elsif v.is_a?(Array)
|
|
171
192
|
hsh[sub_k] = []
|
|
172
193
|
|
|
173
194
|
v.each do |sub_member|
|
|
174
|
-
if sub_member.respond_to?(:to_ordered_hash)
|
|
175
|
-
|
|
195
|
+
hsh[sub_k] << if sub_member.respond_to?(:to_ordered_hash)
|
|
196
|
+
sub_member.to_ordered_hash(sub_opts)
|
|
176
197
|
else
|
|
177
|
-
|
|
198
|
+
sub_member
|
|
178
199
|
end
|
|
179
200
|
end
|
|
180
201
|
else
|
|
@@ -188,7 +209,7 @@ module IIIF
|
|
|
188
209
|
end
|
|
189
210
|
end
|
|
190
211
|
else
|
|
191
|
-
export_hash[k] =
|
|
212
|
+
export_hash[k] = data[k]
|
|
192
213
|
end
|
|
193
214
|
|
|
194
215
|
end
|
|
@@ -198,35 +219,35 @@ module IIIF
|
|
|
198
219
|
export_hash
|
|
199
220
|
end
|
|
200
221
|
|
|
201
|
-
def self.from_ordered_hash(hsh, default_klass=IIIF::OrderedHash)
|
|
222
|
+
def self.from_ordered_hash(hsh, default_klass = IIIF::OrderedHash)
|
|
202
223
|
# Create a new object (new_object)
|
|
203
224
|
type = nil
|
|
204
|
-
if hsh.has_key?(
|
|
205
|
-
type = IIIF::Service.get_descendant_class_by_jld_type(hsh[
|
|
225
|
+
if hsh.has_key?("@type")
|
|
226
|
+
type = IIIF::Service.get_descendant_class_by_jld_type(hsh["@type"])
|
|
206
227
|
end
|
|
207
228
|
new_object = type.nil? ? default_klass.new : type.new
|
|
208
229
|
|
|
209
230
|
hsh.keys.each do |key|
|
|
210
|
-
new_key = key.underscore == key ? key : key.underscore
|
|
211
|
-
if hsh[key].
|
|
231
|
+
new_key = (key.underscore == key) ? key : key.underscore
|
|
232
|
+
if hsh[key].is_a?(Array)
|
|
212
233
|
new_object[new_key] = []
|
|
213
234
|
hsh[key].each do |member|
|
|
214
|
-
if new_key ==
|
|
215
|
-
|
|
216
|
-
elsif new_key ==
|
|
217
|
-
|
|
218
|
-
elsif member.
|
|
219
|
-
|
|
235
|
+
new_object[new_key] << if new_key == "service"
|
|
236
|
+
IIIF::Service.from_ordered_hash(member, IIIF::Presentation::Service)
|
|
237
|
+
elsif new_key == "resource"
|
|
238
|
+
IIIF::Service.from_ordered_hash(hsh[key], IIIF::Presentation::Resource)
|
|
239
|
+
elsif member.is_a?(Hash)
|
|
240
|
+
IIIF::Service.from_ordered_hash(member)
|
|
220
241
|
else
|
|
221
|
-
|
|
242
|
+
member
|
|
222
243
|
# Again, no nested arrays, right?
|
|
223
244
|
end
|
|
224
245
|
end
|
|
225
|
-
elsif new_key ==
|
|
246
|
+
elsif new_key == "service"
|
|
226
247
|
new_object[new_key] = IIIF::Service.from_ordered_hash(hsh[key], IIIF::Presentation::Service)
|
|
227
|
-
elsif new_key ==
|
|
248
|
+
elsif new_key == "resource"
|
|
228
249
|
new_object[new_key] = IIIF::Service.from_ordered_hash(hsh[key], IIIF::Presentation::Resource)
|
|
229
|
-
elsif hsh[key].
|
|
250
|
+
elsif hsh[key].is_a?(Hash)
|
|
230
251
|
new_object[new_key] = IIIF::Service.from_ordered_hash(hsh[key])
|
|
231
252
|
else
|
|
232
253
|
new_object[new_key] = hsh[key]
|
|
@@ -235,8 +256,6 @@ module IIIF
|
|
|
235
256
|
new_object
|
|
236
257
|
end
|
|
237
258
|
|
|
238
|
-
protected
|
|
239
|
-
|
|
240
259
|
def self.get_descendant_class_by_jld_type(type)
|
|
241
260
|
IIIF::Service.all_service_subclasses.find do |klass|
|
|
242
261
|
klass.const_defined?(:TYPE) && klass.const_get(:TYPE) == type
|
|
@@ -248,13 +267,11 @@ module IIIF
|
|
|
248
267
|
@all_service_subclasses ||= IIIF::Service.descendants.reject(&:singleton_class?)
|
|
249
268
|
end
|
|
250
269
|
|
|
251
|
-
|
|
252
|
-
@data = hsh
|
|
253
|
-
end
|
|
270
|
+
protected
|
|
254
271
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
272
|
+
attr_writer :data
|
|
273
|
+
|
|
274
|
+
attr_reader :data
|
|
258
275
|
|
|
259
276
|
def define_methods_for_any_type_keys
|
|
260
277
|
define_accessor_methods(*any_type_keys)
|
|
@@ -263,14 +280,14 @@ module IIIF
|
|
|
263
280
|
# an array for empty values.
|
|
264
281
|
any_type_keys.each do |key|
|
|
265
282
|
define_singleton_method(key) do
|
|
266
|
-
|
|
283
|
+
send(:[], key)
|
|
267
284
|
end
|
|
268
285
|
end
|
|
269
286
|
end
|
|
270
287
|
|
|
271
288
|
def define_methods_for_array_only_keys
|
|
272
289
|
define_accessor_methods(*array_only_keys) do |key, arg|
|
|
273
|
-
unless arg.
|
|
290
|
+
unless arg.is_a?(Array)
|
|
274
291
|
m = "#{key} must be an Array."
|
|
275
292
|
raise IIIF::Presentation::IllegalValueError, m
|
|
276
293
|
end
|
|
@@ -284,7 +301,7 @@ module IIIF
|
|
|
284
301
|
type = hsh[:type]
|
|
285
302
|
|
|
286
303
|
define_accessor_methods(key) do |key, arg|
|
|
287
|
-
unless arg.
|
|
304
|
+
unless arg.is_a?(type)
|
|
288
305
|
m = "#{key} must be an #{type}."
|
|
289
306
|
raise IIIF::Presentation::IllegalValueError, m
|
|
290
307
|
end
|
|
@@ -294,7 +311,7 @@ module IIIF
|
|
|
294
311
|
|
|
295
312
|
def define_methods_for_string_only_keys
|
|
296
313
|
define_accessor_methods(*string_only_keys) do |key, arg|
|
|
297
|
-
unless arg.
|
|
314
|
+
unless arg.is_a?(String)
|
|
298
315
|
m = "#{key} must be an String."
|
|
299
316
|
raise IIIF::Presentation::IllegalValueError, m
|
|
300
317
|
end
|
|
@@ -303,7 +320,7 @@ module IIIF
|
|
|
303
320
|
|
|
304
321
|
def define_methods_for_int_only_keys
|
|
305
322
|
define_accessor_methods(*int_only_keys) do |key, arg|
|
|
306
|
-
unless arg.
|
|
323
|
+
unless arg.is_a?(Integer) && arg > 0
|
|
307
324
|
m = "#{key} must be a positive Integer."
|
|
308
325
|
raise IIIF::Presentation::IllegalValueError, m
|
|
309
326
|
end
|
|
@@ -312,7 +329,7 @@ module IIIF
|
|
|
312
329
|
|
|
313
330
|
def define_methods_for_numeric_only_keys
|
|
314
331
|
define_accessor_methods(*numeric_only_keys) do |key, arg|
|
|
315
|
-
unless arg.
|
|
332
|
+
unless arg.is_a?(Numeric) && arg > 0
|
|
316
333
|
m = "#{key} must be a positive Integer or Float."
|
|
317
334
|
raise IIIF::Presentation::IllegalValueError, m
|
|
318
335
|
end
|
|
@@ -321,15 +338,17 @@ module IIIF
|
|
|
321
338
|
|
|
322
339
|
def define_accessor_methods(*keys, &validation)
|
|
323
340
|
keys.each do |key|
|
|
341
|
+
camelized_key = key.camelize(:lower)
|
|
342
|
+
|
|
324
343
|
# Setter
|
|
325
344
|
define_singleton_method("#{key}=") do |arg|
|
|
326
345
|
validation.call(key, arg) if block_given?
|
|
327
|
-
|
|
346
|
+
send(:[]=, key, arg)
|
|
328
347
|
end
|
|
329
|
-
if
|
|
330
|
-
define_singleton_method("#{
|
|
348
|
+
if camelized_key != key
|
|
349
|
+
define_singleton_method("#{camelized_key}=") do |arg|
|
|
331
350
|
validation.call(key, arg) if block_given?
|
|
332
|
-
|
|
351
|
+
send(:[]=, key, arg)
|
|
333
352
|
end
|
|
334
353
|
end
|
|
335
354
|
# Getter
|
|
@@ -337,9 +356,9 @@ module IIIF
|
|
|
337
356
|
self[key] ||= []
|
|
338
357
|
self[key]
|
|
339
358
|
end
|
|
340
|
-
if
|
|
341
|
-
define_singleton_method(
|
|
342
|
-
|
|
359
|
+
if camelized_key != key
|
|
360
|
+
define_singleton_method(camelized_key) do
|
|
361
|
+
send(:[], key)
|
|
343
362
|
end
|
|
344
363
|
end
|
|
345
364
|
end
|