oai_talia 0.0.14 → 0.0.15

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.
@@ -65,7 +65,7 @@ module OAI::Provider
65
65
  total = model.count(:id, :conditions => conditions)
66
66
  if @limit && total > @limit
67
67
  select_partial(
68
- ResumptionToken.new(options.merge({:last => 0})))
68
+ ResumptionToken.new(last_id(conditions), options.merge({:last => 0}), nil, total))
69
69
  else
70
70
  model.find(:all, :conditions => conditions)
71
71
  end
@@ -34,6 +34,12 @@ module OAI::Provider
34
34
  model.find(:first,
35
35
  :order => "#{timestamp_field} desc").send(timestamp_field)
36
36
  end
37
+
38
+ def last_id(conditions)
39
+ model.find(:first, :conditions => conditions,
40
+ :order => "#{timestamp_field} desc").id
41
+ end
42
+
37
43
  # A model class is expected to provide a method Model.sets that
38
44
  # returns all the sets the model supports. See the
39
45
  # activerecord_provider tests for an example.
@@ -46,8 +52,8 @@ module OAI::Provider
46
52
  conditions = sql_conditions(options)
47
53
  if :all == selector
48
54
  total = model.count(:id, :conditions => conditions)
49
- if @limit && total > @limit
50
- select_partial(ResumptionToken.new(options.merge({:last => 0})))
55
+ if(@limit && total > @limit)
56
+ select_partial(ResumptionToken.new(last_id(conditions), options.merge({:last => 0}), nil, total))
51
57
  else
52
58
  model.find(:all, :conditions => conditions)
53
59
  end
@@ -78,13 +84,7 @@ module OAI::Provider
78
84
  token = ResumptionToken.parse(token_string)
79
85
  total = model.count(:id, :conditions => token_conditions(token))
80
86
 
81
- if @limit < total
82
- select_partial(token)
83
- else # end of result set
84
- model.find(:all,
85
- :conditions => token_conditions(token),
86
- :limit => @limit, :order => "#{model.primary_key} asc")
87
- end
87
+ select_partial(token)
88
88
  end
89
89
 
90
90
  # select a subset of the result set, and return it with a
@@ -96,7 +96,6 @@ module OAI::Provider
96
96
  :order => "#{model.primary_key} asc")
97
97
  raise OAI::ResumptionTokenException.new unless records
98
98
  offset = records.last.send(model.primary_key.to_sym)
99
-
100
99
  PartialResult.new(records, token.next(offset))
101
100
  end
102
101
 
@@ -121,17 +120,29 @@ module OAI::Provider
121
120
  # build a sql conditions statement from an OAI options hash
122
121
  def sql_conditions(opts)
123
122
  sql = []
124
- sql << "#{timestamp_field} >= ?" << "#{timestamp_field} <= ?"
125
- sql << "set = ?" if opts[:set]
126
- esc_values = [sql.join(" AND ")]
127
- esc_values << get_time(opts[:from]).localtime << get_time(opts[:until]).localtime #-- OAI 2.0 hack - UTC fix from record_responce
128
- esc_values << opts[:set] if opts[:set]
123
+ values = []
124
+
125
+ if(opts[:set])
126
+ sql << "set = ?"
127
+ values << opts[:set]
128
+ end
129
+
130
+ if(opts[:from])
131
+ sql << "#{timestamp_field} >= ?"
132
+ values << get_time(opts[:from])
133
+ end
134
+
135
+ if(opts[:until])
136
+ sql << "#{timestamp_field} <= ?"
137
+ values << get_time(opts[:until])
138
+ end
129
139
 
130
- return esc_values
140
+ values.unshift(sql.join(' AND '))
131
141
  end
132
142
 
143
+ #-- OAI 2.0 hack - UTC fix from record_responce
133
144
  def get_time(time)
134
- time.kind_of?(Time) ? time : Time.parse(time)
145
+ (time.kind_of?(Time) ? time : Time.parse(time)).localtime
135
146
  end
136
147
 
137
148
  end
@@ -45,6 +45,11 @@ module OAI::Provider
45
45
  raise NotImplementedError.new
46
46
  end
47
47
 
48
+ # Should return the last id of this model
49
+ def last_id(conditions)
50
+ raise NotImplementedError.new
51
+ end
52
+
48
53
  def sets
49
54
  nil
50
55
  end
@@ -142,7 +142,7 @@ module OAI
142
142
  def internalize(hash = {})
143
143
  internal = {}
144
144
  hash.keys.each do |key|
