umlaut 3.0.0alpha1

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.
Files changed (293) hide show
  1. data/LICENSE +7 -0
  2. data/README.md +49 -0
  3. data/Rakefile +37 -0
  4. data/app/assets/images/error.gif +0 -0
  5. data/app/assets/images/export_bg_bot.gif +0 -0
  6. data/app/assets/images/export_bg_mid.gif +0 -0
  7. data/app/assets/images/export_bg_top.gif +0 -0
  8. data/app/assets/images/famfamfam/book_open.png +0 -0
  9. data/app/assets/images/famfamfam/cross.png +0 -0
  10. data/app/assets/images/famfamfam/page_sound.gif +0 -0
  11. data/app/assets/images/famfamfam/page_text.gif +0 -0
  12. data/app/assets/images/famfamfam/page_up.gif +0 -0
  13. data/app/assets/images/famfamfam/page_white.png +0 -0
  14. data/app/assets/images/famfamfam/readme.html +1495 -0
  15. data/app/assets/images/famfamfam/tiny_cross.png +0 -0
  16. data/app/assets/images/frame_remove.gif +0 -0
  17. data/app/assets/images/ico_go.gif +0 -0
  18. data/app/assets/images/jhu_findit.gif +0 -0
  19. data/app/assets/images/list_closed.png +0 -0
  20. data/app/assets/images/list_open.png +0 -0
  21. data/app/assets/images/more_info.gif +0 -0
  22. data/app/assets/images/rails.png +0 -0
  23. data/app/assets/images/request.gif +0 -0
  24. data/app/assets/images/spinner.gif +0 -0
  25. data/app/assets/javascripts/umlaut/ajax_windows.js +35 -0
  26. data/app/assets/javascripts/umlaut/ensure_window_size.js.erb +34 -0
  27. data/app/assets/javascripts/umlaut/expand_contract_toggle.js +25 -0
  28. data/app/assets/javascripts/umlaut/search_autocomplete.js +46 -0
  29. data/app/assets/javascripts/umlaut/simple_visible_toggle.js +8 -0
  30. data/app/assets/javascripts/umlaut/update_html.js +152 -0
  31. data/app/assets/javascripts/umlaut.js +17 -0
  32. data/app/assets/stylesheets/umlaut.css +857 -0
  33. data/app/controllers/application_controller.rb +14 -0
  34. data/app/controllers/export_email_controller.rb +123 -0
  35. data/app/controllers/js_helper_controller.rb +10 -0
  36. data/app/controllers/link_router_controller.rb +87 -0
  37. data/app/controllers/open_search_controller.rb +9 -0
  38. data/app/controllers/resolve_controller.rb +288 -0
  39. data/app/controllers/resource_controller.rb +83 -0
  40. data/app/controllers/search_controller.rb +328 -0
  41. data/app/controllers/search_methods/sfx3.rb +148 -0
  42. data/app/controllers/search_methods/sfx4.rb +257 -0
  43. data/app/controllers/search_methods/sfx_api.rb +47 -0
  44. data/app/controllers/store_controller.rb +64 -0
  45. data/app/controllers/umlaut/controller_behavior.rb +20 -0
  46. data/app/controllers/umlaut/controller_logic.rb +96 -0
  47. data/app/controllers/umlaut/error_handling.rb +48 -0
  48. data/app/controllers/umlaut_controller.rb +112 -0
  49. data/app/helpers/application_helper.rb +4 -0
  50. data/app/helpers/emailer_helper.rb +43 -0
  51. data/app/helpers/export_email_helper.rb +34 -0
  52. data/app/helpers/open_search_helper.rb +7 -0
  53. data/app/helpers/resolve_helper.rb +225 -0
  54. data/app/helpers/search_helper.rb +50 -0
  55. data/app/helpers/umlaut/footer_helper.rb +64 -0
  56. data/app/helpers/umlaut/helper.rb +62 -0
  57. data/app/helpers/umlaut/html_head_helper.rb +37 -0
  58. data/app/helpers/umlaut/url_generation.rb +77 -0
  59. data/app/mailers/emailer.rb +48 -0
  60. data/app/models/clickthrough.rb +2 -0
  61. data/app/models/collection.rb +259 -0
  62. data/app/models/crossref_lookup.rb +2 -0
  63. data/app/models/dispatched_service.rb +58 -0
  64. data/app/models/permalink.rb +29 -0
  65. data/app/models/referent.rb +473 -0
  66. data/app/models/referent_value.rb +14 -0
  67. data/app/models/request.rb +449 -0
  68. data/app/models/service_response.rb +179 -0
  69. data/app/models/service_store.rb +59 -0
  70. data/app/models/service_type_value.rb +58 -0
  71. data/app/models/service_wave.rb +150 -0
  72. data/app/models/sfx_db/az_additional_title.rb +11 -0
  73. data/app/models/sfx_db/az_letter_group.rb +11 -0
  74. data/app/models/sfx_db/az_title.rb +38 -0
  75. data/app/models/sfx_db/az_title_v2.rb +34 -0
  76. data/app/models/sfx_db/isbn.rb +12 -0
  77. data/app/models/sfx_db/issn.rb +12 -0
  78. data/app/models/sfx_db/object.rb +35 -0
  79. data/app/models/sfx_db/object_portfolio.rb +6 -0
  80. data/app/models/sfx_db/publisher.rb +10 -0
  81. data/app/models/sfx_db/sfx_db_base.rb +54 -0
  82. data/app/models/sfx_db/target.rb +9 -0
  83. data/app/models/sfx_db/target_service.rb +10 -0
  84. data/app/models/sfx_db/title.rb +10 -0
  85. data/app/models/sfx_db.rb +10 -0
  86. data/app/models/sfx_url.rb +35 -0
  87. data/app/views/emailer/citation.text.erb +28 -0
  88. data/app/views/emailer/short_citation.text.erb +8 -0
  89. data/app/views/export_email/_email.html.erb +25 -0
  90. data/app/views/export_email/_send_email.html.erb +3 -0
  91. data/app/views/export_email/_send_txt.html.erb +3 -0
  92. data/app/views/export_email/_txt.html.erb +62 -0
  93. data/app/views/export_email/email.html.erb +3 -0
  94. data/app/views/export_email/send_email.html.erb +1 -0
  95. data/app/views/export_email/send_txt.html.erb +1 -0
  96. data/app/views/export_email/txt.html.erb +3 -0
  97. data/app/views/js_helper/loader.erb.js +13 -0
  98. data/app/views/layouts/umlaut.html.erb +52 -0
  99. data/app/views/open_search/index.html.erb +9 -0
  100. data/app/views/resolve/_api_in_progress.xml.erb +21 -0
  101. data/app/views/resolve/_background_progress.html.erb +51 -0
  102. data/app/views/resolve/_background_updater.html.erb +38 -0
  103. data/app/views/resolve/_citation.html.erb +87 -0
  104. data/app/views/resolve/_coins.html.erb +1 -0
  105. data/app/views/resolve/_compact_citation.html.erb +33 -0
  106. data/app/views/resolve/_cover_image.html.erb +35 -0
  107. data/app/views/resolve/_fulltext.html.erb +55 -0
  108. data/app/views/resolve/_help.html.erb +17 -0
  109. data/app/views/resolve/_holding.html.erb +91 -0
  110. data/app/views/resolve/_related_items.html.erb +35 -0
  111. data/app/views/resolve/_search_inside.html.erb +62 -0
  112. data/app/views/resolve/_section_display.html.erb +49 -0
  113. data/app/views/resolve/_service_errors.html.erb +29 -0
  114. data/app/views/resolve/_standard_response_item.html.erb +89 -0
  115. data/app/views/resolve/api.xml.builder +72 -0
  116. data/app/views/resolve/background_status.html.erb +26 -0
  117. data/app/views/resolve/index.html.erb +73 -0
  118. data/app/views/resolve/partial_html_sections.xml.erb +30 -0
  119. data/app/views/search/_a_to_z.html.erb +6 -0
  120. data/app/views/search/_citation.html.erb +94 -0
  121. data/app/views/search/_pager.html.erb +60 -0
  122. data/app/views/search/books.html.erb +103 -0
  123. data/app/views/search/journal_search.html.erb +90 -0
  124. data/app/views/search/journals.html.erb +167 -0
  125. data/app/views/search/opensearch_description.rxml +10 -0
  126. data/app/views/testing/index.html.erb +1 -0
  127. data/app/views/umlaut/README +5 -0
  128. data/app/views/umlaut/error.html.erb +45 -0
  129. data/db/migrate/01_umlaut_init.rb +113 -0
  130. data/db/orig_fixed_data/service_type_values.yml +120 -0
  131. data/db/seeds.rb +7 -0
  132. data/lib/CronTab.rb +192 -0
  133. data/lib/aws_product_sign.rb +146 -0
  134. data/lib/exlibris/aleph/patron.rb +64 -0
  135. data/lib/exlibris/aleph/record.rb +54 -0
  136. data/lib/exlibris/aleph/rest_api.rb +29 -0
  137. data/lib/exlibris/primo/holding.rb +192 -0
  138. data/lib/exlibris/primo/rsrc.rb +17 -0
  139. data/lib/exlibris/primo/searcher.rb +276 -0
  140. data/lib/exlibris/primo/source/aleph.rb +46 -0
  141. data/lib/exlibris/primo/source/distribution/nyu_aleph.rb +323 -0
  142. data/lib/exlibris/primo/toc.rb +17 -0
  143. data/lib/exlibris/primo_ws.rb +140 -0
  144. data/lib/generators/templates/umlaut_services.yml +237 -0
  145. data/lib/generators/umlaut/asset_hooks_generator.rb +44 -0
  146. data/lib/generators/umlaut/install_generator.rb +110 -0
  147. data/lib/hip3/bib.rb +291 -0
  148. data/lib/hip3/bib_searcher.rb +302 -0
  149. data/lib/hip3/custom_field_lookup.rb +44 -0
  150. data/lib/hip3/holding.rb +50 -0
  151. data/lib/hip3/item.rb +65 -0
  152. data/lib/hip3/receipt.rb +7 -0
  153. data/lib/hip3/serial_copy.rb +82 -0
  154. data/lib/holding.rb +32 -0
  155. data/lib/marc_helper.rb +254 -0
  156. data/lib/metadata_helper.rb +312 -0
  157. data/lib/opensearch_feed.rb +398 -0
  158. data/lib/opensearch_query.rb +98 -0
  159. data/lib/referent_filter.rb +16 -0
  160. data/lib/referent_filters/dissertation_catch.rb +45 -0
  161. data/lib/section_renderer.rb +503 -0
  162. data/lib/service.rb +336 -0
  163. data/lib/service_adaptors/ajax_export.rb +37 -0
  164. data/lib/service_adaptors/amazon.rb +412 -0
  165. data/lib/service_adaptors/blacklight.rb +327 -0
  166. data/lib/service_adaptors/book_finder.rb +40 -0
  167. data/lib/service_adaptors/bx.rb +51 -0
  168. data/lib/service_adaptors/cover_thing.rb +73 -0
  169. data/lib/service_adaptors/elsevier_cover.rb +57 -0
  170. data/lib/service_adaptors/email_export.rb +10 -0
  171. data/lib/service_adaptors/ezproxy.rb +171 -0
  172. data/lib/service_adaptors/google_book_search.rb +442 -0
  173. data/lib/service_adaptors/gpo.rb +124 -0
  174. data/lib/service_adaptors/hathi_trust.rb +308 -0
  175. data/lib/service_adaptors/hip3_service.rb +150 -0
  176. data/lib/service_adaptors/hip_holding_search.rb +237 -0
  177. data/lib/service_adaptors/internet_archive.rb +488 -0
  178. data/lib/service_adaptors/isbn_db.rb +86 -0
  179. data/lib/service_adaptors/isi.rb +258 -0
  180. data/lib/service_adaptors/jcr.rb +146 -0
  181. data/lib/service_adaptors/opac.rb +351 -0
  182. data/lib/service_adaptors/open_library.rb +316 -0
  183. data/lib/service_adaptors/open_library_cover.rb +73 -0
  184. data/lib/service_adaptors/primo_service.rb +392 -0
  185. data/lib/service_adaptors/primo_source.rb +78 -0
  186. data/lib/service_adaptors/pubmed.rb +133 -0
  187. data/lib/service_adaptors/request_to_fixture.rb +68 -0
  188. data/lib/service_adaptors/scopus.rb +295 -0
  189. data/lib/service_adaptors/sfx-new.rb +557 -0
  190. data/lib/service_adaptors/sfx.rb +566 -0
  191. data/lib/service_adaptors/sfx_backchannel_record.rb +69 -0
  192. data/lib/service_adaptors/txt_holding_export.rb +32 -0
  193. data/lib/service_adaptors/ulrichs_cover.rb +57 -0
  194. data/lib/service_adaptors/ulrichs_link.rb +47 -0
  195. data/lib/service_adaptors/worldcat.rb +116 -0
  196. data/lib/service_adaptors/worldcat_identities.rb +591 -0
  197. data/lib/tasks/umlaut.rake +134 -0
  198. data/lib/umlaut/default_configuration.rb +5 -0
  199. data/lib/umlaut/routes.rb +136 -0
  200. data/lib/umlaut/version.rb +3 -0
  201. data/lib/umlaut.rb +37 -0
  202. data/lib/umlaut_configurable.rb +343 -0
  203. data/lib/umlaut_http.rb +100 -0
  204. data/lib/xml_schema_helper.rb +109 -0
  205. data/test/dummy/Rakefile +7 -0
  206. data/test/dummy/app/assets/javascripts/application.js +13 -0
  207. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  208. data/test/dummy/app/controllers/application_controller.rb +3 -0
  209. data/test/dummy/app/controllers/umlaut_controller.rb +112 -0
  210. data/test/dummy/app/helpers/application_helper.rb +2 -0
  211. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  212. data/test/dummy/config/application.rb +45 -0
  213. data/test/dummy/config/boot.rb +10 -0
  214. data/test/dummy/config/database-jhu.yml +44 -0
  215. data/test/dummy/config/database.yml +25 -0
  216. data/test/dummy/config/environment.rb +5 -0
  217. data/test/dummy/config/environments/development.rb +34 -0
  218. data/test/dummy/config/environments/production.rb +60 -0
  219. data/test/dummy/config/environments/test.rb +39 -0
  220. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  221. data/test/dummy/config/initializers/inflections.rb +10 -0
  222. data/test/dummy/config/initializers/mime_types.rb +5 -0
  223. data/test/dummy/config/initializers/secret_token.rb +7 -0
  224. data/test/dummy/config/initializers/session_store.rb +8 -0
  225. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  226. data/test/dummy/config/locales/en.yml +5 -0
  227. data/test/dummy/config/routes.rb +61 -0
  228. data/test/dummy/config/umlaut_services.yml +237 -0
  229. data/test/dummy/config.ru +4 -0
  230. data/test/dummy/db/migrate/20111228211210_umlaut_init.rb +113 -0
  231. data/test/dummy/db/schema.rb +124 -0
  232. data/test/dummy/log/development.log +12981 -0
  233. data/test/dummy/log/production.log +0 -0
  234. data/test/dummy/public/404.html +26 -0
  235. data/test/dummy/public/422.html +26 -0
  236. data/test/dummy/public/500.html +26 -0
  237. data/test/dummy/public/favicon.ico +0 -0
  238. data/test/dummy/script/rails +6 -0
  239. data/test/dummy/tmp/cache/assets/C5F/340/sprockets%2F99692920160b7a279b86a80415b79db7 +0 -0
  240. data/test/dummy/tmp/cache/assets/C70/4D0/sprockets%2F034ad2036e623081bd352800786dfe80 +0 -0
  241. data/test/dummy/tmp/cache/assets/C73/920/sprockets%2Fd371318f22900492fd180f17c5e2a504 +9268 -0
  242. data/test/dummy/tmp/cache/assets/C80/980/sprockets%2Fc94807409c1523d43e18d25f35d93c41 +0 -0
  243. data/test/dummy/tmp/cache/assets/C8F/780/sprockets%2Fe47e28558116fb5f8038754e60d1961d +11769 -0
  244. data/test/dummy/tmp/cache/assets/CAA/EB0/sprockets%2F1d179210e8b76f1ea63c802688a015e4 +9271 -0
  245. data/test/dummy/tmp/cache/assets/CBB/9C0/sprockets%2F706f28923fb754cad04b9107c89986a1 +0 -0
  246. data/test/dummy/tmp/cache/assets/CBF/B60/sprockets%2F08ca89671549936265dcb673bf02e36f +0 -0
  247. data/test/dummy/tmp/cache/assets/CC9/9F0/sprockets%2F306166316e2cafd13c15e62b51a2339d +0 -0
  248. data/test/dummy/tmp/cache/assets/CF6/F20/sprockets%2F5b2ffa1103079dfd555197838f87a99f +0 -0
  249. data/test/dummy/tmp/cache/assets/CF7/2B0/sprockets%2F25a7c73655bd3598173b39d9f98bcd46 +862 -0
  250. data/test/dummy/tmp/cache/assets/CFE/080/sprockets%2F37fe9f4255baddbd549a659914929398 +0 -0
  251. data/test/dummy/tmp/cache/assets/D22/060/sprockets%2F9aec77b768e91a802d284271c58e2f7e +21357 -0
  252. data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  253. data/test/dummy/tmp/cache/assets/D33/6D0/sprockets%2F500129c57f1146e556ec3aacd6cd38c1 +0 -0
  254. data/test/dummy/tmp/cache/assets/D33/FD0/sprockets%2F2ba0b4e6334a77b923e5f770381bb2bf +0 -0
  255. data/test/dummy/tmp/cache/assets/D42/C20/sprockets%2Fbcf14e437b1582bf93b77670acf8e090 +21353 -0
  256. data/test/dummy/tmp/cache/assets/D50/A30/sprockets%2F7d8b294ac433db5d056538f8cf7c66b9 +0 -0
  257. data/test/dummy/tmp/cache/assets/D54/ED0/sprockets%2F71c9fa01091d432b131da3bb73faf3d4 +872 -0
  258. data/test/dummy/tmp/cache/assets/D65/590/sprockets%2Fc1bb92fc3406a126b7dd302edc96d629 +0 -0
  259. data/test/dummy/tmp/cache/assets/D71/6B0/sprockets%2Fde558b71b494cf09b1bf055c8dff0353 +0 -0
  260. data/test/dummy/tmp/cache/assets/D72/610/sprockets%2Fa8c708eeb30ef93de34d755d4f45d023 +859 -0
  261. data/test/dummy/tmp/cache/assets/D76/AD0/sprockets%2Fe2158cde93188cf5ab6457bc6d6602ec +0 -0
  262. data/test/dummy/tmp/cache/assets/D7A/E40/sprockets%2F9622ffcc499a57627cd1bb18fe31b8e4 +11772 -0
  263. data/test/dummy/tmp/cache/assets/D84/210/sprockets%2Fabd0103ccec2b428ac62c94e4c40b384 +0 -0
  264. data/test/dummy/tmp/cache/assets/D9B/770/sprockets%2F8aacf02eb7dbb0949704b28f27b87e0b +0 -0
  265. data/test/dummy/tmp/cache/assets/DA6/A80/sprockets%2F92e26d8e58d5bcc8b8f6c25d1b05b9c1 +0 -0
  266. data/test/dummy/tmp/cache/assets/DE8/790/sprockets%2Fd1333bde2b9aafcc712d11dd09ab35d8 +0 -0
  267. data/test/dummy/tmp/cache/assets/DF7/F30/sprockets%2F7bc16c4109b17fabe29f8ddbbf732d1c +374 -0
  268. data/test/dummy/tmp/cache/assets/E03/570/sprockets%2F493bdc0ac14cd4f57fdfe4253f992bde +0 -0
  269. data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  270. data/test/dummy/tmp/cache/assets/E0B/4B0/sprockets%2F7988df51a61c81ce6ede4a2d4c8cce4f +377 -0
  271. data/test/dummy/tmp/cache/assets/E5F/960/sprockets%2Fdc007b6cad5c7ef08e33ec28cfff0ef6 +0 -0
  272. data/test/fixtures/dispatched_services.yml +5 -0
  273. data/test/fixtures/permalinks.yml +5 -0
  274. data/test/fixtures/referent_values.yml +1734 -0
  275. data/test/fixtures/referents.yml +156 -0
  276. data/test/fixtures/requests.yml +284 -0
  277. data/test/fixtures/service_responses.yml +5 -0
  278. data/test/fixtures/sfx_urls.yml +4 -0
  279. data/test/performance/browsing_test.rb +9 -0
  280. data/test/test_helper.rb +10 -0
  281. data/test/umlaut_test.rb +7 -0
  282. data/test/unit/aleph_patron_test.rb +39 -0
  283. data/test/unit/aleph_record_benchmarks.rb +28 -0
  284. data/test/unit/aleph_record_test.rb +30 -0
  285. data/test/unit/aws_product_sign_test.rb +93 -0
  286. data/test/unit/collection_test.rb +76 -0
  287. data/test/unit/google_book_search_test.rb +101 -0
  288. data/test/unit/primo_searcher_test.rb +403 -0
  289. data/test/unit/primo_service_test.rb +939 -0
  290. data/test/unit/primo_ws_test.rb +131 -0
  291. data/test/unit/service_response_test.rb +9 -0
  292. data/test/unit/service_test.rb +33 -0
  293. metadata +580 -0
