[DS-588] Patch for SFX (OpenURL resolver)

git-svn-id: http://scm.dspace.org/svn/repo/dspace/trunk@5478 9c30dcfa-912a-0410-8fc2-9e0234be79fd
This commit is contained in:
Stuart Lewis
2010-10-20 01:57:33 +00:00
parent d4a6ea6a1c
commit 314b3ed1ba
7 changed files with 495 additions and 107 deletions

View File

@@ -0,0 +1,352 @@
/*
* SFXFileReader.java
*
* Version: $Revision:$
*
* Date: $Date:$
*
* Copyright (c) 2002-2009, Duraspace. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Duraspace nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package org.dspace.app.sfx;
import java.io.File;
import java.io.IOException;
import java.lang.String;
import java.net.URLEncoder;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.dspace.content.DCPersonName;
import org.dspace.content.DCValue;
import org.dspace.content.Item;
import org.dspace.core.Constants;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class SFXFileReader {
/** The SFX configuration file */
private static Document doc;
/** log4j logger */
private static final Logger log = Logger.getLogger(SFXFileReader.class);
/**
* Loads the SFX configuraiton file
*
* @param fileName The name of the SFX configuration file
* @param item The item to process
*
* @return the SFX string
* @throws IOException
*/
public static String loadSFXFile(String fileName, Item item) throws IOException
{
// Parse XML file -> XML document will be build
if (doc == null) doc = parseFile(fileName);
// Return final sfx Query String
return doNodes(doc, item);
}
/** Parses XML file and returns XML document.
* @param fileName XML file to parse
* @return XML document or <B>null</B> if error occured
*/
public static Document parseFile(String fileName) {
log.info("Parsing XML file... " + fileName);
DocumentBuilder docBuilder;
Document doc = null;
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
docBuilderFactory.setIgnoringElementContentWhitespace(true);
try {
docBuilder = docBuilderFactory.newDocumentBuilder();
}
catch (ParserConfigurationException e) {
log.error("Wrong parser configuration: " + e.getMessage());
return null;
}
File sourceFile = new File(fileName);
try {
doc = docBuilder.parse(sourceFile);
}
catch (SAXException e) {
log.error("Wrong XML file structure: " + e.getMessage());
return null;
}
catch (IOException e) {
log.error("Could not read source file: " + e.getMessage());
}
log.info("XML file parsed");
return doc;
}
/**
* Process the item
*
* @param node
* @param item
* @return
* @throws IOException
*/
public static String doNodes(Node node, Item item) throws IOException
{
if (node == null)
{
log.error (" Empty Node ");
return null;
}
Node e = getElement(node);
NodeList nl = e.getChildNodes();
int len = nl.getLength();
String sfxfield = "";
int i = 0;
while ((i < len) && (sfxfield == ""))
{
Node nd = nl.item(i);
if ((nd == null) || isEmptyTextNode(nd))
{
i++;
continue;
}
String tagName = nd.getNodeName();
if (tagName.equals("query-pairs"))
{
sfxfield = processFields(nd, item);
}
i++;
}
log.info("Process fields : " + sfxfield);
return sfxfield;
}
/**
* Process the fields
*
* @param e
* @param item
* @return
* @throws IOException
*/
private static String processFields(Node e, Item item) throws IOException
{
NodeList cl = e.getChildNodes();
int lench = cl.getLength();
String myquery = "";
for (int j = 0; j < lench; j++)
{
Node nch = cl.item(j);
String querystring = "";
String schema = "";
String qualifier = "";
String element = "";
if (nch.getNodeName().equals("field"))
{
NodeList pl = nch.getChildNodes();
int plen = pl.getLength();
int finish = 0;
for (int k = 0; k < plen; k++)
{
Node vn= pl.item(k);
String vName = vn.getNodeName();
if (vName.equals("querystring"))
{
querystring = getValue(vn);
finish ++;
}
else if (vName.equals("dc-schema"))
{
schema = getValue(vn);;
finish ++;
}
else if (vName.equals("dc-element"))
{
element = getValue(vn);
finish ++;
}
else if (vName.equals("dc-qualifier"))
{
qualifier = getValue(vn);
finish ++;
if (qualifier == "")
{
qualifier = null;
}
}
if (finish == 4)
{
DCValue[] dcvalue = item.getMetadata(schema, element, qualifier, Item.ANY);
if (dcvalue.length > 0)
{
// Issued Date
if (element.equals("date") && qualifier.equals("issued"))
{
String fullDate = dcvalue[0].value;
// Remove the time if there is one - day is greatest granularity for SFX
if (fullDate.length() > 10)
{
fullDate = fullDate.substring(0, 10);
}
if (myquery.equals(""))
{ myquery = querystring + URLEncoder.encode(fullDate, Constants.DEFAULT_ENCODING); }
else
{ myquery = myquery + "&" + querystring + URLEncoder.encode(fullDate, Constants.DEFAULT_ENCODING); }
}
else
{
// Contributor Author
if (element.equals("contributor") && qualifier.equals("author"))
{
DCPersonName dpn = new DCPersonName(dcvalue[0].value);
String dpnName = dcvalue[0].value;
if (querystring.endsWith("aulast=")) { dpnName = dpn.getLastName(); }
else { if (querystring.endsWith("aufirst=")) { dpnName = dpn.getFirstNames(); }}
if (myquery.equals(""))
{ myquery = querystring + URLEncoder.encode(dpnName, Constants.DEFAULT_ENCODING); }
else
{ myquery = myquery + "&" + querystring + URLEncoder.encode(dpnName, Constants.DEFAULT_ENCODING); }
}
else
{
if (myquery.equals(""))
{ myquery = querystring + URLEncoder.encode(dcvalue[0].value, Constants.DEFAULT_ENCODING);}
else
{ myquery = myquery + "&" + querystring + URLEncoder.encode(dcvalue[0].value, Constants.DEFAULT_ENCODING);}
}
}
} // if dc.length > 0
finish = 0;
querystring = "";
schema = "";
element = "";
qualifier = "";
} // if finish == 4
} //for k
} // if field
} // for j
return myquery;
}
/** Returns element node
* @param node element (it is XML tag)
* @return Element node otherwise null
*/
public static Node getElement(Node node)
{
NodeList child = node.getChildNodes();
int length = child.getLength();
for (int i = 0; i < length; i++)
{
Node kid = child.item(i);
if (kid.getNodeType() == Node.ELEMENT_NODE)
{
return kid;
}
}
return null;
}
/** Is Empty text Node **/
public static boolean isEmptyTextNode(Node nd)
{
boolean isEmpty = false;
if (nd.getNodeType() == Node.TEXT_NODE)
{
String text = nd.getNodeValue().trim();
if (text.length() == 0)
{
isEmpty = true;
}
}
return isEmpty;
}
/**
* Returns the value of the node's attribute named <name>
**/
public static String getAttribute(Node e, String name)
{
NamedNodeMap attrs = e.getAttributes();
int len = attrs.getLength();
if (len > 0)
{
for (int i = 0; i < len; i++)
{
Node attr = attrs.item(i);
if (name.equals(attr.getNodeName()))
{
return attr.getNodeValue().trim();
}
}
}
//no such attribute
return null;
}
/**
* Returns the value found in the Text node (if any) in the
* node list that's passed in.
*/
public static String getValue(Node node)
{
NodeList child = node.getChildNodes();
for (int i = 0; i < child.getLength(); i++)
{
Node kid = child.item(i);
short type = kid.getNodeType();
if (type == Node.TEXT_NODE)
{
return kid.getNodeValue().trim();
}
}
// Didn't find a text node
return null;
}
}

