blacklight_oai_provider 0.0.1pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +73 -0
- data/Rakefile +4 -0
- data/VERSION +1 -0
- data/blacklight_oai_provider.gemspec +24 -0
- data/config/routes.rb +5 -0
- data/lib/blacklight_oai_provider/README.rdoc +0 -0
- data/lib/blacklight_oai_provider/controller_extension.rb +29 -0
- data/lib/blacklight_oai_provider/engine.rb +17 -0
- data/lib/blacklight_oai_provider/route_sets.rb +13 -0
- data/lib/blacklight_oai_provider/solr_document_extension.rb +10 -0
- data/lib/blacklight_oai_provider/solr_document_provider.rb +19 -0
- data/lib/blacklight_oai_provider/solr_document_wrapper.rb +58 -0
- data/lib/blacklight_oai_provider/version.rb +10 -0
- data/lib/blacklight_oai_provider.rb +33 -0
- data/lib/generators/blacklight_oai_provider/blacklight_oai_provider_generator.rb +27 -0
- metadata +96 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 [name of plugin creator]
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
BlacklightOaiProvider: OAI-PMH service endpoint for Blacklight applications
|
2
|
+
|
3
|
+
= Description
|
4
|
+
|
5
|
+
The BlacklightOaiProvider plugin provides an Open Archives Initiative Protocolo for Metadata Harvesting (OAI-PMH) <http://www.openarchives.org/pmh/> data provider endpoint, using the ruby-oai gem, that let serice providers harvest that metadata.
|
6
|
+
|
7
|
+
= Requirements
|
8
|
+
|
9
|
+
A Rails app using Blacklight 3.x.
|
10
|
+
|
11
|
+
OAI-PMH requires a timestamp field for all records, so your Solr index should include an appropriate field. By default, the name of this field is simply 'timestamp'.
|
12
|
+
|
13
|
+
= Installation
|
14
|
+
|
15
|
+
Add
|
16
|
+
|
17
|
+
gem "blacklight_oai_provider"
|
18
|
+
|
19
|
+
to your Gemfile and run "bundle install".
|
20
|
+
|
21
|
+
Then run "rails generate blacklight_oai_provider" to install the appropriate extensions into your CatalogController and SolrDocument classes. In you want to do customize the way this installs, instead you may:
|
22
|
+
|
23
|
+
- add this to your Solr Document model:
|
24
|
+
|
25
|
+
use_extension(BlacklightOaiProvider::SolrDocumentExtension)
|
26
|
+
|
27
|
+
- add this to your Controler:
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
= Configuration
|
32
|
+
|
33
|
+
While the plugin provides some sensible (albeit generic) defaults out of the box, you probably will want to customize the OAI provider configuration. You can provide OAI-PMH provider parameters by placing the following in your blacklight configuration (in ./config/initializers/blacklight_config.rb), e.g.:
|
34
|
+
|
35
|
+
config[:oai] = {
|
36
|
+
:provider => {
|
37
|
+
:repository_name => 'Test',
|
38
|
+
:repository_url => 'http://localhost',
|
39
|
+
:record_prefix => '',
|
40
|
+
:admin_email => 'root@localhost'
|
41
|
+
},
|
42
|
+
:document => {
|
43
|
+
:timestamp => 'timestamp',
|
44
|
+
:limit => 25
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
The "provider" configuration is documented as part of the ruby-oai gem at http://oai.rubyforge.org/
|
49
|
+
|
50
|
+
|
51
|
+
== Injection
|
52
|
+
|
53
|
+
This plugin assumes it is in a Blacklight Rails app, uses Blacklight methods, Rails methods, and standard ruby module includes to inject it's behaviors into the app.
|
54
|
+
|
55
|
+
You can turn off this injection if you like, although it will make the plugin less (or non-) functional unless you manually do similar injection. See lib/blacklight_oai_provider.rb#inject! to see exactly what's going on.
|
56
|
+
|
57
|
+
In any initializer, you can set:
|
58
|
+
|
59
|
+
BlacklightOaiProvider.omit_inject = true
|
60
|
+
|
61
|
+
to turn off all injection. The plugin will be completely non-functional if you do this, of course. But perhaps you could try to re-use some of it's classes in a non-Blacklight, highly hacked Blacklight, or even non-Rails application this way.
|
62
|
+
|
63
|
+
You can also turn off injection of individual components, which could be more useful:
|
64
|
+
|
65
|
+
BlacklightOaiProvider.omit_inject = {
|
66
|
+
:routes => false,
|
67
|
+
}
|
68
|
+
|
69
|
+
= Tests
|
70
|
+
|
71
|
+
There are none. This is bad I know, sorry. You can test OAI-PMH conformance against http://www.openarchives.org/data/registerasprovider.html#Protocol_Conformance_Testing or browse the data at http://re.cs.uct.ac.za/
|
72
|
+
|
73
|
+
|
data/Rakefile
ADDED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1pre1
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require File.join(File.dirname(__FILE__), "lib/blacklight_oai_provider/version")
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "blacklight_oai_provider"
|
6
|
+
s.version = BlacklightOaiProvider::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Chris Beer"]
|
9
|
+
s.email = ["chris_beer@wgbh.org"]
|
10
|
+
s.homepage = "http://projectblacklight.org/"
|
11
|
+
s.summary = "Blacklight Oai Provider plugin"
|
12
|
+
|
13
|
+
s.rubyforge_project = "blacklight"
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
|
21
|
+
s.add_dependency "rails", "~> 3.0"
|
22
|
+
s.add_dependency "blacklight"
|
23
|
+
s.add_dependency "oai"
|
24
|
+
end
|
data/config/routes.rb
ADDED
File without changes
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Meant to be applied on top of a controller that implements
|
2
|
+
# Blacklight::SolrHelper. Will inject range limiting behaviors
|
3
|
+
# to solr parameters creation.
|
4
|
+
module BlacklightOaiProvider::ControllerExtension
|
5
|
+
def self.included(some_class)
|
6
|
+
some_class.helper_method :oai_config
|
7
|
+
end
|
8
|
+
|
9
|
+
# Action method of our own!
|
10
|
+
# Delivers a _partial_ that's a display of a single fields range facets.
|
11
|
+
# Used when we need a second Solr query to get range facets, after the
|
12
|
+
# first found min/max from result set.
|
13
|
+
def oai
|
14
|
+
options = params.delete_if { |k,v| %w{controller action}.include?(k) }
|
15
|
+
render :text => oai_provider.process_request(options), :content_type => 'text/xml'
|
16
|
+
end
|
17
|
+
|
18
|
+
# Uses Blacklight.config, needs to be modified when
|
19
|
+
# that changes to be controller-based. This is the only method
|
20
|
+
# in this plugin that accesses Blacklight.config, single point
|
21
|
+
# of contact.
|
22
|
+
def oai_config
|
23
|
+
Blacklight.config[:oai] || {}
|
24
|
+
end
|
25
|
+
|
26
|
+
def oai_provider
|
27
|
+
@oai_provider ||= BlacklightOaiProvider::SolrDocumentProvider.new(self, oai_config)
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'blacklight'
|
2
|
+
require 'blacklight_range_limit'
|
3
|
+
require 'rails'
|
4
|
+
|
5
|
+
module BlacklightOaiProvider
|
6
|
+
class Engine < Rails::Engine
|
7
|
+
|
8
|
+
# Do these things in a to_prepare block, to try and make them work
|
9
|
+
# in development mode with class-reloading. The trick is we can't
|
10
|
+
# be sure if the controllers we're modifying are being reloaded in
|
11
|
+
# dev mode, if they are in the BL plugin and haven't been copied to
|
12
|
+
# local, they won't be. But we do our best.
|
13
|
+
config.to_prepare do
|
14
|
+
BlacklightOaiProvider.inject!
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# Meant to be applied on top of SolrDocument to implement
|
2
|
+
# methods required by the ruby-oai provider
|
3
|
+
module BlacklightOaiProvider::SolrDocumentExtension
|
4
|
+
def timestamp
|
5
|
+
Time.parse get('timestamp')
|
6
|
+
end
|
7
|
+
def to_oai_dc
|
8
|
+
export_as('oai_dc_xml')
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module BlacklightOaiProvider
|
2
|
+
class SolrDocumentProvider < ::OAI::Provider::Base
|
3
|
+
attr_accessor :options
|
4
|
+
def initialize controller, options = {}
|
5
|
+
|
6
|
+
options[:provider] ||= {}
|
7
|
+
options[:document] ||= {}
|
8
|
+
|
9
|
+
self.class.model = SolrDocumentWrapper.new(controller, options[:document])
|
10
|
+
|
11
|
+
options[:repository_name] ||= controller.view_context.send(:application_name)
|
12
|
+
options[:repository_url] ||= controller.view_context.send(:oai_provider_url)
|
13
|
+
|
14
|
+
options[:provider].each do |k,v|
|
15
|
+
self.class.send k, v
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module BlacklightOaiProvider
|
2
|
+
class SolrDocumentWrapper < ::OAI::Provider::Model
|
3
|
+
attr_reader :model, :timestamp_field
|
4
|
+
attr_accessor :options, :extra_controller_params
|
5
|
+
def initialize(controller, options = {})
|
6
|
+
@controller = controller
|
7
|
+
|
8
|
+
defaults = { :timestamp => 'timestamp', :limit => 15}
|
9
|
+
@options = defaults.merge options
|
10
|
+
|
11
|
+
@timestamp_field = @options[:timestamp]
|
12
|
+
@limit = @options[:limit]
|
13
|
+
@extra_controller_params = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def sets
|
17
|
+
end
|
18
|
+
|
19
|
+
def earliest
|
20
|
+
Time.parse @controller.get_search_results({:sort => @timestamp_field +' asc', :rows => 1}, extra_controller_params).last.first.get(@timestamp_field)
|
21
|
+
end
|
22
|
+
|
23
|
+
def latest
|
24
|
+
Time.parse @controller.get_search_results({:sort => @timestamp_field +' desc', :rows => 1}, extra_controller_params).last.first.get(@timestamp_field)
|
25
|
+
end
|
26
|
+
|
27
|
+
def find(selector, options={})
|
28
|
+
return next_set(options[:resumption_token]) if options[:resumption_token]
|
29
|
+
|
30
|
+
if :all == selector
|
31
|
+
response, records = @controller.get_search_results({:sort => @timestamp_field + ' asc', :per_page => @limit}, extra_controller_params)
|
32
|
+
|
33
|
+
if @limit && response.total >= @limit
|
34
|
+
return select_partial(OAI::Provider::ResumptionToken.new(options.merge({:last => 0})))
|
35
|
+
end
|
36
|
+
else
|
37
|
+
records = @controller.get_search_results({:phrase_filters => {:id => selector.split('/', 2).last}}, extra_controller_params).last.first
|
38
|
+
end
|
39
|
+
records
|
40
|
+
end
|
41
|
+
|
42
|
+
def select_partial token
|
43
|
+
records = @controller.get_search_results({:sort => @timestamp_field + ' asc', :per_page => @limit, :page => token.last}, extra_controller_params).last
|
44
|
+
|
45
|
+
raise ::OAI::ResumptionTokenException.new unless records
|
46
|
+
|
47
|
+
OAI::Provider::PartialResult.new(records, token.next(token.last+1))
|
48
|
+
end
|
49
|
+
|
50
|
+
def next_set(token_string)
|
51
|
+
raise ::OAI::ResumptionTokenException.new unless @limit
|
52
|
+
|
53
|
+
token = OAI::Provider::ResumptionToken.parse(token_string)
|
54
|
+
select_partial(token)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# BlacklightOaiProvider
|
2
|
+
|
3
|
+
module BlacklightOaiProvider
|
4
|
+
|
5
|
+
autoload :ControllerExtension, 'blacklight_oai_provider/controller_extension'
|
6
|
+
autoload :SolrDocumentExtension, 'blacklight_oai_provider/solr_document_extension'
|
7
|
+
autoload :SolrDocumentProvider, 'blacklight_oai_provider/solr_document_provider'
|
8
|
+
autoload :SolrDocumentWrapper, 'blacklight_oai_provider/solr_document_wrapper'
|
9
|
+
autoload :RouteSets, 'blacklight_oai_provider/route_sets'
|
10
|
+
|
11
|
+
require 'oai'
|
12
|
+
require 'blacklight_oai_provider/version'
|
13
|
+
require 'blacklight_oai_provider/engine'
|
14
|
+
|
15
|
+
@omit_inject = {}
|
16
|
+
def self.omit_inject=(value)
|
17
|
+
value = Hash.new(true) if value == true
|
18
|
+
@omit_inject = value
|
19
|
+
end
|
20
|
+
def self.omit_inject ; @omit_inject ; end
|
21
|
+
|
22
|
+
def self.inject!
|
23
|
+
unless BlacklightRangeLimit.omit_inject[:routes]
|
24
|
+
Blacklight::Routes.send(:include, BlacklightOaiProvider::RouteSets)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Add element to array only if it's not already there
|
29
|
+
def self.safe_arr_add(array, element)
|
30
|
+
array << element unless array.include?(element)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
class BlacklightOaiProviderGenerator < Rails::Generators::Base
|
4
|
+
|
5
|
+
argument :model_name, :type => :string, :default => "SolrDocument"
|
6
|
+
argument :controller_name, :type => :string, :default => "CatalogController"
|
7
|
+
|
8
|
+
def inject_solr_document_extension
|
9
|
+
file_path = "app/models/#{model_name.underscore}.rb"
|
10
|
+
|
11
|
+
if File.exists? file_path
|
12
|
+
inject_into_file file_path, :after => "include Blacklight::Solr::Document" do
|
13
|
+
"\n SolrDocument.use_extension( BlacklightOaiProvider::SolrDocumentExtension )\n"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def inject_catalog_controller_extension
|
19
|
+
file_path = "app/controllers/#{controller_name.underscore}.rb"
|
20
|
+
if File.exists? file_path
|
21
|
+
inject_into_file file_path, :after => "include Blacklight::Catalog" do
|
22
|
+
"\n include BlacklightOaiProvider::ControllerExtension\n"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: blacklight_oai_provider
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1pre1
|
5
|
+
prerelease: 5
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Chris Beer
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-07-22 00:00:00.000000000 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rails
|
17
|
+
requirement: &2153081380 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '3.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *2153081380
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: blacklight
|
28
|
+
requirement: &2153080820 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *2153080820
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: oai
|
39
|
+
requirement: &2153080220 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
type: :runtime
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *2153080220
|
48
|
+
description:
|
49
|
+
email:
|
50
|
+
- chris_beer@wgbh.org
|
51
|
+
executables: []
|
52
|
+
extensions: []
|
53
|
+
extra_rdoc_files: []
|
54
|
+
files:
|
55
|
+
- MIT-LICENSE
|
56
|
+
- README.rdoc
|
57
|
+
- Rakefile
|
58
|
+
- VERSION
|
59
|
+
- blacklight_oai_provider.gemspec
|
60
|
+
- config/routes.rb
|
61
|
+
- lib/blacklight_oai_provider.rb
|
62
|
+
- lib/blacklight_oai_provider/README.rdoc
|
63
|
+
- lib/blacklight_oai_provider/controller_extension.rb
|
64
|
+
- lib/blacklight_oai_provider/engine.rb
|
65
|
+
- lib/blacklight_oai_provider/route_sets.rb
|
66
|
+
- lib/blacklight_oai_provider/solr_document_extension.rb
|
67
|
+
- lib/blacklight_oai_provider/solr_document_provider.rb
|
68
|
+
- lib/blacklight_oai_provider/solr_document_wrapper.rb
|
69
|
+
- lib/blacklight_oai_provider/version.rb
|
70
|
+
- lib/generators/blacklight_oai_provider/blacklight_oai_provider_generator.rb
|
71
|
+
has_rdoc: true
|
72
|
+
homepage: http://projectblacklight.org/
|
73
|
+
licenses: []
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>'
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.3.1
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project: blacklight
|
92
|
+
rubygems_version: 1.6.2
|
93
|
+
signing_key:
|
94
|
+
specification_version: 3
|
95
|
+
summary: Blacklight Oai Provider plugin
|
96
|
+
test_files: []
|