umlaut 3.0.5 → 3.1.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/README.md +48 -5
- data/app/assets/images/umlaut_icons.png +0 -0
- data/app/assets/images/umlaut_icons/famfamfam-book-go.png +0 -0
- data/app/assets/images/{famfamfam/book_open.png → umlaut_icons/famfamfam-book-open.png} +0 -0
- data/app/assets/images/umlaut_icons/famfamfam-book.png +0 -0
- data/app/assets/images/{famfamfam/cross.png → umlaut_icons/famfamfam-cross.png} +0 -0
- data/app/assets/images/umlaut_icons/famfamfam-error.png +0 -0
- data/app/assets/images/umlaut_icons/famfamfam-help.png +0 -0
- data/app/assets/images/umlaut_icons/famfamfam-information.png +0 -0
- data/app/assets/images/umlaut_icons/famfamfam-link.png +0 -0
- data/app/assets/images/umlaut_icons/famfamfam-page-sound.png +0 -0
- data/app/assets/images/umlaut_icons/famfamfam-page-text.png +0 -0
- data/app/assets/images/umlaut_icons/famfamfam-page-up.png +0 -0
- data/app/assets/images/{famfamfam/page_white.png → umlaut_icons/famfamfam-page-white.png} +0 -0
- data/app/assets/images/{famfamfam/readme.html → umlaut_icons/famfamfam-readme.html} +0 -0
- data/app/assets/images/{famfamfam/tiny_cross.png → umlaut_icons/famfamfam-tiny-cross.png} +0 -0
- data/app/assets/images/{list_closed.png → umlaut_icons/list-closed.png} +0 -0
- data/app/assets/images/{list_open.png → umlaut_icons/list-open.png} +0 -0
- data/app/assets/javascripts/umlaut.js +5 -4
- data/app/assets/javascripts/umlaut/ajax_windows.js +41 -23
- data/app/assets/javascripts/umlaut/expand_contract_toggle.js +21 -29
- data/app/assets/javascripts/umlaut/load_permalink.js +26 -0
- data/app/assets/javascripts/umlaut/search_autocomplete.js +103 -44
- data/app/assets/stylesheets/umlaut.css.scss +19 -0
- data/app/assets/stylesheets/umlaut/_admin.scss +14 -0
- data/app/assets/stylesheets/umlaut/_az.scss +29 -0
- data/app/assets/stylesheets/umlaut/_forms.scss +31 -0
- data/app/assets/stylesheets/umlaut/_icons.scss +64 -0
- data/app/assets/stylesheets/umlaut/_layout.scss +52 -0
- data/app/assets/stylesheets/umlaut/_misc.scss +59 -0
- data/app/assets/stylesheets/umlaut/_mixins.scss +65 -0
- data/app/assets/stylesheets/umlaut/_modal.scss +4 -0
- data/app/assets/stylesheets/umlaut/_resolve.scss +308 -0
- data/app/assets/stylesheets/umlaut/_results.scss +34 -0
- data/app/assets/stylesheets/umlaut/_search.scss +14 -0
- data/app/assets/stylesheets/umlaut/_spinner.scss +12 -0
- data/app/assets/stylesheets/umlaut/_variables.scss +72 -0
- data/app/controllers/export_email_controller.rb +22 -39
- data/app/controllers/journal_tocs_controller +90 -0
- data/app/controllers/js_helper_controller.rb +2 -3
- data/app/controllers/link_router_controller.rb +32 -43
- data/app/controllers/open_search_controller.rb +3 -4
- data/app/controllers/resolve_controller.rb +68 -107
- data/app/controllers/resource_controller.rb +14 -20
- data/app/controllers/search_controller.rb +75 -94
- data/app/controllers/search_methods/README.md +28 -0
- data/app/controllers/search_methods/sfx4.rb +50 -119
- data/app/controllers/search_methods/sfx4_solr/README.md +57 -0
- data/app/controllers/search_methods/sfx4_solr/local.rb +40 -0
- data/app/controllers/search_methods/sfx4_solr/searcher.rb +90 -0
- data/app/controllers/store_controller.rb +24 -30
- data/app/controllers/umlaut/controller_behavior.rb +45 -17
- data/app/controllers/umlaut/error_handling.rb +20 -25
- data/{lib → app/controllers}/umlaut_configurable.rb +35 -21
- data/app/controllers/umlaut_controller.rb +43 -46
- data/app/helpers/emailer_helper.rb +9 -16
- data/app/helpers/export_email_helper.rb +8 -8
- data/app/helpers/open_search_helper.rb +2 -3
- data/app/helpers/resolve_helper.rb +130 -100
- data/app/helpers/search_helper.rb +17 -5
- data/app/helpers/umlaut/footer_helper.rb +1 -1
- data/app/helpers/umlaut/helper.rb +34 -0
- data/app/helpers/umlaut/html_head_helper.rb +12 -21
- data/{lib → app/mixin_logic}/marc_helper.rb +1 -1
- data/{lib → app/mixin_logic}/metadata_helper.rb +6 -5
- data/{lib → app/mixin_logic}/umlaut_http.rb +0 -0
- data/{lib → app/mixin_logic}/xml_schema_helper.rb +0 -0
- data/app/models/collection.rb +97 -95
- data/{lib → app/models}/hip3/bib.rb +0 -0
- data/{lib → app/models}/hip3/bib_searcher.rb +0 -0
- data/{lib → app/models}/hip3/custom_field_lookup.rb +0 -0
- data/{lib → app/models}/hip3/holding.rb +0 -0
- data/{lib → app/models}/hip3/item.rb +0 -0
- data/{lib → app/models}/hip3/receipt.rb +0 -0
- data/{lib → app/models}/hip3/serial_copy.rb +0 -0
- data/app/models/permalink.rb +3 -8
- data/app/models/referent.rb +29 -21
- data/app/models/request.rb +19 -8
- data/app/models/service_response.rb +24 -3
- data/app/models/service_store.rb +108 -39
- data/app/models/service_store.rb-NEW +73 -0
- data/app/models/service_wave.rb +2 -0
- data/app/models/sfx4/abstract/README.md +68 -0
- data/app/models/sfx4/abstract/az_extra_info.rb +44 -0
- data/app/models/sfx4/abstract/az_letter_group.rb +24 -0
- data/app/models/sfx4/abstract/az_title.rb +96 -0
- data/app/models/sfx4/abstract/az_title_search.rb +24 -0
- data/app/models/sfx4/abstract/base.rb +77 -0
- data/app/models/sfx4/global/base.rb +24 -0
- data/app/models/sfx4/global/kb_objects.rb +34 -0
- data/app/models/sfx4/local/az_extra_info.rb +7 -0
- data/app/models/sfx4/local/az_letter_group.rb +7 -0
- data/app/models/sfx4/local/az_title.rb +7 -0
- data/app/models/sfx4/local/az_title_search.rb +7 -0
- data/app/models/sfx4/local/base.rb +26 -0
- data/{lib → app/presentation}/section_renderer.rb +0 -12
- data/app/referent_filters/dissertation_catch.rb +67 -0
- data/{lib → app/referent_filters}/referent_filter.rb +0 -0
- data/{lib → app}/service_adaptors/ajax_export.rb +0 -0
- data/{lib → app}/service_adaptors/amazon.rb +2 -0
- data/{lib → app}/service_adaptors/blacklight.rb +22 -10
- data/{lib → app}/service_adaptors/book_finder.rb +0 -0
- data/{lib → app}/service_adaptors/bx.rb +0 -0
- data/{lib → app}/service_adaptors/cover_thing.rb +0 -0
- data/{lib → app}/service_adaptors/dummy_service.rb +0 -0
- data/{lib → app}/service_adaptors/elsevier_cover.rb +0 -0
- data/{lib → app}/service_adaptors/email_export.rb +0 -0
- data/{lib → app}/service_adaptors/ezproxy.rb +0 -0
- data/{lib → app}/service_adaptors/google_book_search.rb +0 -0
- data/app/service_adaptors/google_scholar_link.rb +71 -0
- data/{lib → app}/service_adaptors/gpo.rb +0 -0
- data/{lib → app}/service_adaptors/hathi_trust.rb +0 -0
- data/{lib → app}/service_adaptors/hip3_service.rb +0 -0
- data/{lib → app}/service_adaptors/hip_holding_search.rb +0 -0
- data/{lib → app}/service_adaptors/internet_archive.rb +0 -0
- data/{lib → app}/service_adaptors/isbn_db.rb +0 -0
- data/{lib → app}/service_adaptors/isi.rb +22 -13
- data/{lib → app}/service_adaptors/jcr.rb +0 -0
- data/{lib → app}/service_adaptors/opac.rb +0 -0
- data/{lib → app}/service_adaptors/open_library.rb +0 -0
- data/{lib → app}/service_adaptors/open_library_cover.rb +0 -0
- data/{lib → app}/service_adaptors/pubmed.rb +0 -0
- data/{lib → app}/service_adaptors/request_to_fixture.rb +0 -0
- data/{lib → app}/service_adaptors/scopus.rb +0 -0
- data/{lib → app/service_adaptors}/service.rb +3 -3
- data/{lib → app}/service_adaptors/sfx.rb +154 -11
- data/{lib → app}/service_adaptors/sfx_backchannel_record.rb +0 -0
- data/app/service_adaptors/tr_link.rb +267 -0
- data/app/service_adaptors/tr_links.rb +278 -0
- data/{lib → app}/service_adaptors/txt_holding_export.rb +0 -0
- data/{lib → app}/service_adaptors/ulrichs_cover.rb +0 -0
- data/{lib → app}/service_adaptors/ulrichs_link.rb +0 -0
- data/{lib → app}/service_adaptors/worldcat.rb +0 -0
- data/{lib → app}/service_adaptors/worldcat_identities.rb +0 -0
- data/app/views/admin/service_errors/_dispatched_service.html.erb +13 -13
- data/app/views/admin/service_errors/index.html.erb +11 -21
- data/app/views/export_email/email.html.erb +17 -2
- data/app/views/export_email/send_email.html.erb +2 -1
- data/app/views/export_email/send_txt.html.erb +2 -1
- data/app/views/export_email/txt.html.erb +30 -2
- data/app/views/layouts/umlaut.html.erb +29 -49
- data/app/views/resolve/_background_progress.html.erb +43 -50
- data/app/views/resolve/_background_updater.html.erb +23 -36
- data/app/views/resolve/_citation.html.erb +63 -87
- data/app/views/resolve/_compact_citation.html.erb +15 -33
- data/app/views/resolve/_cover_image.html.erb +34 -43
- data/app/views/resolve/_fulltext.html.erb +29 -50
- data/app/views/resolve/_help.html.erb +17 -14
- data/app/views/resolve/_holding.html.erb +65 -82
- data/app/views/resolve/_manually_entered_warning.html.erb +7 -0
- data/app/views/resolve/_modal.html.erb +19 -0
- data/app/views/resolve/_related_items.html.erb +20 -35
- data/app/views/resolve/_search_inside.html.erb +34 -57
- data/app/views/resolve/_section_display.html.erb +34 -46
- data/app/views/resolve/_section_heading.html.erb +17 -0
- data/app/views/resolve/_service_errors.html.erb +27 -28
- data/app/views/resolve/_standard_response_item.html.erb +42 -72
- data/app/views/resolve/background_status.html.erb +19 -23
- data/app/views/resolve/get_permalink.html.erb +6 -0
- data/app/views/resolve/index.html.erb +47 -73
- data/app/views/search/_a_to_z.html.erb +9 -6
- data/app/views/search/_citation.html.erb +73 -94
- data/app/views/search/_pager.html.erb +6 -6
- data/app/views/search/books.html.erb +34 -102
- data/app/views/search/journal_search.html.erb +53 -90
- data/app/views/search/journals.html.erb +73 -167
- data/app/views/umlaut/_header.html.erb +9 -0
- data/app/views/umlaut/error.html.erb +44 -44
- data/config/locales/en.yml +5 -0
- data/lib/{CronTab.rb → cron_tab.rb} +0 -0
- data/lib/generators/templates/umlaut_services.yml +57 -43
- data/lib/generators/umlaut/install_generator.rb +12 -0
- data/lib/service_adaptors/README.md +0 -0
- data/lib/tasks/umlaut.rake +8 -24
- data/lib/umlaut.rb +1 -21
- data/lib/umlaut/version.rb +1 -1
- data/test/README.md +75 -0
- data/test/dummy/app/controllers/umlaut_controller.rb +3 -3
- data/test/dummy/config/application.rb +3 -0
- data/test/dummy/config/sunspot.yml +20 -0
- data/test/dummy/config/travis_database.yml +96 -0
- data/test/dummy/config/umlaut_services.yml +16 -23
- data/test/dummy/db/migrate/20120927163304_sfx4_global.rb +26 -0
- data/test/dummy/db/migrate/20120927164040_sfx4_local.rb +54 -0
- data/test/dummy/tmp/cache/assets/BBA/6A0/sprockets%2F2a335471966f33256b321f8324041981 +0 -0
- data/test/dummy/tmp/cache/assets/C2A/410/sprockets%2Fd654b74912b4773a2534616863fb6565 +0 -0
- data/test/dummy/tmp/cache/assets/C45/A30/sprockets%2F39494895e462697b478d3d0c79298a26 +0 -0
- data/test/dummy/tmp/cache/assets/C49/730/sprockets%2F212d35831188417b5131e3e693aa69a6 +0 -0
- data/test/dummy/tmp/cache/assets/C55/1D0/sprockets%2F5af2f2a3403040f736981863fd278529 +0 -0
- data/test/dummy/tmp/cache/assets/C5A/A80/sprockets%2F2328c7370b56b4151776981a5f6d394e +0 -0
- 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/C80/980/sprockets%2Fc94807409c1523d43e18d25f35d93c41 +0 -0
- data/test/dummy/tmp/cache/assets/C94/E20/sprockets%2F19579abc248373f419b1c3e287d74598 +0 -0
- data/test/dummy/tmp/cache/assets/C98/330/sprockets%2F0c81574ba94abc10657315d4190c201f +0 -0
- data/test/dummy/tmp/cache/assets/CA4/440/sprockets%2F0feb4425db6319d7d0582192a503671b +0 -0
- data/test/dummy/tmp/cache/assets/CA7/E80/sprockets%2F33310f455a870eaedd6d938e30620714 +0 -0
- data/test/dummy/tmp/cache/assets/CB8/3C0/sprockets%2F697cd846490fda9f0e20c558320610f8 +0 -0
- data/test/dummy/tmp/cache/assets/CBF/B60/sprockets%2F08ca89671549936265dcb673bf02e36f +0 -0
- data/test/dummy/tmp/cache/assets/CC7/F10/sprockets%2F939637f806eef3f0f21584659458ab2e +0 -0
- data/test/dummy/tmp/cache/assets/CC9/9F0/sprockets%2F306166316e2cafd13c15e62b51a2339d +0 -0
- data/test/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
- data/test/dummy/tmp/cache/assets/CF7/2B0/sprockets%2F25a7c73655bd3598173b39d9f98bcd46 +0 -0
- data/test/dummy/tmp/cache/assets/CF8/DA0/sprockets%2Ff5b8c8499d3da954d392fa57739503c5 +0 -0
- data/test/dummy/tmp/cache/assets/CF9/590/sprockets%2F096bcc45cd31b3796fa2121cd203215f +0 -0
- data/test/dummy/tmp/cache/assets/CFE/080/sprockets%2F37fe9f4255baddbd549a659914929398 +0 -0
- data/test/dummy/tmp/cache/assets/D04/CC0/sprockets%2Fe9c1b92f2e437e1bbbe020d718739220 +0 -0
- data/test/dummy/tmp/cache/assets/D0B/090/sprockets%2F58009091c95e3ac328c91c68fca30e0e +0 -0
- data/test/dummy/tmp/cache/assets/D1A/B50/sprockets%2F2db5892438129fe94da8429b8be114ec +0 -0
- data/test/dummy/tmp/cache/assets/D2D/1A0/sprockets%2F376426b4896a3cff7969ce6c7b387e0e +0 -0
- data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/D37/2B0/sprockets%2F40834fb07d7318c1fddd5003bd9e04f6 +0 -0
- data/test/dummy/tmp/cache/assets/D43/0D0/sprockets%2F682843a8d0795a5fbcfeb2f0c81727d0 +0 -0
- data/test/dummy/tmp/cache/assets/D46/F80/sprockets%2Fb15c08e749067d7aad9baf5e9388221c +0 -0
- data/test/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/test/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/dummy/tmp/cache/assets/D6C/7D0/sprockets%2F8a05d6981ec0d38c51739bef0b3a9c2b +0 -0
- data/test/dummy/tmp/cache/assets/D6E/CF0/sprockets%2F5661c6e4f0cea86fe4523f27261aade5 +0 -0
- data/test/dummy/tmp/cache/assets/D94/FF0/sprockets%2F3b56a1aa77de0d570c38a4a9d5f4b1d6 +0 -0
- data/test/dummy/tmp/cache/assets/D97/6B0/sprockets%2Fb070e8c799d1a4ad5e62e0a1ae3b83e6 +0 -0
- data/test/dummy/tmp/cache/assets/D9A/2F0/sprockets%2Fbba0f4b972dc53c15ce6c8c1993b82a4 +0 -0
- data/test/dummy/tmp/cache/assets/D9C/860/sprockets%2Fec2d9f20b270d70e698ff33e53c21fca +0 -0
- data/test/dummy/tmp/cache/assets/DA6/A80/sprockets%2F92e26d8e58d5bcc8b8f6c25d1b05b9c1 +0 -0
- data/test/dummy/tmp/cache/assets/DA8/BB0/sprockets%2F0cf1c7e9f966dce425517c0e2a844efe +0 -0
- data/test/dummy/tmp/cache/assets/DA9/BC0/sprockets%2Fcb9062b73291befe5e5bf2a70978dec8 +0 -0
- data/test/dummy/tmp/cache/assets/DB6/ED0/sprockets%2Ff4482d9b9f76fb65eef16430bde2f8e6 +0 -0
- data/test/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/test/dummy/tmp/cache/assets/DE8/790/sprockets%2Fd1333bde2b9aafcc712d11dd09ab35d8 +0 -0
- data/test/dummy/tmp/cache/assets/DF7/960/sprockets%2F99ac6db10b44a64fbba4ee847b35ba8b +0 -0
- data/test/dummy/tmp/cache/assets/DFD/300/sprockets%2Fabac9489cf7f1db8ef00d72a1571ee1e +0 -0
- data/test/dummy/tmp/cache/assets/E02/C10/sprockets%2F1463cadfce3fc70e61d482f9fcb75ac7 +0 -0
- data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/dummy/tmp/cache/assets/E38/FE0/sprockets%2Fe1fc875efa817cbb94a5d8de25ea4e6b +0 -0
- data/test/dummy/tmp/cache/assets/E50/F00/sprockets%2Fec61afdbb1cc4df075e3dad46f0af571 +0 -0
- data/test/dummy/tmp/cache/assets/E5E/5F0/sprockets%2Feffaeb4d7f9bf4c0cc840ff320fde046 +0 -0
- data/test/dummy/tmp/cache/assets/E5F/960/sprockets%2Fdc007b6cad5c7ef08e33ec28cfff0ef6 +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_accordion.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_alerts.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_breadcrumbs.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_button-groups.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_buttons.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_carousel.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_close.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_code.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_component-animations.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_dropdowns.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_forms.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_grid.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_hero-unit.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_labels-badges.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_layouts.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_media.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_mixins.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_modals.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_navbar.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_navs.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_pager.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_pagination.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_popovers.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_progress-bars.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_reset.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_responsive-1200px-min.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_responsive-767px-max.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_responsive-768px-979px.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_responsive-navbar.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_responsive-utilities.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_scaffolding.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_sprites.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_tables.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_thumbnails.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_tooltip.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_type.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_utilities.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_variables.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/_wells.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/bootstrap.scssc +0 -0
- data/test/dummy/tmp/cache/sass/310d901c169042855feb8cf3903e1e2821d27f13/responsive.scssc +0 -0
- data/test/dummy/tmp/cache/sass/3af72421a0fbed39d3047687ca0ad6e6e5545041/_admin.scssc +0 -0
- data/test/dummy/tmp/cache/sass/3af72421a0fbed39d3047687ca0ad6e6e5545041/_az.scssc +0 -0
- data/test/dummy/tmp/cache/sass/3af72421a0fbed39d3047687ca0ad6e6e5545041/_base.scssc +0 -0
- data/test/dummy/tmp/cache/sass/3af72421a0fbed39d3047687ca0ad6e6e5545041/_forms.scssc +0 -0
- data/test/dummy/tmp/cache/sass/3af72421a0fbed39d3047687ca0ad6e6e5545041/_icons.scssc +0 -0
- data/test/dummy/tmp/cache/sass/3af72421a0fbed39d3047687ca0ad6e6e5545041/_misc.scssc +0 -0
- data/test/dummy/tmp/cache/sass/3af72421a0fbed39d3047687ca0ad6e6e5545041/_mixins.scssc +0 -0
- data/test/dummy/tmp/cache/sass/3af72421a0fbed39d3047687ca0ad6e6e5545041/_modal.scssc +0 -0
- data/test/dummy/tmp/cache/sass/3af72421a0fbed39d3047687ca0ad6e6e5545041/_resolve.scssc +0 -0
- data/test/dummy/tmp/cache/sass/3af72421a0fbed39d3047687ca0ad6e6e5545041/_results.scssc +0 -0
- data/test/dummy/tmp/cache/sass/3af72421a0fbed39d3047687ca0ad6e6e5545041/_search.scssc +0 -0
- data/test/dummy/tmp/cache/sass/3af72421a0fbed39d3047687ca0ad6e6e5545041/_spinner.scssc +0 -0
- data/test/dummy/tmp/cache/sass/3af72421a0fbed39d3047687ca0ad6e6e5545041/_variables.scssc +0 -0
- data/test/dummy/tmp/cache/sass/93d65682d6bddb0b2e6788c1232f4849af20a35e/bootstrap-responsive.scssc +0 -0
- data/test/dummy/tmp/cache/sass/93d65682d6bddb0b2e6788c1232f4849af20a35e/bootstrap.scssc +0 -0
- data/test/dummy/tmp/cache/sass/fb58c04fd15fcc38a8c4d91b7070bcfeaf1c3799/umlaut.css.scssc +0 -0
- data/test/fixtures/dispatched_services.yml +0 -4
- data/test/fixtures/permalinks.yml +23 -4
- data/test/fixtures/referent_values.yml +226 -1493
- data/test/fixtures/referents.yml +14 -137
- data/test/fixtures/requests.yml +22 -260
- data/test/fixtures/service_responses.yml +169 -5
- data/test/fixtures/sfx4/global/KB_OBJECTS.yml +46 -0
- data/test/fixtures/sfx4/local/AZ_EXTRA_INFO.yml +4802 -0
- data/test/fixtures/sfx4/local/AZ_LETTER_GROUP.yml +105 -0
- data/test/fixtures/sfx4/local/AZ_TITLE.yml +165 -0
- data/test/fixtures/sfx4/local/AZ_TITLE_SEARCH.yml +341 -0
- data/test/fixtures/sfx_urls.yml +3 -0
- data/test/functional/export_email_controller_test.rb +43 -0
- data/test/functional/link_router_controller_test.rb +16 -0
- data/test/functional/resolve_controller_test.rb +102 -0
- data/test/functional/search_controller_test.rb +40 -0
- data/test/functional/store_controller_test.rb +29 -0
- data/test/helper/list_with_limit_test.rb +90 -0
- data/test/integration/permalinks_test.rb +14 -0
- data/test/support/search_methods/test_case.rb +0 -0
- data/test/support/service_adaptors/test_case.rb +0 -0
- data/test/support/test_with_cassette.rb +37 -0
- data/test/test_helper.rb +76 -30
- data/test/unit/aws_product_sign_test.rb +2 -0
- data/test/unit/determine_services_test.rb +163 -0
- data/test/unit/google_book_search_test.rb +8 -25
- data/test/unit/google_scholar_link_test.rb +81 -0
- data/test/unit/internet_archive_test.rb +33 -0
- data/test/unit/permalink_test.rb +15 -0
- data/test/unit/service_store_test.rb +47 -0
- data/test/unit/service_test.rb +28 -13
- data/test/unit/sfx/sfx_target_roll_up_test.rb +369 -0
- data/test/unit/sfx4_search_test.rb +102 -0
- data/test/unit/sfx4_solr_search_test.rb +77 -0
- data/test/unit/sfx_test.rb +38 -0
- data/test/unit/worldcat_test.rb +7 -0
- data/test/vcr_cassettes/google_book_search/frankenstein_by_OCLC_number.yml +107 -0
- data/test/vcr_cassettes/internet_archive/momo_by_title_author.yml +116 -0
- data/test/vcr_cassettes/resolve/fulltext_with_edition_warning.yml +44 -0
- data/test/vcr_cassettes/resolve/no_holdings.yml +649 -0
- data/test/vcr_cassettes/resolve/nytimes_by_issn.yml +224 -0
- data/test/vcr_cassettes/sfx/nytimes_by_issn.yml +1395 -0
- data/test/vcr_cassettes/sfx4_solr/find_by_group.yml +109 -0
- data/test/vcr_cassettes/sfx4_solr/find_by_title_begins_with.yml +33 -0
- data/test/vcr_cassettes/sfx4_solr/find_by_title_contains.yml +34 -0
- data/test/vcr_cassettes/sfx4_solr/find_by_title_exact.yml +32 -0
- data/test/view/holding_test.rb +30 -0
- metadata +435 -179
- data/app/assets/images/export_bg_bot.gif +0 -0
- data/app/assets/images/export_bg_mid.gif +0 -0
- data/app/assets/images/export_bg_top.gif +0 -0
- data/app/assets/images/famfamfam/page_sound.gif +0 -0
- data/app/assets/images/famfamfam/page_text.gif +0 -0
- data/app/assets/images/famfamfam/page_up.gif +0 -0
- data/app/assets/images/ico_go.gif +0 -0
- data/app/assets/images/more_info.gif +0 -0
- data/app/assets/images/rails.png +0 -0
- data/app/assets/images/request.gif +0 -0
- data/app/assets/javascripts/umlaut/simple_visible_toggle.js +0 -8
- data/app/assets/stylesheets/umlaut.css +0 -900
- data/app/assets/stylesheets/umlaut/_background_progress_spinner.scss +0 -21
- data/app/assets/stylesheets/umlaut/_expand_contract.scss +0 -28
- data/app/controllers/search_methods/sfx3.rb +0 -148
- data/app/models/sfx_db.rb +0 -10
- data/app/models/sfx_db/az_additional_title.rb +0 -11
- data/app/models/sfx_db/az_letter_group.rb +0 -11
- data/app/models/sfx_db/az_title.rb +0 -40
- data/app/models/sfx_db/az_title_v2.rb +0 -34
- data/app/models/sfx_db/isbn.rb +0 -12
- data/app/models/sfx_db/issn.rb +0 -12
- data/app/models/sfx_db/object.rb +0 -35
- data/app/models/sfx_db/object_portfolio.rb +0 -6
- data/app/models/sfx_db/publisher.rb +0 -10
- data/app/models/sfx_db/sfx_db_base.rb +0 -58
- data/app/models/sfx_db/target.rb +0 -10
- data/app/models/sfx_db/target_service.rb +0 -10
- data/app/models/sfx_db/title.rb +0 -10
- data/app/views/export_email/_email.html.erb +0 -25
- data/app/views/export_email/_send_email.html.erb +0 -3
- data/app/views/export_email/_send_txt.html.erb +0 -3
- data/app/views/export_email/_txt.html.erb +0 -62
- data/lib/holding.rb +0 -32
- data/lib/opensearch_feed.rb +0 -398
- data/lib/opensearch_query.rb +0 -98
- data/lib/referent_filters/dissertation_catch.rb +0 -45
- data/lib/service_adaptors/journal_tocs.progress +0 -68
- data/lib/service_adaptors/primo_service.rb +0 -452
- data/lib/service_adaptors/primo_source.rb +0 -82
- data/lib/umlaut/default_configuration.rb +0 -5
- data/test/dummy/config/primo.yml +0 -271
- data/test/unit/primo_service_test.rb +0 -947
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -32,7 +32,7 @@
|
|
32
32
|
# to. If service returns original url or nil, original url will still be used.
|
33
33
|
|
34
34
|
class Service
|
35
|
-
attr_reader :priority, :service_id, :url, :task, :status, :name
|
35
|
+
attr_reader :priority, :service_id, :url, :task, :status, :name, :group
|
36
36
|
attr_writer :session_id
|
37
37
|
attr_accessor :request
|
38
38
|
@@required_params_for_subclass = {} # initialize class var
|
@@ -66,7 +66,7 @@ class Service
|
|
66
66
|
# handle both cases.
|
67
67
|
raise NameError if value.nil?
|
68
68
|
rescue NameError
|
69
|
-
raise ArgumentError.new("Missing Service configuration parameter. Service type #{self.class} (id: #{self.service_id}) requires a config parameter named '#{param}'. Check your config/
|
69
|
+
raise ArgumentError.new("Missing Service configuration parameter. Service type #{self.class} (id: #{self.service_id}) requires a config parameter named '#{param}'. Check your config/umlaut_services.yml file.")
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
@@ -244,7 +244,7 @@ class Service
|
|
244
244
|
uml_request.dispatched_services.to_a.find do |disp|
|
245
245
|
service == "*" ||
|
246
246
|
(disp.service_id == service &&
|
247
|
-
(disp.status == DispatchedService
|
247
|
+
(disp.status == DispatchedService::Successful ))
|
248
248
|
end
|
249
249
|
else
|
250
250
|
# Check service responses
|
@@ -36,11 +36,18 @@
|
|
36
36
|
# relationships, set to empty array [] to eliminate defaults.
|
37
37
|
# sfx_timeout: in seconds, for both open/read timeout value for SFX connection.
|
38
38
|
# Defaults to 8.
|
39
|
+
# roll_up_prefixes: ARRAY of STRINGs, prefixes like "EBSCOHOST_". If multiple
|
40
|
+
# targets sharing one of the specified prefixes are supplied from SFX,
|
41
|
+
# they will be "rolled up" and collapsed, just the first one included
|
42
|
+
# in response. For TITLE-LEVEL (rather than article-level) requests,
|
43
|
+
# the roll-up algorithm is sensitive to COVERAGES, and will only suppress
|
44
|
+
# targets that have coverages included in remaining non-suppressed targets.
|
39
45
|
class Sfx < Service
|
40
46
|
require 'uri'
|
41
47
|
require 'htmlentities'
|
42
48
|
require 'cgi'
|
43
49
|
require 'nokogiri'
|
50
|
+
require 'date'
|
44
51
|
|
45
52
|
#require 'open_url'
|
46
53
|
|
@@ -184,6 +191,10 @@ class Sfx < Service
|
|
184
191
|
# We're going to keep our @really_distant_relationship stuff here.
|
185
192
|
related_titles = {}
|
186
193
|
|
194
|
+
# We organize our responses in a queue, so we can process them
|
195
|
+
# for collapse function, before actually writing to db.
|
196
|
+
response_queue ||= {}
|
197
|
+
|
187
198
|
0.upto(sfx_objs.length - 1 ) do |sfx_obj_index|
|
188
199
|
|
189
200
|
sfx_obj = sfx_objs[sfx_obj_index]
|
@@ -218,7 +229,7 @@ class Sfx < Service
|
|
218
229
|
|
219
230
|
|
220
231
|
metadata = request.referent.metadata
|
221
|
-
|
232
|
+
|
222
233
|
# For each target delivered by SFX
|
223
234
|
sfx_obj.search("./ctx_obj_targets/target").each_with_index do|target, target_index|
|
224
235
|
response_data = {}
|
@@ -305,7 +316,7 @@ class Sfx < Service
|
|
305
316
|
next
|
306
317
|
end
|
307
318
|
|
308
|
-
related_note = "This version provided from related title: <
|
319
|
+
related_note = "This version provided from related title: <em>" + CGI.unescapeHTML( title ) + "</em>.\n"
|
309
320
|
end
|
310
321
|
|
311
322
|
if ( sfx_service_type == 'getDocumentDelivery' )
|
@@ -316,10 +327,18 @@ class Sfx < Service
|
|
316
327
|
|
317
328
|
response_data[:url] = CGI.unescapeHTML((target/"./target_url").inner_text)
|
318
329
|
response_data[:notes] = related_note.to_s + CGI.unescapeHTML((target/"./note").inner_text)
|
330
|
+
# Set the proxy boolean
|
331
|
+
response_data[:proxy] = CGI.unescapeHTML((target/"./proxy").inner_text).eql?("yes")
|
319
332
|
response_data[:authentication] = CGI.unescapeHTML((target/"./authentication").inner_text)
|
320
333
|
response_data[:source] = source
|
321
334
|
response_data[:coverage] = coverage if coverage
|
322
|
-
|
335
|
+
|
336
|
+
|
337
|
+
# machine actionable coverage elements, used for collapsing
|
338
|
+
( response_data[:coverage_begin_date], response_data[:coverage_end_date] ) =
|
339
|
+
determine_coverage_boundaries(target)
|
340
|
+
|
341
|
+
|
323
342
|
# Sfx metadata we want
|
324
343
|
response_data[:sfx_base_url] = @base_url
|
325
344
|
response_data[:sfx_obj_index] = sfx_obj_index + 1 # sfx is 1 indexed
|
@@ -345,19 +364,34 @@ class Sfx < Service
|
|
345
364
|
response_data[:debug_info] =" Target: #{sfx_target_name} ; SFX object ID: #{object_id}"
|
346
365
|
|
347
366
|
response_data[:display_text] = (target/"./target_public_name").inner_text
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
367
|
+
|
368
|
+
response_data.merge!(
|
369
|
+
:service => self,
|
370
|
+
:service_type_value => umlaut_service
|
371
|
+
)
|
372
|
+
|
373
|
+
#request.add_service_response( response_data )
|
374
|
+
# We add the response_data to a list for now, so we can post-process
|
375
|
+
# for collapse feature before we actually add them.
|
376
|
+
response_queue[umlaut_service] ||= []
|
377
|
+
response_queue[umlaut_service] << response_data
|
355
378
|
|
356
379
|
|
357
380
|
end
|
358
381
|
end
|
359
382
|
end
|
360
383
|
|
384
|
+
if response_queue["fulltext"].present?
|
385
|
+
response_queue["fulltext"] = roll_up_responses(response_queue["fulltext"], :coverage_sensitive => request.title_level_citation? )
|
386
|
+
end
|
387
|
+
|
388
|
+
# Now that they've been post-processed, actually commit them.
|
389
|
+
response_queue.each_pair do |type, list|
|
390
|
+
list.each do |response|
|
391
|
+
request.add_service_response( response )
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
361
395
|
# Add in links to our related titles
|
362
396
|
related_titles.each_pair do |issn, hash|
|
363
397
|
request.add_service_response(
|
@@ -377,6 +411,115 @@ class Sfx < Service
|
|
377
411
|
|
378
412
|
end
|
379
413
|
|
414
|
+
# pass in a nokogiri element for <target>, we'll calculate
|
415
|
+
# ruby Date objects for begin date and end date of coverage,
|
416
|
+
# passed out as a two-element array [begin, end].
|
417
|
+
#
|
418
|
+
# taking embargoes into account. nil if unbounded.
|
419
|
+
def determine_coverage_boundaries(target)
|
420
|
+
# machine actionable coverage elements, used for collapsing
|
421
|
+
if (in_node = target.at_xpath("./coverage/in"))
|
422
|
+
year = in_node.at_xpath("year").try(:text).try(:to_i)
|
423
|
+
if year && year != 0
|
424
|
+
begin_date = Date.new(year, 1, 1)
|
425
|
+
end_date = Date.new(year, 12, 31)
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
if (from = target.at_xpath("./coverage/from"))
|
430
|
+
year = from.at_xpath("year").try(:text).try(:to_i)
|
431
|
+
# SFX KB does not have month/day, only year, set to begin of year
|
432
|
+
begin_date = Date.new(year, 1, 1) if year && year != 0
|
433
|
+
end
|
434
|
+
|
435
|
+
if (from = target.at_xpath("./coverage/to"))
|
436
|
+
year = from.at_xpath("year").try(:text).try(:to_i)
|
437
|
+
# set to end of year
|
438
|
+
end_date = Date.new(year, 12, 31) if year && year != 0
|
439
|
+
end
|
440
|
+
|
441
|
+
|
442
|
+
|
443
|
+
# If there's an embargo too, it may modify existing dates
|
444
|
+
if (embargo = target.at_xpath("./coverage/embargo"))
|
445
|
+
days = embargo.at_xpath("days").try(:text).try(:to_i)
|
446
|
+
days.try do |days|
|
447
|
+
embargo_days = Date.today - days
|
448
|
+
if embargo.at_xpath("availability").try(:text) == "available"
|
449
|
+
# only most recent X days, at earliest start
|
450
|
+
begin_date =
|
451
|
+
[begin_date || embargo_days, embargo_days].max
|
452
|
+
else # not_available
|
453
|
+
# stops at most recent X days, at latest end
|
454
|
+
end_date =
|
455
|
+
[end_date || embargo_days, embargo_days].min
|
456
|
+
end
|
457
|
+
end
|
458
|
+
end
|
459
|
+
return [begin_date, end_date]
|
460
|
+
end
|
461
|
+
|
462
|
+
# Pass in a list of hashes for making ServiceResponse's, we will roll up
|
463
|
+
# those that should be rolled up per roll_up_prefixes configuration.
|
464
|
+
#
|
465
|
+
# In :coverage_sensitive => true, will roll up sensitive to overlapping
|
466
|
+
# coverage to not remove any coverage.
|
467
|
+
#
|
468
|
+
# Does not mutate list passed in, don't try to change it to mutate,
|
469
|
+
# makes it hard to deal with list changing from underneath you in logic.
|
470
|
+
def roll_up_responses(list, options = {})
|
471
|
+
options = options.reverse_merge(:coverage_sensitive => true)
|
472
|
+
|
473
|
+
prefixes = @roll_up_prefixes
|
474
|
+
|
475
|
+
# If not configured for roll-up, just return it directly.
|
476
|
+
return list unless prefixes.present?
|
477
|
+
|
478
|
+
|
479
|
+
if options[:coverage_sensitive] == true
|
480
|
+
# roll up targets with same prefix only if coverage is a strict
|
481
|
+
# subset of an existing one. If two are equal, take first.
|
482
|
+
list = list.reject.each_with_index do |item, index|
|
483
|
+
prefix = prefixes.find {|p| item[:sfx_target_name].start_with?(p)}
|
484
|
+
bdate = item[:coverage_begin_date] || Date.new(1,1,1)
|
485
|
+
edate = item[:coverage_end_date] || Date.today
|
486
|
+
|
487
|
+
prefix && (
|
488
|
+
# earlier is equal or superset
|
489
|
+
list.slice(0, index).find do |candidate|
|
490
|
+
# nil considered very early or very late, unbounded
|
491
|
+
candidate_bdate = candidate[:coverage_begin_date] || Date.new(1,1,1)
|
492
|
+
candidate_edate = candidate[:coverage_end_date] || Date.today
|
493
|
+
|
494
|
+
candidate[:sfx_target_name].start_with?(prefix) &&
|
495
|
+
(candidate_bdate <= bdate) && (candidate_edate >= edate)
|
496
|
+
end ||
|
497
|
+
# later is superset, not equal
|
498
|
+
list.slice(index+1, list.length).find do |candidate|
|
499
|
+
candidate_bdate = (candidate[:coverage_begin_date] || Date.new(1,1,1))
|
500
|
+
candidate_edate = (candidate[:coverage_end_date] || Date.today)
|
501
|
+
|
502
|
+
candidate[:sfx_target_name].start_with?(prefix) &&
|
503
|
+
(candidate_bdate <= bdate) && (candidate_edate >= edate) &&
|
504
|
+
(! (bdate == candidate_bdate && edate == candidate_edate))
|
505
|
+
end
|
506
|
+
)
|
507
|
+
end
|
508
|
+
else # not coverage_sensitive
|
509
|
+
# Just roll up to FIRST of each prefix
|
510
|
+
list = list.reject.each_with_index do |item, index|
|
511
|
+
prefix = prefixes.find {|p| item[:sfx_target_name].start_with?(p)}
|
512
|
+
|
513
|
+
prefix && list.slice(0,index).find do |candidate|
|
514
|
+
candidate[:sfx_target_name].start_with?(prefix)
|
515
|
+
end
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
|
520
|
+
return list
|
521
|
+
end
|
522
|
+
|
380
523
|
|
381
524
|
def sfx_click_passthrough
|
382
525
|
# From config, or default to false.
|
@@ -387,7 +530,7 @@ class Sfx < Service
|
|
387
530
|
# umlaut service response is so old that we can't use it for
|
388
531
|
# sfx click passthrough anymore.
|
389
532
|
def expired_sfx_request(response)
|
390
|
-
require '
|
533
|
+
require 'cron_tab'
|
391
534
|
|
392
535
|
crontab_str = @sfx_requests_expire_crontab
|
393
536
|
|
File without changes
|
@@ -0,0 +1,267 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Uses ISI Web of Knowledge to generates links to "cited by" and "similar"
|
4
|
+
# articles.
|
5
|
+
#
|
6
|
+
# REQUIREMENTS: You must be an ISI customer if you want these links to actually
|
7
|
+
# work for your users. Off-campus users should be sent through EZProxy, see
|
8
|
+
# the EZProxy plug-in.
|
9
|
+
#
|
10
|
+
# You need to register for the the Thomson 'Links Article Match Retrieval'
|
11
|
+
# (LAMR) service api, which is used here. To register, see:
|
12
|
+
# http://wokinfo.com/products_tools/products/related/amr/
|
13
|
+
#
|
14
|
+
# You register by IP address, so no API key is needed once your registration
|
15
|
+
# goes through.
|
16
|
+
#
|
17
|
+
# If you later need to change the IP addresses entitled to use this API, use
|
18
|
+
# http://scientific.thomson.com/scientific/techsupport/cpe/form.html.
|
19
|
+
# to request a change.
|
20
|
+
#
|
21
|
+
# File support/outage tickets at http://ip-science.thomsonreuters.com/support/
|
22
|
+
#
|
23
|
+
# Note, as of 13 april 09, there's a bug in ISI where journal titles including
|
24
|
+
# ampersands cause an error. We will catch those errors and output a 'warning'
|
25
|
+
# instead of an 'error', since it's a known problem.
|
26
|
+
class Isi < Service
|
27
|
+
require 'open-uri'
|
28
|
+
require 'nokogiri'
|
29
|
+
require 'net/http'
|
30
|
+
require 'builder'
|
31
|
+
|
32
|
+
include MetadataHelper
|
33
|
+
|
34
|
+
|
35
|
+
def service_types_generated
|
36
|
+
return [ServiceTypeValue[:cited_by]]
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize(config)
|
40
|
+
#defaults
|
41
|
+
@wos_app_name = "Umlaut"
|
42
|
+
@display_name = "Web of Knowledge\xc2\xae" # trademark symbol
|
43
|
+
@api_url = "https://ws.isiknowledge.com/cps/xrpc"
|
44
|
+
@include_cited_by = true
|
45
|
+
@include_similar = true
|
46
|
+
|
47
|
+
@credits = {
|
48
|
+
@display_name => "http://apps.webofknowledge.com"
|
49
|
+
}
|
50
|
+
|
51
|
+
super(config)
|
52
|
+
end
|
53
|
+
|
54
|
+
def handle(request)
|
55
|
+
|
56
|
+
unless ( sufficient_metadata?(request.referent))
|
57
|
+
return request.dispatched(self, true)
|
58
|
+
end
|
59
|
+
|
60
|
+
xml = gen_lamr_request(request)
|
61
|
+
|
62
|
+
isi_response = do_lamr_request(xml)
|
63
|
+
|
64
|
+
|
65
|
+
begin
|
66
|
+
#raise if it's an error HTTP response
|
67
|
+
isi_response.value
|
68
|
+
|
69
|
+
response_xml = Nokogiri::XML(isi_response.body)
|
70
|
+
# Check for errors.
|
71
|
+
if (error = (response_xml.at('val[@name = "error"]') || response_xml.at("error") || response_xml.at('null[@name = "error"]')))
|
72
|
+
raise IsiResponseException.new("ISI service reported error: #{error.inner_text}")
|
73
|
+
end
|
74
|
+
|
75
|
+
add_responses( request, response_xml )
|
76
|
+
rescue IsiResponseException => e
|
77
|
+
# Is this the known problem with ampersands?
|
78
|
+
# if so, output a warning, but report success not exception,
|
79
|
+
# because this is a known condition.
|
80
|
+
metadata = request.referent.metadata
|
81
|
+
if ( (metadata["title"] && metadata["title"].include?('&')) ||
|
82
|
+
(metadata["jtitle"] && metadata['jtitle'].include?('&')))
|
83
|
+
Rails.logger.warn("ISI LAMR still exhibiting ampersand problems: #{e.message} ; OpenURL: ?#{request.to_context_object.kev}")
|
84
|
+
return request.dispatched(self, true)
|
85
|
+
else
|
86
|
+
# Log the error, return exception condition.
|
87
|
+
|
88
|
+
error_parts = []
|
89
|
+
error_parts << "ISI URI: #{@api_url}"
|
90
|
+
error_parts << "Request XML: #{xml}"
|
91
|
+
error_parts << "ISI Response body: #{response_xml}"
|
92
|
+
|
93
|
+
|
94
|
+
Rails.logger.error("#{e.message} ; " + error_parts.join("\n ") )
|
95
|
+
return request.dispatched(self, false, e)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
return request.dispatched(self, true)
|
100
|
+
end
|
101
|
+
|
102
|
+
# A DOI is always sufficient. Otherwise, it gets complicated because the ISI
|
103
|
+
# service is kind of picky in weird ways. ISSN alone is not enough, we need
|
104
|
+
# jtitle. Once you have jtitle, Vol/issue/start page are often enough, but
|
105
|
+
# article title really helps, and jtitle+atitle+year is often enough too.
|
106
|
+
def sufficient_metadata?(referent)
|
107
|
+
metadata = referent.metadata
|
108
|
+
return get_doi(referent) || get_pmid(referent) ||
|
109
|
+
( ( metadata['jtitle'] ||
|
110
|
+
metadata['title'] ) &&
|
111
|
+
(! (metadata['atitle'].blank? ||
|
112
|
+
metadata['date'].blank?
|
113
|
+
) ||
|
114
|
+
! ( metadata['volume'].blank? || metadata['issue'].blank? ||
|
115
|
+
metadata['spage'].blank?))
|
116
|
+
)
|
117
|
+
end
|
118
|
+
|
119
|
+
# produces XML to be posted to Thomson 'Links Article Match Retrieval' service api.
|
120
|
+
def gen_lamr_request(request)
|
121
|
+
output = ""
|
122
|
+
|
123
|
+
builder = Builder::XmlMarkup.new(:target => output, :indent => 2)
|
124
|
+
builder.instruct!(:xml, :encoding => "UTF-8")
|
125
|
+
|
126
|
+
builder.request(:xmlns => "http://www.isinet.com/xrpc41", :src => "app.id=Umlaut") do
|
127
|
+
builder.fn(:name => "LinksAMR.retrieve") do
|
128
|
+
builder.list do
|
129
|
+
# first map is authentication info. empty 'map' element since we are IP authenticated.
|
130
|
+
builder.map
|
131
|
+
# specify what we're requesting
|
132
|
+
builder.map do
|
133
|
+
builder.list(:name=>"WOS") do
|
134
|
+
builder.val("timesCited")
|
135
|
+
builder.val("ut")
|
136
|
+
builder.val("doi")
|
137
|
+
builder.val("sourceURL")
|
138
|
+
builder.val("citingArticlesURL")
|
139
|
+
builder.val("relatedRecordsURL")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
# specify our query
|
143
|
+
builder.map do
|
144
|
+
builder.map(:name => "cite_id") do
|
145
|
+
# Here's the tricky part, depends on what we've got.
|
146
|
+
metadata = request.referent.metadata
|
147
|
+
|
148
|
+
# DOI
|
149
|
+
if ( doi = get_doi(request.referent))
|
150
|
+
builder.val(doi, :name => "doi")
|
151
|
+
end
|
152
|
+
|
153
|
+
if ( pmid = get_pmid(request.referent))
|
154
|
+
builder.val(pmid, :name => "pmid")
|
155
|
+
end
|
156
|
+
|
157
|
+
# Journal title is crucial for ISI -- ISSN alone is
|
158
|
+
# not enough, weirdly!
|
159
|
+
if ( ! metadata['jtitle'].blank? )
|
160
|
+
builder.val(metadata['jtitle'], :name => "stitle" )
|
161
|
+
else
|
162
|
+
builder.val(metadata['title'], :name => 'stitle' )
|
163
|
+
end
|
164
|
+
|
165
|
+
# ISSN, not actually used much by ISI, but can't hurt.
|
166
|
+
if ( issn = request.referent.issn )
|
167
|
+
# ISSN _needs_ a hyphen for WoS, bah!
|
168
|
+
unless issn.match( /\-/ )
|
169
|
+
issn = issn[0,4] + '-' + issn[4,7]
|
170
|
+
end
|
171
|
+
builder.val(issn, :name => "issn")
|
172
|
+
end
|
173
|
+
|
174
|
+
# article title often helpful.
|
175
|
+
unless ( metadata['atitle'].blank?)
|
176
|
+
builder.val( metadata['atitle'], :name => "atitle")
|
177
|
+
end
|
178
|
+
# year
|
179
|
+
unless ( metadata['date'].blank?)
|
180
|
+
#first four digits are year
|
181
|
+
builder.val( metadata["date"][0,4], :name => "year" )
|
182
|
+
end
|
183
|
+
|
184
|
+
# Vol/issue/page. Oddly, issue isn't used very strongly
|
185
|
+
# by ISI, but can't hurt.
|
186
|
+
unless ( metadata['volume'].blank? )
|
187
|
+
builder.val(metadata['volume'], :name => 'vol')
|
188
|
+
end
|
189
|
+
unless ( metadata['issue'].blank? )
|
190
|
+
builder.val( metadata['issue'] , :name => 'issue')
|
191
|
+
end
|
192
|
+
unless ( metadata['spage'].blank? )
|
193
|
+
builder.val(metadata['spage'], :name => 'spage ')
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
return output
|
202
|
+
end
|
203
|
+
|
204
|
+
def do_lamr_request(xml)
|
205
|
+
uri = URI.parse(@api_url)
|
206
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
207
|
+
http.use_ssl = true if (uri.scheme == 'https')
|
208
|
+
|
209
|
+
headers = {'Content-Type' => 'application/xml'}
|
210
|
+
|
211
|
+
return http.post(uri.request_uri, xml, headers)
|
212
|
+
end
|
213
|
+
|
214
|
+
def add_responses(request, response_xml)
|
215
|
+
|
216
|
+
results = response_xml.at('map[@name ="cite_id"] map[@name="WOS"]')
|
217
|
+
unless (results)
|
218
|
+
error_message = "#{self.id}: "
|
219
|
+
error_message << 'Unexpected ISI response. The ISI response was not reported as an error, but did not contain a <map name="WOS"> inside a <map name="cite_id"> as we expected it to:'
|
220
|
+
error_message << "\n ISI XML request:\n#{gen_lamr_request(request)}\n"
|
221
|
+
error_message << "\n ISI http response status: #{isi_response.code}\n"
|
222
|
+
error_message << "\n ISI http response body:\n#{isi_response.body}\n"
|
223
|
+
Rails.logger.error(error_message)
|
224
|
+
end
|
225
|
+
|
226
|
+
|
227
|
+
# cited by
|
228
|
+
count = results.at('val[@name="timesCited"]')
|
229
|
+
count = count ? count.inner_text.to_i : 0
|
230
|
+
|
231
|
+
cited_by_url = results.at('val[@name="citingArticlesURL"]')
|
232
|
+
cited_by_url = cited_by_url.inner_text if cited_by_url
|
233
|
+
|
234
|
+
if (@include_cited_by && count > 0 && cited_by_url )
|
235
|
+
label = ServiceTypeValue[:cited_by].display_name_pluralize.downcase.capitalize
|
236
|
+
if count && count == 1
|
237
|
+
label = ServiceTypeValue[:cited_by].display_name.downcase.capitalize
|
238
|
+
end
|
239
|
+
|
240
|
+
request.add_service_response(:service=>self,
|
241
|
+
:display_text => "#{count} #{label}",
|
242
|
+
:count=> count,
|
243
|
+
:url => cited_by_url,
|
244
|
+
:debug_info => "url: " + cited_by_url,
|
245
|
+
:service_type_value => :cited_by)
|
246
|
+
end
|
247
|
+
|
248
|
+
# similar
|
249
|
+
|
250
|
+
similar_url = results.at('val[@name ="relatedRecordsURL"]')
|
251
|
+
similar_url = similar_url.inner_text if similar_url
|
252
|
+
|
253
|
+
if (@include_similar && similar_url )
|
254
|
+
request.add_service_response( :service=>self,
|
255
|
+
:display_text => " #{ServiceTypeValue[:similar].display_name_pluralize.downcase.capitalize}",
|
256
|
+
:url => similar_url,
|
257
|
+
:debug_info => "url: " + similar_url,
|
258
|
+
:service_type_value => :similar)
|
259
|
+
end
|
260
|
+
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
264
|
+
|
265
|
+
class IsiResponseException < StandardError
|
266
|
+
|
267
|
+
end
|