fieldhand 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a1f8b4934a70d78dda2f03bb151deea7ed553424
4
+ data.tar.gz: f39842d9de77f6a43203f6795ef35836ac5efbff
5
+ SHA512:
6
+ metadata.gz: 6ce68385c9352deabd07c6f60ef904853c934a79d1488a88abbffaed9c1802e59f06437501cc23f79b68bbacc801608c758085753373525e9484d4c0b566c181
7
+ data.tar.gz: 22c515794f85150b621f0a8ef0d7af25505590a707ff86b8972e5751c69cf5a0bc46508cfb53b5d8ebe5458be778d10b9d69c1cfd13e731b92806b1de69e7cec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Altmetric LLP
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,538 @@
1
+ # Fieldhand [![Build Status](https://travis-ci.org/altmetric/fieldhand.svg?branch=master)](https://travis-ci.org/altmetric/fieldhand)
2
+
3
+ A Ruby library for harvesting metadata from [OAI-PMH](https://www.openarchives.org/OAI/openarchivesprotocol.html) repositories.
4
+
5
+ **Current version:** 0.1.0
6
+ **Supported Ruby versions:** 1.8.7, 1.9.2, 1.9.3, 2.0, 2.1, 2.2
7
+
8
+ ## Usage
9
+
10
+ ```ruby
11
+ require 'fieldhand'
12
+
13
+ repository = Fieldhand::Repository.new('http://example.com/oai')
14
+ repository.identify.name
15
+ #=> "Repository Name"
16
+
17
+ repository.metadata_formats.map { |format| format.prefix }
18
+ #=> ["oai_dc"]
19
+
20
+ repository.sets.map { |set| set.name }
21
+ #=> ["Set A.", "Set B."]
22
+
23
+ repository.records.each do |record|
24
+ # ...
25
+ end
26
+
27
+ repository.get('oai:www.example.com:12345')
28
+ #=> #<Fieldhand::Record: ...>
29
+ ```
30
+
31
+ ## API Documentation
32
+
33
+ * [`Fieldhand::Repository`](#fieldhandrepository)
34
+ * [`.new(uri[, logger])`](#fieldhandrepositorynewuri-logger)
35
+ * [`#identify`](#fieldhandrepositoryidentify)
36
+ * [`#metadata_formats([identifier])`](#fieldhandrepositorymetadata_formatsidentifier)
37
+ * [`#sets`](#fieldhandrepositorysets)
38
+ * [`#records([arguments])`](#fieldhandrepositoryrecordsarguments)
39
+ * [`#identifiers([arguments])`](#fieldhandrepositoryidentifiersarguments)
40
+ * [`#get(identifier[, arguments])`](#fieldhandgetidentifier-arguments)
41
+ * [`Fieldhand::Identify`](#fieldhandidentify)
42
+ * [`#name`](#fieldhandidentifyname)
43
+ * [`#base_url`](#fieldhandidentifybase_url)
44
+ * [`#protocol_version`](#fieldhandidentifyprotocol_version)
45
+ * [`#earliest_datestamp`](#fieldhandidentifyearliest_datestamp)
46
+ * [`#deleted_record`](#fieldhandidentifydeleted_record)
47
+ * [`#granularity`](#fieldhandidentifygranularity)
48
+ * [`#admin_emails`](#fieldhandidentifyadmin_emails)
49
+ * [`#compression`](#fieldhandidentifycompression)
50
+ * [`#descriptions`](#fieldhandidentifydescriptions)
51
+ * [`Fieldhand::MetadataFormat`](#fieldhandmetadataformat)
52
+ * [`#prefix`](#fieldhandmetadataformatprefix)
53
+ * [`#schema`](#fieldhandmetadataformatschema)
54
+ * [`#namespace`](#fieldhandmetadataformatnamespace)
55
+ * [`Fieldhand::Set`](#fieldhandset)
56
+ * [`#spec`](#fieldhandsetspec)
57
+ * [`#name`](#fieldhandsetname)
58
+ * [`#descriptions`](#fieldhandsetdescriptions)
59
+ * [`Fieldhand::Record`](#fieldhandrecord)
60
+ * [`#deleted?`](#fieldhandrecorddeleted)
61
+ * [`#status`](#fieldhandrecordstatus)
62
+ * [`#identifier`](#fieldhandrecordidentifier)
63
+ * [`#datestamp`](#fieldhandrecorddatestamp)
64
+ * [`#sets`](#fieldhandrecordsets)
65
+ * [`#metadata`](#fieldhandrecordmetadata)
66
+ * [`#about`](#fieldhandrecordabout)
67
+ * [`Fieldhand::Header`](#fieldhandheader)
68
+ * [`#deleted?`](#fieldhandheaderdeleted)
69
+ * [`#status`](#fieldhandheaderstatus)
70
+ * [`#identifier`](#fieldhandheaderidentifier)
71
+ * [`#datestamp`](#fieldhandheaderdatestamp)
72
+ * [`#sets`](#fieldhandheadersets)
73
+ * [`Fieldhand::NetworkError`](#fieldhandnetworkerror)
74
+ * [`Fieldhand::ProtocolError`](#fieldhandprotocolerror)
75
+ * [`Fieldhand::BadArgumentError`](#fieldhandbadargumenterror)
76
+ * [`Fieldhand::BadResumptionTokenError`](#fieldhandbadresumptiontokenerror)
77
+ * [`Fieldhand::BadVerbError`](#fieldhandbadverberror)
78
+ * [`Fieldhand::CannotDisseminateFormatError`](#fieldhandcannotdisseminateformaterror)
79
+ * [`Fieldhand::IdDoesNotExistError`](#fieldhandiddoesnotexisterror)
80
+ * [`Fieldhand::NoRecordsMatchError`](#fieldhandnorecordsmatcherror)
81
+ * [`Fieldhand::NoMetadataFormatsError`](#fieldhandnometadataformatserror)
82
+ * [`Fieldhand::NoSetHierarchyError`](#fieldhandnosethierarchyerror)
83
+
84
+ ### `Fieldhand::Repository`
85
+
86
+ A class to represent [an OAI-PMH repository](https://www.openarchives.org/OAI/openarchivesprotocol.html#Repository):
87
+
88
+ > A repository is a network accessible server that can process the 6 OAI-PMH
89
+ > requests [...]. A repository is managed by a data provider to expose metadata
90
+ > to harvesters.
91
+
92
+ #### `Fieldhand::Repository.new(uri[, logger])`
93
+
94
+ ```ruby
95
+ Fieldhand::Repository.new('http://www.example.com/oai')
96
+ Fieldhand::Repository.new(URI('http://www.example.com/oai'))
97
+ Fieldhand::Repository.new('http://www.example.com/oai', Logger.new(STDOUT))
98
+ ```
99
+
100
+ Return a new [`Repository`](#fieldhandrepository) instance accessible at the given `uri` (specified
101
+ either as a [`URI`][URI] or
102
+ something that can be coerced into a `URI` such as a `String`) with an optional
103
+ [`Logger`](http://ruby-doc.org/stdlib/libdoc/logger/rdoc/Logger.html)-compatible
104
+ `logger`.
105
+
106
+ #### `Fieldhand::Repository#identify`
107
+
108
+ ```ruby
109
+ repository.identify
110
+ #=> #<Fieldhand::Identify: ...>
111
+ ```
112
+
113
+ Return an [`Identify`](#fieldhandidentify) for the repository including information such as the repository name, base URL, protocol version, etc.
114
+
115
+ May raise a [`NetworkError`](#fieldhandnetworkerror) if there is a problem contacting the repository or any descendant [`ProtocolError`](#fieldhandprotocolerror) if received in response.
116
+
117
+ #### `Fieldhand::Repository#metadata_formats([identifier])`
118
+
119
+ ```ruby
120
+ repository.metadata_formats
121
+ #=> #<Enumerator: ...>
122
+ repository.metadata_formats('oai:www.example.com:1')
123
+ ```
124
+
125
+ Return an [`Enumerator`][Enumerator] of [`MetadataFormat`](#fieldhandmetadataformat)s available from the repository. Optionally takes an `identifier` that specifies the unique identifier of the item for which available metadata formats are being requested.
126
+
127
+ May raise a [`NetworkError`](#fieldhandnetworkerror) if there is a problem contacting the repository or any descendant [`ProtocolError`](#fieldhandprotocolerror) if received in response.
128
+
129
+ #### `Fieldhand::Repository#sets`
130
+
131
+ ```ruby
132
+ repository.sets
133
+ #=> #<Enumerator: ...>
134
+ ```
135
+
136
+ Return an [`Enumerator`][Enumerator] of [`Set`](#fieldhandset)s that represent the set structure of a repository.
137
+
138
+ May raise a [`NetworkError`](#fieldhandnetworkerror) if there is a problem contacting the repository or any descendant [`ProtocolError`](#fieldhandprotocolerror) if received in response.
139
+
140
+ #### `Fieldhand::Repository#records([arguments])`
141
+
142
+ ```ruby
143
+ repository.records
144
+ repository.records(:metadata_prefix => 'oai_dc', :from => '2001-01-01')
145
+ repository.records(:metadata_prefix => 'oai_dc', :from => Date.new(2001, 1, 1))
146
+ repository.records(:set => 'A', :until => Time.utc(2010, 1, 1, 12, 0))
147
+ ```
148
+
149
+ Return an [`Enumerator`][Enumerator] of all [`Record`](#fieldhandrecord)s harvested from the repository.
150
+
151
+ Optional arguments can be passed as a `Hash` of `arguments` to permit selective harvesting of records based on set membership and/or datestamp:
152
+
153
+ * `:metadata_prefix`: a `String` or [`MetadataFormat`](#fieldhandmetadataformat) to specify the metadata format that should be included in the metadata part of the returned record, defaults to `oai_dc`;
154
+ * `:from`: an optional argument with a `String`, [`Date`][Date] or [`Time`][Time] [UTCdatetime](https://www.openarchives.org/OAI/openarchivesprotocol.html#Dates) value, which specifies a lower bound for datestamp-based selective harvesting;
155
+ * `:until`: an optional argument with a `String`, [`Date`][Date] or [`Time`][Time] [UTCdatetime](https://www.openarchives.org/OAI/openarchivesprotocol.html#Dates) value, which specifies a upper bound for datestamp-based selective harvesting;
156
+ * `:set`: an optional argument with a [set spec](#fieldhandsetspec) value (passed as either a `String` or a [`Set`](#fieldhandset)), which specifies set criteria for selective harvesting;
157
+ * `:resumption_token`: an exclusive argument with a `String` value that is the flow control token returned by a previous request that issued an incomplete list.
158
+
159
+ Note that datetimes should respect the repository's [granularity](#fieldhandidentifygranularity) otherwise they will return a [`BadArgumentError`](#fieldhandbadargumenterror).
160
+
161
+ May raise a [`NetworkError`](#fieldhandnetworkerror) if there is a problem contacting the repository or any descendant [`ProtocolError`](#fieldhandprotocolerror) if received in response.
162
+
163
+ #### `Fieldhand::Repository#identifiers(metadata_prefix[, arguments])`
164
+
165
+ ```ruby
166
+ repository.identifiers
167
+ repository.identifiers(:metadata_prefix => 'oai_dc', :from => '2001-01-01')
168
+ repository.identifiers(:metadata_prefix => 'oai_dc', :from => Date.new(2001, 1, 1))
169
+ repository.identifiers(:set => 'A', :until => Time.utc(2010, 1, 1, 12, 0))
170
+ ```
171
+
172
+ Return an [`Enumerator`][Enumerator] for an abbreviated form of [records](#fieldhandrepositoryrecordsarguments), retrieving only [`Header`](#fieldhandheader)s with the given optional `arguments`.
173
+
174
+ See [`Fieldhand::Repository#records`](#fieldhandrepositoryrecordsarguments) for supported `arguments`.
175
+
176
+ May raise a [`NetworkError`](#fieldhandnetworkerror) if there is a problem contacting the repository or any descendant [`ProtocolError`](#fieldhandprotocolerror) if received in response.
177
+
178
+ #### `Fieldhand::Repository#get(identifier[, arguments])`
179
+
180
+ ```ruby
181
+ repository.get('oai:www.example.com:1')
182
+ repository.get('oai:www.example.com:1', :metadata_prefix => 'oai_dc')
183
+ #=> #<Fieldhand::Record: ...>
184
+ ```
185
+
186
+ Return an individual metadata [`Record`](#fieldhandrecord) from a repository with the given `identifier` and optional `:metadata_prefix` argument (defaults to `oai_dc`).
187
+
188
+ May raise a [`NetworkError`](#fieldhandnetworkerror) if there is a problem contacting the repository or any descendant [`ProtocolError`](#fieldhandprotocolerror) if received in response.
189
+
190
+ ### `Fieldhand::Identify`
191
+
192
+ A class to represent information about a repository as returned from the [`Identify` request](https://www.openarchives.org/OAI/openarchivesprotocol.html#Identify).
193
+
194
+ #### `Fieldhand::Identify#name`
195
+
196
+ ```ruby
197
+ repository.identify.name
198
+ #=> "Repository Name"
199
+ ```
200
+
201
+ Return a human readable name for the repository as a `String`.
202
+
203
+ #### `Fieldhand::Identify#base_url`
204
+
205
+ ```ruby
206
+ repository.identify.base_url
207
+ #=> #<URI::HTTP http://www.example.com/oai>
208
+ ```
209
+
210
+ Returns the [base URL](https://www.openarchives.org/OAI/openarchivesprotocol.html#HTTPRequestFormat) of the repository as a [`URI`][URI].
211
+
212
+ #### `Fieldhand::Identify#protocol_version`
213
+
214
+ ```ruby
215
+ repository.identify.protocol_version
216
+ #=> "2.0"
217
+ ```
218
+
219
+ Returns the version of the OAI-PMH protocol supported by the repository as a `String`.
220
+
221
+ #### `Fieldhand::Identify#earliest_datestamp`
222
+
223
+ ```ruby
224
+ repository.identify.earliest_datestamp
225
+ #=> 2011-01-01 00:00:00 UTC
226
+ repository.identify.earliest_datestamp
227
+ #=> #<Date: 2001-01-01 ((2451911j,0s,0n),+0s,2299161j)>
228
+ ```
229
+
230
+ Returns the guaranteed lower limit of all datestamps recording changes, modifications, or deletions in the repository as a [`Time`][Time] or [`Date`][Date]. Note that the datestamp will be at the finest [granularity](#fieldhandidentifygranularity) supported by the repository.
231
+
232
+ #### `Fieldhand::Identify#deleted_record`
233
+
234
+ ```ruby
235
+ repository.identify.deleted_record
236
+ #=> "persistent"
237
+ ```
238
+
239
+ Returns the manner in which the repository supports the notion of deleted records as a `String`. Legitimate values are `no`; `transient`; `persistent` with meanings defined in [the section on deletion](https://www.openarchives.org/OAI/openarchivesprotocol.html#DeletedRecords).
240
+
241
+ #### `Fieldhand::Identify#granularity`
242
+
243
+ ```ruby
244
+ repository.identify.granularity
245
+ #=> "YYYY-MM-DDThh:mm:ssZ"
246
+ ```
247
+
248
+ Returns the finest [harvesting granularity](https://www.openarchives.org/OAI/openarchivesprotocol.html#Datestamp) supported by the repository as a `String`. The legitimate values are `YYYY-MM-DD` and `YYYY-MM-DDThh:mm:ssZ` with meanings as defined in [ISO 8601](http://www.w3.org/TR/NOTE-datetime).
249
+
250
+ #### `Fieldhand::Identify#admin_emails`
251
+
252
+ ```ruby
253
+ repository.identify.admin_emails
254
+ #=> ["admin@example.com"]
255
+ ```
256
+
257
+ Returns the e-mail addresses of administrators of the repository as an `Array` of `String`s.
258
+
259
+ #### `Fieldhand::Identify#compression`
260
+
261
+ ```ruby
262
+ repository.identify.compression
263
+ #=> ["gzip", "deflate"]
264
+ ```
265
+
266
+ Returns the compression encodings supported by the repository as an `Array` of `String`s. The recommended values are those defined for the Content-Encoding header in Section 14.11 of [RFC 2616](http://www.ietf.org/rfc/rfc2616.txt) describing HTTP 1.1
267
+
268
+ #### `Fieldhand::Identify#descriptions`
269
+
270
+ ```ruby
271
+ repository.identify.descriptions
272
+ #=> [#<Ox::Element...>]
273
+ ```
274
+
275
+ Returns XML elements describing this repository as an `Array` of [`Ox::Element`][Element]s.
276
+
277
+ As descriptions can be in any format, Fieldhand doesn't attempt to parse descriptions but leaves parsing to the client.
278
+
279
+ ### `Fieldhand::MetadataFormat`
280
+
281
+ A class to represent a metadata format available from a repository.
282
+
283
+ #### `Fieldhand::MetadataFormat#prefix`
284
+
285
+ ```ruby
286
+ repository.metadata_formats.first.prefix
287
+ #=> "oai_dc"
288
+ ```
289
+
290
+ Return the prefix of the metadata format to be used when requesting records as a `String`.
291
+
292
+ #### `Fieldhand::MetadataFormat#schema`
293
+
294
+ ```ruby
295
+ repository.metadata_formats.first.schema
296
+ #=> #<URI::HTTP http://www.openarchives.org/OAI/2.0/oai_dc.xsd>
297
+ ```
298
+
299
+ Return the location of an XML Schema describing the format as a [`URI`][URI].
300
+
301
+ #### `Fieldhand::MetadataFormat#namespace`
302
+
303
+ ```ruby
304
+ repository.metadata_formats.first.namespace
305
+ #=> #<URI::HTTP http://www.openarchives.org/OAI/2.0/oai_dc/>
306
+ ```
307
+
308
+ Return the XML Namespace URI for the format as a [`URI`][URI].
309
+
310
+ ### `Fieldhand::Set`
311
+
312
+ A class representing an optional construct for grouping items for the purpose of selective harvesting.
313
+
314
+ #### `Fieldhand::Set#spec`
315
+
316
+ ```ruby
317
+ repository.sets.first.spec
318
+ #=> "A"
319
+ ```
320
+
321
+ Return unique identifier for the set which is also the path from the root of the set hierarchy to the respective node as a `String`.
322
+
323
+ #### `Fieldhand::Set#name`
324
+
325
+ ```ruby
326
+ repository.sets.first.name
327
+ #=> "Set A."
328
+ ```
329
+
330
+ Return a short human-readable `String` naming the set.
331
+
332
+ #### `Fieldhand::Set#descriptions`
333
+
334
+ ```ruby
335
+ repository.sets.first.descriptions
336
+ #=> [#<Ox::Element: ...>]
337
+ ```
338
+
339
+ Return an `Array` of [`Ox::Element`][Element]s of any optional and repeatable containers that may hold community-specific XML-encoded data about the set.
340
+
341
+ ### `Fieldhand::Record`
342
+
343
+ A class representing a [record](https://www.openarchives.org/OAI/openarchivesprotocol.html#Record) from the repository:
344
+
345
+ > A record is metadata expressed in a single format.
346
+
347
+ #### `Fieldhand::Record#deleted?`
348
+
349
+ ```ruby
350
+ repository.records.first.deleted?
351
+ #=> true
352
+ ```
353
+
354
+ Return whether or not a record is [deleted](https://www.openarchives.org/OAI/openarchivesprotocol.html#DeletedRecords) as a `Boolean`.
355
+
356
+ #### `Fieldhand::Record#status`
357
+
358
+ ```ruby
359
+ repository.records.first.status
360
+ #=> "deleted"
361
+ ```
362
+
363
+ Return the optional `status` attribute of the [record's header](https://www.openarchives.org/OAI/openarchivesprotocol.html#header) as a `String` or `nil`.
364
+
365
+ > [A] value of deleted indicates the withdrawal of availability of the specified metadata format for the item, dependent on the repository support for deletions.
366
+
367
+ #### `Fieldhand::Record#identifier`
368
+
369
+ ```ruby
370
+ repository.records.first.identifier
371
+ #=> "oai:www.example.com:1"
372
+ ```
373
+
374
+ Return the [unique identifier](https://www.openarchives.org/OAI/openarchivesprotocol.html#UniqueIdentifier) for this record in the repository.
375
+
376
+ #### `Fieldhand::Record#datestamp`
377
+
378
+ ```ruby
379
+ repository.records.first.datestamp
380
+ #=> 2011-03-03 16:29:24 UTC
381
+ ```
382
+
383
+ Return the date of creation, modification or deletion of the record for the purpose of selective harvesting as a [`Time`][Time] or [`Date`][Date] depending on the [granularity](#fieldhandidentifygranularity) of the repository.
384
+
385
+ #### `Fieldhand::Record#sets`
386
+
387
+ ```ruby
388
+ repository.records.first.sets
389
+ #=> ["A", "B"]
390
+ ```
391
+
392
+ Return an `Array` of `String` [set specs](#fieldhandsetspec) indicating set memberships of this record.
393
+
394
+ #### `Fieldhand::Record#metadata`
395
+
396
+ ```ruby
397
+ repository.records.first.metadata
398
+ #=> #<Ox::Element: ...>
399
+ ```
400
+
401
+ Return a single manifestation of the metadata from a record as [`Ox::Element`][Element]s or `nil` if this is a deleted record.
402
+
403
+ As the metadata can be in [any format supported by the repository](#fieldhandrepositorymetadata_formatsidentifier), Fieldhand doesn't attempt to parse the metadata but leaves parsing to the client.
404
+
405
+ #### `Fieldhand::Record#about`
406
+
407
+ ```ruby
408
+ repository.records.first.about
409
+ #=> [#<Ox::Element: ...>]
410
+ ```
411
+
412
+ Return an `Array` of [`Ox::Element`][Element]s of any optional and repeatable containers holding data about the metadata part of the record.
413
+
414
+ ### `Fieldhand::Header`
415
+
416
+ A class representing the [header](https://www.openarchives.org/OAI/openarchivesprotocol.html#header) of a record:
417
+
418
+ > Contains the unique identifier of the item and properties necessary for selective harvesting. The header consists of
419
+ > the following parts:
420
+ >
421
+ > * the unique identifier -- the unique identifier of an item in a repository;
422
+ > * the datestamp -- the date of creation, modification or deletion of the record for the purpose of selective
423
+ > harvesting.
424
+ > * zero or more setSpec elements -- the set membership of the item for the purpose of selective harvesting.
425
+ > * an optional status attribute with a value of deleted indicates the withdrawal of availability of the specified
426
+ > metadata format for the item, dependent on the repository support for deletions.
427
+
428
+ #### `Fieldhand::Header#deleted?`
429
+
430
+ ```ruby
431
+ repository.identifiers.first.deleted?
432
+ #=> true
433
+ ```
434
+
435
+ Return whether or not a record is [deleted](https://www.openarchives.org/OAI/openarchivesprotocol.html#DeletedRecords) as a `Boolean`.
436
+
437
+ #### `Fieldhand::Header#status`
438
+
439
+ ```ruby
440
+ repository.identifiers.first.status
441
+ #=> "deleted"
442
+ ```
443
+
444
+ Return the optional `status` attribute of the header as a `String` or `nil`.
445
+
446
+ > [A] value of deleted indicates the withdrawal of availability of the specified metadata format for the item, dependent on the repository support for deletions.
447
+
448
+ #### `Fieldhand::Header#identifier`
449
+
450
+ ```ruby
451
+ repository.identifiers.first.identifier
452
+ #=> "oai:www.example.com:1"
453
+ ```
454
+
455
+ Return the [unique identifier](https://www.openarchives.org/OAI/openarchivesprotocol.html#UniqueIdentifier) for this record in the repository.
456
+
457
+ #### `Fieldhand::Header#datestamp`
458
+
459
+ ```ruby
460
+ repository.identifiers.first.datestamp
461
+ #=> 2011-03-03 16:29:24 UTC
462
+ ```
463
+
464
+ Return the date of creation, modification or deletion of the record for the purpose of selective harvesting as a [`Time`][Time] or [`Date`][Date] depending on the [granularity](#fieldhandidentifygranularity) of the repository.
465
+
466
+ #### `Fieldhand::Header#sets`
467
+
468
+ ```ruby
469
+ repository.identifiers.first.sets
470
+ #=> ["A", "B"]
471
+ ```
472
+
473
+ Return an `Array` of `String` [set specs](#fieldhandsetspec) indicating set memberships of this record.
474
+
475
+ ### `Fieldhand::NetworkError`
476
+
477
+ An error (descended from `StandardError`) to represent any network issues encountered during interaction with the repository. Any underlying exception is exposed in Ruby 2.1 onwards through [`Exception#cause`](https://ruby-doc.org/core-2.1.0/Exception.html#method-i-cause).
478
+
479
+ ### `Fieldhand::ProtocolError`
480
+
481
+ The parent error class (descended from `StandardError`) for any errors returned by a repository as defined in the [protocol's Error and Exception Conditions](https://www.openarchives.org/OAI/openarchivesprotocol.html#ErrorConditions).
482
+
483
+ This can be used to rescue all the following child error types.
484
+
485
+ ### `Fieldhand::BadArgumentError`
486
+
487
+ > The request includes illegal arguments, is missing required arguments,
488
+ > includes a repeated argument, or values for arguments have an illegal syntax.
489
+
490
+ ### `Fieldhand::BadResumptionTokenError`
491
+
492
+ > The value of the `resumptionToken` argument is invalid or expired.
493
+
494
+ ### `Fieldhand::BadVerbError`
495
+
496
+ > Value of the `verb` argument is not a legal OAI-PMH verb, the `verb` argument is
497
+ > missing, or the `verb` argument is repeated.
498
+
499
+ ### `Fieldhand::CannotDisseminateFormatError`
500
+
501
+ > The metadata format identified by the value given for the `metadataPrefix`
502
+ > argument is not supported by the item or by the repository.
503
+
504
+ ### `Fieldhand::IdDoesNotExistError`
505
+
506
+ > The value of the `identifier` argument is unknown or illegal in this
507
+ > repository.
508
+
509
+ ### `Fieldhand::NoRecordsMatchError`
510
+
511
+ > The combination of the values of the `from`, `until`, `set` and `metadataPrefix`
512
+ > arguments results in an empty list.
513
+
514
+ ### `Fieldhand::NoMetadataFormatsError`
515
+
516
+ > There are no metadata formats available for the specified item.
517
+
518
+ ### `Fieldhand::NoSetHierarchyError`
519
+
520
+ > The repository does not support sets.
521
+
522
+ [Date]: https://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html
523
+ [Enumerator]: https://ruby-doc.org/core/Enumerator.html
524
+ [Time]: https://ruby-doc.org/core/Time.html
525
+ [URI]: https://ruby-doc.org/stdlib/libdoc/uri/rdoc/URI.html
526
+ [Element]: http://www.rubydoc.info/github/ohler55/ox/Ox/Element
527
+
528
+ ## Acknowledgements
529
+
530
+ * Example XML responses are taken from [Datacite's OAI-PMH repository](https://oai.datacite.org/).
531
+ * Null device detection is based on the implementation from the [backports](https://github.com/marcandre/backports) gem.
532
+ * Much of the documentation relies on wording from version 2.0 of [The Open Archives Initiative Protocol for Metadata Harvesting](https://www.openarchives.org/OAI/openarchivesprotocol.html).
533
+
534
+ ## License
535
+
536
+ Copyright © 2017 Altmetric LLP
537
+
538
+ Distributed under the MIT License.