umlaut 3.0.0alpha2 → 3.0.0alpha3
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/app/controllers/link_router_controller.rb +0 -14
- data/app/controllers/resolve_controller.rb +1 -14
- data/app/controllers/umlaut/controller_behavior.rb +15 -0
- data/app/models/sfx_db/sfx_db_base.rb +4 -0
- data/lib/generators/umlaut/install_generator.rb +1 -1
- data/lib/tasks/umlaut_migrate_permalinks.rake +106 -0
- data/lib/umlaut/version.rb +1 -1
- data/lib/umlaut.rb +9 -8
- data/test/dummy/config/database.yml +53 -0
- data/test/dummy/log/development.log +0 -12981
- metadata +115 -181
- data/lib/service_adaptors/sfx-new.rb +0 -557
- data/test/dummy/config/database.yml-jh +0 -19
- data/test/dummy/tmp/cache/assets/C5F/340/sprockets%2F99692920160b7a279b86a80415b79db7 +0 -0
- data/test/dummy/tmp/cache/assets/C70/4D0/sprockets%2F034ad2036e623081bd352800786dfe80 +0 -0
- data/test/dummy/tmp/cache/assets/C73/920/sprockets%2Fd371318f22900492fd180f17c5e2a504 +0 -9268
- data/test/dummy/tmp/cache/assets/C80/980/sprockets%2Fc94807409c1523d43e18d25f35d93c41 +0 -0
- data/test/dummy/tmp/cache/assets/C8F/780/sprockets%2Fe47e28558116fb5f8038754e60d1961d +0 -11769
- data/test/dummy/tmp/cache/assets/CAA/EB0/sprockets%2F1d179210e8b76f1ea63c802688a015e4 +0 -9271
- data/test/dummy/tmp/cache/assets/CBB/9C0/sprockets%2F706f28923fb754cad04b9107c89986a1 +0 -0
- data/test/dummy/tmp/cache/assets/CBF/B60/sprockets%2F08ca89671549936265dcb673bf02e36f +0 -0
- data/test/dummy/tmp/cache/assets/CC9/9F0/sprockets%2F306166316e2cafd13c15e62b51a2339d +0 -0
- data/test/dummy/tmp/cache/assets/CF6/F20/sprockets%2F5b2ffa1103079dfd555197838f87a99f +0 -0
- data/test/dummy/tmp/cache/assets/CF7/2B0/sprockets%2F25a7c73655bd3598173b39d9f98bcd46 +0 -862
- data/test/dummy/tmp/cache/assets/CFE/080/sprockets%2F37fe9f4255baddbd549a659914929398 +0 -0
- data/test/dummy/tmp/cache/assets/D22/060/sprockets%2F9aec77b768e91a802d284271c58e2f7e +0 -21357
- data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/D33/6D0/sprockets%2F500129c57f1146e556ec3aacd6cd38c1 +0 -0
- data/test/dummy/tmp/cache/assets/D33/FD0/sprockets%2F2ba0b4e6334a77b923e5f770381bb2bf +0 -0
- data/test/dummy/tmp/cache/assets/D42/C20/sprockets%2Fbcf14e437b1582bf93b77670acf8e090 +0 -21353
- data/test/dummy/tmp/cache/assets/D50/A30/sprockets%2F7d8b294ac433db5d056538f8cf7c66b9 +0 -0
- data/test/dummy/tmp/cache/assets/D54/ED0/sprockets%2F71c9fa01091d432b131da3bb73faf3d4 +0 -872
- data/test/dummy/tmp/cache/assets/D65/590/sprockets%2Fc1bb92fc3406a126b7dd302edc96d629 +0 -0
- data/test/dummy/tmp/cache/assets/D71/6B0/sprockets%2Fde558b71b494cf09b1bf055c8dff0353 +0 -0
- data/test/dummy/tmp/cache/assets/D72/610/sprockets%2Fa8c708eeb30ef93de34d755d4f45d023 +0 -859
- data/test/dummy/tmp/cache/assets/D76/AD0/sprockets%2Fe2158cde93188cf5ab6457bc6d6602ec +0 -0
- data/test/dummy/tmp/cache/assets/D7A/E40/sprockets%2F9622ffcc499a57627cd1bb18fe31b8e4 +0 -11772
- data/test/dummy/tmp/cache/assets/D84/210/sprockets%2Fabd0103ccec2b428ac62c94e4c40b384 +0 -0
- data/test/dummy/tmp/cache/assets/D9B/770/sprockets%2F8aacf02eb7dbb0949704b28f27b87e0b +0 -0
- data/test/dummy/tmp/cache/assets/DA6/A80/sprockets%2F92e26d8e58d5bcc8b8f6c25d1b05b9c1 +0 -0
- data/test/dummy/tmp/cache/assets/DE8/790/sprockets%2Fd1333bde2b9aafcc712d11dd09ab35d8 +0 -0
- data/test/dummy/tmp/cache/assets/DF7/F30/sprockets%2F7bc16c4109b17fabe29f8ddbbf732d1c +0 -374
- data/test/dummy/tmp/cache/assets/E03/570/sprockets%2F493bdc0ac14cd4f57fdfe4253f992bde +0 -0
- data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/dummy/tmp/cache/assets/E0B/4B0/sprockets%2F7988df51a61c81ce6ede4a2d4c8cce4f +0 -377
- data/test/dummy/tmp/cache/assets/E5F/960/sprockets%2Fdc007b6cad5c7ef08e33ec28cfff0ef6 +0 -0
@@ -1,557 +0,0 @@
|
|
1
|
-
# NOTE: In your SFX Admin, under Menu Configuration / API, you should enable ALL
|
2
|
-
# 'extra' API information for full umlaut functionality.
|
3
|
-
# With the exception of "Include openURL parameter", can't figure out how
|
4
|
-
# that's useful.
|
5
|
-
#
|
6
|
-
# config parameters in services.yml
|
7
|
-
# display name: User displayable name for this service
|
8
|
-
# base_url: SFX base url.
|
9
|
-
# click_passthrough: DEPRECATED. Caused problems. Use the SFXBackchannelRecord
|
10
|
-
# link filter service instead.
|
11
|
-
# When set to true, Umlaut will send all SFX clicks
|
12
|
-
# through SFX, for SFX to capture statistics. This is currently done
|
13
|
-
# using a backdoor into the SFX sfxresolve.cgi script. Defaults to false.
|
14
|
-
# Note that
|
15
|
-
# after SFX requests have been removed in the nightly job, the
|
16
|
-
# click passthrough will cause an error! Set sfx_requests_expire_crontab
|
17
|
-
# with the crontab pattern you use for requests to expire, and we won't
|
18
|
-
# try to click passthrough with expired requests.
|
19
|
-
# sfx_requests_expire_crontab: Crontab pattern that the SFX admin is using
|
20
|
-
# to expire SFX requests. Used to refrain from click passthrough with
|
21
|
-
# expired requests, since that is destined to fail.
|
22
|
-
# services_of_interest: Optional. over-ride the built in list of what types of
|
23
|
-
# SFX services we want to grab, and what the corresponding umlaut types are.
|
24
|
-
# hash, with SFX service type name as key, and Umlaut ServiceTypeValue
|
25
|
-
# name as value.
|
26
|
-
# extra_targets_of_interest: sfx target_names of targets you want to make
|
27
|
-
# sure to include in umlaut. A hash with target_name as key, and umlaut
|
28
|
-
# ResponseTypeValue name as value.
|
29
|
-
# really_distant_relationships: An array of relationship type codes from SFX
|
30
|
-
# "related objects". See Table 18 in SFX 3.0 User's Manual. Related
|
31
|
-
# objects that have only a "really distant relationship" will NOT
|
32
|
-
# be shown as fulltext, but will instead be banished to the see also
|
33
|
-
# "highlighted_link" section. You must have display of related objects
|
34
|
-
# turned ON in SFX display admin, to get related objects at all in
|
35
|
-
# Umlaut. NOTE: This parameter has a default value to a certain set of
|
36
|
-
# relationships, set to empty array [] to eliminate defaults.
|
37
|
-
# sfx_timeout: in seconds, for both open/read timeout value for SFX connection.
|
38
|
-
# Defaults to 8.
|
39
|
-
class Sfx < Service
|
40
|
-
require 'uri'
|
41
|
-
require 'htmlentities'
|
42
|
-
require 'cgi'
|
43
|
-
require 'nokogiri'
|
44
|
-
|
45
|
-
#require 'open_url'
|
46
|
-
|
47
|
-
required_config_params :base_url
|
48
|
-
|
49
|
-
def initialize(config)
|
50
|
-
|
51
|
-
# Key is sfx service_type, value is umlaut servicetype string.
|
52
|
-
# These are the SFX service types we will translate to umlaut
|
53
|
-
@services_of_interest = {'getFullTxt' => 'fulltext',
|
54
|
-
'getSelectedFullTxt' => 'fulltext',
|
55
|
-
'getDocumentDelivery' => 'document_delivery',
|
56
|
-
'getDOI' => 'highlighted_link',
|
57
|
-
'getAbstract' => 'abstract',
|
58
|
-
'getTOC' => 'table_of_contents'}
|
59
|
-
|
60
|
-
# Special targets. Key is SFX target_name.
|
61
|
-
# Value is umlaut service type.
|
62
|
-
# These targets will be included even if their sfx service_type doesn't
|
63
|
-
# match our services_of_interest, and the umlaut service ID string given
|
64
|
-
# here will take precedence and be used even if these targets DO match
|
65
|
-
# services_of_interest. Generally loaded from yml config in super.
|
66
|
-
@extra_targets_of_interest = {}
|
67
|
-
|
68
|
-
@sfx_timeout = 8
|
69
|
-
|
70
|
-
@really_distant_relationships = ["CONTINUES_IN_PART", "CONTINUED_IN_PART_BY", "ABSORBED_IN_PART", "ABSORBED_BY"]
|
71
|
-
|
72
|
-
super(config)
|
73
|
-
end
|
74
|
-
|
75
|
-
# Standard method, used by auto background updater. See Service docs.
|
76
|
-
def service_types_generated
|
77
|
-
service_strings = []
|
78
|
-
service_strings.concat( @services_of_interest.values() )
|
79
|
-
service_strings.concat( @extra_targets_of_interest.values() )
|
80
|
-
service_strings.uniq!
|
81
|
-
|
82
|
-
return service_strings.collect { |s| ServiceTypeValue[s] }
|
83
|
-
end
|
84
|
-
|
85
|
-
def base_url
|
86
|
-
return @base_url
|
87
|
-
end
|
88
|
-
|
89
|
-
def handle(request)
|
90
|
-
client = self.initialize_client(request)
|
91
|
-
begin
|
92
|
-
response = self.do_request(client)
|
93
|
-
self.parse_response(response, request)
|
94
|
-
return request.dispatched(self, true)
|
95
|
-
rescue Errno::ETIMEDOUT, Timeout::Error => e
|
96
|
-
# Request to SFX timed out. Record this as unsuccessful in the dispatch table. Temporary.
|
97
|
-
return request.dispatched(self, DispatchedService::FailedTemporary, e)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def initialize_client(request)
|
102
|
-
transport = OpenURL::Transport.new(@base_url, nil, :open_timeout => @sfx_timeout, :read_timeout => @sfx_timeout)
|
103
|
-
|
104
|
-
context_object = request.to_context_object
|
105
|
-
transport.add_context_object(context_object)
|
106
|
-
transport.extra_args["sfx.response_type"]="multi_obj_xml"
|
107
|
-
|
108
|
-
@get_coverage = false
|
109
|
-
|
110
|
-
metadata = request.referent.metadata
|
111
|
-
if ( metadata['date'].blank? &&
|
112
|
-
metadata['year'].blank? &&
|
113
|
-
(! request.referent.identifiers.find {|i| i =~ /^info\:(doi|pmid)/})
|
114
|
-
)
|
115
|
-
# No article-level metadata, do some special stuff.
|
116
|
-
transport.extra_args["sfx.ignore_date_threshold"]="1"
|
117
|
-
transport.extra_args["sfx.show_availability"]="1"
|
118
|
-
@get_coverage = true
|
119
|
-
end
|
120
|
-
# Workaround to SFX bug, not sure if this is really still neccesary
|
121
|
-
# I think it's not, but leave it in anyway just in case.
|
122
|
-
if (context_object.referent.identifiers.find {|i| i =~ /^info:doi\// })
|
123
|
-
transport.extra_args['sfx.doi_url']='http://dx.doi.org'
|
124
|
-
end
|
125
|
-
|
126
|
-
return transport
|
127
|
-
end
|
128
|
-
|
129
|
-
def do_request(client)
|
130
|
-
client.transport_inline
|
131
|
-
return client.response
|
132
|
-
end
|
133
|
-
|
134
|
-
def parse_response(resolver_response, request)
|
135
|
-
doc = Nokogiri::XML(resolver_response)
|
136
|
-
|
137
|
-
# Catch an SFX error message (in HTML) that's not an XML
|
138
|
-
# document at all.
|
139
|
-
unless doc.at('/ctx_obj_set')
|
140
|
-
Rails.logger.error("sfx.rb: SFX did not return expected response. SFX response: #{resolver_response}")
|
141
|
-
raise "SFX did not return expected response."
|
142
|
-
end
|
143
|
-
|
144
|
-
# There can be several context objects in the response.
|
145
|
-
# We need to keep track of which data comes from which, for
|
146
|
-
# SFX click-through generating et alia
|
147
|
-
sfx_objs = doc.search('/ctx_obj_set/ctx_obj')
|
148
|
-
|
149
|
-
# As we go through the possibly multiple SFX context objects,
|
150
|
-
# we need to keep track of which one, if any, we want to use
|
151
|
-
# to enhance the Umlaut referent metadata.
|
152
|
-
#
|
153
|
-
# We only enhance for journal type metadata. For book type
|
154
|
-
# metadata SFX will return something, but it may not be the manifestation
|
155
|
-
# we want. With journal titles, less of an issue.
|
156
|
-
#
|
157
|
-
# In case of multiple SFX hits, enhance metadata only from the
|
158
|
-
# one that actually had fulltext. If more than one had fulltext, forget it,
|
159
|
-
# too error prone. If none had full text, just pick the first.
|
160
|
-
#
|
161
|
-
# We'll use these variables to keep track of our 'best fit' as
|
162
|
-
# we loop through em.
|
163
|
-
best_fulltext_ctx = nil
|
164
|
-
best_nofulltext_ctx = nil
|
165
|
-
|
166
|
-
# We're going to keep our @really_distant_relationship stuff here.
|
167
|
-
related_titles = {}
|
168
|
-
|
169
|
-
0.upto(sfx_objs.length - 1 ) do |sfx_obj_index|
|
170
|
-
|
171
|
-
sfx_obj = sfx_objs[sfx_obj_index]
|
172
|
-
|
173
|
-
# Get out the "perl_data" section, with our actual OpenURL style
|
174
|
-
# context object information. This was XML escaped as a String (actually
|
175
|
-
# double-escaped, weirdly), so
|
176
|
-
# we need to extract the string, unescape it, and then feed it to Nokogiri
|
177
|
-
# again.
|
178
|
-
ctx_obj_atts =
|
179
|
-
CGI.unescapeHTML( sfx_obj.at('./ctx_obj_attributes').inner_html)
|
180
|
-
|
181
|
-
perl_data = Nokogiri::XML( ctx_obj_atts )
|
182
|
-
# parse it into an OpenURL, we might need it like that.
|
183
|
-
sfx_co = Sfx.parse_perl_data(perl_data)
|
184
|
-
sfx_metadata = sfx_co.to_hash
|
185
|
-
|
186
|
-
|
187
|
-
# get SFX objectID
|
188
|
-
object_id_node =
|
189
|
-
perl_data.at("./perldata/hash/item[@key='rft.object_id']")
|
190
|
-
object_id = object_id_node ? object_id_node.inner_html : nil
|
191
|
-
|
192
|
-
# Get SFX requestID
|
193
|
-
request_id_node =
|
194
|
-
perl_data.at("./perldata/hash/item[@key='sfx.request_id']")
|
195
|
-
request_id = request_id_node ? request_id_node.inner_html : nil
|
196
|
-
|
197
|
-
# Get targets service ids
|
198
|
-
sfx_target_service_ids =
|
199
|
-
sfx_obj.search('ctx_obj_targets/target/target_service_id').collect {|e| e.inner_html}
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
metadata = request.referent.metadata
|
204
|
-
|
205
|
-
# For each target delivered by SFX
|
206
|
-
sfx_obj.search("./ctx_obj_targets/target").each_with_index do|target, target_index|
|
207
|
-
response_data = {}
|
208
|
-
|
209
|
-
# First check @extra_targets_of_interest
|
210
|
-
sfx_target_name = target.at('./target_name').inner_html
|
211
|
-
umlaut_service = @extra_targets_of_interest[sfx_target_name]
|
212
|
-
|
213
|
-
# If not found, look for it in services_of_interest
|
214
|
-
unless ( umlaut_service )
|
215
|
-
sfx_service_type = target.at("./service_type").inner_html
|
216
|
-
umlaut_service = @services_of_interest[sfx_service_type]
|
217
|
-
end
|
218
|
-
|
219
|
-
# If we have multiple context objs, skip the ill and ask-a-librarian
|
220
|
-
# links for all but the first, to avoid dups. This is a bit messy,
|
221
|
-
# but this whole multiple hits thing is messy.
|
222
|
-
if ( sfx_obj_index > 0 &&
|
223
|
-
( umlaut_service == 'document_delivery' ||
|
224
|
-
umlaut_service == 'export_citation' ||
|
225
|
-
umlaut_service == 'help'))
|
226
|
-
next
|
227
|
-
end
|
228
|
-
|
229
|
-
|
230
|
-
# Okay, keep track of best fit ctx for metadata enhancement
|
231
|
-
if request.referent.format == "journal"
|
232
|
-
if ( umlaut_service == 'fulltext')
|
233
|
-
best_fulltext_ctx = perl_data
|
234
|
-
best_nofulltext_ctx = nil
|
235
|
-
elsif best_nofulltext_ctx == nil
|
236
|
-
best_nofulltext_ctx = perl_data
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
if ( umlaut_service ) # Okay, it's in services or targets of interest
|
241
|
-
if (target/"./displayer")
|
242
|
-
source = "SFX/"+(target/"./displayer").inner_html
|
243
|
-
else
|
244
|
-
source = "SFX"+URI.parse(self.url).path
|
245
|
-
end
|
246
|
-
|
247
|
-
target_service_id = (target/"./target_service_id").inner_html
|
248
|
-
|
249
|
-
coverage = nil
|
250
|
-
if ( @get_coverage )
|
251
|
-
# Make sure you turn on "Include availability info in text format"
|
252
|
-
# in the SFX Admin API configuration.
|
253
|
-
thresholds_str = ""
|
254
|
-
target.search('coverage/coverage_text/threshold_text/coverage_statement').each do | threshold |
|
255
|
-
thresholds_str += threshold.inner_html.to_s + ".\n";
|
256
|
-
end
|
257
|
-
|
258
|
-
embargoes_str = "";
|
259
|
-
target.search('coverage/coverage_text/embargo_text/embargo_statement').each do |embargo |
|
260
|
-
embargoes_str += embargo.inner_html.to_s + ".\n";
|
261
|
-
end
|
262
|
-
|
263
|
-
unless ( thresholds_str.blank? && embargoes_str.blank? )
|
264
|
-
coverage = thresholds_str + embargoes_str
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
|
269
|
-
related_note = ""
|
270
|
-
# If this is from a related object, add that on as a note too...
|
271
|
-
# And maybe skip this entirely!
|
272
|
-
if (related_node = target.at('./related_service_info'))
|
273
|
-
relationship = related_node.at('./relation_type').inner_text
|
274
|
-
issn = related_node.at('./related_object_issn').inner_text
|
275
|
-
sfx_object_id = related_node.at('./related_object_id').inner_text
|
276
|
-
title = related_node.at('./related_object_title').inner_text
|
277
|
-
|
278
|
-
if @really_distant_relationships.include?(
|
279
|
-
related_node.at('./relation_type').inner_text)
|
280
|
-
# Show title-level link in see-also instead of full text.
|
281
|
-
related_titles[issn] = {
|
282
|
-
:sfx_object_id => sfx_object_id,
|
283
|
-
:title => title,
|
284
|
-
:relationship => relationship,
|
285
|
-
:issn => issn
|
286
|
-
}
|
287
|
-
|
288
|
-
next
|
289
|
-
end
|
290
|
-
|
291
|
-
related_note = "This version provided from related title: <i>" + CGI.unescapeHTML( title ) + "</i>.\n"
|
292
|
-
end
|
293
|
-
|
294
|
-
if ( sfx_service_type == 'getDocumentDelivery' )
|
295
|
-
value_string = request_id
|
296
|
-
else
|
297
|
-
value_string = (target/"./target_service_id").inner_html
|
298
|
-
end
|
299
|
-
|
300
|
-
response_data[:url] = CGI.unescapeHTML((target/"./target_url").inner_html)
|
301
|
-
response_data[:notes] = related_note.to_s + CGI.unescapeHTML((target/"./note").inner_html)
|
302
|
-
response_data[:authentication] = CGI.unescapeHTML((target/"./authentication").inner_html)
|
303
|
-
response_data[:source] = source
|
304
|
-
response_data[:coverage] = coverage if coverage
|
305
|
-
|
306
|
-
# Sfx metadata we want
|
307
|
-
response_data[:sfx_base_url] = @base_url
|
308
|
-
response_data[:sfx_obj_index] = sfx_obj_index + 1 # sfx is 1 indexed
|
309
|
-
response_data[:sfx_target_index] = target_index + 1
|
310
|
-
response_data[:sfx_request_id] = (perl_data/"//hash/item[@key='sfx.request_id']").first.inner_html
|
311
|
-
response_data[:sfx_target_service_id] = target_service_id
|
312
|
-
response_data[:sfx_target_name] = sfx_target_name
|
313
|
-
# At url-generation time, the request isn't available to us anymore,
|
314
|
-
# so we better store this citation info here now, since we need it
|
315
|
-
# for sfx click passthrough
|
316
|
-
|
317
|
-
# Oops, need to take this from SFX delivered metadata.
|
318
|
-
|
319
|
-
response_data[:citation_year] = sfx_metadata['rft.date'].to_s[0,4] if sfx_metadata['rft.date']
|
320
|
-
response_data[:citation_volume] = sfx_metadata['rft.volume'];
|
321
|
-
response_data[:citation_issue] = sfx_metadata['rft.issue']
|
322
|
-
response_data[:citation_spage] = sfx_metadata['rft.spage']
|
323
|
-
|
324
|
-
# Some debug info
|
325
|
-
response_data[:debug_info] =" Target: #{sfx_target_name} ; SFX object ID: #{object_id}"
|
326
|
-
|
327
|
-
response_data[:display_text] = (target/"./target_public_name").inner_html
|
328
|
-
|
329
|
-
request.add_service_response(
|
330
|
-
response_data.merge(
|
331
|
-
:service => self,
|
332
|
-
:service_type_value => umlaut_service
|
333
|
-
))
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
end
|
338
|
-
end
|
339
|
-
end
|
340
|
-
|
341
|
-
# Add in links to our related titles
|
342
|
-
related_titles.each_pair do |issn, hash|
|
343
|
-
request.add_service_response(
|
344
|
-
:service => self,
|
345
|
-
:display_text => "#{sfx_relationship_display(hash[:relationship])}: #{hash[:title]}",
|
346
|
-
:notes => "#{ServiceTypeValue['fulltext'].display_name} available",
|
347
|
-
:related_object_hash => hash,
|
348
|
-
:service_type_value => "highlighted_link")
|
349
|
-
end
|
350
|
-
|
351
|
-
# Did we find a ctx best fit for enhancement?
|
352
|
-
if best_fulltext_ctx
|
353
|
-
enhance_referent(request, best_fulltext_ctx)
|
354
|
-
elsif best_nofulltext_ctx
|
355
|
-
enhance_referent(request, best_nofulltext_ctx)
|
356
|
-
end
|
357
|
-
|
358
|
-
end
|
359
|
-
|
360
|
-
|
361
|
-
def sfx_click_passthrough
|
362
|
-
# From config, or default to false.
|
363
|
-
return @click_passthrough || false;
|
364
|
-
end
|
365
|
-
|
366
|
-
# Using the value of sfx_request_expire_crontab, determine if the
|
367
|
-
# umlaut service response is so old that we can't use it for
|
368
|
-
# sfx click passthrough anymore.
|
369
|
-
def expired_sfx_request(response)
|
370
|
-
require 'CronTab'
|
371
|
-
|
372
|
-
crontab_str = @sfx_requests_expire_crontab
|
373
|
-
|
374
|
-
return false unless crontab_str # no param, no determination possible
|
375
|
-
|
376
|
-
crontab = CronTab.new( crontab_str )
|
377
|
-
|
378
|
-
time_of_response = response.created_at
|
379
|
-
|
380
|
-
return false unless time_of_response # no recorded time, not possible either
|
381
|
-
|
382
|
-
expire_time = crontab.nexttime( time_of_response )
|
383
|
-
|
384
|
-
# Give an extra five minutes of time, in case the expire
|
385
|
-
# process takes up to five minutes to finish.
|
386
|
-
return( Time.now > (expire_time + 5.minutes) )
|
387
|
-
end
|
388
|
-
|
389
|
-
# Try to provide a weird reverse-engineered url to take the user THROUGH
|
390
|
-
# sfx to their destination, so sfx will capture for statistics.
|
391
|
-
# This relies on certain information from the orignal sfx response
|
392
|
-
# being stored in the Response object at that point. Used by
|
393
|
-
# sfx_backchannel_record service.
|
394
|
-
def self.pass_through_url(response)
|
395
|
-
base_url = response[:sfx_base_url]
|
396
|
-
|
397
|
-
sfx_resolver_cgi_url = base_url + "/cgi/core/sfxresolver.cgi"
|
398
|
-
|
399
|
-
|
400
|
-
dataString = "?tmp_ctx_svc_id=#{response[:sfx_target_index]}"
|
401
|
-
dataString += "&tmp_ctx_obj_id=#{response[:sfx_obj_index]}"
|
402
|
-
|
403
|
-
# Don't understand what this is, but it sometimes needs to be 1?
|
404
|
-
# Hopefully it won't mess anything up when it's not neccesary.
|
405
|
-
# Really have no idea when it would need to be something other
|
406
|
-
# than 1.
|
407
|
-
# Nope, sad to say it does mess up cases where it is not neccesary.
|
408
|
-
# Grr.
|
409
|
-
#dataString += "&tmp_parent_ctx_obj_id=1"
|
410
|
-
|
411
|
-
dataString += "&service_id=#{response[:sfx_target_service_id]}"
|
412
|
-
dataString += "&request_id=#{response[:sfx_request_id]}"
|
413
|
-
dataString += "&rft.year="
|
414
|
-
dataString += URI.escape(response[:citation_year].to_s) if response[:citation_year]
|
415
|
-
dataString += "&rft.volume="
|
416
|
-
dataString += URI.escape(response[:citation_volume].to_s) if response[:citation_volume]
|
417
|
-
dataString += "&rft.issue="
|
418
|
-
dataString += URI.escape(response[:citation_issue].to_s) if response[:citation_issue]
|
419
|
-
dataString += "&rft.spage="
|
420
|
-
dataString += URI.escape(response[:citation_spage]).to_s if response[:citation_spage]
|
421
|
-
|
422
|
-
return sfx_resolver_cgi_url + dataString
|
423
|
-
end
|
424
|
-
|
425
|
-
# Class method to parse a perl_data block as XML in String
|
426
|
-
# into a ContextObject. Argument is Nokogiri doc containing
|
427
|
-
# the SFX <perldata> element and children.
|
428
|
-
def self.parse_perl_data(doc)
|
429
|
-
|
430
|
-
co = OpenURL::ContextObject.new
|
431
|
-
co.referent.set_format('journal') # default
|
432
|
-
|
433
|
-
html_ent_coder = HTMLEntities.new
|
434
|
-
|
435
|
-
doc.search('perldata/hash/item').each do |item|
|
436
|
-
key = item['key'].to_s
|
437
|
-
value = item.inner_html
|
438
|
-
# But this still has HTML entities in it sometimes. Now we've
|
439
|
-
# got to decode THAT.
|
440
|
-
value = html_ent_coder.decode(value)
|
441
|
-
|
442
|
-
# Some normalization. SFX uses rft.year, which is not actually
|
443
|
-
# legal. Stick it in rft.date instead.
|
444
|
-
key = "rft.date" if key == "rft.year"
|
445
|
-
|
446
|
-
prefix, stripped = key.split('.')
|
447
|
-
|
448
|
-
# The auinit1 value is COMPLETELY messed up for reasons I do not know.
|
449
|
-
# Double encoded in bizarre ways.
|
450
|
-
next if key == '@rft.auinit1' || key == '@rft.auinit'
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
# Darn multi-value SFX hackery, indicated with keys beginning
|
456
|
-
# with '@'. Just take the first one,
|
457
|
-
# our context object can't store more than one. Then regularize the
|
458
|
-
# key name.
|
459
|
-
if (prefix == '@rft')
|
460
|
-
array_items = item.search("array/item")
|
461
|
-
array_i = array_items[0] unless array_items.blank?
|
462
|
-
|
463
|
-
prefix = prefix.slice(1, prefix.length)
|
464
|
-
value = array_i ? array_i.inner_html : nil
|
465
|
-
end
|
466
|
-
|
467
|
-
# object_type? Fix that to be the right way.
|
468
|
-
if (prefix=='rft') && (key=='object_type')
|
469
|
-
co.referent.set_format( value.downcase )
|
470
|
-
next
|
471
|
-
end
|
472
|
-
|
473
|
-
if (prefix == 'rft' && value)
|
474
|
-
co.referent.set_metadata(stripped, value)
|
475
|
-
end
|
476
|
-
|
477
|
-
if (prefix=='@rft_id')
|
478
|
-
identifiers = item.search('array/item')
|
479
|
-
identifiers.each do |id|
|
480
|
-
co.referent.add_identifier(id.inner_html)
|
481
|
-
end
|
482
|
-
end
|
483
|
-
if (prefix=='@rfr_id')
|
484
|
-
identifiers = item.search('array/item')
|
485
|
-
identifiers.each do |id|
|
486
|
-
co.referrer.add_identifier(id.inner_html)
|
487
|
-
end
|
488
|
-
end
|
489
|
-
end
|
490
|
-
return co
|
491
|
-
end
|
492
|
-
|
493
|
-
# Custom url generation for the weird case
|
494
|
-
def response_url(service_response, submitted_params)
|
495
|
-
if (related_object = service_response.data_values[:related_object_hash])
|
496
|
-
{:controller => 'resolve', "rft.issn" => related_object[:issn], "rft.title" => related_object[:title], "rft.object_id" => related_object[:sfx_object_id] }
|
497
|
-
else
|
498
|
-
service_response['url']
|
499
|
-
end
|
500
|
-
end
|
501
|
-
|
502
|
-
protected
|
503
|
-
# Second argument is a Nokogiri element representing the <perldata>
|
504
|
-
# tag and children.
|
505
|
-
def enhance_referent(request, perl_data)
|
506
|
-
ActiveRecord::Base.connection_pool.with_connection do
|
507
|
-
metadata = request.referent.metadata
|
508
|
-
|
509
|
-
sfx_co = Sfx.parse_perl_data(perl_data)
|
510
|
-
|
511
|
-
sfx_metadata = sfx_co.referent.metadata
|
512
|
-
# Do NOT enhance for metadata type 'BOOK', unreliable matching from
|
513
|
-
# SFX!
|
514
|
-
return if sfx_metadata["object_type"] == "BOOK" || sfx_metadata["genre"] == "book"
|
515
|
-
|
516
|
-
# If we already had metadata for journal title and the SFX one
|
517
|
-
# differs, we want to over-write it. This is good for ambiguous
|
518
|
-
# incoming OpenURLs, among other things.
|
519
|
-
|
520
|
-
if request.referent.format == 'journal'
|
521
|
-
request.referent.enhance_referent("jtitle", sfx_metadata['jtitle'])
|
522
|
-
end
|
523
|
-
# And ISSN
|
524
|
-
if request.referent.format == 'journal' && ! sfx_metadata['issn'].blank?
|
525
|
-
request.referent.enhance_referent('issn', sfx_metadata['issn'])
|
526
|
-
end
|
527
|
-
|
528
|
-
|
529
|
-
# The rest, we write only if blank, we don't over-write
|
530
|
-
sfx_metadata.each do |key, value|
|
531
|
-
if (metadata[key].blank?)
|
532
|
-
|
533
|
-
# watch out for SFX's weird array values.
|
534
|
-
request.referent.enhance_referent(key, value)
|
535
|
-
end
|
536
|
-
end
|
537
|
-
end
|
538
|
-
end
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
# From Table 18 in SFX General User's Guide 3.0.
|
543
|
-
def sfx_relationship_display(sfx_code)
|
544
|
-
sfx_code = sfx_code.to_s
|
545
|
-
# Most can simply be #humanized, a couple of over-rides
|
546
|
-
@sfx_relationship_display ||= {
|
547
|
-
"TRANSLATION_ENTRY" => "Translation",
|
548
|
-
}
|
549
|
-
|
550
|
-
display = @sfx_relationship_display[sfx_code]
|
551
|
-
display = sfx_code.humanize if display.nil?
|
552
|
-
|
553
|
-
return display
|
554
|
-
end
|
555
|
-
|
556
|
-
end
|
557
|
-
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# SQLite version 3.x
|
2
|
-
# gem install sqlite3
|
3
|
-
#
|
4
|
-
# Ensure the SQLite 3 gem is defined in your Gemfile
|
5
|
-
# gem 'sqlite3'
|
6
|
-
adfadf# Warning: The database defined as "test" will be erased and
|
7
|
-
# re-generated from your development database when you run "rake".
|
8
|
-
# Do not set this db to the same as development or production.
|
9
|
-
test:
|
10
|
-
adapter: sqlite3
|
11
|
-
database: db/test.sqlite3
|
12
|
-
pool: 5
|
13
|
-
timeout: 5000
|
14
|
-
|
15
|
-
production:
|
16
|
-
adapter: sqlite3
|
17
|
-
database: db/production.sqlite3
|
18
|
-
pool: 5
|
19
|
-
timeout: 5000
|
Binary file
|