View File

@@ -39,6 +39,7 @@
*/ */
package org.dspace.app.webui.jsptag; package org.dspace.app.webui.jsptag;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URLEncoder; import java.net.URLEncoder;
@@ -51,6 +52,10 @@ import org.dspace.content.Item;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.w3c.dom.*;
import org.dspace.app.sfx.SFXFileReader;
/** /**
* Renders an SFX query link. Takes one attribute - "item" which must be an Item * Renders an SFX query link. Takes one attribute - "item" which must be an Item
* object. * object.
@@ -61,8 +66,13 @@ import org.dspace.core.Constants;
public class SFXLinkTag extends TagSupport public class SFXLinkTag extends TagSupport
{ {
/** Item to display SFX link for */ /** Item to display SFX link for */
private Item item; private Item item;
/** The fully qualified pathname of the SFX XML file */
private String sfxFile = ConfigurationManager.getProperty("dspace.dir") + File.separator
+ "config" + File.separator + "sfx.xml";
public SFXLinkTag() public SFXLinkTag()
{ {
super(); super();
@@ -81,78 +91,15 @@ public class SFXLinkTag extends TagSupport
return SKIP_BODY; return SKIP_BODY;
} }
String sfxQuery = ""; String sfxQuery = "";
DCValue[] titles = item.getDC("title", null, Item.ANY); sfxQuery = SFXFileReader.loadSFXFile(sfxFile, item);
if (titles.length > 0)
{
sfxQuery = sfxQuery
+ "&title="
+ URLEncoder.encode(titles[0].value,
Constants.DEFAULT_ENCODING);
}
DCValue[] authors = item.getDC("contributor", "author", Item.ANY);
if (authors.length > 0)
{
DCPersonName dpn = new DCPersonName(authors[0].value);
sfxQuery = sfxQuery
+ "&aulast="
+ URLEncoder.encode(dpn.getLastName(),
Constants.DEFAULT_ENCODING);
sfxQuery = sfxQuery
+ "&aufirst="
+ URLEncoder.encode(dpn.getFirstNames(),
Constants.DEFAULT_ENCODING);
}
DCValue[] isbn = item.getDC("identifier", "isbn", Item.ANY);
if (isbn.length > 0)
{
sfxQuery = sfxQuery
+ "&isbn="
+ URLEncoder.encode(isbn[0].value,
Constants.DEFAULT_ENCODING);
}
DCValue[] issn = item.getDC("identifier", "issn", Item.ANY);
if (issn.length > 0)
{
sfxQuery = sfxQuery
+ "&issn="
+ URLEncoder.encode(issn[0].value,
Constants.DEFAULT_ENCODING);
}
DCValue[] dates = item.getDC("date", "issued", Item.ANY);
if (dates.length > 0)
{
String fullDate = dates[0].value;
// Remove the time if there is one - day is greatest granularity
// for SFX
if (fullDate.length() > 10)
{
fullDate = fullDate.substring(0, 10);
}
sfxQuery = sfxQuery
+ "&date="
+ URLEncoder.encode(fullDate,
Constants.DEFAULT_ENCODING);
}
// Remove initial &, if any // Remove initial &, if any
if (sfxQuery.startsWith("&")) if (sfxQuery.startsWith("&"))
{ {
sfxQuery = sfxQuery.substring(1); sfxQuery = sfxQuery.substring(1);
} }
pageContext.getOut().print(sfxServer + sfxQuery); pageContext.getOut().print(sfxServer + sfxQuery);
} }
catch (IOException ie) catch (IOException ie)
@@ -183,4 +130,5 @@ public class SFXLinkTag extends TagSupport
{ {
item = itemIn; item = itemIn;
} }
} }

