package org.sakaiproject.citation.impl.openurl; import java.util.Hashtable; import java.util.Map; import java.util.StringTokenizer; import javax.servlet.http.HttpServletRequest; import org.sakaiproject.citation.api.Citation; import org.sakaiproject.citation.api.Schema; import org.sakaiproject.citation.impl.openurl.ContextObject.Entity; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.test.AbstractSingleSpringContextTests; public class OpenURLServiceImplTest extends AbstractSingleSpringContextTests { private static final String PRIMO_EXAMPLE = "ctx_ver=Z39.88-2004&ctx_enc=info:ofi/enc:UTF-8&" + "ctx_tim=2010-10-20T13:27:00IST&url_ver=Z39.88-2004&url_ctx_fmt=infofi/fmt:kev:mtx:ctx&" + "rfr_id=info:sid/primo.exlibrisgroup.com:primo3-Journal-UkOxU&rft_val_fmt=info:ofi/fmt:kev:mtx:book&" + "rft.genre=book&rft.atitle=&rft.jtitle=&rft.btitle=Linux in a nutshell&rft.aulast=Siever&" + "rft.auinit=&rft.auinit1=&rft.auinitm=&rft.ausuffix=&rft.au=&rft.aucorp=&rft.volume=&rft.issue=&" + "rft.part=&rft.quarter=&rft.ssn=&rft.spage=&rft.epage=&rft.pages=&rft.artnum=&rft.issn=&rft.eissn=&" + "rft.isbn=9780596154486&rft.sici=&rft.coden=&rft_id=info:doi/&rft.object_id=&" + "rft_dat=<UkOxU>UkOxUb17140770</UkOxU>&rft.eisbn="; private static final String PRIMO_EXAMPLE_FULL_ID = "ctx_ver=Z39.88-2004&ctx_enc=info:ofi/enc:UTF-8&ctx_tim=2011-04-11T15%3A40%3A37IST&url_ver=Z39.88-2004&url_ctx_fmt=infofi/fmt:kev:mtx:ctx&rfr_id=info:sid/primo.exlibrisgroup.com:primo3-Article-crossref&rft_val_fmt=info:ofi/fmt:kev:mtx:&rft.genre=article&rft.atitle=Cheese&rft.jtitle=Journal of Agricultural %26 Food Information&rft.btitle=&rft.aulast=Cherubin&rft.auinit=&rft.auinit1=&rft.auinitm=&rft.ausuffix=&rft.au=Cherubin, Dan&rft.aucorp=&rft.date=2007049&rft.volume=7&rft.issue=4&rft.part=&rft.quarter=&rft.ssn=&rft.spage=3&rft.epage=10&rft.pages=&rft.artnum=&rft.issn=1049-6505&rft.eissn=&rft.isbn=&rft.sici=&rft.coden=&rft_id=info:doi/10.1300/J108v07n04_02&rft.object_id=&rft_dat=%3Ccrossref%3E10.1300/J108v07n04_02%3C/crossref%3E&rft.eisbn=&rft_id=http%3A%2F%2Fsolo.bodleian.ox.ac.uk%2Fprimo_library%2Flibweb%2Faction%2Fdisplay.do%3Fdoc%3DTN_crossref10.1300/J108v07n04_02%26vid%3DOXVU1%26fn%3Ddisplay%26displayMode%3Dfull&rft_id=info:oai/"; private OpenURLServiceImpl service; protected void onSetUp() throws Exception { this.service = (OpenURLServiceImpl) getApplicationContext().getBean("org.sakaiproject.citation.impl.openurl.OpenURLServiceImpl"); } protected String[] getConfigLocations() { return new String[] { "classpath:org/sakaiproject/citation/impl/openurl.xml", "classpath:org/sakaiproject/citation/impl/openurl/test-beans.xml" }; } public void testConvertCitation() { assertNull(service.convert((Citation)null)); } public void testConvertContextObject() { assertNull(service.convert((ContextObject)null)); } public void testParseNull() { MockHttpServletRequest req = new MockHttpServletRequest("GET", "http://localhost:8080/someurl"); ContextObject contextObject = service.parse(req); assertNull(contextObject); } public void testParsePrimo() { MockHttpServletRequest req = createRequest("http://localhost:8080/someurl?"+PRIMO_EXAMPLE); ContextObject contextObject = service.parse(req); assertNotNull(contextObject); ContextObjectEntity book = contextObject.getEntity(Entity.REFERENT); assertEquals("Linux in a nutshell", book.getValue("btitle")); Citation bookCitation = service.convert(contextObject); assertEquals("Linux in a nutshell", bookCitation.getCitationProperty(Schema.TITLE, false)); } private MockHttpServletRequest createRequest(String openUrl) { MockHttpServletRequest req = new MockHttpServletRequest("GET", openUrl); req.setQueryString(openUrl); req.setParameters(parseQueryString(openUrl)); return req; } public void testParsePrimoFullId() { MockHttpServletRequest req = createRequest("http://localhost:8080/someurl?"+PRIMO_EXAMPLE_FULL_ID); ContextObject contextObject = service.parse(req); Citation citation = service.convert(contextObject); assertNotNull(citation.getCitationProperty("otherIds", false)); assertEquals("Cheese", citation.getCitationProperty("title", false)); } public void testParseBook() { Citation book = convert(find(mockGetRequest(SamplePrimoOpenURLs.BOOK))); Map props = book.getCitationProperties(); assertEquals("Patent searching: tools & techniques", props.get("title")); assertEquals("047178379X", props.get("isnIdentifier")); assertEquals("[edited By] David Hunt, Long Nguyen, Matthew Rodgers.", props.get("creator")); } public Citation convert(ContextObject contextObject) { Citation citation = service.convert(contextObject); assertNotNull(citation); return citation; } public HttpServletRequest mockGetRequest(String url) { MockHttpServletRequest req = new MockHttpServletRequest("GET", url); init(req); return req; } public ContextObject find(HttpServletRequest req) { ContextObject contextObject = service.parse(req); assertNotNull(contextObject); return contextObject; } /** * Sets up the query string and parameters based on the URL. * @param req */ public void init(MockHttpServletRequest req) { String url = req.getRequestURL().toString(); int queryStart = url.indexOf('?'); if (queryStart >= 0) { String query = url.substring(queryStart+1); req.setQueryString(query); req.setParameters(parseQueryString(query)); } } // Stolen from HttpUtils.parseQueryString() public static Map parseQueryString(String s) { String valArray[] = null; if (s == null) { throw new IllegalArgumentException(); } Hashtable ht = new Hashtable(); StringBuffer sb = new StringBuffer(); StringTokenizer st = new StringTokenizer(s, "&"); while (st.hasMoreTokens()) { String pair = (String) st.nextToken(); int pos = pair.indexOf('='); if (pos == -1) { // XXX // should give more detail about the illegal argument throw new IllegalArgumentException(); } String key = parseName(pair.substring(0, pos), sb); String val = parseName(pair.substring(pos + 1, pair.length()), sb); if (ht.containsKey(key)) { String oldVals[] = (String[]) ht.get(key); valArray = new String[oldVals.length + 1]; for (int i = 0; i < oldVals.length; i++) valArray[i] = oldVals[i]; valArray[oldVals.length] = val; } else { valArray = new String[1]; valArray[0] = val; } ht.put(key, valArray); } return ht; } // Stolen from HttpUtils.parseQueryString() static private String parseName(String s, StringBuffer sb) { sb.setLength(0); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); switch (c) { case '+': sb.append(' '); break; case '%': try { sb.append((char) Integer.parseInt( s.substring(i + 1, i + 3), 16)); i += 2; } catch (NumberFormatException e) { // XXX // need to be more specific about illegal arg throw new IllegalArgumentException(); } catch (StringIndexOutOfBoundsException e) { String rest = s.substring(i); sb.append(rest); if (rest.length() == 2) i++; } break; default: sb.append(c); break; } } return sb.toString(); } public void testParseSampleArticle() { HttpServletRequest req = createRequest(SamplePrimoOpenURLs.ARTICLE); ContextObject co = service.parse(req); ContextObjectEntity entity = co.getEntity(Entity.REFERENT); assertEquals("Patent", entity.getValue("atitle")); Citation citation = service.convert(co); assertEquals("Patent", citation.getCitationProperty("title", false)); assertEquals("Metal Powder Report", citation.getCitationProperty("sourceTitle", false)); assertEquals("199206", citation.getCitationProperty("date", false)); assertEquals("47", citation.getCitationProperty("volume", false)); assertEquals("6", citation.getCitationProperty("issue", false)); assertEquals("59", citation.getCitationProperty("startPage", false)); assertEquals("61", citation.getCitationProperty("endPage", false)); assertEquals("00260657", citation.getCitationProperty("isnIdentifier", false)); assertEquals("10.1016/0026-0657(92)91523-M", citation.getCitationProperty("doi", false)); } public void testParseSampleNewspaper() { HttpServletRequest req = createRequest(SamplePrimoOpenURLs.NEWSPAPER); ContextObject co = service.parse(req); ContextObjectEntity entity = co.getEntity(Entity.REFERENT); assertEquals("THE NATIONAL ERA", entity.getValue("jtitle")); Citation citation = service.convert(co); assertTrue(((String)citation.getCitationProperty("title", false)).startsWith("AZA")); assertEquals("THE NATIONAL ERA", citation.getCitationProperty("sourceTitle", false)); assertEquals("18590310", citation.getCitationProperty("date", false)); assertEquals("XIII", citation.getCitationProperty("volume", false)); assertEquals("636", citation.getCitationProperty("issue", false)); } public void testParseSampleOther() { HttpServletRequest req = createRequest(SamplePrimoOpenURLs.OTHER); ContextObject co = service.parse(req); ContextObjectEntity entity = co.getEntity(Entity.REFERENT); assertEquals("European Journal of Echocardiography", entity.getValue("jtitle")); Citation citation = service.convert(co); // Fails because it's described as a book, but is actually a journal assertEquals("Eustachian valve interfering with transcatheter closure of patent foramen ovale", citation.getCitationProperty("title", false)); assertEquals("European Journal of Echocardiography", citation.getCitationProperty("sourceTitle", false)); assertEquals("Roelandt, Philip", citation.getCitationProperty("creator", false)); assertEquals("200707", citation.getCitationProperty("date", false)); assertEquals("9", citation.getCitationProperty("volume", false)); assertEquals("1", citation.getCitationProperty("issue", false)); assertEquals("158", citation.getCitationProperty("startPage", false)); assertEquals("159", citation.getCitationProperty("endPage", false)); assertEquals("1525-2167", citation.getCitationProperty("isnIdentifier", false)); assertEquals("10.1016/j.euje.2007.05.006", citation.getCitationProperty("doi", false)); } public void testParseSampleText() { HttpServletRequest req = createRequest(SamplePrimoOpenURLs.TEXT); ContextObject co = service.parse(req); ContextObjectEntity entity = co.getEntity(Entity.REFERENT); assertEquals("Cardiology in the Young", entity.getValue("jtitle")); Citation citation = service.convert(co); assertEquals("Complete transcatheter closure of a patent arterial duct with subsequent haemolysis", citation.getCitationProperty("title", false)); assertEquals("Cardiology in the Young", citation.getCitationProperty("sourceTitle", false)); assertEquals("Cace, Neven", citation.getCitationProperty("creator", false)); assertEquals("20100325201008", citation.getCitationProperty("date", false)); assertEquals("20", citation.getCitationProperty("volume", false)); assertEquals("4", citation.getCitationProperty("issue", false)); assertEquals("462", citation.getCitationProperty("startPage", false)); assertEquals("464", citation.getCitationProperty("endPage", false)); assertEquals("1047-9511", citation.getCitationProperty("isnIdentifier", false)); assertEquals("10.1017/S1047951110000326", citation.getCitationProperty("doi", false)); } public void testParseSampleBook() { HttpServletRequest req = createRequest(SamplePrimoOpenURLs.BOOK); ContextObject co = service.parse(req); ContextObjectEntity entity = co.getEntity(Entity.REFERENT); assertEquals("Patent searching: tools & techniques", entity.getValue("btitle")); Citation citation = service.convert(co); assertEquals("Patent searching: tools & techniques", citation.getCitationProperty("title", false)); assertEquals("[edited By] David Hunt, Long Nguyen, Matthew Rodgers.", citation.getCitationProperty("creator", false)); assertEquals("047178379X", citation.getCitationProperty("isnIdentifier", false)); } public void testParseSampleReview() { // Rather screwed, a book by rft_val_fmt but using journal properties. HttpServletRequest req = createRequest(SamplePrimoOpenURLs.REVIEW); ContextObject co = service.parse(req); ContextObjectEntity entity = co.getEntity(Entity.REFERENT); assertEquals("Theatre Research International", entity.getValue("jtitle")); Citation citation = service.convert(co); assertEquals("Children of the Queen's Revels: A Jacobean Theatre Repertory (Book Review)", citation.getCitationProperty("title", false)); assertEquals("Theatre Research International", citation.getCitationProperty("sourceTitle", false)); assertEquals("PRICE, VICTORIA E", citation.getCitationProperty("creator", false)); assertEquals("200707", citation.getCitationProperty("date", false)); assertEquals("32", citation.getCitationProperty("volume", false)); assertEquals("2", citation.getCitationProperty("issue", false)); assertEquals("225", citation.getCitationProperty("startPage", false)); assertEquals("0307-8833", citation.getCitationProperty("isnIdentifier", false)); assertEquals("10.1017/S0307883306002653", citation.getCitationProperty("doi", false)); } public void testSampleJournal() { HttpServletRequest req = createRequest(SamplePrimoOpenURLs.JOURNAL); ContextObject co = service.parse(req); ContextObjectEntity entity = co.getEntity(Entity.REFERENT); assertEquals("Kingston Journal", entity.getValue("jtitle")); Citation citation = service.convert(co); assertEquals("Kingston Journal", citation.getCitationProperty("title", false)); assertEquals("1789", citation.getCitationProperty("date", false)); } public void testSampleLegal() { HttpServletRequest req = createRequest(SamplePrimoOpenURLs.LEGAL); ContextObject co = service.parse(req); ContextObjectEntity entity = co.getEntity(Entity.REFERENT); assertEquals("198604", entity.getValue("date")); Citation citation = service.convert(co); assertTrue(((String)citation.getCitationProperty("title", false)).startsWith("Patent Policy")); assertEquals("198604", citation.getCitationProperty("date", false)); } public void testSampleDissertation() { // Again a book, but using article title. HttpServletRequest req = createRequest(SamplePrimoOpenURLs.DISSERTATION); ContextObject co = service.parse(req); ContextObjectEntity entity = co.getEntity(Entity.REFERENT); assertEquals("Thomas Blanchard's Patent Management", entity.getValue("atitle")); Citation citation = service.convert(co); assertEquals("Thomas Blanchard's Patent Management", citation.getCitationProperty("title", false)); assertEquals("The Journal of Economic History", citation.getCitationProperty("sourceTitle", false)); assertEquals("Cooper, Carolyn C", citation.getCitationProperty("creator", false)); assertEquals("198706", citation.getCitationProperty("date", false)); assertEquals("47", citation.getCitationProperty("volume", false)); assertEquals("2", citation.getCitationProperty("issue", false)); assertEquals("487", citation.getCitationProperty("startPage", false)); assertEquals("488", citation.getCitationProperty("endPage", false)); assertEquals("0022-0507", citation.getCitationProperty("isnIdentifier", false)); assertEquals("10.1017/S002205070004821X", citation.getCitationProperty("doi", false)); } public void testSamplePrimoImage() { HttpServletRequest req = createRequest(SamplePrimoOpenURLs.IMAGE); ContextObject co = service.parse(req); ContextObjectEntity entity = co.getEntity(Entity.REFERENT); assertEquals("Cocktail Hour", entity.getValue("atitle")); Citation citation = service.convert(co); assertEquals("Cocktail Hour", citation.getCitationProperty("title", false)); assertEquals("2008", citation.getCitationProperty("date", false)); assertEquals("Nov/Dec 2008", citation.getCitationProperty("issue", false)); assertEquals("58", citation.getCitationProperty("startPage", false)); assertEquals("63", citation.getCitationProperty("endPage", false)); assertEquals("1836-7526", citation.getCitationProperty("isnIdentifier", false)); } // We had an issue with this one where both the title and sourceTitle ended up with being the the same. public void testSamplePrimoJournalCorrect() { HttpServletRequest req = createRequest(SamplePrimoOpenURLs.CORRECT_JOURNAL); ContextObject co = service.parse(req); ContextObjectEntity entity = co.getEntity(Entity.REFERENT); assertEquals("Theory and practice of logic programming", entity.getValue("jtitle")); Citation citation = service.convert(co); assertEquals("Theory and practice of logic programming", citation.getCitationProperty("title", false)); assertEquals("", citation.getCitationProperty("sourceTitle", false)); } public void testLinuxInANutshellGood() { HttpServletRequest req = createRequest(SamplePrimoOpenURLs.WORKING_IMPORT); ContextObject co = service.parse(req); ContextObjectEntity entity = co.getEntity(Entity.REFERENT); assertNotNull(entity.getIds()); assertTrue(entity.getIds().contains("http://solo.bodleian.ox.ac.uk/primo_library/libweb/action/display.do?doc=UkOxUUkOxUb15585873&vid=OXVU1&fn=display&displayMode=full")); } public void testLinuxInANutshellBad() { HttpServletRequest req = createRequest(SamplePrimoOpenURLs.BROKEN_IMPORT); ContextObject co = service.parse(req); ContextObjectEntity entity = co.getEntity(Entity.REFERENT); assertNotNull(entity.getIds()); assertTrue(entity.getIds().contains("http://solo.bodleian.ox.ac.uk/primo_library/libweb/action/display.do?doc=UkOxUUkOxUb17140770&vid=OXVU1&fn=display&displayMode=full")); } }