blacklight_internet_archive 0.1.2
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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +25 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/Rakefile +6 -0
- data/blacklight_internet_archive.gemspec +30 -0
- data/lib/blacklight_internet_archive.rb +23 -0
- data/lib/blacklight_internet_archive/blacklight_response.rb +6 -0
- data/lib/blacklight_internet_archive/client.rb +92 -0
- data/lib/blacklight_internet_archive/entity_processor.rb +135 -0
- data/lib/blacklight_internet_archive/hash_with_response.rb +9 -0
- data/lib/blacklight_internet_archive/internet_archive.rb +11 -0
- data/lib/blacklight_internet_archive/repository.rb +32 -0
- data/lib/blacklight_internet_archive/request.rb +44 -0
- data/lib/blacklight_internet_archive/response.rb +84 -0
- data/lib/blacklight_internet_archive/response_adapter.rb +59 -0
- data/lib/blacklight_internet_archive/version.rb +3 -0
- metadata +154 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6a5310c53053a495a98c09dab7cf64d56a1c8e48
|
4
|
+
data.tar.gz: 16a8bd98a70c27fb9c0ec65777c40487c521b1df
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 11759e993dfa3dccceb7a20272313c1550a82f798b5636271fa872fabe9397ae4a45f28504b243ce621be395b6814b008829a131dd3bec0c73dbfb21e4a6c430
|
7
|
+
data.tar.gz: a18c00ed489997bdfbdb4853bb2c57a8b3a28535f0b108d8ccd2aa03b39d457a049bd283b59bdc46b745dd30e9ba34d0a66437b66818899b7db57bb05575c810
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require: rubocop-rspec
|
2
|
+
|
3
|
+
AllCops:
|
4
|
+
DisplayCopNames: true
|
5
|
+
Exclude:
|
6
|
+
- "blacklight_internet_archive.gemspec"
|
7
|
+
|
8
|
+
Metrics/BlockLength:
|
9
|
+
Exclude:
|
10
|
+
- 'spec/**/*'
|
11
|
+
|
12
|
+
Metrics/LineLength:
|
13
|
+
Max: 200
|
14
|
+
|
15
|
+
Style/StringLiterals:
|
16
|
+
Enabled: false
|
17
|
+
|
18
|
+
Layout/IndentationConsistency:
|
19
|
+
EnforcedStyle: normal
|
20
|
+
|
21
|
+
Rails/OutputSafety:
|
22
|
+
Enabled: false
|
23
|
+
|
24
|
+
Style/Documentation:
|
25
|
+
Enabled: false
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 JackBlackLight
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# BlacklightInternetArchive
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/blacklight_internet_archive`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'blacklight_internet_archive'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install blacklight_internet_archive
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/blacklight_internet_archive. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
36
|
+
|
37
|
+
## License
|
38
|
+
|
39
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
40
|
+
|
41
|
+
## Code of Conduct
|
42
|
+
|
43
|
+
Everyone interacting in the BlacklightInternetArchive project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/blacklight_internet_archive/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "blacklight_internet_archive/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "blacklight_internet_archive"
|
8
|
+
spec.version = BlacklightInternetArchive::VERSION
|
9
|
+
spec.authors = ["jd2148"]
|
10
|
+
spec.email = ["jd2148@columbia.edu"]
|
11
|
+
spec.summary = %q{Blacklight discovery interface for an Internet Archive collection.}
|
12
|
+
spec.license = "MIT"
|
13
|
+
|
14
|
+
|
15
|
+
# Specify which files should be added to the gem when it is released.
|
16
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
17
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
18
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
end
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
27
|
+
spec.add_development_dependency 'rubocop', '~> 0.50.0'
|
28
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 1.18', '>= 1.18.0'
|
29
|
+
spec.add_development_dependency "blacklight", '~> 6.0'
|
30
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "blacklight_internet_archive/version"
|
2
|
+
|
3
|
+
module BlacklightInternetArchive
|
4
|
+
|
5
|
+
autoload :InternetArchive, 'blacklight_internet_archive/internet_archive'
|
6
|
+
autoload :Client, 'blacklight_internet_archive/client'
|
7
|
+
autoload :Repository, 'blacklight_internet_archive/repository'
|
8
|
+
autoload :Request, 'blacklight_internet_archive/request'
|
9
|
+
autoload :Response, 'blacklight_internet_archive/response'
|
10
|
+
autoload :ResponseAdapter, 'blacklight_internet_archive/response_adapter'
|
11
|
+
autoload :EntityProcessor, 'blacklight_internet_archive/entity_processor'
|
12
|
+
autoload :BlacklightResponse, 'blacklight_internet_archive/blacklight_response'
|
13
|
+
autoload :HashWithResponse, 'blacklight_internet_archive/hash_with_response'
|
14
|
+
|
15
|
+
def self.connect(args)
|
16
|
+
connection = args[:url]
|
17
|
+
opts = args[:opts]
|
18
|
+
|
19
|
+
Client.new connection, opts
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
|
5
|
+
module BlacklightInternetArchive
|
6
|
+
class Client
|
7
|
+
def initialize(connection_url, options = {})
|
8
|
+
@connection_url = connection_url
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
# +execute_query+ is the main request method responsible for sending requests to the +connection+ object.
|
13
|
+
#
|
14
|
+
# "path" : A string value that represents the repository request handler (set url value in blacklight.yml)
|
15
|
+
# "opts" : A hash containing searh parameters
|
16
|
+
|
17
|
+
def execute_query(path, opts)
|
18
|
+
request_context = build_request path, opts
|
19
|
+
execute request_context
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute(request_context)
|
23
|
+
uri_string = request_context[:params][:uri]
|
24
|
+
uri = URI.parse(uri_string)
|
25
|
+
|
26
|
+
res = Net::HTTP.get_response(uri)
|
27
|
+
if res.is_a?(Net::HTTPSuccess)
|
28
|
+
res_data = res.read_body
|
29
|
+
return if res_data.nil? || res_data.empty?
|
30
|
+
res_data_mod = BlacklightInternetArchive::ResponseAdapter.adapt_response(res_data, @connection_url)
|
31
|
+
BlacklightInternetArchive::HashWithResponse.new(request_context, res, res_data_mod)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# +build_request+ accepts a path and options hash
|
36
|
+
# +build_request+ sets up the uri/query string
|
37
|
+
# returns a hash with the following keys:
|
38
|
+
# :uri
|
39
|
+
# :path
|
40
|
+
# :query
|
41
|
+
|
42
|
+
def build_request(path, opts)
|
43
|
+
raise "path must be a string or symbol, not #{path.inspect}" unless [String, Symbol].include?(path.class)
|
44
|
+
path = "#{path}.json"
|
45
|
+
|
46
|
+
opts[:path] = path
|
47
|
+
query_opts = {}
|
48
|
+
query_opts['pageSize'] = '10'
|
49
|
+
if opts['rows']
|
50
|
+
query_opts['pageSize'] = opts['rows']
|
51
|
+
else
|
52
|
+
query_opts['pageSize'] = '10'
|
53
|
+
end
|
54
|
+
if opts['page']
|
55
|
+
query_opts['page'] = opts['page']
|
56
|
+
else
|
57
|
+
query_opts['page'] = '1'
|
58
|
+
end
|
59
|
+
if query_opts['page'].to_i < 2
|
60
|
+
opts[:start] = 0
|
61
|
+
else
|
62
|
+
opts[:start] = ((query_opts['page'].to_i - 1) * query_opts['pageSize'].to_i)
|
63
|
+
end
|
64
|
+
|
65
|
+
query_opts['q'] = ''
|
66
|
+
query_opts['q'] = CGI.escape(opts['q']) if opts['q']
|
67
|
+
|
68
|
+
facet_string = ''
|
69
|
+
if opts['f']
|
70
|
+
opts['f'].each do |k, v|
|
71
|
+
v.each do |fv|
|
72
|
+
fval = CGI.escape(fv)
|
73
|
+
facet_string = "#{facet_string}fc=#{k}%3A#{fval}&"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
facet_string = facet_string.tr(' ', '+').chomp('&')
|
79
|
+
query = query_opts.to_query
|
80
|
+
query = "#{query}&#{facet_string}" if facet_string
|
81
|
+
|
82
|
+
opts[:query] = query
|
83
|
+
opts[:uri] = path.to_s + (query ? "?#{query}" : '')
|
84
|
+
|
85
|
+
opts[:rows] = 10 if opts[:rows].nil?
|
86
|
+
|
87
|
+
opts[:start] = 0 if opts[:start].nil?
|
88
|
+
|
89
|
+
{ :params => opts }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'active_support/core_ext/string/output_safety'
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
module BlacklightInternetArchive
|
5
|
+
# extract and convert individual results from response
|
6
|
+
class EntityProcessor
|
7
|
+
@metadata_fields = %w[meta_Creator meta_Coverage meta_Subject meta_Language meta_Collector meta_Title]
|
8
|
+
@date_fields = %w[firstCapture lastCapture]
|
9
|
+
@linkable_fields = { 'meta_Title' => 'allURL', 'url' => 'allURL', 'numCaptures' => 'allURL',
|
10
|
+
'numVideos' => 'seedVideosUrl' }
|
11
|
+
|
12
|
+
def self.run(response_json, base_url)
|
13
|
+
raise ArgumentError 'No entities in response.' unless response_json['results']['entities']
|
14
|
+
raise ArgumentError 'Base url required.' unless base_url
|
15
|
+
entities = response_json['results']['entities']
|
16
|
+
entities_clone = entities.clone
|
17
|
+
entities.each do |entity|
|
18
|
+
next unless entity['isSeed']
|
19
|
+
entities_clone[entities.index(entity)] = reformat_entity(entity, response_json['results']['searchedFacets'], base_url)
|
20
|
+
end
|
21
|
+
puts entities_clone.class
|
22
|
+
entities_clone
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.reformat_entity(entity, searched_facets, base_url)
|
26
|
+
entity_clone = entity.clone
|
27
|
+
entity.each do |entity_key, entity_val|
|
28
|
+
if entity_key == 'metadata'
|
29
|
+
entity_clone = facet_link_metadata(entity_val, entity_clone, searched_facets)
|
30
|
+
end
|
31
|
+
entity_clone = set_date_fields(entity_clone, entity_key, entity_val)
|
32
|
+
entity_clone = set_linked_fields(entity_clone, base_url)
|
33
|
+
end
|
34
|
+
# this field is not under the metadata node and not handled by process_entities
|
35
|
+
entity_clone['linked_websiteGroup'] = link_faceted_results_data('websiteGroup', [entity['websiteGroup']], searched_facets)
|
36
|
+
entity_clone
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.facet_link_metadata(entval, ent_clone, facet_info)
|
40
|
+
@metadata_fields.each do |k|
|
41
|
+
if entval[k]
|
42
|
+
ent_clone[k] = entval[k].map(&:html_safe)
|
43
|
+
ent_clone["linked_#{k}"] = link_faceted_results_data(k, entval[k], facet_info)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
ent_clone
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.set_date_fields(e_clone, ent, entval)
|
50
|
+
@date_fields.each do |d|
|
51
|
+
next unless ent == d
|
52
|
+
new_key = "#{d}_date"
|
53
|
+
next unless entval['formattedDate']
|
54
|
+
formatted_date = entval['formattedDate']
|
55
|
+
date_url = entval['waybackUrl']
|
56
|
+
date_link = make_link(formatted_date, date_url)
|
57
|
+
e_clone[new_key] = formatted_date
|
58
|
+
e_clone["linked_#{new_key}"] = date_link.html_safe
|
59
|
+
end
|
60
|
+
e_clone
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.set_linked_fields(e_clone, base_url)
|
64
|
+
@linkable_fields.each do |l, l_url|
|
65
|
+
val = e_clone[l]
|
66
|
+
val_url = e_clone[l_url]
|
67
|
+
if val_url.start_with?('?')
|
68
|
+
val_url = "#{base_url}#{val_url}"
|
69
|
+
end
|
70
|
+
linked_val = make_link(val, val_url)
|
71
|
+
e_clone["linked_#{l}"] = linked_val
|
72
|
+
end
|
73
|
+
e_clone
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.link_faceted_results_data(meta_field, meta_val, searched_facets)
|
77
|
+
link_facets = []
|
78
|
+
meta_val.each do |mv|
|
79
|
+
searched_facets.each do |sf|
|
80
|
+
next unless sf['id'] == meta_field
|
81
|
+
sf['results'].each do |ra|
|
82
|
+
if ra['name'] == mv
|
83
|
+
link_facets << make_link(ra['name'], convert_ia_facet_url(ra['addFacetURL']))
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
link_facets.map(&:html_safe)
|
89
|
+
end
|
90
|
+
|
91
|
+
# translate ia facet url into blacklight facet syntax
|
92
|
+
def self.convert_ia_facet_url(ia_facet_url)
|
93
|
+
ifu_hash = CGI.parse(ia_facet_url.tr('?', ''))
|
94
|
+
url_arrays = prepare_url_params(ifu_hash, [], [])
|
95
|
+
compose_url(url_arrays)
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.prepare_url_params(facet_hash, facet_url_arr, new_url_arr)
|
99
|
+
facet_hash.each do |k, v|
|
100
|
+
if k == 'fc'
|
101
|
+
v.each do |v_fc|
|
102
|
+
facet_url_arr << convert_ia_facet_url_param(v_fc)
|
103
|
+
end
|
104
|
+
else
|
105
|
+
new_url_arr << "#{k}=#{v[0]}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
[new_url_arr, facet_url_arr]
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.compose_url(url_arrays)
|
112
|
+
new_url = ''
|
113
|
+
url_arrays[0].each do |param_string|
|
114
|
+
new_url = if new_url == ''
|
115
|
+
"#{param_string}&"
|
116
|
+
else
|
117
|
+
"#{new_url}&#{param_string}&"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
url_arrays[1].each do |fps|
|
121
|
+
new_url = "#{new_url}#{fps}&"
|
122
|
+
end
|
123
|
+
"?#{new_url.chomp('&')}"
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.convert_ia_facet_url_param(value)
|
127
|
+
ifu_arr = value.split(':')
|
128
|
+
"f[#{ifu_arr[0]}][]=#{ifu_arr[1]}"
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.make_link(value, url)
|
132
|
+
"<a href=\"#{url}\">#{value}</a>".html_safe
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'blacklight'
|
3
|
+
|
4
|
+
module BlacklightInternetArchive
|
5
|
+
class Repository < Blacklight::AbstractRepository
|
6
|
+
##
|
7
|
+
# Find a single document result by a known id
|
8
|
+
# @param [String] id document's unique key value
|
9
|
+
# @param [Hash] params additional query parameters
|
10
|
+
def find(id, params = {})
|
11
|
+
# response = send_and_receive id, params
|
12
|
+
# raise Blacklight::Exceptions::RecordNotFound if response.documents.empty?
|
13
|
+
# response
|
14
|
+
end
|
15
|
+
|
16
|
+
##
|
17
|
+
# Execute a search query against a search index
|
18
|
+
# @param [Hash] params query parameters
|
19
|
+
def search(builder)
|
20
|
+
send_and_receive connection_config[:url], builder.blacklight_params
|
21
|
+
end
|
22
|
+
|
23
|
+
def send_and_receive(path, search_params = {})
|
24
|
+
res = connection.execute_query(path, search_params)
|
25
|
+
blacklight_config.response_model.new(res, search_params)
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_connection
|
29
|
+
BlacklightInternetArchive.connect(connection_config)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BlacklightInternetArchive
|
4
|
+
class Request < ActiveSupport::HashWithIndifferentAccess
|
5
|
+
SINGULAR_KEYS = %w(facet fl q qt rows start spellcheck spellcheck.q sort per_page wt hl group defType)
|
6
|
+
ARRAY_KEYS = %w(facet.field facet.query facet.pivot fq hl.fl)
|
7
|
+
|
8
|
+
def initialize(constructor = {})
|
9
|
+
if constructor.is_a?(Hash)
|
10
|
+
super()
|
11
|
+
update(constructor)
|
12
|
+
else
|
13
|
+
super(constructor)
|
14
|
+
end
|
15
|
+
ARRAY_KEYS.each do |key|
|
16
|
+
self[key] ||= []
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def append_filter_query(query)
|
21
|
+
self['fq'] << query
|
22
|
+
end
|
23
|
+
|
24
|
+
def append_facet_fields(values)
|
25
|
+
self['facet.field'] += Array(values)
|
26
|
+
end
|
27
|
+
|
28
|
+
def append_facet_query(values)
|
29
|
+
self['facet.query'] += Array(values)
|
30
|
+
end
|
31
|
+
|
32
|
+
def append_facet_pivot(query)
|
33
|
+
self['facet.pivot'] << query
|
34
|
+
end
|
35
|
+
|
36
|
+
def append_highlight_field(query)
|
37
|
+
self['hl.fl'] << query
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_hash
|
41
|
+
reject { |key, value| ARRAY_KEYS.include?(key) && value.blank? }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module BlacklightInternetArchive::Response
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
unless base < Hash
|
5
|
+
raise ArgumentError, "InternetArchive::Response expects to included only in (sub)classes of Hash; got included in '#{base}' instead."
|
6
|
+
end
|
7
|
+
base.send(:attr_reader, :request, :response)
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize_response(request, response, result)
|
11
|
+
@request = request
|
12
|
+
@response = response
|
13
|
+
self.merge!(result)
|
14
|
+
if self['response'] && self['response']['docs'].is_a?(::Array)
|
15
|
+
docs = PaginatedDocSet.new(self['response']['docs'])
|
16
|
+
docs.per_page = request[:params]['rows']
|
17
|
+
docs.page_start = request[:params]['start']
|
18
|
+
docs.total = self['response']['numFound'].to_s.to_i
|
19
|
+
self['response']['docs'] = docs
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def with_indifferent_access
|
24
|
+
if defined?(::BlacklightInternetArchive::HashWithIndifferentAccessWithResponse)
|
25
|
+
::BlacklightInternetArchive::HashWithIndifferentAccessWithResponse.new(request, response, self)
|
26
|
+
else
|
27
|
+
if defined?(ActiveSupport::HashWithIndifferentAccess)
|
28
|
+
BlacklightInternetArchive.const_set('HashWithIndifferentAccessWithResponse', Class.new(ActiveSupport::HashWithIndifferentAccess))
|
29
|
+
BlacklightInternetArchive::HashWithIndifferentAccessWithResponse.class_eval <<-eos
|
30
|
+
include BlacklightInternetArchive::Response
|
31
|
+
|
32
|
+
def initialize(request, response, result)
|
33
|
+
super()
|
34
|
+
initialize_response(request, response, result)
|
35
|
+
end
|
36
|
+
eos
|
37
|
+
::BlacklightInternetArchive::HashWithIndifferentAccessWithResponse.new(request, response, self)
|
38
|
+
else
|
39
|
+
raise RuntimeError, 'HashWithIndifferentAccess is not currently defined'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# A response module which gets mixed into the ['response']['docs'] array.
|
45
|
+
class PaginatedDocSet < ::Array
|
46
|
+
attr_accessor :page_start, :per_page, :page_total
|
47
|
+
if !(Object.const_defined?('RUBY_ENGINE') && Object::RUBY_ENGINE == 'rbx')
|
48
|
+
alias_method(:start, :page_start)
|
49
|
+
alias_method(:start=, :page_start=)
|
50
|
+
alias_method(:total, :page_total)
|
51
|
+
alias_method(:total=, :page_total=)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns the current page calculated from 'rows' and 'start'
|
55
|
+
def current_page
|
56
|
+
return 1 if start < 1
|
57
|
+
per_page_normalized = per_page < 1 ? 1 : per_page
|
58
|
+
@current_page ||= (start / per_page_normalized).ceil + 1
|
59
|
+
end
|
60
|
+
|
61
|
+
# Calcuates the total pages from 'numFound' and 'rows'
|
62
|
+
def total_pages
|
63
|
+
@total_pages ||= per_page > 0 ? (total / per_page.to_f).ceil : 1
|
64
|
+
end
|
65
|
+
|
66
|
+
# returns the previous page number or 1
|
67
|
+
def previous_page
|
68
|
+
@previous_page ||= current_page > 1 ? current_page - 1 : 1
|
69
|
+
end
|
70
|
+
|
71
|
+
# returns the next page number or the last
|
72
|
+
def next_page
|
73
|
+
@next_page ||= current_page == total_pages ? total_pages : current_page + 1
|
74
|
+
end
|
75
|
+
|
76
|
+
def has_next?
|
77
|
+
current_page < total_pages
|
78
|
+
end
|
79
|
+
|
80
|
+
def has_previous?
|
81
|
+
current_page > 1
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module BlacklightInternetArchive
|
4
|
+
class ResponseAdapter
|
5
|
+
def self.adapt_response(response_body, base_url)
|
6
|
+
response_body_string = convert_highlighting(response_body.to_s)
|
7
|
+
res_data_json = JSON.parse(response_body_string)
|
8
|
+
|
9
|
+
entities = res_data_json['results']['entities']
|
10
|
+
# processed_entities = process_entities(entities, res_data_json['results']['searchedFacets'], base_url)
|
11
|
+
# response_docs = { 'response' => { 'docs' => processed_entities } }
|
12
|
+
|
13
|
+
# response_docs = EntityProcessor.run(res_data_json, base_url)
|
14
|
+
response_docs = { 'response' => { 'docs' => EntityProcessor.run(res_data_json, base_url) } }
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
response_docs.merge!('facet_counts' => { 'facet_queries' => {},
|
19
|
+
'facet_fields' => reformat_facets(res_data_json), 'facet_dates' => {} })
|
20
|
+
set_paging_stats(response_docs, res_data_json)
|
21
|
+
response_docs
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.convert_highlighting(response_string)
|
25
|
+
response_string.gsub!('$high%', "<span class='highlight'>")
|
26
|
+
response_string.gsub!('/$light%', '</span>')
|
27
|
+
response_string
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def self.set_paging_stats(response_docs, res_data_json)
|
32
|
+
response_docs['response']['numFound'] = res_data_json['results']['totalResultCount']
|
33
|
+
response_docs['response']['page'] = res_data_json['pageParams']['page']
|
34
|
+
response_docs['response']['rows'] = res_data_json['pageParams']['pageSize']
|
35
|
+
response_docs
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def self.reformat_facets(response_json)
|
40
|
+
facets_hash = {}
|
41
|
+
facets = response_json['results']['searchedFacets']
|
42
|
+
facets.each do |f|
|
43
|
+
key_name = f['id']
|
44
|
+
facets_hash[key_name] = reformat_item(f['results'])
|
45
|
+
end
|
46
|
+
facets_hash
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.reformat_item(item_arr)
|
50
|
+
new_item_arr = []
|
51
|
+
item_arr.each do |item_hash|
|
52
|
+
new_item_arr << item_hash['name']
|
53
|
+
new_item_arr << item_hash['count']
|
54
|
+
end
|
55
|
+
new_item_arr
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
metadata
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: blacklight_internet_archive
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- jd2148
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-08-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.50.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.50.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop-rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.18'
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 1.18.0
|
79
|
+
type: :development
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - "~>"
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '1.18'
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 1.18.0
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: blacklight
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '6.0'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '6.0'
|
103
|
+
description:
|
104
|
+
email:
|
105
|
+
- jd2148@columbia.edu
|
106
|
+
executables: []
|
107
|
+
extensions: []
|
108
|
+
extra_rdoc_files: []
|
109
|
+
files:
|
110
|
+
- ".gitignore"
|
111
|
+
- ".rspec"
|
112
|
+
- ".rubocop.yml"
|
113
|
+
- ".travis.yml"
|
114
|
+
- Gemfile
|
115
|
+
- LICENSE.txt
|
116
|
+
- README.md
|
117
|
+
- Rakefile
|
118
|
+
- blacklight_internet_archive.gemspec
|
119
|
+
- lib/blacklight_internet_archive.rb
|
120
|
+
- lib/blacklight_internet_archive/blacklight_response.rb
|
121
|
+
- lib/blacklight_internet_archive/client.rb
|
122
|
+
- lib/blacklight_internet_archive/entity_processor.rb
|
123
|
+
- lib/blacklight_internet_archive/hash_with_response.rb
|
124
|
+
- lib/blacklight_internet_archive/internet_archive.rb
|
125
|
+
- lib/blacklight_internet_archive/repository.rb
|
126
|
+
- lib/blacklight_internet_archive/request.rb
|
127
|
+
- lib/blacklight_internet_archive/response.rb
|
128
|
+
- lib/blacklight_internet_archive/response_adapter.rb
|
129
|
+
- lib/blacklight_internet_archive/version.rb
|
130
|
+
homepage:
|
131
|
+
licenses:
|
132
|
+
- MIT
|
133
|
+
metadata: {}
|
134
|
+
post_install_message:
|
135
|
+
rdoc_options: []
|
136
|
+
require_paths:
|
137
|
+
- lib
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
requirements: []
|
149
|
+
rubyforge_project:
|
150
|
+
rubygems_version: 2.6.10
|
151
|
+
signing_key:
|
152
|
+
specification_version: 4
|
153
|
+
summary: Blacklight discovery interface for an Internet Archive collection.
|
154
|
+
test_files: []
|