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 CHANGED
@@ -206,8 +206,7 @@ module OAI
206
206
  case @parser
207
207
  when 'libxml'
208
208
  begin
209
- parser = XML::Parser.new()
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
@@ -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
@@ -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
- # # List all records
6
- # i = 1
7
- # begin
8
- # response = client.list_records
9
- # while response.entries.size > 0
10
- # response.entries.each { |entry|
11
- # puts "<b>#{i}</b> #{entry.header.identifier}<br/>"
12
- # i +=1
13
- # }
14
- # token = response.resumption_token
15
- # response = client.list_records :resumption_token => token if token
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
@@ -1,3 +1,4 @@
1
+ require 'time'
1
2
  require 'zlib'
2
3
  require 'net/smtp'
3
4
  require 'yaml'
@@ -72,7 +72,7 @@ module OAI
72
72
 
73
73
  file = Tempfile.new('oai_data')
74
74
  gz = Zlib::GzipWriter.new(file)
75
- gz << "<? xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
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
 
@@ -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
@@ -14,6 +14,7 @@ module OAI::Provider::Response
14
14
  r.record do
15
15
  header_for record
16
16
  data_for record unless deleted?(record)
17
+ about_for record unless deleted?(record)
17
18
  end
18
19
  end
19
20
  end
@@ -23,4 +24,4 @@ module OAI::Provider::Response
23
24
 
24
25
  end
25
26
 
26
-
27
+
@@ -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
 
@@ -15,6 +15,7 @@ module OAI::Provider::Response
15
15
  r.record do
16
16
  header_for rec
17
17
  data_for rec unless deleted?(rec)
18
+ about_for rec unless deleted?(rec)
18
19
  end
19
20
  end
20
21
 
@@ -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
@@ -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.1.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-06-01 00:00:00.000000000 Z
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: -1260822851612593558
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: -1260822851612593558
239
+ hash: 1810922164571931912
208
240
  requirements: []
209
241
  rubyforge_project:
210
242
  rubygems_version: 1.8.24