Class: OAI::Provider::ResumptionToken

Inherits:
Object
  • Object
show all
Defined in:
lib/oai/provider/resumption_token.rb

Overview

OAI::Provider::ResumptionToken

The ResumptionToken class forms the basis of paging query results. It provides several helper methods for dealing with resumption tokens.

OAI-PMH spec does not specify anything about resumptionToken format, they can be purely opaque tokens.

Our implementation however encodes everything needed to construct the next page inside the resumption token.

The ‘last’ component: offset or ID/pk to resume from

The #last component is an offset or ID to resume from. In the case of it being an ID to resume from, this assumes that ID’s are sortable and results are returned in ID order, so that the ‘last’ ID can be used as the place to resume from.

Originally it was assumed that #last was always an integer, but since existing implementations (like ActiveRecordWrapper) used it as an ID, and identifiers and primary keys are not always integers (can be UUID etc), we have expanded to allow any string value.

However, for backwards compatibility #last always returns an integer (sometimes 0 if actual last component is not an integer), and #last_str returns the full string version. Trying to change #last itself to be string broke a lot of existing code in this gem in mysterious ways.

Also beware that in some cases the value 0/“0” seems to be a special value used to signify some special case. A lot of “code archeology” going on here after significant period of no maintenance to this gem.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options, expiration = nil, total = nil) ⇒ ResumptionToken

Returns a new instance of ResumptionToken.



69
70
71
72
73
74
75
76
77
# File 'lib/oai/provider/resumption_token.rb', line 69

def initialize(options, expiration = nil, total = nil)
  @prefix = options[:metadata_prefix]
  @set = options[:set]
  self.last = options[:last]
  @from = options[:from] if options[:from]
  @until = options[:until] if options[:until]
  @expiration = expiration if expiration
  @total = total if total
end

Instance Attribute Details

#expirationObject (readonly)

Returns the value of attribute expiration.



37
38
39
# File 'lib/oai/provider/resumption_token.rb', line 37

def expiration
  @expiration
end

#fromObject (readonly)

Returns the value of attribute from.



37
38
39
# File 'lib/oai/provider/resumption_token.rb', line 37

def from
  @from
end

#lastObject

Returns the value of attribute last.



37
38
39
# File 'lib/oai/provider/resumption_token.rb', line 37

def last
  @last
end

#last_strObject (readonly)

Returns the value of attribute last_str.



37
38
39
# File 'lib/oai/provider/resumption_token.rb', line 37

def last_str
  @last_str
end

#prefixObject (readonly)

Returns the value of attribute prefix.



37
38
39
# File 'lib/oai/provider/resumption_token.rb', line 37

def prefix
  @prefix
end

#setObject (readonly)

Returns the value of attribute set.



37
38
39
# File 'lib/oai/provider/resumption_token.rb', line 37

def set
  @set
end

#totalObject (readonly)

Returns the value of attribute total.



37
38
39
# File 'lib/oai/provider/resumption_token.rb', line 37

def total
  @total
end

#untilObject (readonly)

Returns the value of attribute until.



37
38
39
# File 'lib/oai/provider/resumption_token.rb', line 37

def until
  @until
end

Class Method Details

.extract_format(token_string) ⇒ Object

extracts the metadata prefix from a token string



65
66
67
# File 'lib/oai/provider/resumption_token.rb', line 65

def self.extract_format(token_string)
  return token_string.split('.')[0]
end

.parse(token_string) ⇒ Object

parses a token string and returns a ResumptionToken



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/oai/provider/resumption_token.rb', line 40

def self.parse(token_string)
  begin
    options = {}
    matches = /(.+):([^ :]+)$/.match(token_string)
    options[:last] = matches.captures[1]

    parts = matches.captures[0].split('.')
    options[:metadata_prefix] = parts.shift
    parts.each do |part|
      case part
      when /^s/
        options[:set] = part.sub(/^s\(/, '').sub(/\)$/, '')
      when /^f/
        options[:from] = Time.parse(part.sub(/^f\(/, '').sub(/\)$/, '')).localtime
      when /^u/
        options[:until] = Time.parse(part.sub(/^u\(/, '').sub(/\)$/, '')).localtime
      end
    end
    self.new(options)
  rescue => err
    raise OAI::ResumptionTokenException.new
  end
end

Instance Method Details

#==(other) ⇒ Object



85
86
87
88
89
# File 'lib/oai/provider/resumption_token.rb', line 85

def ==(other)
  prefix == other.prefix and set == other.set and from == other.from and
    self.until == other.until and last == other.last and
    expiration == other.expiration and total == other.total
end

#next(last) ⇒ Object

convenience method for setting the offset of the next set of results



80
81
82
83
# File 'lib/oai/provider/resumption_token.rb', line 80

def next(last)
  self.last = last
  self
end

#to_conditions_hashObject

return a hash containing just the model selection parameters



99
100
101
102
103
104
105
# File 'lib/oai/provider/resumption_token.rb', line 99

def to_conditions_hash
  conditions = {:metadata_prefix => self.prefix }
  conditions[:set] = self.set if self.set
  conditions[:from] = self.from if self.from
  conditions[:until] = self.until if self.until
  conditions
end

#to_sObject

return the a string representation of the token minus the offset/ID

Q: Why does it eliminate the offset/id “last” on the end? Doesn’t fully

represent state without it, which is confusing. Not sure, but
other code seems to rely on it, tests break if not.


112
113
114
# File 'lib/oai/provider/resumption_token.rb', line 112

def to_s
  encode_conditions.gsub(/:\w+?$/, '')
end

#to_xmlObject

output an xml resumption token



92
93
94
95
96
# File 'lib/oai/provider/resumption_token.rb', line 92

def to_xml
  xml = Builder::XmlMarkup.new
  xml.resumptionToken(encode_conditions, hash_of_attributes)
  xml.target!
end