blacklight_oai_provider 0.0.1pre1

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/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
@@ -0,0 +1,4 @@
1
+ require 'rake'
2
+ require 'bundler'
3
+
4
+ Bundler::GemHelper.install_tasks
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
@@ -0,0 +1,5 @@
1
+ # We want to add a new collection action to Catalog, without over-writing
2
+ # what's already there. This SEEMS to do it.
3
+ Rails.application.routes.draw do
4
+ end
5
+
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,13 @@
1
+ module BlacklightOaiProvider
2
+ module RouteSets
3
+ protected
4
+ def catalog
5
+ add_routes do |options|
6
+ match 'catalog/oai' => 'catalog#oai', :as => 'oai_provider'
7
+ end
8
+
9
+ super
10
+ end
11
+ end
12
+ end
13
+
@@ -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,10 @@
1
+ module BlacklightOaiProvider
2
+ unless BlacklightOaiProvider.const_defined? :VERSION
3
+ def self.version
4
+ @version ||= File.read(File.join(File.dirname(__FILE__), '..', '..', 'VERSION')).chomp
5
+ end
6
+
7
+ VERSION = self.version
8
+ end
9
+ end
10
+
@@ -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: []