oai 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.
- data/lib/oai/client.rb +1 -2
- data/lib/oai/client/record.rb +2 -1
- data/lib/oai/client/response.rb +11 -16
- data/lib/oai/harvester.rb +1 -0
- data/lib/oai/harvester/harvest.rb +1 -1
- data/lib/oai/provider.rb +6 -1
- data/lib/oai/provider/model.rb +7 -1
- data/lib/oai/provider/model/activerecord_wrapper.rb +18 -2
- data/lib/oai/provider/response/get_record.rb +2 -1
- data/lib/oai/provider/response/identify.rb +12 -0
- data/lib/oai/provider/response/list_records.rb +1 -0
- data/lib/oai/provider/response/record_response.rb +15 -0
- data/test/client/tc_get_record.rb +2 -0
- data/test/provider/models.rb +9 -0
- data/test/provider/tc_provider.rb +7 -0
- data/test/provider/test_helper.rb +10 -1
- metadata +36 -4
data/lib/oai/client.rb
CHANGED
@@ -206,8 +206,7 @@ module OAI
|
|
206
206
|
case @parser
|
207
207
|
when 'libxml'
|
208
208
|
begin
|
209
|
-
parser = XML::Parser.
|
210
|
-
parser.string = xml
|
209
|
+
parser = XML::Parser.string()
|
211
210
|
return parser.parse
|
212
211
|
rescue XML::Parser::ParseError => e
|
213
212
|
raise OAI::Exception, 'response not well formed XML: '+e, caller
|
data/lib/oai/client/record.rb
CHANGED
@@ -10,11 +10,12 @@ module OAI
|
|
10
10
|
|
11
11
|
class Record
|
12
12
|
include OAI::XPath
|
13
|
-
attr_accessor :header, :metadata
|
13
|
+
attr_accessor :header, :metadata, :about
|
14
14
|
|
15
15
|
def initialize(element)
|
16
16
|
@header = OAI::Header.new xpath_first(element, './/header')
|
17
17
|
@metadata = xpath_first(element, './/metadata')
|
18
|
+
@about = xpath_first(element, './/about')
|
18
19
|
end
|
19
20
|
|
20
21
|
# a convenience method which digs into the header status attribute
|
data/lib/oai/client/response.rb
CHANGED
@@ -2,22 +2,17 @@ module OAI
|
|
2
2
|
|
3
3
|
# An OAI::Response contains entries and a resumption token. If a resumption token is present,
|
4
4
|
# then you must use it to fetch the rest of the entries for your query. For example:
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
# end
|
17
|
-
# rescue OAI::Exception => e
|
18
|
-
# puts 'No records to process'
|
19
|
-
# end
|
20
|
-
# puts "Done processing #{i} records"
|
5
|
+
# # List all records in a given set
|
6
|
+
# client = OAI::Client.new 'http://my-oai-provider.example.com/oai'
|
7
|
+
# response = client.list_records :set => 'my_set_name'
|
8
|
+
# while response.entries.count > 0
|
9
|
+
# response.entries.each { |entry|
|
10
|
+
# puts entry.header.identifier
|
11
|
+
# }
|
12
|
+
# token = response.resumption_token
|
13
|
+
# # Note: You do not need to pass the options hash again, just the verb and the resumption token
|
14
|
+
# response = client.list_records :resumption_token => token if token
|
15
|
+
# end
|
21
16
|
|
22
17
|
class Response
|
23
18
|
include OAI::XPath
|
data/lib/oai/harvester.rb
CHANGED
@@ -72,7 +72,7 @@ module OAI
|
|
72
72
|
|
73
73
|
file = Tempfile.new('oai_data')
|
74
74
|
gz = Zlib::GzipWriter.new(file)
|
75
|
-
gz << "<?
|
75
|
+
gz << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
|
76
76
|
gz << "<records>"
|
77
77
|
begin
|
78
78
|
response = client.list_records(options)
|
data/lib/oai/provider.rb
CHANGED
@@ -55,6 +55,7 @@ end
|
|
55
55
|
# repository_url 'http://localhost/provider'
|
56
56
|
# record_prefix 'oai:localhost'
|
57
57
|
# admin_email 'root@localhost'
|
58
|
+
# sample_identifier 'oai:pubmedcentral.gov:13900'
|
58
59
|
# source_model MyModel.new
|
59
60
|
# end
|
60
61
|
#
|
@@ -97,6 +98,7 @@ end
|
|
97
98
|
# record_prefix 'oai:blog'
|
98
99
|
# admin_email 'root@localhost'
|
99
100
|
# source_model OAI::Provider::ActiveRecordWrapper.new(Post)
|
101
|
+
# sample_identifier 'oai:pubmedcentral.gov:13900'
|
100
102
|
# end
|
101
103
|
#
|
102
104
|
# Create a custom controller:
|
@@ -184,7 +186,7 @@ module OAI::Provider
|
|
184
186
|
|
185
187
|
class << self
|
186
188
|
attr_reader :formats
|
187
|
-
attr_accessor :name, :url, :prefix, :email, :delete_support, :granularity, :model
|
189
|
+
attr_accessor :name, :url, :prefix, :email, :delete_support, :granularity, :model, :identifier, :description
|
188
190
|
|
189
191
|
def register_format(format)
|
190
192
|
@formats ||= {}
|
@@ -218,6 +220,8 @@ module OAI::Provider
|
|
218
220
|
alias_method :deletion_support, :delete_support=
|
219
221
|
alias_method :update_granularity, :granularity=
|
220
222
|
alias_method :source_model, :model=
|
223
|
+
alias_method :sample_id, :identifier=
|
224
|
+
alias_method :extra_description, :description=
|
221
225
|
|
222
226
|
end
|
223
227
|
|
@@ -228,6 +232,7 @@ module OAI::Provider
|
|
228
232
|
Base.admin_email 'nobody@localhost'
|
229
233
|
Base.deletion_support OAI::Const::Delete::TRANSIENT
|
230
234
|
Base.update_granularity OAI::Const::Granularity::HIGH
|
235
|
+
Base.sample_id '13900'
|
231
236
|
|
232
237
|
Base.register_format(OAI::Provider::Metadata::DublinCore.instance)
|
233
238
|
|
data/lib/oai/provider/model.rb
CHANGED
@@ -17,6 +17,8 @@ module OAI::Provider
|
|
17
17
|
# available_formats - if overridden, individual records should return an
|
18
18
|
# array of prefixes for all formats in which that record is available,
|
19
19
|
# if other than ["oai_dc"]
|
20
|
+
# about - if overridden, should return a String or Array of XML Strings to
|
21
|
+
# insert into the OAI Record <about> chunks.
|
20
22
|
#
|
21
23
|
# == Resumption Tokens
|
22
24
|
#
|
@@ -68,7 +70,11 @@ module OAI::Provider
|
|
68
70
|
def deleted?
|
69
71
|
false
|
70
72
|
end
|
71
|
-
|
73
|
+
|
74
|
+
# can return a String or Array of XML Strings add as OAI Record <about> chunks.
|
75
|
+
def about record
|
76
|
+
nil
|
77
|
+
end
|
72
78
|
end
|
73
79
|
|
74
80
|
end
|
@@ -24,7 +24,7 @@ module OAI::Provider
|
|
24
24
|
)
|
25
25
|
end
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
def earliest
|
29
29
|
model.find(:first,
|
30
30
|
:order => "#{timestamp_field} asc").send(timestamp_field)
|
@@ -65,6 +65,22 @@ module OAI::Provider
|
|
65
65
|
false
|
66
66
|
end
|
67
67
|
|
68
|
+
def respond_to?(m, *args)
|
69
|
+
if m =~ /^map_/
|
70
|
+
model.respond_to?(m, *args)
|
71
|
+
else
|
72
|
+
super
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def method_missing(m, *args, &block)
|
77
|
+
if m =~ /^map_/
|
78
|
+
model.send(m, *args, &block)
|
79
|
+
else
|
80
|
+
super
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
68
84
|
protected
|
69
85
|
|
70
86
|
# Request the next set in this sequence.
|
@@ -120,7 +136,7 @@ module OAI::Provider
|
|
120
136
|
sql << "#{timestamp_field} >= ?" << "#{timestamp_field} <= ?"
|
121
137
|
sql << "set = ?" if opts[:set]
|
122
138
|
esc_values = [sql.join(" AND ")]
|
123
|
-
esc_values << Time.parse(opts[:from]).localtime << Time.parse(opts[:until]).localtime #-- OAI 2.0 hack - UTC fix from record_responce
|
139
|
+
esc_values << Time.parse(opts[:from].to_s).localtime << Time.parse(opts[:until].to_s).localtime.to_s #-- OAI 2.0 hack - UTC fix from record_responce
|
124
140
|
esc_values << opts[:set] if opts[:set]
|
125
141
|
|
126
142
|
return esc_values
|
@@ -16,7 +16,19 @@ module OAI::Provider::Response
|
|
16
16
|
r.earliestDatestamp Time.parse(provider.model.earliest.to_s).utc.xmlschema
|
17
17
|
r.deletedRecord provider.delete_support.to_s
|
18
18
|
r.granularity provider.granularity
|
19
|
+
r.description do
|
20
|
+
r.tag! 'oai-identifier', 'xmlns' => 'http://www.openarchives.org/OAI/2.0/oai-identifier', 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation' => 'http://www.openarchives.org/OAI/2.0/oai-identifier http://www.openarchives.org/OAI/2.0/oai-identifier.xsd' do
|
21
|
+
r.scheme 'oai'
|
22
|
+
r.repositoryIdentifier provider.prefix.gsub(/oai:/, '')
|
23
|
+
r.delimiter ':'
|
24
|
+
r.sampleIdentifier "#{provider.prefix}:#{provider.identifier}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
if provider.description
|
28
|
+
r.target! << provider.description
|
29
|
+
end
|
19
30
|
end
|
31
|
+
|
20
32
|
end
|
21
33
|
end
|
22
34
|
|
@@ -26,6 +26,21 @@ module OAI::Provider::Response
|
|
26
26
|
@builder.target! << provider.format(requested_format).encode(provider.model, record)
|
27
27
|
end
|
28
28
|
end
|
29
|
+
|
30
|
+
# about - core routine for delivering about records
|
31
|
+
#
|
32
|
+
def about_for(record)
|
33
|
+
return unless provider.model.respond_to? :about
|
34
|
+
|
35
|
+
about = provider.model.about(record)
|
36
|
+
return if about.nil?
|
37
|
+
|
38
|
+
Array(about).each do |a|
|
39
|
+
@builder.about do
|
40
|
+
@builder.target! << a
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
29
44
|
|
30
45
|
private
|
31
46
|
|
@@ -9,6 +9,7 @@ class GetRecordTest < Test::Unit::TestCase
|
|
9
9
|
assert_kind_of OAI::Record, response.record
|
10
10
|
assert_kind_of REXML::Element, response.record.metadata
|
11
11
|
assert_kind_of OAI::Header, response.record.header
|
12
|
+
assert_kind_of REXML::Element, response.record.about
|
12
13
|
|
13
14
|
# minimal check that the header is working
|
14
15
|
assert_equal 'oai:test/3',
|
@@ -16,6 +17,7 @@ class GetRecordTest < Test::Unit::TestCase
|
|
16
17
|
|
17
18
|
# minimal check that the metadata is working
|
18
19
|
#assert 'en', response.record.metadata.elements['.//dc:language'].text
|
20
|
+
assert_equal 'Ruby OAI test data', response.record.about.elements['.//dc:publisher'].text
|
19
21
|
end
|
20
22
|
|
21
23
|
def test_missing_identifier
|
data/test/provider/models.rb
CHANGED
@@ -231,5 +231,14 @@ class ComplexModel < TestModel
|
|
231
231
|
generate_records(250, Time.parse("December 25 2005"), [set_four, set_three_four])
|
232
232
|
end
|
233
233
|
|
234
|
+
def about record
|
235
|
+
<<-eos
|
236
|
+
<oai_dc:dc
|
237
|
+
xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/"
|
238
|
+
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
239
|
+
<dc:publisher>Ruby OAI test data</dc:publisher>
|
240
|
+
</oai_dc:dc>
|
241
|
+
eos
|
242
|
+
end
|
234
243
|
end
|
235
244
|
|
@@ -5,6 +5,13 @@ class OaiTest < Test::Unit::TestCase
|
|
5
5
|
def setup
|
6
6
|
@mapped_provider = MappedProvider.new
|
7
7
|
@big_provider = BigProvider.new
|
8
|
+
@described_provider = DescribedProvider.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_additional_description
|
12
|
+
doc = REXML::Document.new(@described_provider.identify)
|
13
|
+
assert_equal "oai:test:13900", doc.elements['OAI-PMH/Identify/description/oai-identifier/sampleIdentifier'].text
|
14
|
+
assert_not_nil doc.elements['OAI-PMH/Identify/my_custom_xml']
|
8
15
|
end
|
9
16
|
|
10
17
|
def test_list_identifiers_for_correct_xml
|
@@ -33,4 +33,13 @@ class ComplexProvider < Provider::Base
|
|
33
33
|
repository_url 'http://localhost'
|
34
34
|
record_prefix 'oai:test'
|
35
35
|
source_model ComplexModel.new(100)
|
36
|
-
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class DescribedProvider < Provider::Base
|
39
|
+
repository_name 'Described PRovider'
|
40
|
+
repository_url 'http://localhost'
|
41
|
+
record_prefix 'oai:test'
|
42
|
+
source_model SimpleModel.new
|
43
|
+
sample_id '13900'
|
44
|
+
extra_description "<my_custom_xml />"
|
45
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oai
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire: oai
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-07-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: builder
|
@@ -75,6 +75,38 @@ dependencies:
|
|
75
75
|
- - ! '>='
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: activerecord
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: sqlite3
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
78
110
|
- !ruby/object:Gem::Dependency
|
79
111
|
name: rdoc
|
80
112
|
requirement: !ruby/object:Gem::Requirement
|
@@ -195,7 +227,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
195
227
|
version: '0'
|
196
228
|
segments:
|
197
229
|
- 0
|
198
|
-
hash:
|
230
|
+
hash: 1810922164571931912
|
199
231
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
200
232
|
none: false
|
201
233
|
requirements:
|
@@ -204,7 +236,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
204
236
|
version: '0'
|
205
237
|
segments:
|
206
238
|
- 0
|
207
|
-
hash:
|
239
|
+
hash: 1810922164571931912
|
208
240
|
requirements: []
|
209
241
|
rubyforge_project:
|
210
242
|
rubygems_version: 1.8.24
|