145
- internal[key.to_s.gsub(/([A-Z])/, '_\1').downcase.intern] = hash[key].dup
145
+ internal[key.to_s.gsub(/([A-Z])/, '_\1').downcase.intern] = hash[key].nil? ? nil : hash[key].dup
146
146
  end
147
147
 
148
148
  # Convert date formated strings into internal time values
@@ -9,7 +9,8 @@ module OAI::Provider
9
9
  # provides several helper methods for dealing with resumption tokens.
10
10
  #
11
11
  class ResumptionToken
12
- attr_reader :prefix, :set, :from, :until, :last, :expiration, :total
12
+ attr_reader :prefix, :set, :from, :until, :last, :expiration, :last_id
13
+ attr_accessor :total
13
14
 
14
15
  # parses a token string and returns a ResumptionToken
15
16
  def self.parse(token_string)
@@ -17,6 +18,8 @@ module OAI::Provider
17
18
  options = {}
18
19
  matches = /(.+):(\d+)$/.match(token_string)
19
20
  options[:last] = matches.captures[1].to_i
21
+ last_id = nil
22
+ total = nil
20
23
 
21
24
  parts = matches.captures[0].split('.')
22
25
  options[:metadata_prefix] = parts.shift
@@ -28,9 +31,13 @@ module OAI::Provider
28
31
  options[:from] = Time.parse(part.sub(/^f\(/, '').sub(/\)$/, ''))
29
32
  when /^u/
30
33
  options[:until] = Time.parse(part.sub(/^u\(/, '').sub(/\)$/, ''))
34
+ when /^l/
35
+ last_id = part.sub(/^l\(/, '').sub(/\)$/, '')
36
+ when /^t/
37
+ total = part.sub(/^t\(/, '').sub(/\)$/, '')
31
38
  end
32
39
  end
33
- self.new(options)
40
+ self.new(last_id, options, nil, total)
34
41
  rescue => err
35
42
  raise ResumptionTokenException.new
36
43
  end
@@ -41,7 +48,7 @@ module OAI::Provider
41
48
  return token_string.split('.')[0]
42
49
  end
43
50
 
44
- def initialize(options, expiration = nil, total = nil)
51
+ def initialize(last_id, options, expiration = nil, total = nil)
45
52
  @prefix = options[:metadata_prefix]
46
53
  @set = options[:set]
47
54
  @last = options[:last]
@@ -49,6 +56,7 @@ module OAI::Provider
49
56
  @until = options[:until] if options[:until]
50
57
  @expiration = expiration if expiration
51
58
  @total = total if total
59
+ @last_id = last_id
52
60
  end
53
61
 
54
62
  # convenience method for setting the offset of the next set of results
@@ -66,7 +74,13 @@ module OAI::Provider
66
74
  # output an xml resumption token
67
75
  def to_xml
68
76
  xml = Builder::XmlMarkup.new
69
- xml.resumptionToken(encode_conditions, hash_of_attributes)
77
+ token_content = if(last_id.to_s == last.to_s)
78
+ [] # Empty token required on last page of results
79
+ else
80
+ [encode_conditions, hash_of_attributes]
81
+ end
82
+
83
+ xml.resumptionToken(*token_content)
70
84
  xml.target!
71
85
  end
72
86
 
@@ -91,6 +105,8 @@ module OAI::Provider
91
105
  encoded_token << ".s(#{set})" if set
92
106
  encoded_token << ".f(#{self.from.utc.xmlschema})" if self.from
93
107
  encoded_token << ".u(#{self.until.utc.xmlschema})" if self.until
108
+ encoded_token << ".t(#{self.total})" if(self.total)
109
+ encoded_token << ".l(#{last_id})"
94
110
  encoded_token << ":#{last}"
95
111
  end
96
112
 
@@ -8,17 +8,21 @@ class SimpleResumptionProviderTest < Test::Unit::TestCase
8
8
  assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
9
9
  assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
10
10
  token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
11
+ assert_not_nil token
11
12
  doc = Document.new(@provider.list_records(:resumption_token => token))
12
13
  assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
13
14
  token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
15
+ assert_not_nil token
14
16
  assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
15
17
  doc = Document.new(@provider.list_records(:resumption_token => token))
16
18
  assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
17
19
  token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
20
+ assert_not_nil token
18
21
  assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
19
22
  doc = Document.new(@provider.list_records(:resumption_token => token))
20
- assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
21
- assert_equal 25, doc.elements["/OAI-PMH/ListRecords"].to_a.size
23
+ assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
24
+ assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
25
+ assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
22
26
  end
23
27
 
24
28
  def test_from_and_until
@@ -41,8 +45,9 @@ class SimpleResumptionProviderTest < Test::Unit::TestCase
41
45
  assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
