pho 0.7.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +4 -0
- data/Rakefile +1 -1
- data/bin/talis_store +1 -1
- data/doc/rdoc/classes/Pho/CommandLine.html +108 -108
- data/doc/rdoc/classes/Pho/DatatypeProperty.html +12 -12
- data/doc/rdoc/classes/Pho/Enrichment/StoreEnricher.html +29 -29
- data/doc/rdoc/classes/Pho/Etags.html +36 -36
- data/doc/rdoc/classes/Pho/Facet/Results.html +19 -19
- data/doc/rdoc/classes/Pho/Facet/Term.html +6 -6
- data/doc/rdoc/classes/Pho/FieldPredicateMap.html +90 -90
- data/doc/rdoc/classes/Pho/FieldWeighting.html +12 -12
- data/doc/rdoc/classes/Pho/Job.html +64 -64
- data/doc/rdoc/classes/Pho/Jobs.html +60 -60
- data/doc/rdoc/classes/Pho/OAI/Record.html +11 -11
- data/doc/rdoc/classes/Pho/OAI/Records.html +96 -18
- data/doc/rdoc/classes/Pho/QueryProfile.html +60 -60
- data/doc/rdoc/classes/Pho/RDF/Parser.html +24 -24
- data/doc/rdoc/classes/Pho/ResourceHash/Converter.html +36 -36
- data/doc/rdoc/classes/Pho/ResourceHash/SetAlgebra.html +12 -12
- data/doc/rdoc/classes/Pho/Snapshot.html +35 -35
- data/doc/rdoc/classes/Pho/Status.html +26 -26
- data/doc/rdoc/classes/Pho/Store.html +232 -222
- data/doc/rdoc/classes/Pho/StoreSparqlClient.html +14 -14
- data/doc/rdoc/classes/String.html +1 -1
- data/doc/rdoc/created.rid +1 -1
- data/doc/rdoc/files/CHANGES.html +8 -1
- data/doc/rdoc/files/lib/pho/oai_rb.html +1 -1
- data/doc/rdoc/files/lib/pho/store_rb.html +1 -1
- data/doc/rdoc/files/lib/pho_rb.html +2 -1
- data/doc/rdoc/fr_method_index.html +148 -147
- data/lib/pho.rb +1 -0
- data/lib/pho/oai.rb +53 -16
- data/lib/pho/store.rb +12 -2
- data/tests/tc_oai.rb +109 -2
- metadata +3 -3
data/lib/pho.rb
CHANGED
data/lib/pho/oai.rb
CHANGED
@@ -6,11 +6,11 @@ module Pho
|
|
6
6
|
class Record
|
7
7
|
|
8
8
|
attr_reader :identifier
|
9
|
-
attr_reader :
|
9
|
+
attr_reader :datestamp
|
10
10
|
|
11
|
-
def initialize(identifier,
|
11
|
+
def initialize(identifier, datestamp)
|
12
12
|
@identifier = identifier
|
13
|
-
@
|
13
|
+
@datestamp = datestamp
|
14
14
|
end
|
15
15
|
|
16
16
|
end
|
@@ -18,39 +18,76 @@ module Pho
|
|
18
18
|
#Collection of records
|
19
19
|
class Records
|
20
20
|
|
21
|
-
attr_reader :
|
21
|
+
attr_reader :response_date, :from, :to, :records, :resumption_token, :list_size, :cursor
|
22
22
|
|
23
|
-
def initialize(responseDate,
|
24
|
-
@
|
25
|
-
@token = token
|
23
|
+
def initialize(responseDate, from, to, records=[], token=nil, list_size=nil, cursor=nil)
|
24
|
+
@response_date = responseDate
|
26
25
|
@from = from
|
27
26
|
@to = to
|
28
27
|
@records = records
|
28
|
+
@resumption_token = token
|
29
|
+
@list_size = list_size
|
30
|
+
@cursor = cursor
|
29
31
|
end
|
30
32
|
|
31
33
|
def Records.parse(response)
|
32
34
|
doc = REXML::Document.new(response)
|
33
|
-
|
35
|
+
if doc.root.get_elements("error")[0] != nil
|
36
|
+
code = doc.root.get_elements("error")[0].attributes["code"]
|
37
|
+
if code == "noRecordsMatch"
|
38
|
+
return nil
|
39
|
+
else
|
40
|
+
raise "Unable to list records: #{code}, #{doc.root.get_elements("error")[0].text}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
records = []
|
44
|
+
responseDate = doc.root.get_elements("responseDate")[0].text
|
45
|
+
from = DateTime.parse( doc.root.get_elements("request")[0].attributes["from"] )
|
46
|
+
to = doc.root.get_elements("request")[0].attributes["until"]
|
47
|
+
to = DateTime.parse( to ) unless to == nil
|
34
48
|
REXML::XPath.each( doc.root, "//oai:header", {"oai" => "http://www.openarchives.org/OAI/2.0/"} ) do |header|
|
35
49
|
uri = header.get_elements("identifier")[0].text
|
36
50
|
datestamp = header.get_elements("datestamp")[0].text
|
37
|
-
records << Record.new(uri, datestamp)
|
51
|
+
records << Record.new(uri, DateTime.parse( datestamp ) )
|
52
|
+
end
|
53
|
+
resumption_token = doc.root.get_elements("//resumptionToken")[0]
|
54
|
+
if resumption_token != nil
|
55
|
+
token = resumption_token.text
|
56
|
+
list_size = resumption_token.attributes["completeListSize"].to_i if resumption_token.attributes["completeListSize"] != nil
|
57
|
+
cursor = resumption_token.attributes["cursor"].to_i if resumption_token.attributes["cursor"] != nil
|
38
58
|
end
|
39
|
-
|
40
|
-
return Records.new(nil, nil, nil, nil, records)
|
59
|
+
return Records.new(DateTime.parse(responseDate), from, to, records, token, list_size, cursor)
|
41
60
|
end
|
42
61
|
|
43
62
|
#List records from a store
|
44
|
-
|
45
|
-
|
46
|
-
def Records.read_from_store(store)
|
47
|
-
resp = store.list_records
|
63
|
+
def Records.read_from_store(store, from=nil, to=nil, resumption_token=nil)
|
64
|
+
resp = store.list_records(from, to, resumption_token)
|
48
65
|
if resp.status != 200
|
49
66
|
raise "Unable to list records"
|
50
67
|
end
|
51
68
|
return parse(resp.content)
|
52
69
|
end
|
53
|
-
|
70
|
+
|
71
|
+
#Fetch the next list of records from a store, using a resumption token
|
72
|
+
#
|
73
|
+
#Returns nil if there are no records to retrieve. Can be used as a simple iterator, e.g:
|
74
|
+
#
|
75
|
+
# records = store.list_records
|
76
|
+
# while records != nil
|
77
|
+
# #do something with retrieved records
|
78
|
+
# records = Records.read_next_records(store, records.resumption_token
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
#store:: the store
|
82
|
+
#records:: previously retrieved resumption_token
|
83
|
+
def Records.read_next_records(store, resumption_token)
|
84
|
+
#list is already complete
|
85
|
+
if records.resumption_token = nil
|
86
|
+
return nil
|
87
|
+
end
|
88
|
+
return Records.read_from_store(store, nil, nil, token)
|
89
|
+
end
|
90
|
+
|
54
91
|
end
|
55
92
|
|
56
93
|
end
|
data/lib/pho/store.rb
CHANGED
@@ -443,9 +443,19 @@ module Pho
|
|
443
443
|
# OAI
|
444
444
|
#############
|
445
445
|
|
446
|
-
def list_records
|
446
|
+
def list_records(from=nil, to=nil, resumption_token=nil)
|
447
447
|
u = build_uri("/services/oai-pmh")
|
448
|
-
|
448
|
+
params = {"verb" => "ListRecords", "metadataPrefix" => "oai_dc"}
|
449
|
+
if from != nil
|
450
|
+
params["from"] = from.strftime("%Y-%m-%dT%H:%M:%SZ") if from.respond_to? :strftime
|
451
|
+
params["from"] = from.to_s if !from.respond_to? :strftime
|
452
|
+
end
|
453
|
+
if to != nil
|
454
|
+
params["until"] = to.strftime("%Y-%m-%dT%H:%M:%SZ") if to.respond_to? :strftime
|
455
|
+
params["until"] = to.to_s if !to.respond_to? :strftime
|
456
|
+
end
|
457
|
+
params["resumptionToken"] = resumption_token if resumption_token != nil
|
458
|
+
response = @client.get(u, params)
|
449
459
|
return response
|
450
460
|
end
|
451
461
|
|
data/tests/tc_oai.rb
CHANGED
@@ -3,13 +3,50 @@ require 'pho'
|
|
3
3
|
require 'test/unit'
|
4
4
|
require 'mocha'
|
5
5
|
require 'rexml/document'
|
6
|
-
|
6
|
+
require 'date'
|
7
7
|
class OAITest < Test::Unit::TestCase
|
8
8
|
|
9
|
+
NO_RECORDS = <<-EOL
|
10
|
+
<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
11
|
+
xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
|
12
|
+
<responseDate>2010-04-04T14:33:00Z</responseDate>
|
13
|
+
<request from="2010-04-04T14:33:00Z" metadataPrefix="oai_dc" verb="ListRecords">http://api.talis.com/stores/ldodds-dev2/services/oai-pmh</request>
|
14
|
+
<error code="noRecordsMatch">No matching records were found</error></OAI-PMH>
|
15
|
+
EOL
|
16
|
+
|
9
17
|
LIST_RECORDS = <<-EOL
|
10
|
-
<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd"
|
18
|
+
<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
|
19
|
+
<responseDate>2010-03-19T13:02:14Z</responseDate>
|
20
|
+
<request from="2010-03-19T13:02:14Z" metadataPrefix="oai_dc" verb="ListRecords">http://api.talis.com/stores/ldodds-dev1/services/oai-pmh</request>
|
21
|
+
<ListRecords>
|
22
|
+
<record><header><identifier>http://www.example.org</identifier><datestamp>2010-03-19T12:57:06Z</datestamp></header>
|
23
|
+
<metadata><oai_dc:dc xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/">
|
24
|
+
<dc:identifier>http://www.example.org</dc:identifier></oai_dc:dc></metadata>
|
25
|
+
</record>
|
26
|
+
<record><header><identifier>http://api.talis.com/stores/ldodds-dev1/items/atom.xml</identifier><datestamp>2010-03-19T12:57:10Z</datestamp></header>
|
27
|
+
<metadata><oai_dc:dc xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/">
|
28
|
+
<dc:identifier>http://api.talis.com/stores/ldodds-dev1/items/atom.xml</dc:identifier></oai_dc:dc></metadata>
|
29
|
+
</record>
|
30
|
+
</ListRecords></OAI-PMH>
|
11
31
|
EOL
|
12
32
|
|
33
|
+
LIST_RECORDS_WITH_TOKEN = <<-EOL
|
34
|
+
<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
|
35
|
+
<responseDate>2010-03-19T13:02:14Z</responseDate>
|
36
|
+
<request from="2010-03-19T13:02:14Z" metadataPrefix="oai_dc" verb="ListRecords">http://api.talis.com/stores/ldodds-dev1/services/oai-pmh</request>
|
37
|
+
<ListRecords>
|
38
|
+
<record><header><identifier>http://www.example.org</identifier><datestamp>2010-03-19T12:57:06Z</datestamp></header>
|
39
|
+
<metadata><oai_dc:dc xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/">
|
40
|
+
<dc:identifier>http://www.example.org</dc:identifier></oai_dc:dc></metadata>
|
41
|
+
</record>
|
42
|
+
<record><header><identifier>http://api.talis.com/stores/ldodds-dev1/items/atom.xml</identifier><datestamp>2010-03-19T12:57:10Z</datestamp></header>
|
43
|
+
<metadata><oai_dc:dc xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/">
|
44
|
+
<dc:identifier>http://api.talis.com/stores/ldodds-dev1/items/atom.xml</dc:identifier></oai_dc:dc></metadata>
|
45
|
+
</record>
|
46
|
+
<resumptionToken completeListSize="6151294" cursor="0">b2FpX2RjfDEwMHwxOTcwLTAxLTAxVDAwOjAwOjAwWnwyMDEwLTA0LTA0VDEzOjU0OjMyWg==</resumptionToken>
|
47
|
+
</ListRecords></OAI-PMH>
|
48
|
+
EOL
|
49
|
+
|
13
50
|
def test_request
|
14
51
|
mc = mock()
|
15
52
|
mc.expects(:set_auth)
|
@@ -21,11 +58,81 @@ EOL
|
|
21
58
|
assert_equal(LIST_RECORDS, response.content)
|
22
59
|
end
|
23
60
|
|
61
|
+
def test_parse_no_records
|
62
|
+
results = Pho::OAI::Records.parse(NO_RECORDS)
|
63
|
+
assert_nil(results)
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_request_with_from
|
67
|
+
mc = mock()
|
68
|
+
mc.expects(:set_auth)
|
69
|
+
mc.expects(:get).with("http://api.talis.com/stores/testing/services/oai-pmh", {"verb" => "ListRecords", "metadataPrefix" => "oai_dc", "from" => "2010-03-19T13:02:14Z"} ).returns(
|
70
|
+
HTTP::Message.new_response(LIST_RECORDS))
|
71
|
+
|
72
|
+
store = Pho::Store.new("http://api.talis.com/stores/testing", "user", "pass", mc)
|
73
|
+
response = store.list_records("2010-03-19T13:02:14Z")
|
74
|
+
assert_equal(LIST_RECORDS, response.content)
|
75
|
+
|
76
|
+
mc = mock()
|
77
|
+
mc.expects(:set_auth)
|
78
|
+
mc.expects(:get).with("http://api.talis.com/stores/testing/services/oai-pmh", {"verb" => "ListRecords", "metadataPrefix" => "oai_dc", "from" => "2010-03-19T13:02:14Z"} ).returns(
|
79
|
+
HTTP::Message.new_response(LIST_RECORDS))
|
80
|
+
|
81
|
+
store = Pho::Store.new("http://api.talis.com/stores/testing", "user", "pass", mc)
|
82
|
+
response = store.list_records(DateTime.parse("2010-03-19T13:02:14Z"))
|
83
|
+
assert_equal(LIST_RECORDS, response.content)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_request_with_to
|
87
|
+
mc = mock()
|
88
|
+
mc.expects(:set_auth)
|
89
|
+
mc.expects(:get).with("http://api.talis.com/stores/testing/services/oai-pmh", {"verb" => "ListRecords", "metadataPrefix" => "oai_dc", "until" => "2010-03-19T13:02:14Z"} ).returns(
|
90
|
+
HTTP::Message.new_response(LIST_RECORDS))
|
91
|
+
|
92
|
+
store = Pho::Store.new("http://api.talis.com/stores/testing", "user", "pass", mc)
|
93
|
+
response = store.list_records(nil, "2010-03-19T13:02:14Z")
|
94
|
+
assert_equal(LIST_RECORDS, response.content)
|
95
|
+
|
96
|
+
mc = mock()
|
97
|
+
mc.expects(:set_auth)
|
98
|
+
mc.expects(:get).with("http://api.talis.com/stores/testing/services/oai-pmh", {"verb" => "ListRecords", "metadataPrefix" => "oai_dc", "until" => "2010-03-19T13:02:14Z"} ).returns(
|
99
|
+
HTTP::Message.new_response(LIST_RECORDS))
|
100
|
+
store = Pho::Store.new("http://api.talis.com/stores/testing", "user", "pass", mc)
|
101
|
+
response = store.list_records(nil, DateTime.parse("2010-03-19T13:02:14Z"))
|
102
|
+
assert_equal(LIST_RECORDS, response.content)
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_request_with_token
|
106
|
+
mc = mock()
|
107
|
+
mc.expects(:set_auth)
|
108
|
+
mc.expects(:get).with("http://api.talis.com/stores/testing/services/oai-pmh", {"verb" => "ListRecords", "metadataPrefix" => "oai_dc", "resumptionToken" => "abc"} ).returns(
|
109
|
+
HTTP::Message.new_response(LIST_RECORDS))
|
110
|
+
|
111
|
+
store = Pho::Store.new("http://api.talis.com/stores/testing", "user", "pass", mc)
|
112
|
+
response = store.list_records(nil, nil, "abc")
|
113
|
+
assert_equal(LIST_RECORDS, response.content)
|
114
|
+
end
|
115
|
+
|
24
116
|
def test_parse
|
25
117
|
|
26
118
|
results = Pho::OAI::Records.parse(LIST_RECORDS)
|
27
119
|
assert_not_nil(results)
|
120
|
+
assert_equal(2010, results.from.year)
|
121
|
+
assert_equal(3, results.from.month)
|
122
|
+
assert_equal(nil, results.to)
|
28
123
|
assert_equal(2, results.records.size)
|
124
|
+
assert_equal("http://www.example.org", results.records[0].identifier)
|
125
|
+
assert_equal(2010, results.records[0].datestamp.year)
|
126
|
+
assert_equal("http://api.talis.com/stores/ldodds-dev1/items/atom.xml", results.records[1].identifier)
|
127
|
+
assert_equal(2010, results.records[1].datestamp.year)
|
29
128
|
end
|
30
129
|
|
130
|
+
def test_parse_with_token
|
131
|
+
|
132
|
+
results = Pho::OAI::Records.parse(LIST_RECORDS_WITH_TOKEN)
|
133
|
+
assert_not_nil(results)
|
134
|
+
assert_equal(6151294, results.list_size)
|
135
|
+
assert_equal(0, results.cursor)
|
136
|
+
assert_equal("b2FpX2RjfDEwMHwxOTcwLTAxLTAxVDAwOjAwOjAwWnwyMDEwLTA0LTA0VDEzOjU0OjMyWg==", results.resumption_token)
|
137
|
+
end
|
31
138
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 7
|
8
|
-
-
|
9
|
-
version: 0.7.
|
8
|
+
- 2
|
9
|
+
version: 0.7.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Leigh Dodds
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
17
|
+
date: 2010-04-04 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|