@@ -0,0 +1,14 @@
1
+ # Filters added to this controller apply to all controllers in the application.
2
+ # Likewise, all the methods added will be available for all controllers.
3
+
4
+ class ApplicationController < ActionController::Base
5
+
6
+
7
+ protect_from_forgery
8
+
9
+
10
+
11
+
12
+ end
13
+
14
+
@@ -0,0 +1,123 @@
1
+ class ExportEmailController < UmlautController
2
+
3
+ before_filter :load_objects
4
+ layout Proc.new { |controller|
5
+ if (controller.request.xhr? ||
6
+ controller.params["X-Requested-With"] == "XmlHttpRequest")
7
+ nil
8
+ else
9
+ config.layout
10
+ end
11
+ }
12
+
13
+ def load_objects
14
+ @svc_response = ServiceResponse.find(params[:id])
15
+ @user_request = @svc_response.request if @svc_response
16
+ end
17
+
18
+ def email
19
+
20
+ end
21
+
22
+ def txt
23
+
24
+ end
25
+
26
+ def send_email
27
+ @email = params[:email]
28
+ @fulltexts = @user_request.get_service_type('fulltext', { :refresh=>true })
29
+ @holdings = @user_request.get_service_type('holding', { :refresh=>true })
30
+
31
+ if valid_email?
32
+ Emailer.citation(@email, @user_request, @fulltexts, @holdings).deliver
33
+ respond_to do |format|
34
+ format.html { render }
35
+ end
36
+ else
37
+ @partial = "email"
38
+ flash[:error] = email_validation_error
39
+ redirect_to params_preserve_xhr(params.merge(:action => "email"))
40
+ end
41
+
42
+ end
43
+
44
+ def send_txt
45
+ @number = params[:number]
46
+ # Remove any punctuation or spaces etc
47
+ @number.gsub!(/[^\d]/, '') if @number
48
+
49
+
50
+ @provider = params[:provider]
51
+
52
+ @email = "#{@number}@#{@provider}" unless @number.nil? or @provider.nil?
53
+
54
+ @holding_id = params[:holding]
55
+
56
+ if valid_txt_number? && valid_txt_holding?
57
+ Emailer.short_citation(@email, @user_request, location(@holding_id), call_number(@holding_id)).deliver
58
+
59
+ render # send_txt.rhtml
60
+ else
61
+ flash[:error] = txt_validation_error
62
+ redirect_to params_preserve_xhr(params.merge(:action => "txt"))
63
+ end
64
+ end
65
+
66
+ private
67
+ def valid_txt_number?
68
+ return (! @number.blank?) && @number.length == 10
69
+ end
70
+
71
+ def valid_txt_holding?
72
+ return ! @holding_id.blank?
73
+ end
74
+
75
+ def valid_email?
76
+ return @email =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
77
+ end
78
+
79
+
80
+ def txt_validation_error
81
+ rv = ""
82
+ unless valid_txt_number? && valid_txt_holding?
83
+ rv += "<div class=\"validation_errors\">"
84
+ rv += "<span>Please provide the following:</span>"
85
+ rv += "<ul>"
86
+ rv += "<li>a valid number</li>" unless valid_txt_number?
87
+ rv += "<li>the item you wish to send</li>" unless valid_txt_holding?
88
+ rv += "</ul>"
89
+ rv += "</div>"
90
+ end
91
+ return rv
92
+ end
93
+
94
+ def email_validation_error
95
+ rv = ""
96
+ unless valid_email?
97
+ rv += "<div class=\"validation_errors\">"
98
+ rv += "<span>Please provide the following:</span>"
99
+ rv += "<ul>"
100
+ rv += "<li>a valid email address</li>"
101
+ rv += "</ul>"
102
+ rv += "</div>"
103
+ end
104
+ return rv
105
+ end
106
+
107
+ def holding(id)
108
+ return ServiceResponse.find(id) unless id.nil?
109
+ end
110
+
111
+ def location(id)
112
+ return holding(id).view_data[:collection_str] unless holding(id).nil?
113
+ end
114
+
115
+ def call_number(id)
116
+ return holding(id).view_data[:call_number] unless holding(id).nil?
117
+ end
118
+
119
+
120
+
121
+
122
+
123
+ end
@@ -0,0 +1,10 @@
1
+ # Controller that just has one helper action for external sites using
2
+ # our Javascript HTML updater stuff.
3
+ class JsHelperController < UmlautController
4
+
5
+ def loader
6
+ @generate_urls_with_host = true
7
+ render :template => "js_helper/loader.erb.js"
8
+ end
9
+
10
+ end
@@ -0,0 +1,87 @@
1
+ # All clicks on a ServiceResponse are actually sent through this controller,
2
+ # which redirects to actual destination. That allows statistic logging,
3
+ # as well as special behavior (like EZProxy redirection, or showing in a
4
+ # bannered frameset).
5
+ require 'cgi'
6
+ class LinkRouterController < UmlautController
7
+ def index
8
+
9
+ # Capture mysterious exception for better error reporting.
10
+ begin
11
+ svc_response = ServiceResponse.find(params[:id])
12
+ rescue ActiveRecord::RecordNotFound => exception
13
+ # Usually this happens when it's a spider trying an old link. "go" links
14
+ # don't stay good forever! Bad spider, ignoring our robots.txt.
15
+ log_error_with_context(exception, :warn)
16
+
17
+ raise exception# will be caught by top level rescue_from
18
+ end
19
+
20
+
21
+ @collection = self.create_collection
22
+
23
+ clickthrough = Clickthrough.new
24
+ clickthrough.request_id = svc_response.request_id
25
+ clickthrough.service_response_id = svc_response.id
26
+ clickthrough.save
27
+
28
+
29
+ redirect_to calculate_url_for_response(svc_response)
30
+ end
31
+
32
+ protected
33
+
34
+ # Must return a Hash where each key is a unique service name, and
35
+ # each value a hash that defines a service. Like the hash in services.yml
36
+ # under default/services. By default, this method in fact just loads
37
+ # and returns that hash, but can be over-ridden with local logic for
38
+ # determining proper list of services for current request.
39
+ #
40
+ # Local over-ride could even in theory return a custom subclass of Collection,
41
+ # with customized dispatch behavior. Probably not a great idea though.
42
+ def create_collection
43
+ # trim out ones with disabled:true
44
+ services = ServiceStore.config["default"]["services"].reject {|id, hash| hash["disabled"] == true}
45
+
46
+ return Collection.new(@user_request, services)
47
+ end
48
+
49
+
50
+ # Used to calculate a destination/target url for an Umlaut response item.
51
+ #
52
+ # Pass in a ServiceType join object (not actually a ServiceResponse, sorry)
53
+ # Calculates the URL for it, and then runs our link_out_filters on it,
54
+ # returning the final calculated url.
55
+ #
56
+ # Also requires a rails 'params' object, since url calculation sometimes
57
+ # depends on submitted HTTP params.
58
+ #
59
+ # Used from LinkController's index,
60
+ def calculate_url_for_response(svc_response)
61
+ svc = ServiceStore.instantiate_service!(svc_response.service_id, nil)
62
+
63
+ destination = svc.response_url(svc_response, params)
64
+
65
+ # if response_url returned a string, it's an external url and we're
66
+ # done. If it's something else, usually a hash, then pass it to
67
+ # url_for to generate a url.
68
+ if destination.kind_of?(String)
69
+ url = destination
70
+
71
+ # Call link_out_filters, if neccesary.
72
+ # These are services listed as task: link_out_filter in services.yml
73
+ (1..9).each do |priority|
74
+ @collection.link_out_service_level( priority ).each do |filter|
75
+ filtered_url = filter.link_out_filter(url, svc_response)
76
+ url = filtered_url if filtered_url
77
+ end
78
+ end
79
+ return url
80
+ else
81
+ return url_for(params_preserve_xhr(destination))
82
+ end
83
+ end
84
+
85
+
86
+
87
+ end
@@ -0,0 +1,9 @@
1
+ class OpenSearchController < UmlautController
2
+
3
+ layout false
4
+
5
+
6
+ def index
7
+ render(:content_type => "application/xml")
8
+ end
9
+ end
@@ -0,0 +1,288 @@
1
+ # Requests to the Resolve controller are OpenURLs.
2
+ # There is one exception: Instead of an OpenURL, you can include the
3
+ # parameter umlaut.request_id=[some id] to hook up to a pre-existing
4
+ # umlaut request (that presumably was an OpenURL).
5
+
6
+ class ResolveController < UmlautController
7
+
8
+ before_filter :init_processing
9
+ # Init processing will look at this list, and for actions mentioned,
10
+ # will not create a @user_request if an existing one can't be found.
11
+ # Used for actions meant only to deal with existing requests.
12
+ @@no_create_request_actions = ['background_update']
13
+ after_filter :save_request
14
+
15
+ # Take layout from config, default to resolve_basic.rhtml layout.
16
+ layout umlaut_config.resolve_layout,
17
+ :except => [:partial_html_sections]
18
+
19
+
20
+ def index
21
+ self.service_dispatch()
22
+
23
+ # check for menu skipping configuration. link is a ServiceType object
24
+ link = should_skip_menu
25
+ if ( ! link.nil? )
26
+
27
+ redirect_to url_for(:controller => "link_router",
28
+ :action => "index",
29
+ :id => link.id )
30
+ else
31
+ # Render configed view, if configed, or default view if not.
32
+ render umlaut_config.resolve_view
33
+ end
34
+
35
+ end
36
+
37
+ # inputs an OpenURL request into the system and stores it, but does
38
+ # NOT actually dispatch services to provide a response. Will usually
39
+ # be called by software, not a human browser. Sometimes
40
+ # it's useful to do this as a first step before redirecting the user
41
+ # to the actual resolve action for the supplied request--for instance,
42
+ # when the OpenURL metadata comes in a POST and can't be redirected.
43
+ def register_request
44
+ # init before filter already took care of setting up the request.
45
+ @user_request.save!
46
+
47
+ # Return data in headers allowing client to redirect user
48
+ # to view actual response.
49
+ headers["x-umlaut-request_id"] = @user_request.id
50
+ headers["x-umlaut-resolve_url"] = url_for( :controller => 'resolve', 'umlaut.request_id'.to_sym => @user_request.id )
51
+ headers["x-umlaut-permalink_url"] = permalink_url( request, @user_request )
52
+
53
+ # Return empty body. Once we have the xml response done,
54
+ # this really ought to return an xml response, but with
55
+ # no service responses yet available.
56
+ render(:nothing => true)
57
+ end
58
+
59
+ # Useful for developers, generate a coins. Start from
60
+ # search/journals?umlaut.display_coins=true
61
+ # or search/books?umlaut.display_coins=true
62
+ def display_coins
63
+
64
+ end
65
+
66
+ # Display a non-javascript background service status page--or
67
+ # redirect back to index if we're done.
68
+ def background_status
69
+
70
+ unless ( @user_request.any_services_in_progress? )
71
+
72
+ # Just redirect to ordinary index, no need to show progress status.
73
+ # Include request.id, but also context object kev.
74
+
75
+ params_hash =
76
+ {:controller=>"resolve",
77
+ :action=>'index',
78
+ 'umlaut.skip_resolve_menu'.to_sym => params['umlaut.skip_resolve_menu'],
79
+ 'umlaut.request_id'.to_sym => @user_request.id }
80
+
81
+ url = url_for_with_co( params_hash, @user_request.to_context_object )
82
+
83
+ redirect_to( url )
84
+ else
85
+ # If we fall through, we'll show the background_status view, a non-js
86
+ # meta-refresh update on progress of background services.
87
+ # Your layout should respect this instance var--it will if it uses
88
+ # the resolve_head_content partial, which it should.
89
+ @meta_refresh_self = umlaut_config.lookup!("poll_wait_seconds", 4)
90
+ end
91
+ end
92
+
93
+ # This action is for external callers. An external caller _could_ get
94
+ # data as xml or json or whatever. But Umlaut already knows how to render
95
+ # it. What if the external caller wants the rendered content, but in
96
+ # discrete letter packets, a packet of HTML for each ServiceTypeValue?
97
+ # This does that, and also let's the caller know if background
98
+ # services are still running and should be refreshed, and gives
99
+ # the caller a URL to refresh from if neccesary.
100
+
101
+ def partial_html_sections
102
+ # Tell our application_helper#url_for to generate urls with hostname
103
+ @generate_urls_with_host = true
104
+
105
+ # Force background status to be the spinner--default js way of putting
106
+ # spinner in does not generally work through ajax techniques.
107
+ @force_bg_progress_spinner = true
108
+
109
+ # Mark that we're doing a partial generation, because it might
110
+ # matter later.
111
+ @generating_embed_partials = true
112
+
113
+ # Run the request if neccesary.
114
+ self.service_dispatch()
115
+ @user_request.save!
116
+
117
+ self.api_render()
118
+
119
+ end
120
+
121
+ def api
122
+
123
+ # Run the request if neccesary.
124
+ self.service_dispatch()
125
+ @user_request.save!
126
+
127
+ api_render()
128
+
129
+ end
130
+
131
+
132
+
133
+ def rescue_action_in_public(exception)
134
+ render(:template => "error/resolve_error", :status => 500 )
135
+ end
136
+
137
+ protected
138
+
139
+
140
+ # Must return a Hash where each key is a unique service name, and
141
+ # each value a hash that defines a service. Like the hash in services.yml
142
+ # under default/services. By default, this method in fact just loads
143
+ # and returns that hash, but can be over-ridden with local logic for
144
+ # determining proper list of services for current request.
145
+ #
146
+ # Local over-ride could even in theory return a custom subclass of Collection,
147
+ # with customized dispatch behavior. Probably not a great idea though.
148
+ def create_collection
149
+ # trim out ones with disabled:true
150
+ services = ServiceStore.config["default"]["services"].reject {|id, hash| hash && hash["disabled"] == true}
151
+
152
+ return Collection.new(@user_request, services)
153
+ end
154
+
155
+ # Retrives or sets up the relevant Umlaut Request, and returns it.
156
+ def init_processing
157
+ # intentionally trigger creation of session if it didn't already exist
158
+ # because we need to track session ID for caching. Can't find any
159
+ # way to force session creation without setting a value in session,
160
+ # so we do this weird one.
161
+ session[nil] = nil
162
+
163
+ # Create an UmlautRequest object.
164
+ options = {}
165
+ if ( @@no_create_request_actions.include?(params[:action]) )
166
+ options[:allow_create] = false
167
+ end
168
+ @user_request ||= Request.find_or_create(params, session, request, options )
169
+
170
+ # If we chose not to create a request and still don't have one, bale out.
171
+ return unless @user_request
172
+
173
+ @user_request.save!
174
+
175
+ @collection = create_collection
176
+ end
177
+
178
+ def save_request
179
+ @user_request.save!
180
+ end
181
+
182
+
183
+ # Based on app config and context, should we skip the resolve
184
+ # menu and deliver a 'direct' link? Returns nil if menu
185
+ # should be displayed, or the ServiceType join object
186
+ # that should be directly linked to.
187
+ def should_skip_menu
188
+ # From usabilty test, do NOT skip if coming from A-Z list/journal lookup.
189
+ # First, is it over-ridden in url?
190
+ if ( params['umlaut.skip_resolve_menu'] == 'false')
191
+ return nil
192
+ elsif ( params['umlaut.skip_resolve_menu_for_type'] )
193
+ skip = {:service_types => params['umlaut.skip_resolve_menu_for_type'].split(",") }
194
+ end
195
+
196
+ # Otherwise if not from url, load from app config
197
+ skip ||= umlaut_config.skip_resolve_menu if skip.nil?
198
+
199
+ if (skip.kind_of?( FalseClass ))
200
+ # nope
201
+ return nil
202
+ end
203
+
204
+ return_value = nil
205
+ if (skip.kind_of?(Hash) )
206
+ # excluded rfr_ids?
207
+ exclude_rfr_ids = skip[:excluded_rfr_ids]
208
+ rfr_id = @user_request.referrer_id
209
+ return nil if exclude_rfr_ids != nil && exclude_rfr_ids.find {|i| i == rfr_id}
210
+
211
+ # Services to skip for?
212
+ skip[:service_types].each do | service |
213
+ service = ServiceTypeValue[service] unless service.kind_of?(ServiceTypeValue)
214
+
215
+ candidates =
216
+ @user_request.service_responses.find(:all,
217
+ :conditions => ["service_type_value_name = ?", service.name])
218
+
219
+ return_value = candidates.first
220
+
221
+ end
222
+
223
+ # But wait, make sure it's included in :services if present.
224
+ if (return_value && skip[:services] )
225
+ return_value = nil unless skip[:services].include?( return_value.service_id )
226
+ end
227
+ elsif (skip.kind_of?(Proc ))
228
+ return_value = skip.call( :request => @user_request )
229
+
230
+ else
231
+ logger.error( "Unexpected value in config 'skip_resolve_menu'; assuming false." )
232
+ end
233
+
234
+ return return_value;
235
+ end
236
+
237
+
238
+
239
+
240
+ # Uses an "umlaut.response_format" param to return either
241
+ # XML or JSON(p). Is called from an action that has a standardly rendered
242
+ # Rails template that delivers XML. Will convert that standardly rendered
243
+ # template output to json using built in converters if needed.
244
+ def api_render
245
+ # Format?
246
+ request.format = "xml" if request.format.html? # weird hack to support legacy behavior, with xml as default
247
+ if params["umlaut.response_format"] == "jsonp"
248
+ request.format = "json"
249
+ params["umlaut.jsonp"] ||= "umlautLoaded"
250
+ elsif params["umlaut.response_format"]
251
+ request.format = params["umlaut.response_format"]
252
+ end
253
+
254
+
255
+ respond_to do |format|
256
+ format.xml do
257
+ render(:layout => false)
258
+ end
259
+
260
+ format.json do
261
+ # get the xml in a string
262
+ xml_str =
263
+ with_format(:xml) do
264
+ render_to_string(:layout=>false)
265
+ end
266
+ # convert to hash. For some reason the ActionView::OutputBuffer
267
+ # we actually have (which looks like a String but isn't exactly)
268
+ # can't be converted to a hash, we need to really force String
269
+ # with #to_str
270
+ data_as_hash = Hash.from_xml( xml_str.to_str )
271
+ # And conver to json. Ta-da!
272
+ json_str = data_as_hash.to_json
273
+
274
+ # Handle jsonp, deliver JSON inside a javascript function call,
275
+ # with function name specified in parameters.
276
+ render(:json => json_str, :callback => params["umlaut.jsonp"] )
277
+ end
278
+ end
279
+ end
280
+
281
+ def service_dispatch()
282
+ @collection.dispatch_services!
283
+ end
284
+
285
+
286
+
287
+ end
288
+