42
46
  token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
43
47
  doc = Document.new(@provider.list_records(:resumption_token => token))
44
- assert_equal 25, doc.elements["/OAI-PMH/ListRecords"].to_a.size
45
- assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
48
+ assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
49
+ assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
50
+ assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
46
51
  end
47
52
 
48
53
  def setup
@@ -64,12 +64,9 @@ class TestModel < OAI::Provider::Model
64
64
  raise OAI::ResumptionTokenException.new unless @limit
65
65
  begin
66
66
  token = ResumptionToken.parse(opts[:resumption_token])
67
+ token.total = @groups.size
67
68
 
68
- if token.last < @groups.size - 1
69
- PartialResult.new(@groups[token.last], token.next(token.last + 1))
70
- else
71
- @groups[token.last]
72
- end
69
+ PartialResult.new(@groups[token.last], token.next(token.last + 1))
73
70
  rescue
74
71
  raise OAI::ResumptionTokenException.new
75
72
  end
@@ -88,7 +85,7 @@ class TestModel < OAI::Provider::Model
88
85
  if @limit && records.size > @limit
89
86
  @groups = generate_chunks(records, @limit)
90
87
  return PartialResult.new(@groups[0],
91
- ResumptionToken.new(opts.merge({:last => 1})))
88
+ ResumptionToken.new(@groups.size, opts.merge({:last => 1}), nil, records.size))
92
89
  end
93
90
  return records
94
91
  end
@@ -34,10 +34,11 @@ class ResumptionTokenFunctionalTest < Test::Unit::TestCase
34
34
  assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
35
35
  assert_equal 101, doc.elements["/OAI-PMH/ListRecords"].to_a.size
36
36
  token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
37
-
37
+
38
38
  doc = Document.new(@provider.list_records(:resumption_token => token))
39
- assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
40
- assert_equal 100, doc.elements["/OAI-PMH/ListRecords"].to_a.size
39
+ assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
40
+ assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
41
+ assert_equal 101, doc.elements["/OAI-PMH/ListRecords"].to_a.size
41
42
  end
42
43
 
43
44
  end
@@ -5,17 +5,24 @@ class ResumptionTokenTest < Test::Unit::TestCase
5
5
  include OAI::Provider
6
6
 
7
7
  def setup
8
- @token = ResumptionToken.new(
8
+ @token = ResumptionToken.new(2, {
9
9
  :from => Time.utc(2005,"jan",1,17,0,0),
10
10
  :until => Time.utc(2005,"jan",31,17,0,0),
11
11
  :set => "A",
12
12
  :metadata_prefix => "oai_dc",
13
- :last => 1
13
+ :last => 1 }
14
+ )
15
+ @last_token = ResumptionToken.new(1, {
16
+ :from => Time.utc(2005,"jan",1,17,0,0),
17
+ :until => Time.utc(2005,"jan",31,17,0,0),
18
+ :set => "A",
19
+ :metadata_prefix => "oai_dc",
20
+ :last => 1 }
14
21
  )
15
22
  end
16
23
 
17
24
  def test_resumption_token_options_encoding
18
- assert_equal "oai_dc.s(A).f(2005-01-01T17:00:00Z).u(2005-01-31T17:00:00Z)",
25
+ assert_equal "oai_dc.s(A).f(2005-01-01T17:00:00Z).u(2005-01-31T17:00:00Z).l(2)",
19
26
  @token.to_s
20
27
  end
21
28
 
@@ -33,7 +40,7 @@ class ResumptionTokenTest < Test::Unit::TestCase
33
40
 
34
41
  def test_resumption_token_parsing
35
42
  new_token = ResumptionToken.parse(
36
- "oai_dc.s(A).f(2005-01-01T17:00:00Z).u(2005-01-31T17:00:00Z):1"
43
+ "oai_dc.s(A).f(2005-01-01T17:00:00Z).u(2005-01-31T17:00:00Z).l(2):1"
37
44
  )
38
45
  assert_equal @token, new_token
39
46
  end
@@ -43,4 +50,10 @@ class ResumptionTokenTest < Test::Unit::TestCase
43
50
  assert_equal "#{@token.to_s}:#{@token.last}", doc.elements['/resumptionToken'].text
44
51
  end
45
52
 
53
+ def test_last_resumption_token_to_xml
54
+ doc = REXML::Document.new(@last_token.to_xml)
55
+ assert_not_nil doc.elements['/resumptionToken']
56
+ assert_nil doc.elements['/resumptionToken'].text
57
+ end
58
+
46
59
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oai_talia
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.14
4
+ version: 0.0.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ed Summers