View File

@@ -39,12 +39,14 @@
*/ */
package org.dspace.app.xmlui.aspect.artifactbrowser; package org.dspace.app.xmlui.aspect.artifactbrowser;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.io.StringWriter; import java.io.StringWriter;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.net.URLEncoder;
import javax.servlet.ServletException; import javax.servlet.ServletException;
@@ -82,6 +84,8 @@ import org.jdom.Element;
import org.jdom.Text; import org.jdom.Text;
import org.jdom.output.XMLOutputter; import org.jdom.output.XMLOutputter;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import org.dspace.core.ConfigurationManager;
import org.dspace.app.sfx.SFXFileReader;
/** /**
* Display a single item. * Display a single item.
@@ -114,6 +118,11 @@ public class ItemViewer extends AbstractDSpaceTransformer implements CacheablePr
/** XHTML crosswalk instance */ /** XHTML crosswalk instance */
private DisseminationCrosswalk xHTMLHeadCrosswalk = null; private DisseminationCrosswalk xHTMLHeadCrosswalk = null;
private String sfxFile = ConfigurationManager.getProperty("dspace.dir") + File.separator
+ "config" + File.separator + "sfx.xml";
private String sfxQuery = null;
/** /**
* Generate the unique caching key. * Generate the unique caching key.
* This key must be unique inside the space of this component. * This key must be unique inside the space of this component.
@@ -187,6 +196,24 @@ public class ItemViewer extends AbstractDSpaceTransformer implements CacheablePr
HandleUtil.buildHandleTrail(item,pageMeta,contextPath); HandleUtil.buildHandleTrail(item,pageMeta,contextPath);
pageMeta.addTrail().addContent(T_trail); pageMeta.addTrail().addContent(T_trail);
// Add SFX link
String sfxserverUrl = ConfigurationManager.getProperty("sfx.server.url");
if (sfxserverUrl != null && sfxserverUrl.length() > 0)
{
sfxQuery = "";
// parse XML file -> XML document will be build
sfxQuery = SFXFileReader.loadSFXFile(sfxFile, item);
// Remove initial &, if any
if (sfxQuery.startsWith("&"))
{
sfxQuery = sfxQuery.substring(1);
}
sfxserverUrl = sfxserverUrl.trim() +"&" + sfxQuery.trim();
pageMeta.addMetadata("sfx","server").addContent(sfxserverUrl);
}
// Metadata for <head> element // Metadata for <head> element
if (xHTMLHeadCrosswalk == null) if (xHTMLHeadCrosswalk == null)
{ {

View File

@@ -1012,21 +1012,14 @@
coins coins
--> -->
<xsl:template name="renderCOinS"> <!--- SFX renderCOinS -->
<xsl:text>ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;</xsl:text>
<xsl:for-each select=".//dim:field[@element = 'identifier']"> <xsl:template name="renderCOinS">
<xsl:text>rft_id=</xsl:text> <xsl:text>ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;</xsl:text>
<xsl:value-of select="encoder:encode(string(.))"/> <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='sfx'][@qualifier='server']"/>
<xsl:text>&amp;</xsl:text> <xsl:text>&amp;</xsl:text>
</xsl:for-each>
<xsl:text>rfr_id=info%3Asid%2Fdatadryad.org%3Arepo&amp;</xsl:text> <xsl:text>rfr_id=info%3Asid%2Fdatadryad.org%3Arepo&amp;</xsl:text>
<xsl:for-each select=".//dim:field[@element != 'description' and @mdschema !='dc' and @qualifier != 'provenance']"> </xsl:template>
<xsl:value-of select="concat('rft.', @element,'=',encoder:encode(string(.))) "/>
<xsl:if test="position()!=last()">
<xsl:text>&amp;</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet> </xsl:stylesheet>

View File

@@ -502,6 +502,14 @@
</div> </div>
</xsl:if> </xsl:if>
<xsl:apply-templates /> <xsl:apply-templates />
<xsl:if test="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='sfx'][@qualifier='server']">
<a>
<xsl:attribute name="href">
<xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='sfx'][@qualifier='server']"/>
</xsl:attribute>
<xsl:text>Find Full text</xsl:text>
</a>
</xsl:if>
</div> </div>
</xsl:template> </xsl:template>

View File

@@ -1,5 +1,8 @@
1.7.0 1.7.0
===== =====
(Yin Yin Latt)
- [DS-588] Patch for SFX (OpenURL resolver)
(Michael B. Klein) (Michael B. Klein)
- [DS-699] ChoiceAuthority plugin for old-style controlled vocabularies - [DS-699] ChoiceAuthority plugin for old-style controlled vocabularies

57
dspace/config/sfx.xml Normal file
View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<openurl>
<query-pairs>
<field>
<querystring>rft_id=info:doi/</querystring>
<dc-schema>dc</dc-schema>
<dc-element>identifier</dc-element>
<dc-qualifier>doi</dc-qualifier>
</field>
</query-pairs>
<query-pairs>
<field>
<querystring>rft_id=info:pmid/</querystring>
<dc-schema>dc</dc-schema>
<dc-element>identifier</dc-element>
<dc-qualifier>pmid</dc-qualifier>
</field>
</query-pairs>
<query-pairs>
<field>
<querystring>rft.issn=</querystring>
<dc-schema>dc</dc-schema>
<dc-element>identifier</dc-element>
<dc-qualifier>issn</dc-qualifier>
</field>
<field>
<querystring>rft.isbn=</querystring>
<dc-schema>dc</dc-schema>
<dc-element>identifier</dc-element>
<dc-qualifier>isbn</dc-qualifier>
</field>
<field>
<querystring>rft.atitle=</querystring>
<dc-schema>dc</dc-schema>
<dc-element>title</dc-element>
<dc-qualifier></dc-qualifier>
</field>
<field>
<querystring>rft.aulast=</querystring>
<dc-schema>dc</dc-schema>
<dc-element>contributor</dc-element>
<dc-qualifier>author</dc-qualifier>
</field>
<field>
<querystring>rft.aufirst=</querystring>
<dc-schema>dc</dc-schema>
<dc-element>contributor</dc-element>
<dc-qualifier>author</dc-qualifier>
</field>
<field>
<querystring>rft.date=</querystring>
<dc-schema>dc</dc-schema>
<dc-element>date</dc-element>
<dc-qualifier>issued</dc-qualifier>
</field>
</query-pairs>
</openurl>