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,237 @@
1
+
2
+ # Configure what service plugins are used by Umlaut. This skeleton file
3
+ # has been generated into your app to help you get started.
4
+ #
5
+ # If a service has "disabled:true", it's currently turned off.
6
+ #
7
+ # Some services require local api key or connection details as config.
8
+ # Most services take other options for custom configuration too, not
9
+ # all options are neccesarily listed as examples here, see source
10
+ # or source-generated docs for more info.
11
+
12
+ default:
13
+ services:
14
+
15
+ # SFX has pubmed lookup built in, so this service not generally
16
+ # needed with SFX, but included here as an example of it's availability
17
+ Pubmed:
18
+ disabled: true
19
+ priority: 0
20
+
21
+ # Priority 3
22
+
23
+ SFX:
24
+ type: Sfx
25
+ disabled: true
26
+ display_name: Find It
27
+ base_url: YOUR_SFX_BASE_URL
28
+ priority: 3
29
+
30
+
31
+ # First half of Amazon, run in foreground, get metadata and cover images.
32
+ Amazon:
33
+ disabled: true
34
+ display_name: Amazon.com
35
+ type: Amazon
36
+ url: http://webservices.amazon.com/onca/xml
37
+ api_key: "NEED_API_KEY"
38
+ secret_key: "NEED_SECRET_KEY"
39
+ associate_tag: "NEED_ASSOCIATE_ID"
40
+ priority: 3
41
+ service_types:
42
+ - abstract
43
+ - referent_enhance
44
+ - cover_image
45
+
46
+
47
+ # Priority c : Background
48
+
49
+ # Second half of Amazon. It's Slow to lookup highlighted_link and search_inside
50
+ # availability, so we do it in a bg wave.
51
+ Amazon_bg:
52
+ type: Amazon
53
+ disabled: true
54
+ api_key: "NEED_API_KEY"
55
+ secret_key: "NEED_SECRET_KEY"
56
+ associate_tag: "NEED_ASSOCIATE_ID"
57
+ priority: c
58
+ make_aws_call: false
59
+ service_types:
60
+ - highlighted_link
61
+ - search_inside
62
+ - excerpts
63
+
64
+
65
+
66
+ CoverThing:
67
+ type: CoverThing
68
+ disabled: true
69
+ developer_key: YOUR_LT_KEY
70
+ priority: c
71
+ # Pre-empted by says if we already have a cover_image response
72
+ # from somewhere else that runs earlier, don't run this.
73
+ preempted_by:
74
+ existing_type: cover_image
75
+
76
+ ElsevierCover:
77
+ type: ElsevierCover
78
+ priority: c
79
+
80
+ UlrichsCover:
81
+ type: UlrichsCover
82
+ priority: c
83
+
84
+ GoogleBookSearch:
85
+ type: GoogleBookSearch
86
+ disabled: true
87
+ priority: c
88
+ api_key: 'YOUR_GBS_API_KEY'
89
+
90
+ Ulrichs:
91
+ display_name: "Ulrich's Directory"
92
+ type: UlrichsLink
93
+ priority: c
94
+
95
+ IsbnDb:
96
+ display_name: isbndb.com
97
+ disabled: true
98
+ type: IsbnDb
99
+ priority: c
100
+ access_key: YOUR_ISBNDB_ACCESS_KEY
101
+
102
+ InternetArchive:
103
+ display_name: the Internet Archive
104
+ type: InternetArchive
105
+ priority: c
106
+ # disable audio results? uncomment:
107
+ #num_results_for_types:
108
+ # audio: 0
109
+
110
+
111
+ # Priority d
112
+
113
+ HathiTrust:
114
+ type: HathiTrust
115
+ priority: d
116
+ # Uncomment to link through this 'internal' URL instead
117
+ # of following permalinks. jrochkind does this to use
118
+ # a WAYFless shibboleth login with EZProxy.
119
+ #direct_link_base: 'https://babel.hathitrust.org/shcgi/'
120
+ #
121
+ # This next says:
122
+ # Don't add HathiTrust fulltext if there's already a
123
+ # GoogleBookSearch fulltext. Still add other HT response
124
+ # types.
125
+ preempted_by:
126
+ self_type: fulltext
127
+ existing_service: GoogleBookSearch
128
+ existing_type: fulltext
129
+
130
+ EmailExport:
131
+ type: EmailExport
132
+ priority: d
133
+
134
+ TxtHoldingExport:
135
+ type: TxtHoldingExport
136
+ priority: d
137
+
138
+
139
+
140
+ ScopusCitations:
141
+ type: Scopus
142
+ disabled: true
143
+ priority: c
144
+ json_api_key: YOUR_SCOPUS_API_KEY
145
+ partner_id: YOUR_SCOPUS_PARTNER_ID
146
+ link_salt_key: "YOUR_SCOPUS_LINK_SALT_KEY"
147
+
148
+ # Web of Knowledge API has no api key, but your
149
+ # IP needs to be registered with them. See source docs
150
+ # for how.
151
+ IsiCitations:
152
+ type: Isi
153
+ disabled: true
154
+ priority: c
155
+
156
+ # Thomson JCR LAMR api has no api key, but your
157
+ # IP needs to be registered with them. Same registraiton
158
+ # as for ISI WoK generally.
159
+ Jcr:
160
+ type: Jcr
161
+ disabled: true
162
+ priority: c
163
+
164
+ # Worldcat scraper can be quite slow, move it to wave 'd' to avoid
165
+ # holding up wave 'c'
166
+ Worldcat:
167
+ display_name: OCLC Worldcat.org
168
+ type: Worldcat
169
+ priority: d
170
+ # suppress_precheck says don't actually screen-scrape to
171
+ # see if the link is good, just link blindly. Mostly works
172
+ # for WorldCat, avoids the performance hit.
173
+ suppress_precheck: true
174
+
175
+
176
+ WorldcatIdentities:
177
+ type: WorldcatIdentities
178
+ priority: d
179
+ # Turn off certain response types:
180
+ #note_types: false
181
+ #wikipedia_link: false
182
+ #openurl_widely_held: false
183
+ #require_identifier: true
184
+
185
+
186
+ # GPO is kind of experimental, it doesn't work great, but IF an
187
+ # OpenURL includes a sudoc call number or other GPO identifiers,
188
+ # will try to link to full text via GPO catalog scrape.
189
+ Gpo:
190
+ type: Gpo
191
+ disabled: true
192
+ priority: e
193
+ #preempted_by:
194
+ # - existing_type: fulltext
195
+ # - existing_type: fulltext_title_level
196
+
197
+
198
+ ####
199
+ # Link out filters: Effect what happens when a user clicks
200
+ # on an Umlaut link to a third party source. Link out filters
201
+ # can operate to change where link goes or execute side effects
202
+ # on click.
203
+ ####
204
+
205
+ # Redirect outgoing links through EZProxy
206
+ EZProxy:
207
+ type: Ezproxy
208
+ disabled: true
209
+ task: link_out_filter
210
+ proxy_server: HOSTNAME_OF_YOUR_EZPROXY
211
+ # By default, will pre-check with EZProxy api and
212
+ # only send links through EZProxy that are proxyable.
213
+ # requires proxy_password to be set.
214
+ # optionally, set precheck_with_api false, and the EZProxy
215
+ # api won't be used, ALL links go through EZProxy. You may
216
+ # have EZProxy itself set to transparently redirect non-proxyable
217
+ # URLs back to non-proxied version.
218
+ #
219
+ #precheck_with_api: false
220
+ priority: 5
221
+ proxy_password: YOUR_EZPROXY_API_PWD
222
+ # Want to exclude certain hostnames from being directed through EZProxy?
223
+ # list them in array here:
224
+ #exclude: [ host.unversity.edu, otherhost.somewhere.com]
225
+
226
+
227
+ # Use of SFX api means that SFX can no longer keep statistics on
228
+ # clickthroughs. This link out filter will attempt to fake SFX into
229
+ # thinking a direct click happened when user clicks on an SFX link
230
+ # via Umlaut. This is VERY fragile logic, required reverse engineering
231
+ # SFX and faking it out, still doesn't work all the time. But works
232
+ # much of the time.
233
+ SFX_backchannel_record:
234
+ disabled: true
235
+ type: SfxBackchannelRecord
236
+ task: link_out_filter
237
+ priority: 6
@@ -0,0 +1,44 @@
1
+ require 'rails/generators'
2
+
3
+ module Umlaut
4
+ class AssetHooks < Rails::Generators::Base
5
+
6
+ def add_to_stylesheet_manifest
7
+ unless IO.read("app/assets/stylesheets/application.css").include?('Umlaut')
8
+ insert_into_file "app/assets/stylesheets/application.css", :after => "/*" do
9
+ %q{
10
+ * The base Umlaut styles:
11
+ *= require 'umlaut'
12
+ }
13
+ end
14
+ append_to_file("app/assets/stylesheets/application.css") do
15
+ %q{
16
+
17
+ /* Umlaut needs a jquery-ui theme CSS. Here's an easy way to get one,
18
+ you can replace with another theme. */
19
+ @import url(http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/themes/ui-lightness/jquery-ui.css);
20
+ }
21
+ end
22
+ else
23
+ say_status("skipped", "Your application.css already references Umlaut", :yellow)
24
+ end
25
+ end
26
+
27
+ def add_to_javascript_manifest
28
+ unless IO.read("app/assets/javascripts/application.js").include?('Umlaut')
29
+ prepend_to_file "app/assets/javascripts/application.js" do
30
+ %q{
31
+ // Umlaut javascript required for proper functionality. The 'umlaut' file
32
+ // also forces require of jquery and jquery-ui, dependencies.
33
+ //= require 'umlaut'
34
+ }
35
+ end
36
+ else
37
+ say_status("skipped", "Your application.js already references Umlaut", :yellow)
38
+ end
39
+
40
+ end
41
+
42
+
43
+ end
44
+ end
@@ -0,0 +1,110 @@
1
+ require 'rails/generators'
2
+
3
+ module Umlaut
4
+ class Install < Rails::Generators::Base
5
+ source_root File.join(Umlaut::Engine.root)
6
+
7
+ class_option :only, :type=>:array
8
+ class_option :except, :type=>:array
9
+
10
+ include ActionView::Helpers::TextHelper
11
+
12
+ def config_cache_classes
13
+ guarded(:config_cache_classes) do
14
+ /^((\s*)config\.cache_classes +\= +false\s*)$/
15
+ gsub_file("config/environments/development.rb", /^(\s*)config\.cache_classes +\= +false\s*$/) do |match|
16
+ # for some reason we can't make access to $1 in here from the above
17
+ # regexp work, so we need to match again
18
+ match =~ /^(\s*)/
19
+ <<-EOS
20
+ #{$1}#
21
+ #{$1}# UMLAUT: Umlaut's use of threading is not compatible with class
22
+ #{$1}# reloading, even in development. Umlaut requires true here.
23
+ #{$1}# Rails 3.2 _might_ let you get away with false when it comes out.
24
+ #{$1}config.cache_classes = true
25
+ EOS
26
+ end
27
+ end
28
+ end
29
+
30
+ def database_yml_hint
31
+ guarded(:database_yml_hint) do
32
+ insert_into_file("config/database.yml", :before => /^(\s*)development:/) do
33
+ <<-eos
34
+ #
35
+ # UMLAUT: mysql db with mysql2 adapter strongly recommended for Umlaut, in both
36
+ # production and development. sqlite3 has unclear semantics under threaded
37
+ # concurrency which umlaut uses, and in many cases simply does not work.
38
+ #
39
+ # A high (connection) pool setting is also, sadly, generally
40
+ # required at present.
41
+ #
42
+ # development:
43
+ # adapter: mysql2
44
+ # host:
45
+ # username:
46
+ # password:
47
+ # database:
48
+ # pool: 30
49
+
50
+ eos
51
+ end
52
+ end
53
+ end
54
+
55
+
56
+ def routes
57
+ guarded(:routes) do
58
+ route("Umlaut::Routes.new(self).draw")
59
+ end
60
+ end
61
+
62
+ def umlaut_services_skeleton
63
+ guarded(:umlaut_services_skeleton) do
64
+ copy_file("lib/generators/templates/umlaut_services.yml", "config/umlaut_services.yml")
65
+ end
66
+ end
67
+
68
+ def migrations
69
+ guarded(:migrations) do
70
+ rake("umlaut:install:migrations")
71
+ end
72
+ end
73
+
74
+ def asset_hooks
75
+ guarded(:asset_hooks) do
76
+ generate("umlaut:asset_hooks")
77
+ end
78
+ end
79
+
80
+ def local_umlaut_controller
81
+ guarded(:local_umlaut_controller) do
82
+ copy_file("app/controllers/umlaut_controller.rb")
83
+ end
84
+ end
85
+
86
+ def post_install_message
87
+ say("\n Umlaut installed, now:", :yellow)
88
+ $stdout.puts(
89
+ " " +
90
+ word_wrap("After setting up your 'development' database in config/databases.yml, run `rake db:migrate`", :line_width => 60).
91
+ split("\n").
92
+ join("\n ")
93
+ )
94
+
95
+ end
96
+
97
+ no_tasks do
98
+ def guarded(section, &block)
99
+ if (options[:only].nil? || options[:only].include?(section.to_s)) &&
100
+ (options[:except].nil? || ! options[:except].include?(section.to_s))
101
+ yield
102
+ else
103
+ say_status("skipped", section.to_s, :blue)
104
+ end
105
+
106
+ end
107
+ end
108
+
109
+ end
110
+ end
data/lib/hip3/bib.rb ADDED
@@ -0,0 +1,291 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'marc'
4
+ require 'stringio'
5
+
6
+ module Hip3
7
+ # Bib record/object from HIP. Fetches in it's own data via
8
+ # HIP XML interface. Which may make it sensitive, sorry. If not fetched in yet, # for an item with 'copy' (serial) control, we
9
+ # have to do TWO fetches to get complete information, one for summary
10
+ # holdings statements, plus another for items. Sigh, sorry.
11
+ class Bib
12
+ attr_accessor :httpSession, :hip_base_url
13
+ # should have copies or items, not both
14
+ attr_accessor :bibNum, :copies, :items
15
+ attr_writer :title
16
+
17
+ # CustomFieldLookup objects
18
+ attr_accessor :item_field_lookup, :copy_field_lookup, :bib_field_lookup # We cache HIP's XML representation of bib with and without items serial items.
19
+ attr_accessor :bib_xml, :xml_with_items
20
+ # and the beautiful MARC xml object for the bib, ruby-marc object.
21
+ attr_accessor :marx_xml
22
+
23
+ # First arg: Horizon BibNo this thing represents.
24
+ # Second arg: Net::URI representing HIP base path.
25
+ # labelled args:
26
+ # bib_xml_doc => is optional Hpricot representing bib from HIP. If you have
27
+ # it already, give it to us and we won't have to fetch it.
28
+ # http_session => optional already initialized http session. You are
29
+ # advised to use a Hip3::HTTPSession for it's error
30
+ # handling.
31
+ def initialize(argBibNum, a_hip_base_path, params)
32
+ @title_label = 'Title'
33
+
34
+ self.bibNum = argBibNum
35
+ raise ArgumentException.new("Nil 1st argument: You must supply a bib number to first arg of Bib.new") unless self.bibNum
36
+
37
+ self.hip_base_url = a_hip_base_path
38
+ raise ArgumentException.new("Nil 2nd arg: You must supply the HIP instance base URL as a Net::URI object in 2nd arg to Bib.new") unless self.hip_base_url
39
+
40
+
41
+ self.httpSession = params[:http_session]
42
+ self.httpSession ||= Hip3::HTTPSession.create(hip_base_url.host() )
43
+
44
+ self.title = params[:title]
45
+
46
+ self.copies = nil
47
+
48
+ @bib_xml = params[:bib_xml_doc]
49
+ end
50
+
51
+
52
+
53
+ def hip_http_path
54
+ # 1000 items and copies per page, we want em all
55
+ return hip_base_url.path + "?index=BIB&term=#{bibNum}&ipp=1000&cpp=1000"
56
+ end
57
+ def hip_http_xml_path
58
+ return hip_http_path + "&GetXML=1"
59
+ end
60
+
61
+ # Fetch in our data from HIP. Called lazily by accessor methods.
62
+ def load_from_store
63
+
64
+ # If we have serial copies, load those. We never should have both, but oh well.
65
+ serialElements = bib_xml.search('searchresponse/subscriptionsummary/serial')
66
+ self.copies = serialElements.collect do |serialElement|
67
+ holding = Hip3::SerialCopy.new( self, serialElement )
68
+
69
+ holding # collect holdings
70
+ end
71
+ @copies_loaded = true
72
+
73
+ # If we didn't have copies, we might have items directly in this bib.
74
+ if (self.copies.length == 0 &&
75
+ !bib_xml.search('searchresponse/items/searchresults/results/row').nil?)
76
+ self.xml_with_items = bib_xml
77
+ load_items_from_store
78
+ end
79
+ @items_loaded = true
80
+
81
+ end
82
+
83
+ # This method gets the XML from HIP and puts it in an ivar.
84
+ def xml_with_items
85
+ # first try to load our bib record, that might give us items.
86
+ unless (@xml_with_items)
87
+ load_from_store
88
+ end
89
+ # If we still don't have it, have to load the item xml
90
+ unless (@xml_with_items)
91
+ # Got to make another request
92
+ # give us up to 1000 item records!
93
+ bibWithItemsRequestPath = self.hip_http_xml_path + "&view=items&ipp=1000"
94
+
95
+
96
+ resp = Hip3::HTTPSession.safe_get(httpSession, bibWithItemsRequestPath)
97
+ @xml_with_items = Hpricot.XML( resp.body )
98
+ end
99
+
100
+ return @xml_with_items
101
+ end
102
+
103
+ def bib_xml
104
+ unless (@bib_xml)
105
+ summaryRequestPath = hip_http_xml_path
106
+
107
+ resp = Hip3::HTTPSession.safe_get(httpSession, summaryRequestPath )
108
+ @bib_xml = Hpricot.XML( resp.body )
109
+ end
110
+
111
+ return @bib_xml
112
+ end
113
+
114
+
115
+
116
+ def marc_xml
117
+ # Sadly, loading this takes ANOTHER request. At least this
118
+ # request, unlike the HIP requests, is speedy. We need this
119
+ # for getting 856 urls with sub-fields. Depends on Casey
120
+ # Durfee's package to provide marcxml from hip being installed.
121
+ unless (@marc_xml)
122
+ # should have copies or items, not both
123
+ path = "/mods/?format=marcxml&bib=#{bibNum}"
124
+ #host = hip_base_url.host
125
+ host = hip_base_url.host
126
+ port = hip_base_url.port
127
+
128
+ # If it's https, rejigger it to be http, that's just the way we roll.
129
+ port = 80 if port == 443;
130
+
131
+ # put in a rescue on bad http, reword error.
132
+ resp = Hip3::HTTPSession.start(host, port) {|http| http.get(path) }
133
+
134
+
135
+
136
+ reader = MARC::XMLReader.new( StringIO.new(resp.body.to_s) )
137
+ # there should only be one record in there, just grap one. Since
138
+ # this is an odd object, we can't just do reader[0], but instead:
139
+ xml = reader.find { true }
140
+
141
+ # HIP marc doesn't have the bibID in it. We want the bibID in there.
142
+ # Set it ourselves.
143
+ xml.fields.push( MARC::ControlField.new('001', bibNum()))
144
+
145
+ @marc_xml = xml
146
+ end
147
+ return @marc_xml
148
+ end
149
+
150
+ # Load _serial_ Item data from HIP belonging to this BIB. Called lazily by accessors.
151
+ # Will also work for mono item data, but no reason to call it, can get mono item data
152
+ # without this extra fetch.
153
+ def load_items_from_store
154
+
155
+ itemRowElements = xml_with_items.search('searchresponse/items/searchresults/results/row');
156
+ itemRowElements.each do | el |
157
+ # constructor will take care of registering the thing with us
158
+ Hip3::Item.new(el, self)
159
+ end
160
+ # Tell all our copies they're loaded, so they won't try and load again
161
+ copies.each { |c| c.items_loaded = true }
162
+
163
+ end
164
+
165
+ def item_field_lookup
166
+
167
+ # This guy loads our lookup obj
168
+ unless @item_field_lookup
169
+ xml = self.xml_with_items
170
+ itemLabels = xml.search('searchresponse/items/searchresults/header/col/label').collect {|e| e.inner_text}
171
+ @item_field_lookup = CustomFieldLookup.new(itemLabels)
172
+ end
173
+
174
+ return @item_field_lookup
175
+ end
176
+
177
+ # Lookup custom HIP admin assigned fields in copy summary record
178
+ # => CustomFieldLookup object.
179
+ def copy_field_lookup
180
+ unless @copy_field_lookup
181
+ labels = self.bib_xml.search('searchresponse/subscriptionsummary/header/col/label').collect {|e| e.inner_text}
182
+ @copy_field_lookup = CustomFieldLookup.new(labels)
183
+ end
184
+
185
+ return @copy_field_lookup
186
+ end
187
+
188
+ def bib_field_lookup
189
+ unless ( @bib_field_lookup)
190
+ labels = self.bib_xml.search('searchresponse/fullnonmarc/header/col/label').collect {|e| e.inner_text}
191
+ @bib_field_lookup = CustomFieldLookup.new(labels)
192
+ end
193
+ return @bib_field_lookup
194
+ end
195
+
196
+ # Look up a field added in HIP Admin screen, by label given in that screen.
197
+ def custom_field_for_label(label)
198
+ dataRows = self.bib_xml.search('searchresponse/fullnonmarc/results/row[1]/cell');
199
+ return bib_field_lookup.text_value_for(dataRows, label)
200
+ end
201
+
202
+ # copy records, in case of serial bib
203
+ def copies
204
+ self.load_from_store unless @copies_loaded
205
+ return @copies || [] # never return nil, always return an array
206
+ end
207
+
208
+ # Items directly held by this bib, only in case of mono bib
209
+ def items
210
+ self.load_from_store unless @items_loaded
211
+
212
+ return @items || []
213
+ end
214
+
215
+ # Returns items OR copies, depending on whether it's a serial
216
+ # or a mono bib. HIP doesn't generally allow a mixture of of both.
217
+ def holdings
218
+ return items + copies
219
+ end
220
+
221
+ def title
222
+ unless (@title)
223
+ # title may already have been lazily loaded, or loaded by the
224
+ # bibsearcher. Otherwise, we need to extract it from the bib_xml,
225
+ # which is kind of a pain.
226
+
227
+ # first find the index number of the title.
228
+ labels = bib_xml().search('//fullnonmarc/searchresults/header/col/label')
229
+ title_index = nil
230
+ (0..(labels.length-1)).each do |i|
231
+ if (labels[i].inner_text == @title_label)
232
+ title_index = i
233
+ break
234
+ end
235
+ end
236
+
237
+ if title_index
238
+ raw_title = bib_xml().at("//fullnonmarc/searchresults/results/row/cell[#{title_index + 1}]/data/text").inner_text
239
+ # remove possible author on there, after a '/' char. That's how HIP rolls.
240
+ @title = raw_title.sub(/\/.*$/, '')
241
+ else
242
+ @title = 'unknown'
243
+ end
244
+
245
+ end
246
+
247
+
248
+ return @title
249
+ end
250
+
251
+ # We could try to store the copies in a hash for efficiency, but
252
+ # we're only going to have a handful, it's not worth it.
253
+ def copy_for_id(copy_id)
254
+ copies.find { |c| c.id == copy_id }
255
+ end
256
+
257
+
258
+ # Will add this to an appropriate Copy record if one exists,
259
+ # otherwise directly to our items array. According to HIP's
260
+ # constriants, a bib should never have copies _and_ directly
261
+ # included items, just one or the other.
262
+ def register_item(item)
263
+ copy = copy_for_id( item.copy_id )
264
+ if ( copy.nil? )
265
+ # can't find a copy record, guess it's a directly registered item
266
+ register_direct_item( item )
267
+ else
268
+ copy.register_item( item )
269
+ end
270
+
271
+ end
272
+
273
+ # An item that does not have a copy parent, but is directly
274
+ # related to the big.
275
+ def register_direct_item( item )
276
+ @items ||= []
277
+ @items.push( item ) if ! @items.include?(item)
278
+ end
279
+
280
+ def http_url
281
+
282
+ return "#{hip_base_url.scheme}://#{hip_base_url.host}:#{hip_base_url.port}#{hip_http_path}"
283
+ end
284
+
285
+ def to_s
286
+ return "#<Hip3::Bib bibnum=#{bibNum} #{http_url}>"
287
+ end
288
+ end
289
+
290
+
291
+ end