Merge pull request #1163 from atmire/DS-2880

DS-2880: Pubmed integration into XMLUI submission
This commit is contained in:
Mark H. Wood
2016-01-27 10:22:16 -05:00
31 changed files with 5230 additions and 2 deletions

View File

@@ -682,6 +682,11 @@
<artifactId>axiom-api</artifactId>
<version>1.2.14</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.9.1</version>
</dependency>
<!-- S3 -->
<dependency>
<groupId>com.amazonaws</groupId>

View File

@@ -0,0 +1,36 @@
- [Introduction](#Introduction)
- [Additional Config](#Additional-config)
- [Pubmed specific Config](#Pubmed-specific)
- [Metadata mapping classes](#Metadata-classes)
- [Service classes](#Service-classes)
# Introduction <a name="Introduction"></a> #
**[First read the base documentation on external importing](../README.md)**
This documentation explains the implementation of the importer framework using pubmed as an example.
The configuration done for pubmed specifically is located at pubmed-integration.xml in dspace/config/spring/api
I will not go into detail to what exactly is configured for the pubmed integration as it is simply a usage of the classes explained [here](../README.md)
# Additional Config <a name="Additional-config"></a> #
To be able to do the lookup for our configured import-service, we need to be able to know what url to use to check for publications.
This can be done by setting the publication.url property though maven using 2 different ways.
- Setting the publication.url property to the address as defined in the configured importservice (PubmedImportService in this case) in the file spring-dspace-addon-import-services.xml. This will check this single configured url for publications.
- Setting the publication url property to an askterisk '*'. This will check all configured importServices for their urls to base the search for publications on.
# Pubmed specific classes Config <a name="Pubmed-specific"></a> #
These classes are simply implementations based of the base classes defined in importer/external. They add characteristic behaviour for services/mapping for the pubmed specific data.
## Metadata mapping classes <a name="Metadata-classes"></a> ##
- "PubmedFieldMapping". An implementation of AbstractMetadataFieldMapping, linking to the bean that serves as the entry point of other metadata mapping
- "PubmedDateMetadatumContributor"/"PubmedLanguageMetadatumContributor". Pubmed specific implementations of the "MetadataContributor" interface
## Service classes <a name="Service-classes"></a> ##
- "GeneratePubmedQueryService". Generates the pubmed query which is used to retrieve the records. This is based on a given item.
- "ImportMetadataSourceServiceImpl". Child class of "AbstractImportMetadataSourceService", retrieving the records from pubmed.

View File

@@ -0,0 +1,146 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.importer.external.pubmed.metadatamapping;
import org.apache.log4j.Logger;
import org.dspace.content.DCDate;
import org.dspace.importer.external.metadatamapping.MetadataFieldConfig;
import org.dspace.importer.external.metadatamapping.MetadataFieldMapping;
import org.dspace.importer.external.metadatamapping.MetadatumDTO;
import org.dspace.importer.external.metadatamapping.contributor.MetadataContributor;
import org.springframework.beans.factory.annotation.Required;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
/**
* Created by Philip Vissenaekens (philip at atmire dot com)
* Date: 06/07/15
* Time: 13:48
*/
public class PubmedDateMetadatumContributor<T> implements MetadataContributor<T> {
Logger log = Logger.getLogger(PubmedDateMetadatumContributor.class);
private MetadataFieldMapping<T, MetadataContributor<T>> metadataFieldMapping;
private List<String> dateFormatsToAttempt;
public List<String> getDateFormatsToAttempt() {
return dateFormatsToAttempt;
}
@Required
public void setDateFormatsToAttempt(List<String> dateFormatsToAttempt) {
this.dateFormatsToAttempt = dateFormatsToAttempt;
}
private MetadataFieldConfig field;
private MetadataContributor day;
private MetadataContributor month;
private MetadataContributor year;
@Override
public void setMetadataFieldMapping(MetadataFieldMapping<T, MetadataContributor<T>> metadataFieldMapping) {
this.metadataFieldMapping = metadataFieldMapping;
day.setMetadataFieldMapping(metadataFieldMapping);
month.setMetadataFieldMapping(metadataFieldMapping);
year.setMetadataFieldMapping(metadataFieldMapping);
}
public PubmedDateMetadatumContributor() {
}
public PubmedDateMetadatumContributor(MetadataFieldConfig field, MetadataContributor day, MetadataContributor month, MetadataContributor year) {
this.field = field;
this.day = day;
this.month = month;
this.year = year;
}
@Override
public Collection<MetadatumDTO> contributeMetadata(T t) {
List<MetadatumDTO> values = new LinkedList<MetadatumDTO>();
try {
LinkedList<MetadatumDTO> yearList = (LinkedList<MetadatumDTO>) year.contributeMetadata(t);
LinkedList<MetadatumDTO> monthList = (LinkedList<MetadatumDTO>) month.contributeMetadata(t);
LinkedList<MetadatumDTO> dayList = (LinkedList<MetadatumDTO>) day.contributeMetadata(t);
for (int i = 0; i < yearList.size(); i++) {
DCDate dcDate = null;
String dateString = "";
if (monthList.size() > i && dayList.size() > i) {
dateString = yearList.get(i).getValue() + "-" + monthList.get(i).getValue() + "-" + dayList.get(i).getValue();
} else if (monthList.size() > i) {
dateString = yearList.get(i).getValue() + "-" + monthList.get(i).getValue();
} else {
dateString = yearList.get(i).getValue();
}
for (String dateFormat : dateFormatsToAttempt) {
try {
SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
Date date = formatter.parse(dateString);
dcDate = new DCDate(date);
} catch (ParseException e) {
log.error(e.getMessage(), e);
}
}
if (dcDate != null) {
values.add(metadataFieldMapping.toDCValue(field, dcDate.toString()));
}
}
} catch (Exception e) {
log.error("Error", e);
}
return values;
}
public MetadataFieldConfig getField() {
return field;
}
public void setField(MetadataFieldConfig field) {
this.field = field;
}
public MetadataContributor getDay() {
return day;
}
public void setDay(MetadataContributor day) {
this.day = day;
}
public MetadataContributor getMonth() {
return month;
}
public void setMonth(MetadataContributor month) {
this.month = month;
}
public MetadataContributor getYear() {
return year;
}
public void setYear(MetadataContributor year) {
this.year = year;
}
}

View File

@@ -0,0 +1,26 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.importer.external.pubmed.metadatamapping;
import org.dspace.importer.external.metadatamapping.AbstractMetadataFieldMapping;
import javax.annotation.Resource;
import java.util.Map;
/**
* Created by jonas - jonas@atmire.com on 06/11/15.
*/
public class PubmedFieldMapping extends AbstractMetadataFieldMapping {
@Override
@Resource (name = "pubmedMetadataFieldMap")
public void setMetadataFieldMap(Map metadataFieldMap) {
super.setMetadataFieldMap(metadataFieldMap);
}
}

View File

@@ -0,0 +1,84 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.importer.external.pubmed.metadatamapping;
import org.apache.log4j.Logger;
import org.dspace.importer.external.metadatamapping.MetadataFieldConfig;
import org.dspace.importer.external.metadatamapping.MetadataFieldMapping;
import org.dspace.importer.external.metadatamapping.MetadatumDTO;
import org.dspace.importer.external.metadatamapping.contributor.MetadataContributor;
import java.util.*;
/**
* Created by Philip Vissenaekens (philip at atmire dot com)
* Date: 07/07/15
* Time: 15:08
*/
public class PubmedLanguageMetadatumContributor<T> implements MetadataContributor<T> {
Logger log = Logger.getLogger(PubmedDateMetadatumContributor.class);
private MetadataFieldMapping<T,MetadataContributor<T>> metadataFieldMapping;
private HashMap<String,String> iso3toIso2;
private MetadataFieldConfig field;
private MetadataContributor language;
public PubmedLanguageMetadatumContributor() {
iso3toIso2=new HashMap<>();
for (Locale locale : Locale.getAvailableLocales()) {
iso3toIso2.put(locale.getISO3Language(),locale.getLanguage());
}
}
public PubmedLanguageMetadatumContributor(MetadataFieldConfig field, MetadataContributor language) {
this();
this.field = field;
this.language = language;
}
@Override
public void setMetadataFieldMapping(MetadataFieldMapping<T, MetadataContributor<T>> metadataFieldMapping) {
this.metadataFieldMapping = metadataFieldMapping;
language.setMetadataFieldMapping(metadataFieldMapping);
}
@Override
public Collection<MetadatumDTO> contributeMetadata(T t) {
List<MetadatumDTO> values=new LinkedList<MetadatumDTO>();
try {
LinkedList<MetadatumDTO> languageList = (LinkedList<MetadatumDTO>) language.contributeMetadata(t);
for (MetadatumDTO metadatum : languageList) {
values.add(metadataFieldMapping.toDCValue(field, iso3toIso2.get(metadatum.getValue().toLowerCase())));
}
} catch (Exception e) {
log.error("Error", e);
}
return values;
}
public MetadataContributor getLanguage() {
return language;
}
public void setLanguage(MetadataContributor language) {
this.language = language;
}
public MetadataFieldConfig getField() {
return field;
}
public void setField(MetadataFieldConfig field) {
this.field = field;
}
}

View File

@@ -0,0 +1,47 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.importer.external.pubmed.metadatamapping.service;
import org.dspace.content.Item;
import org.dspace.content.MetadataValue;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.ItemService;
import org.dspace.importer.external.MetadataSourceException;
import org.dspace.importer.external.Query;
import org.dspace.importer.external.metadatamapping.service.GenerateQueryService;
import java.util.List;
/**
* Created by jonas - jonas@atmire.com on 06/11/15.
*/
public class GeneratePubmedQueryService implements GenerateQueryService {
@Override
public Query generateQueryForItem(Item item) throws MetadataSourceException {
Query query = new Query();
ItemService itemService = ContentServiceFactory.getInstance().getItemService();
List<MetadataValue> doi = itemService.getMetadata(item, "dc", "identifier", "doi", Item.ANY);
if(doi.size()>0){
query.addParameter("term", doi.get(0).getValue());
query.addParameter("field","ELocationID");
return query;
}
List<MetadataValue> title = itemService.getMetadata(item, "dc", "title", null, Item.ANY);
if(title.size()>0) {
query.addParameter("term", title.get(0).getValue());
query.addParameter("field","title");
return query;
}
return null;
}
}

View File

@@ -0,0 +1,308 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.importer.external.pubmed.service.other;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMXMLBuilderFactory;
import org.apache.axiom.om.OMXMLParserWrapper;
import org.apache.axiom.om.xpath.AXIOMXPath;
import org.dspace.content.Item;
import org.dspace.importer.external.MetadataSourceException;
import org.dspace.importer.external.Query;
import org.dspace.importer.external.datamodel.ImportRecord;
import org.jaxen.JaxenException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.StringReader;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
/**
* Created by jonas - jonas@atmire.com on 06/11/15.
*/
public class ImportMetadataSourceServiceImpl extends org.dspace.importer.external.service.AbstractImportMetadataSourceService {
private String baseAddress;
private WebTarget pubmedWebTarget;
@Override
public int getNbRecords(String query) throws MetadataSourceException {
return retry(new GetNbRecords(query));
}
@Override
public int getNbRecords(Query query) throws MetadataSourceException {
return retry(new GetNbRecords(query));
}
@Override
public Collection<ImportRecord> getRecords(String query, int start, int count) throws MetadataSourceException {
return retry(new GetRecords(query, start, count));
}
@Override
public Collection<ImportRecord> getRecords(Query q) throws MetadataSourceException {
return retry(new GetRecords(q));
}
@Override
public ImportRecord getRecord(String id) throws MetadataSourceException {
return retry(new GetRecord(id));
}
@Override
public ImportRecord getRecord(Query q) throws MetadataSourceException {
return retry(new GetRecord(q));
}
@Override
public String getImportSource() {
return baseAddress;
}
@Override
public Collection<ImportRecord> findMatchingRecords(Item item) throws MetadataSourceException {
return retry(new FindMatchingRecords(item));
}
@Override
public Collection<ImportRecord> findMatchingRecords(Query q) throws MetadataSourceException {
return retry(new FindMatchingRecords(q));
}
@Override
public void init() throws Exception {
Client client = ClientBuilder.newClient();
WebTarget webTarget = client.target(baseAddress);
pubmedWebTarget = webTarget.queryParam("db", "pubmed");
}
public String getBaseAddress() {
return baseAddress;
}
public void setBaseAddress(String baseAddress) {
this.baseAddress = baseAddress;
}
private class GetNbRecords implements Callable<Integer> {
private GetNbRecords(String queryString) {
query = new Query();
query.addParameter("query",queryString);
}
private Query query;
public GetNbRecords(Query query) {
this.query = query;
}
@Override
public Integer call() throws Exception {
WebTarget getRecordIdsTarget = pubmedWebTarget.queryParam("term", query.getParameterAsClass("query", String.class));
getRecordIdsTarget = getRecordIdsTarget.path("esearch.fcgi");
Invocation.Builder invocationBuilder = getRecordIdsTarget.request(MediaType.TEXT_PLAIN_TYPE);
Response response = invocationBuilder.get();
String responseString = response.readEntity(String.class);
String count = getSingleElementValue(responseString, "Count");
return Integer.parseInt(count);
}
}
private String getSingleElementValue(String src, String elementName){
OMXMLParserWrapper records = OMXMLBuilderFactory.createOMBuilder(new StringReader(src));
OMElement element = records.getDocumentElement();
AXIOMXPath xpath = null;
String value = null;
try {
xpath = new AXIOMXPath("//" + elementName);
List<OMElement> recordsList = xpath.selectNodes(element);
if(!recordsList.isEmpty()) {
value = recordsList.get(0).getText();
}
} catch (JaxenException e) {
value = null;
}
return value;
}
private class GetRecords implements Callable<Collection<ImportRecord>> {
private Query query;
private GetRecords(String queryString, int start, int count) {
query = new Query();
query.addParameter("query",queryString);
query.addParameter("start",start);
query.addParameter("count",count);
}
private GetRecords(Query q) {
this.query = q;
}
@Override
public Collection<ImportRecord> call() throws Exception {
String queryString = query.getParameterAsClass("query",String.class);
Integer start = query.getParameterAsClass("start",Integer.class);
Integer count = query.getParameterAsClass("count",Integer.class);
if(count==null || count < 0){
count = 10;
}
if(start==null || start < 0){
start = 0;
}
List<ImportRecord> records = new LinkedList<ImportRecord>();
WebTarget getRecordIdsTarget = pubmedWebTarget.queryParam("term", queryString);
getRecordIdsTarget = getRecordIdsTarget.queryParam("retstart", start);
getRecordIdsTarget = getRecordIdsTarget.queryParam("retmax", count);
getRecordIdsTarget = getRecordIdsTarget.queryParam("usehistory", "y");
getRecordIdsTarget = getRecordIdsTarget.path("esearch.fcgi");
Invocation.Builder invocationBuilder = getRecordIdsTarget.request(MediaType.TEXT_PLAIN_TYPE);
Response response = invocationBuilder.get();
String responseString = response.readEntity(String.class);
String queryKey = getSingleElementValue(responseString, "QueryKey");
String webEnv = getSingleElementValue(responseString, "WebEnv");
WebTarget getRecordsTarget = pubmedWebTarget.queryParam("WebEnv", webEnv);
getRecordsTarget = getRecordsTarget.queryParam("query_key", queryKey);
getRecordsTarget = getRecordsTarget.queryParam("retmode", "xml");
getRecordsTarget = getRecordsTarget.path("efetch.fcgi");
getRecordsTarget = getRecordsTarget.queryParam("retmax", count);
getRecordsTarget = getRecordsTarget.queryParam("retstart", start);
invocationBuilder = getRecordsTarget.request(MediaType.TEXT_PLAIN_TYPE);
response = invocationBuilder.get();
List<OMElement> omElements = splitToRecords(response.readEntity(String.class));
for (OMElement record : omElements) {
records.add(transformSourceRecords(record));
}
return records;
}
}
private List<OMElement> splitToRecords(String recordsSrc) {
OMXMLParserWrapper records = OMXMLBuilderFactory.createOMBuilder(new StringReader(recordsSrc));
OMElement element = records.getDocumentElement();
AXIOMXPath xpath = null;
try {
xpath = new AXIOMXPath("//PubmedArticle");
List<OMElement> recordsList = xpath.selectNodes(element);
return recordsList;
} catch (JaxenException e) {
return null;
}
}
private class GetRecord implements Callable<ImportRecord> {
private Query query;
private GetRecord(String id) {
query = new Query();
query.addParameter("id",id);
}
public GetRecord(Query q) {
query = q;
}
@Override
public ImportRecord call() throws Exception {
String id = query.getParameterAsClass("id", String.class);
WebTarget getRecordTarget = pubmedWebTarget.queryParam("id", id);
getRecordTarget = getRecordTarget.queryParam("retmode", "xml");
getRecordTarget = getRecordTarget.path("efetch.fcgi");
Invocation.Builder invocationBuilder = getRecordTarget.request(MediaType.TEXT_PLAIN_TYPE);
Response response = invocationBuilder.get();
List<OMElement> omElements = splitToRecords(response.readEntity(String.class));
if(omElements.size()==0) {
return null;
}
return transformSourceRecords(omElements.get(0));
}
}
private class FindMatchingRecords implements Callable<Collection<ImportRecord>> {
private Query query;
private FindMatchingRecords(Item item) throws MetadataSourceException {
query = getGenerateQueryForItem().generateQueryForItem(item);
}
public FindMatchingRecords(Query q) {
query = q;
}
@Override
public Collection<ImportRecord> call() throws Exception {
List<ImportRecord> records = new LinkedList<ImportRecord>();
WebTarget getRecordIdsTarget = pubmedWebTarget.queryParam("term", query.getParameterAsClass("term", String.class));
getRecordIdsTarget = getRecordIdsTarget.queryParam("field", query.getParameterAsClass("field",String.class));
getRecordIdsTarget = getRecordIdsTarget.queryParam("usehistory", "y");
getRecordIdsTarget = getRecordIdsTarget.path("esearch.fcgi");
Invocation.Builder invocationBuilder = getRecordIdsTarget.request(MediaType.TEXT_PLAIN_TYPE);
Response response = invocationBuilder.get();
String responseString = response.readEntity(String.class);
String queryKey = getSingleElementValue(responseString, "QueryKey");
String webEnv = getSingleElementValue(responseString, "WebEnv");
WebTarget getRecordsTarget = pubmedWebTarget.queryParam("WebEnv", webEnv);
getRecordsTarget = getRecordsTarget.queryParam("query_key", queryKey);
getRecordsTarget = getRecordsTarget.queryParam("retmode", "xml");
getRecordsTarget = getRecordsTarget.path("efetch.fcgi");
invocationBuilder = getRecordsTarget.request(MediaType.TEXT_PLAIN_TYPE);
response = invocationBuilder.get();
List<OMElement> omElements = splitToRecords(response.readEntity(String.class));
for (OMElement record : omElements) {
records.add(transformSourceRecords(record));
}
return records;
}
}
}

View File

@@ -0,0 +1,85 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.submit.step;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.dspace.app.util.SubmissionInfo;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Item;
import org.dspace.content.MetadataValue;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.ItemService;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context;
import org.dspace.importer.external.MetadataSourceException;
import org.dspace.importer.external.datamodel.ImportRecord;
import org.dspace.importer.external.metadatamapping.MetadatumDTO;
import org.dspace.importer.external.service.ImportService;
import org.dspace.submit.AbstractProcessingStep;
import org.dspace.utils.DSpace;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
/**
* Created by jonas - jonas@atmire.com on 06/11/15.
*/
public class XMLUIStartSubmissionLookupStep extends AbstractProcessingStep {
private static String publicationUrl = null;
private static Logger log = Logger.getLogger(XMLUIStartSubmissionLookupStep.class);
private ItemService itemService = ContentServiceFactory.getInstance().getItemService();
@Override
public int doProcessing(Context context, HttpServletRequest request, HttpServletResponse response, SubmissionInfo subInfo) throws ServletException, IOException, AuthorizeException, SQLException {
String publicationID = request.getParameter("publication_id");
if (StringUtils.isNotBlank(publicationID)) {
ImportService importService = new DSpace().getServiceManager().getServiceByName(null, ImportService.class);
Item item = subInfo.getSubmissionItem().getItem();
try {
ImportRecord record = importService.getRecord(getPublicationUrl(), publicationID);
for (MetadataValue metadatum : itemService.getMetadata(item, Item.ANY, Item.ANY, Item.ANY, Item.ANY)) {
itemService.clearMetadata(context, item, metadatum.getMetadataField().getMetadataSchema().getName(), metadatum.getMetadataField().getElement(), metadatum.getMetadataField().getQualifier(), metadatum.getLanguage());
}
for (MetadatumDTO metadatum : record.getValueList()) {
itemService.addMetadata(context, item, metadatum.getSchema(), metadatum.getElement(), metadatum.getQualifier(),null, metadatum.getValue());
}
itemService.update(context, item);
context.dispatchEvents();
} catch (MetadataSourceException e) {
log.error(e);
}
}
return 0;
}
@Override
public int getNumberOfPages(HttpServletRequest request, SubmissionInfo subInfo) throws ServletException {
return 1;
}
public String getPublicationUrl(){
if(publicationUrl==null){
publicationUrl=ConfigurationManager.getProperty("publication-lookup","publication.url");
}
return publicationUrl;
}
}

View File

@@ -20,6 +20,22 @@
<context:annotation-config /> <!-- allows us to use spring annotations in beans -->
<bean id="importService" class="org.dspace.importer.external.service.ImportService" scope="singleton"
lazy-init="false" autowire="byType" destroy-method="destroy"/>
lazy-init="false" autowire="byType" destroy-method="destroy">
</bean>
<bean id="PubmedImportService" class="org.dspace.importer.external.pubmed.service.other.ImportMetadataSourceServiceImpl" scope="singleton">
<property name="metadataFieldMapping" ref="PubmedMetadataFieldMapping"/>
<property name="baseAddress" value="http://eutils.ncbi.nlm.nih.gov/entrez/eutils/"/>
</bean>
<bean id="PubmedMetadataFieldMapping"
class="org.dspace.importer.external.pubmed.metadatamapping.PubmedFieldMapping">
</bean>
<!-- Metadatafield used to check against if it's already imported or not during the JSONLookupSearcher-->
<bean id="lookupID" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.identifier.other"/>
</bean>
</beans>

View File

@@ -0,0 +1,32 @@
<!--
The contents of this file are subject to the license and copyright
detailed in the LICENSE and NOTICE files at the root of the source
tree and available online at
http://www.dspace.org/license/
-->
<p>Showing records {{shownStart}}-{{shownCount}} of {{total}}</p>
<ul class="publication-records-modal">
<li>
<ul>
{{#each records}}
<li {{#if record.[imported]}}class="imported"{{/if}}>
{{#each record.[dc.title]}}
{{#ifCond @index "==" 0}}<span class="bold">{{this}}</span> {{/ifCond}}
{{/each}}
</li>
<li {{#if record.[imported]}}class="imported"{{/if}}>
{{#each record.[dc.contributor.author]}}
{{#ifCond @index "<" 5}} <span>{{this}}{{#unless @last}}, {{/unless}} </span>{{/ifCond}}
{{#ifCond @index "==" 5}}...{{/ifCond}}
{{/each}}
</li>
<li {{#if record.[imported]}}class="imported"{{/if}}>
<button id="publication-records-import-{{record.[dc.identifier.other]}}" class="ds-button-field btn btn-default publication-records-import-btn float-right" name="import" type="submit">Import</button>
</li>
{{/each}}
</ul>
</li>
</ul>

View File

@@ -78,6 +78,26 @@
</xsl:apply-templates>
</xsl:template>
<xsl:template match="dri:div[@n='lookup-modal']" priority="2">
<div id="lookup-search-results" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&#215;</button>
<h4 class="modal-title">Publication Results</h4>
</div>
<div class="modal-body">
<p class="help-block">help</p>
</div>
<div class="modal-footer">
<button class="ds-button-field btn btn-default pull-left" id="publication-pagination-previous">Previous results</button>
<button class="ds-button-field btn btn-default pull-left" id="publication-pagination-next">Next results</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</xsl:template>
<!-- Special case for divs tagged as "notice" -->
<xsl:template match="dri:div[@n='general-message']" priority="3">
<div>

View File

@@ -795,6 +795,13 @@
<xsl:template name="addJavascript">
<script type="text/javascript"><xsl:text>
if(typeof window.publication === 'undefined'){
window.publication={};
};
window.publication.contextPath= '</xsl:text><xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'][not(@qualifier)]"/><xsl:text>';</xsl:text>
<xsl:text>window.publication.themePath= '</xsl:text><xsl:value-of select="$theme-path"/><xsl:text>';</xsl:text>
</script>
<!--TODO concat & minify!-->
<script>

View File

@@ -61,6 +61,7 @@
<exclude>**/DD_belated*</exclude>
<exclude>**/detectmobile*</exclude>
<exclude>**/sc-mobile*</exclude>
<exclude>**/handlebars/**</exclude>
</excludes>
</configuration>
</plugin>

View File

@@ -0,0 +1,174 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.xmlui.aspect.submission.submit;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.generation.AbstractGenerator;
import org.apache.cocoon.xml.dom.DOMStreamer;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.dspace.app.xmlui.utils.ContextUtil;
import org.dspace.app.xmlui.wing.WingConstants;
import org.dspace.content.Item;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.ItemService;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context;
import org.dspace.importer.external.datamodel.ImportRecord;
import org.dspace.importer.external.metadatamapping.MetadataFieldConfig;
import org.dspace.importer.external.metadatamapping.MetadatumDTO;
import org.dspace.importer.external.service.ImportService;
import org.dspace.utils.DSpace;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Created by jonas - jonas@atmire.com on 06/11/15.
*/
public class JSONLookupSearcher extends AbstractGenerator {
private ImportService importService;
private String lookupURI = null;
private static Logger log = Logger.getLogger(JSONLookupSearcher.class);
private ItemService itemService = ContentServiceFactory.getInstance().getItemService();
private Request request;
private Context context;
@Override
public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par) throws ProcessingException, SAXException, IOException {
super.setup(resolver, objectModel, src, par);
request = ObjectModelHelper.getRequest(objectModel);
try {
context = ContextUtil.obtainContext(objectModel);
} catch (SQLException e) {
log.error(e.getMessage(),e);
}
importService = new DSpace().getServiceManager().getServiceByName(null, ImportService.class);
}
@Override
public void generate() throws IOException, SAXException, ProcessingException {
String query = request.getParameter("search");
int start = 0;
String startString = request.getParameter("start");
if(StringUtils.isNotBlank(startString)){
int parsedStart = Integer.parseInt(startString);
if(parsedStart>=0){
start = parsedStart;
}
}
try {
int total = importService.getNbRecords(getLookupURI(), query);
Collection<ImportRecord> records = importService.getRecords(getLookupURI(), query, start, 20);
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
org.w3c.dom.Document document = docBuilder.newDocument();
Element rootnode = document.createElement("root");
document.appendChild(rootnode);
rootnode.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:i18n", WingConstants.I18N.URI);
Element totalNode = document.createElement("total");
totalNode.setTextContent(String.valueOf(total));
rootnode.appendChild(totalNode);
Element startNode = document.createElement("start");
startNode.setTextContent(String.valueOf(start));
rootnode.appendChild(startNode);
Element recordsNode = document.createElement("records");
recordsNode.setAttribute("array", "true");
rootnode.appendChild(recordsNode);
recordsNode.setAttribute("array", "true");
MetadataFieldConfig importIdField = new DSpace().getServiceManager().getServiceByName("lookupID", MetadataFieldConfig.class);
for (ImportRecord record : records) {
Element recordWrapperNode = document.createElement("recordWrapper");
recordWrapperNode.setAttribute("object", "true");
recordsNode.appendChild(recordWrapperNode);
Element recordNode = document.createElement("record");
recordNode.setAttribute("namedObject", "true");
HashMap<String,Element> metadatumValueNodes = new HashMap();
for (MetadatumDTO metadatum : record.getValueList()) {
if(!metadatumValueNodes.containsKey(getField(metadatum))) {
Element metadatumNode = document.createElement(getField(metadatum));
metadatumNode.setAttribute("array", "true");
metadatumValueNodes.put(getField(metadatum), metadatumNode);
if (getField(metadatum).equals(importIdField.getField())) {
Iterator<Item> iterator = itemService.findByMetadataField(context, importIdField.getSchema(), importIdField.getElement(), importIdField.getQualifier(), metadatum.getValue());
if(iterator.hasNext()){
Element existsInDSpaceNode = document.createElement("imported");
existsInDSpaceNode.setTextContent("true");
recordNode.appendChild(existsInDSpaceNode);
}
}
}
Element metadatumValueNode = document.createElement("metadatumValue");
metadatumValueNode.setTextContent(metadatum.getValue());
metadatumValueNodes.get(getField(metadatum)).appendChild(metadatumValueNode);
}
for (Element element : metadatumValueNodes.values()) {
recordNode.appendChild(element);
}
recordWrapperNode.appendChild(recordNode);
}
DOMStreamer streamer = new DOMStreamer(contentHandler, lexicalHandler);
streamer.stream(document);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
private String getField(MetadatumDTO metadatum) {
return metadatum.getSchema()+"."+metadatum.getElement()+((metadatum.getQualifier()!=null)?"."+metadatum.getQualifier():"");
}
public String getLookupURI() {
if(lookupURI ==null){
lookupURI = ConfigurationManager.getProperty("publication-lookup","publication.url");
}
return lookupURI;
}
public void setLookupURI(String lookupURI) {
this.lookupURI = lookupURI;
}
}

View File

@@ -0,0 +1,123 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.xmlui.aspect.submission.submit;
import org.dspace.app.xmlui.aspect.submission.AbstractSubmissionStep;
import org.dspace.app.xmlui.utils.UIException;
import org.dspace.app.xmlui.wing.Message;
import org.dspace.app.xmlui.wing.WingException;
import org.dspace.app.xmlui.wing.element.*;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection;
import org.dspace.content.MetadataValue;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.ItemService;
import org.dspace.content.service.MetadataFieldService;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.sql.SQLException;
/**
* Created by jonas - jonas@atmire.com on 06/11/15.
*/
public class StartSubmissionLookupStep extends AbstractSubmissionStep {
protected static final Message T_title =
message("xmlui.Submission.submit.StartSubmissionLookupStep.title");
protected static final Message T_lookup_help =
message("xmlui.Submission.submit.StartSubmissionLookupStep.lookup_help");
protected static final Message T_submit_lookup =
message("xmlui.Submission.submit.StartSubmissionLookupStep.submit_lookup");
protected static final Message T_submit_publication_item=
message("xmlui.Submission.submit.StartSubmissionLookupStep.submit_publication_item");
private ItemService itemService = ContentServiceFactory.getInstance().getItemService();
MetadataFieldService metadataFieldService = ContentServiceFactory.getInstance().getMetadataFieldService();
@Override
public List addReviewSection(List reviewList) throws SAXException, WingException, UIException, SQLException, IOException, AuthorizeException {
return null;
}
public void addPageMeta(PageMeta pageMeta) throws SAXException,
WingException
{
pageMeta.addMetadata("title").addContent(T_submission_title);
pageMeta.addTrailLink(contextPath + "/",T_dspace_home);
pageMeta.addTrail().addContent(T_submission_trail);
pageMeta.addMetadata("javascript", null, "handlebars", true).addContent("../../static/handlebars/handlebars.js");
pageMeta.addMetadata("javascript", null, "submission-lookup", true).addContent("../../static/js/submission-lookup.js");
pageMeta.addMetadata("stylesheet", "screen", "datatables", true).addContent("../../static/Datatables/DataTables-1.8.0/media/css/datatables.css");
pageMeta.addMetadata("javascript", "static", "datatables", true).addContent("static/Datatables/DataTables-1.8.0/media/js/jquery.dataTables.min.js");
}
public void addBody(Body body) throws SAXException, WingException,
UIException, SQLException, IOException, AuthorizeException
{
Collection collection = submission.getCollection();
String actionURL = contextPath + "/handle/"+collection.getHandle() + "/submit/" + knot.getId() + ".continue";
Division div = body.addInteractiveDivision("StartSubmissionLookupStep",actionURL,Division.METHOD_POST,"primary submission");
div.setHead(T_submission_head);
addSubmissionProgressList(div);
List form = div.addList("submit-lookup",List.TYPE_FORM);
form.setHead(T_title);
form.addItem().addContent(T_lookup_help);
Item item = form.addItem("lookup-group","input-group");
item.addText("search");
item.addButton("lookup").setValue(T_submit_lookup);
org.dspace.content.Item submissionItem = submission.getItem();
java.util.List<MetadataValue> pubmedId = itemService.getMetadata(submissionItem, "dc", "identifier", "other", org.dspace.content.Item.ANY);
if(pubmedId.size()>0){
form.addItem("publication-header","page-header").addContent(T_submit_publication_item);
java.util.List<MetadataValue> titles = itemService.getMetadata(submissionItem,"dc","title",null,org.dspace.content.Item.ANY);
if(titles.size()>0){
form.addItem("publication-title", "bold").addContent(titles.get(0).getValue());
}
java.util.List<MetadataValue> authors = itemService.getMetadata(submissionItem,"dc", "contributor", "author", org.dspace.content.Item.ANY);
if(authors.size()>0){
StringBuilder builder = new StringBuilder();
for (int i = 0;i<authors.size();i++) {
builder.append(authors.get(i).getValue());
if(i+1<authors.size()){
builder.append(", ");
}
}
if(builder.length()>150){
builder.setLength(147);
builder.append("...");
}
form.addItem().addContent(builder.toString());
}
}
div.addDivision("lookup-modal");
div.addHidden("publication_id");
addControlButtons(form);
}
}

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
The contents of this file are subject to the license and copyright
detailed in the LICENSE and NOTICE files at the root of the source
tree and available online at
http://www.dspace.org/license/
-->
<map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0">
<map:components>
<map:generators>
<map:generator name="JSONLookupSearcher" src="org.dspace.app.xmlui.aspect.submission.submit.JSONLookupSearcher"/>
</map:generators>
<map:serializers>
<map:serializer name="text" src="org.apache.cocoon.serialization.TextSerializer" mime-type="text/plain;charset=UTF-8" logger="sitemap.serializer.text" />
</map:serializers>
</map:components>
<map:pipelines>
<map:pipeline>
<map:match pattern="**">
<map:generate type="JSONLookupSearcher"/>
<map:act type="locale">
<map:transform type="i18n">
<map:parameter name="locale" value="{locale}"/>
</map:transform>
</map:act>
<map:transform src="translatedxml2text.xslt"/>
<map:transform src="xml2json.xslt"/>
<map:serialize type="text"/>
</map:match>
</map:pipeline>
</map:pipelines>
</map:sitemap>

View File

@@ -0,0 +1,343 @@
<!--
The contents of this file are subject to the license and copyright
detailed in the LICENSE and NOTICE files at the root of the source
tree and available online at
http://www.dspace.org/license/
-->
<!--
The purpose of this xml is the following
In the generators several elements are created with the sole purpose of translation bij the i18ntransformer
These elements that have been translated need to go back to text so we can pass them along to the jason xslt
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="@*|node()|text()|comment()|processing-instruction()">
<xsl:copy>
<xsl:apply-templates select="@*|node()|text()|comment()|processing-instruction()"/>
</xsl:copy>
</xsl:template>
<xsl:param name="use-empty-syntax" select="true()"/>
<xsl:param name="exclude-unused-prefixes" select="true()"/>
<!-- a node-set; each node's string-value
will be interpreted as a namespace URI to be
excluded from the serialization. -->
<xsl:param name="namespaces-to-exclude" select="/.."/>
<!-- initialized to empty node-set -->
<xsl:param name="start-tag-start" select="'&lt;'"/>
<xsl:param name="start-tag-end" select="'>'"/>
<xsl:param name="empty-tag-end" select="'/>'"/>
<xsl:param name="end-tag-start" select="'&lt;/'"/>
<xsl:param name="end-tag-end" select="'>'"/>
<xsl:param name="space" select="' '"/>
<xsl:param name="ns-decl" select="'xmlns'"/>
<xsl:param name="colon" select="':'"/>
<xsl:param name="equals" select="'='"/>
<xsl:param name="attribute-delimiter" select="'&quot;'"/>
<xsl:param name="comment-start" select="'&lt;!--'"/>
<xsl:param name="comment-end" select="'-->'"/>
<xsl:param name="pi-start" select="'&lt;?'"/>
<xsl:param name="pi-end" select="'?>'"/>
<xsl:template name="xml-to-string">
<xsl:param name="node-set" select="."/>
<xsl:apply-templates select="$node-set" mode="xml-to-string">
<xsl:with-param name="depth" select="1"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="cell/*" name="xml-to-string-root-rule">
<xsl:call-template name="xml-to-string"/>
</xsl:template>
<xsl:template match="/" mode="xml-to-string">
<xsl:param name="depth"/>
<xsl:apply-templates mode="xml-to-string">
<xsl:with-param name="depth" select="$depth"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*" mode="xml-to-string">
<xsl:param name="depth"/>
<xsl:variable name="element" select="."/>
<xsl:value-of select="$start-tag-start"/>
<xsl:call-template name="element-name">
<xsl:with-param name="text" select="name()"/>
</xsl:call-template>
<xsl:apply-templates select="@*" mode="xml-to-string"/>
<xsl:for-each select="namespace::*">
<xsl:call-template name="process-namespace-node">
<xsl:with-param name="element" select="$element"/>
<xsl:with-param name="depth" select="$depth"/>
</xsl:call-template>
</xsl:for-each>
<xsl:choose>
<xsl:when test="node() or not($use-empty-syntax)">
<xsl:value-of select="$start-tag-end"/>
<xsl:apply-templates mode="xml-to-string">
<xsl:with-param name="depth" select="$depth + 1"/>
</xsl:apply-templates>
<xsl:value-of select="$end-tag-start"/>
<xsl:call-template name="element-name">
<xsl:with-param name="text" select="name()"/>
</xsl:call-template>
<xsl:value-of select="$end-tag-end"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$empty-tag-end"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="process-namespace-node">
<xsl:param name="element"/>
<xsl:param name="depth"/>
<xsl:variable name="declaredAbove">
<xsl:call-template name="isDeclaredAbove">
<xsl:with-param name="depth" select="$depth - 1"/>
<xsl:with-param name="element" select="$element/.."/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="is-used-on-this-element" select="($element | $element/@*) [namespace-uri() = current()]"/>
<xsl:variable name="is-used-on-a-descendant" select="($element//* | $element//@*)[namespace-uri() = current()]"/>
<xsl:variable name="is-unused" select="not($is-used-on-this-element) and
not($is-used-on-a-descendant)"/>
<xsl:variable name="exclude-ns" select="($is-unused and $exclude-unused-prefixes) or
(. = $namespaces-to-exclude)"/>
<xsl:variable name="force-include" select="$is-used-on-this-element and (. = $namespaces-to-exclude)"/>
<xsl:if test="(name() != 'xml') and ($force-include or (not($exclude-ns) and not(string($declaredAbove))))">
<xsl:value-of select="$space"/>
<xsl:value-of select="$ns-decl"/>
<xsl:if test="name()">
<xsl:value-of select="$colon"/>
<xsl:call-template name="ns-prefix">
<xsl:with-param name="text" select="name()"/>
</xsl:call-template>
</xsl:if>
<xsl:value-of select="$equals"/>
<xsl:value-of select="$attribute-delimiter"/>
<xsl:call-template name="ns-uri">
<xsl:with-param name="text" select="string(.)"/>
</xsl:call-template>
<xsl:value-of select="$attribute-delimiter"/>
</xsl:if>
</xsl:template>
<xsl:template name="isDeclaredAbove">
<xsl:param name="element"/>
<xsl:param name="depth"/>
<xsl:if test="$depth > 0">
<xsl:choose>
<xsl:when test="$element/namespace::*[name(.)=name(current()) and .=current()]">1</xsl:when>
<xsl:when test="$element/namespace::*[name(.)=name(current())]"/>
<xsl:otherwise>
<xsl:call-template name="isDeclaredAbove">
<xsl:with-param name="depth" select="$depth - 1"/>
<xsl:with-param name="element" select="$element/.."/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template match="@*" mode="xml-to-string" name="serialize-attribute">
<xsl:param name="att-value" select="string(.)"/>
<xsl:value-of select="$space"/>
<xsl:call-template name="attribute-name">
<xsl:with-param name="text" select="name()"/>
</xsl:call-template>
<xsl:value-of select="$equals"/>
<xsl:value-of select="$attribute-delimiter"/>
<xsl:call-template name="attribute-value">
<xsl:with-param name="text" select="$att-value"/>
</xsl:call-template>
<xsl:value-of select="$attribute-delimiter"/>
</xsl:template>
<xsl:template match="comment()" mode="xml-to-string">
<xsl:value-of select="$comment-start"/>
<xsl:call-template name="comment-text">
<xsl:with-param name="text" select="string(.)"/>
</xsl:call-template>
<xsl:value-of select="$comment-end"/>
</xsl:template>
<xsl:template match="processing-instruction()" mode="xml-to-string">
<xsl:value-of select="$pi-start"/>
<xsl:call-template name="pi-target">
<xsl:with-param name="text" select="name()"/>
</xsl:call-template>
<xsl:value-of select="$space"/>
<xsl:call-template name="pi-text">
<xsl:with-param name="text" select="string(.)"/>
</xsl:call-template>
<xsl:value-of select="$pi-end"/>
</xsl:template>
<xsl:template match="text()" mode="xml-to-string">
<xsl:call-template name="text-content">
<xsl:with-param name="text" select="string(.)"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="element-name">
<xsl:param name="text"/>
<xsl:value-of select="$text"/>
</xsl:template>
<xsl:template name="attribute-name">
<xsl:param name="text"/>
<xsl:value-of select="$text"/>
</xsl:template>
<xsl:template name="attribute-value">
<xsl:param name="text"/>
<xsl:variable name="escaped-markup">
<xsl:call-template name="escape-markup-characters">
<xsl:with-param name="text" select="$text"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$attribute-delimiter = &quot;'&quot;">
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="$escaped-markup"/>
<xsl:with-param name="replace" select="&quot;'&quot;"/>
<xsl:with-param name="with" select="'&amp;apos;'"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="$attribute-delimiter = '&quot;'">
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="$escaped-markup"/>
<xsl:with-param name="replace" select="'&quot;'"/>
<xsl:with-param name="with" select="'&amp;quot;'"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="$escaped-markup"/>
<xsl:with-param name="replace" select="$attribute-delimiter"/>
<xsl:with-param name="with" select="''"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="ns-prefix">
<xsl:param name="text"/>
<xsl:value-of select="$text"/>
</xsl:template>
<xsl:template name="ns-uri">
<xsl:param name="text"/>
<xsl:call-template name="attribute-value">
<xsl:with-param name="text" select="$text"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="text-content">
<xsl:param name="text"/>
<xsl:call-template name="escape-markup-characters">
<xsl:with-param name="text" select="$text"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="pi-target">
<xsl:param name="text"/>
<xsl:value-of select="$text"/>
</xsl:template>
<xsl:template name="pi-text">
<xsl:param name="text"/>
<xsl:value-of select="$text"/>
</xsl:template>
<xsl:template name="comment-text">
<xsl:param name="text"/>
<xsl:value-of select="$text"/>
</xsl:template>
<xsl:template name="escape-markup-characters">
<xsl:param name="text"/>
<xsl:variable name="ampEscaped">
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="$text"/>
<xsl:with-param name="replace" select="'&amp;'"/>
<xsl:with-param name="with" select="'&amp;amp;'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="ltEscaped">
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="$ampEscaped"/>
<xsl:with-param name="replace" select="'&lt;'"/>
<xsl:with-param name="with" select="'&amp;lt;'"/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="$ltEscaped"/>
<xsl:with-param name="replace" select="']]>'"/>
<xsl:with-param name="with" select="']]&amp;gt;'"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="replace-string">
<xsl:param name="text"/>
<xsl:param name="replace"/>
<xsl:param name="with"/>
<xsl:variable name="stringText" select="string($text)"/>
<xsl:choose>
<xsl:when test="contains($stringText,$replace)">
<xsl:value-of select="substring-before($stringText,$replace)"/>
<xsl:value-of select="$with"/>
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="substring-after($stringText,$replace)"/>
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="with" select="$with"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$stringText"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

View File

@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
The contents of this file are subject to the license and copyright
detailed in the LICENSE and NOTICE files at the root of the source
tree and available online at
http://www.dspace.org/license/
-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="no" omit-xml-declaration="yes" method="text" encoding="UTF-8" media-type="text/x-json"/>
<xsl:strip-space elements="*"/>
<!--contant-->
<xsl:variable name="d">0123456789</xsl:variable>
<!-- convert root element to an anonymous container -->
<xsl:template match="root">
<xsl:text>{</xsl:text>
<xsl:apply-templates select="child::node()"/>
<xsl:text>}</xsl:text>
</xsl:template>
<!-- ignore document text -->
<xsl:template match="text()[preceding-sibling::node() or following-sibling::node()]"/>
<!-- string -->
<xsl:template match="text()">
<xsl:call-template name="escape-string">
<xsl:with-param name="s" select="."/>
</xsl:call-template>
</xsl:template>
<!-- Main template for escaping strings; used by above template and for object-properties
Responsibilities: placed quotes around string, and chain up to next filter, escape-bs-string -->
<xsl:template name="escape-string">
<xsl:param name="s"/>
<xsl:text>"</xsl:text>
<xsl:call-template name="escape-bs-string">
<xsl:with-param name="s" select="$s"/>
</xsl:call-template>
<xsl:text>"</xsl:text>
</xsl:template>
<!-- Escape the backslash (\) before everything else. -->
<xsl:template name="escape-bs-string">
<xsl:param name="s"/>
<xsl:choose>
<xsl:when test="contains($s,'\')">
<xsl:call-template name="escape-quot-string">
<xsl:with-param name="s" select="concat(substring-before($s,'\'),'\\')"/>
</xsl:call-template>
<xsl:call-template name="escape-bs-string">
<xsl:with-param name="s" select="substring-after($s,'\')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="escape-quot-string">
<xsl:with-param name="s" select="$s"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Escape the double quote ("). -->
<xsl:template name="escape-quot-string">
<xsl:param name="s"/>
<xsl:choose>
<xsl:when test="contains($s,'&quot;')">
<xsl:call-template name="encode-string">
<xsl:with-param name="s" select="concat(substring-before($s,'&quot;'),'\&quot;')"/>
</xsl:call-template>
<xsl:call-template name="escape-quot-string">
<xsl:with-param name="s" select="substring-after($s,'&quot;')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="encode-string">
<xsl:with-param name="s" select="$s"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Replace tab, line feed and/or carriage return by its matching escape code. Can't escape backslash
or double quote here, because they don't replace characters (&#x0; becomes \t), but they prefix
characters (\ becomes \\). Besides, backslash should be seperate anyway, because it should be
processed first. This function can't do that. -->
<xsl:template name="encode-string">
<xsl:param name="s"/>
<xsl:choose>
<!-- tab -->
<xsl:when test="contains($s,'&#x9;')">
<xsl:call-template name="encode-string">
<xsl:with-param name="s" select="concat(substring-before($s,'&#x9;'),'\t',substring-after($s,'&#x9;'))"/>
</xsl:call-template>
</xsl:when>
<!-- line feed -->
<xsl:when test="contains($s,'&#xA;')">
<xsl:call-template name="encode-string">
<xsl:with-param name="s" select="concat(substring-before($s,'&#xA;'),'\n',substring-after($s,'&#xA;'))"/>
</xsl:call-template>
</xsl:when>
<!-- carriage return -->
<xsl:when test="contains($s,'&#xD;')">
<xsl:call-template name="encode-string">
<xsl:with-param name="s" select="concat(substring-before($s,'&#xD;'),'\r',substring-after($s,'&#xD;'))"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise><xsl:value-of select="$s"/></xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- number (no support for javascript mantise) -->
<xsl:template match="text()[not(string(number())='NaN')]">
<xsl:value-of select="."/>
</xsl:template>
<!-- boolean, case-insensitive -->
<xsl:template match="text()[translate(.,'TRUE','true')='true']">true</xsl:template>
<xsl:template match="text()[translate(.,'FALSE','false')='false']">false</xsl:template>
<!-- item:null -->
<xsl:template match="*[count(child::node())=0]">
<xsl:call-template name="escape-string">
<xsl:with-param name="s" select="local-name()"/>
</xsl:call-template>
<xsl:text>:null</xsl:text>
<xsl:if test="following-sibling::*">,</xsl:if>
</xsl:template>
<!-- object -->
<xsl:template match="*" name="base">
<!--<xsl:if test="not(preceding-sibling::*)">{</xsl:if>-->
<xsl:call-template name="escape-string">
<xsl:with-param name="s" select="name()"/>
</xsl:call-template>
<xsl:text>:</xsl:text>
<xsl:apply-templates select="child::node()"/>
<xsl:if test="following-sibling::*">,</xsl:if>
<!--<xsl:if test="not(following-sibling::*)">}</xsl:if>-->
</xsl:template>
<xsl:template match="*" mode="array">
<xsl:apply-templates select="child::node()"/>
<xsl:if test="following-sibling::*">,</xsl:if>
</xsl:template>
<!-- array -->
<xsl:template match="*[@array = 'true']">
<xsl:call-template name="escape-string">
<xsl:with-param name="s" select="name()"/>
</xsl:call-template>
<xsl:text>:[</xsl:text>
<xsl:apply-templates select="child::node()" mode="array"/>
<xsl:text>]</xsl:text>
<xsl:if test="following-sibling::*">,</xsl:if>
</xsl:template>
<xsl:template match="*[@array = 'true']" mode="array">
<xsl:text>[</xsl:text>
<xsl:apply-templates select="child::node()" mode="array"/>
<xsl:text>]</xsl:text>
<xsl:if test="following-sibling::*">,</xsl:if>
</xsl:template>
<!--Object array-->
<xsl:template match="*[@object = 'true']" mode="array" priority="2">
<xsl:text>{</xsl:text>
<xsl:apply-templates select="child::node()"/>
<xsl:text>}</xsl:text>
<xsl:if test="following-sibling::*">,</xsl:if>
</xsl:template>
<xsl:template match="*[@object = 'true']">
<xsl:text>{</xsl:text>
<xsl:apply-templates select="child::node()"/>
<xsl:text>}</xsl:text>
<xsl:if test="following-sibling::*">,</xsl:if>
</xsl:template>
<!--Object array-->
<xsl:template match="*[@namedObject = 'true']" mode="array" priority="2">
<xsl:call-template name="escape-string">
<xsl:with-param name="s" select="name()"/>
</xsl:call-template>
<xsl:text>:</xsl:text>
<xsl:text>{</xsl:text>
<xsl:apply-templates select="child::node()"/>
<xsl:text>}</xsl:text>
<xsl:if test="following-sibling::*">,</xsl:if>
</xsl:template>
<xsl:template match="*[@namedObject = 'true']">
<xsl:call-template name="escape-string">
<xsl:with-param name="s" select="name()"/>
</xsl:call-template>
<xsl:text>:</xsl:text>
<xsl:text>{</xsl:text>
<xsl:apply-templates select="child::node()"/>
<xsl:text>}</xsl:text>
<xsl:if test="following-sibling::*">,</xsl:if>
</xsl:template>
</xsl:stylesheet>

View File

@@ -2492,4 +2492,15 @@
<message key="xmlui.mirage2.choice-authority-control.loading">Loading...</message>
<message key="xmlui.mirage2.item-list.thumbnail">Thumbnail</message>
<!-- org.dspace.app.xmlui.Submission.submit.StartSubmissionLookupStep -->
<message key="xmlui.Submission.submit.StartSubmissionLookupStep.submit_lookup">Search</message>
<message key="xmlui.Submission.submit.StartSubmissionLookupStep.title">Publication Search</message>
<message key="xmlui.Submission.submit.StartSubmissionLookupStep.lookup_help">Fill in a publication ID, DOI, Title or Author and then press "Search". A list of all matching publications will be shown to you to select in order to proceed with the submission process.</message>
<message key="xmlui.Submission.submit.StartSubmissionLookupStep.submit_publication_item">Imported publication Record</message>
<message key="xmlui.Submission.submit.progressbar.lookup">Lookup</message>
<message key="xmlui.ChoiceLookupTransformer.lookup">Lookup</message>
</catalogue>

View File

@@ -445,6 +445,9 @@
<map:match pattern="JSON/controlled-vocabulary">
<map:read type="JSONControlledVocabularyReader"/>
</map:match>
<map:match pattern="json/submissionLookup">
<map:mount check-reload="no" src="aspects/json-lookup.xmap" uri-prefix="json/"/>
</map:match>
</map:pipeline>
<!-- new AJAX menu (choices) responses for metadata authority control -->

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,123 @@
/*
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
(function($) {
if (DSpace === undefined) DSpace= {};
DSpace.getTemplate = function(name) {
if (DSpace.dev_mode || DSpace.templates === undefined || DSpace.templates[name] === undefined) {
$.ajax({
url : DSpace.theme_path + 'templates/' + name + '.hbs',
success : function(data) {
if (DSpace.templates === undefined) {
DSpace.templates = {};
}
DSpace.templates[name] = Handlebars.compile(data);
},
dataType :'text',
async : false
});
}
return DSpace.templates[name];
};
var publication_records_template = DSpace.getTemplate('publication_records');
Handlebars.registerHelper('ifCond', function (v1, operator, v2, options) {
switch (operator) {
case '==':
return (v1 == v2) ? options.fn(this) : options.inverse(this);
case '<':
return (v1 < v2) ? options.fn(this) : options.inverse(this);
default:
return options.inverse(this);
}
});
$('#aspect_submission_StepTransformer_field_lookup').click(function(event){
event.preventDefault();
var searchInput = $('#aspect_submission_StepTransformer_field_search').val();
startLookup(searchInput,0);
});
function startLookup(searchInput,start) {
$.ajax({url: window.publication.contextPath+"/json/submissionLookup?search=" + searchInput +"&start="+start,
type: "POST",
dataType: "json",
async: true,
contentType: "application/x-www-form-urlencoded;charset=UTF-8",
error: function(xhr, status, error){
var err = eval("(" + xhr.responseText + ")");
alert(err.Message);
},
success: function(info) {
info.shownStart = start + 1;
info.shownCount = start + info.records.length;
fillModal(info);
setPagination(start,info,searchInput);
$(".publication-records-import-btn").click(function(event) {
event.preventDefault();
var pmid = $(this).attr("id").substring( $(this).attr("id").lastIndexOf("-") + 1);
$("#aspect_submission_StepTransformer_field_publication_id").val(pmid);
$("#aspect_submission_StepTransformer_div_StartSubmissionLookupStep").submit();
});
}
});
}
function fillModal(info){
var lookupModal = $('#lookup-search-results');
lookupModal.removeClass('hidden');
var htmlData;
if(info.records.length>0) {
htmlData = html = publication_records_template(info);
}
else {
htmlData = html = "<p>No records found</p>";
}
lookupModal.find('.modal-body').html(htmlData);
if((typeof $().modal == 'function')){
lookupModal.modal('show');
}
}
function setPagination(start, info, searchInput){
if(start + info.records.length<info.total){
$("#publication-pagination-next").attr("disabled", false);
}
else {
$("#publication-pagination-next").attr("disabled", true);
}
if(start>0){
$("#publication-pagination-previous").attr("disabled", false);
}
else {
$("#publication-pagination-previous").attr("disabled", true);
}
$("#publication-pagination-previous").unbind("click");
$("#publication-pagination-previous").click(function(event) {
$( this ).unbind( event );
event.preventDefault();
startLookup(searchInput, start - 20);
});
$("#publication-pagination-next").unbind("click");
$("#publication-pagination-next").click(function(event) {
event.preventDefault();
startLookup(searchInput, start + 20);
});
$('.close-modal-results').click(function(){
$('#lookup-search-results').addClass('hidden');
});
}
})(jQuery);

View File

@@ -1482,3 +1482,34 @@ ol.ds-ordered-list ol.ds-ordered-list {
ol.ds-ordered-list ol.ds-ordered-list ol.ds-ordered-list {
list-style-type: lower-roman;
}
.publication-records-modal, .publication-records-modal ul {
list-style-type: none;
padding-left: 0px;
}
.publication-records-import-btn {
margin: 5px 0px 15px 0px;
}
.imported {
background-color: #E2E2E2;
}
#aspect_submission_StepTransformer_div_StartSubmissionLookupStep #aspect_submission_StepTransformer_field_search {
width: 81%;
display: inline;
}
#aspect_submission_StepTransformer_div_StartSubmissionLookupStep #aspect_submission_StepTransformer_field_lookup {
width:19%
}
#aspect_submission_StepTransformer_div_StartSubmissionLookupStep .modal .modal-body {
max-height: 500px;
overflow-y: auto;
}
#aspect_submission_StepTransformer_div_StartSubmissionLookupStep #aspect_submission_StepTransformer_item_publication-title{
margin-bottom:5px;
}

View File

@@ -92,4 +92,24 @@
</xsl:call-template>
</xsl:template>
<xsl:template match="dri:div[@n='lookup-modal']" priority="2">
<div id="lookup-search-results" class="modal fade hidden" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close close-modal-results">&#215;</button>
<h4 class="modal-title">Publication Results</h4>
</div>
<div class="modal-body">
<p/>
</div>
<div class="modal-footer">
<button class="ds-button-field btn btn-default pull-left" id="publication-pagination-previous">Previous results</button>
<button class="ds-button-field btn btn-default pull-left" id="publication-pagination-next">Next results</button>
<button type="button" class="btn btn-default close-modal-results">Close</button>
</div>
</div>
</div>
</div>
</xsl:template>
</xsl:stylesheet>

View File

@@ -686,6 +686,7 @@
<xsl:text>1.6.2</xsl:text>
</xsl:variable>
<script type="text/javascript" src="{concat($scheme, 'ajax.googleapis.com/ajax/libs/jquery/', $jqueryVersion ,'/jquery.min.js')}">&#160;</script>
<xsl:variable name="localJQuerySrc">
@@ -700,6 +701,16 @@
select="$localJQuerySrc"/><xsl:text disable-output-escaping="yes">"&gt;&#160;&lt;\/script&gt;')</xsl:text>
</script>
<script type="text/javascript"><xsl:text>
if(typeof window.publication === 'undefined'){
window.publication={};
};
window.publication.contextPath= '</xsl:text><xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'][not(@qualifier)]"/><xsl:text>';</xsl:text>
<xsl:text>window.publication.themePath= '</xsl:text><xsl:value-of select="$theme-path"/><xsl:text>';</xsl:text>
</script>
<script>
<xsl:text>if(!window.DSpace){window.DSpace={};}window.DSpace.context_path='</xsl:text><xsl:value-of select="$context-path"/><xsl:text>';window.DSpace.theme_path='</xsl:text><xsl:value-of select="$theme-path"/><xsl:text>/';</xsl:text>
</script>
<!-- Add theme javascript -->

View File

@@ -0,0 +1,32 @@
<!--
The contents of this file are subject to the license and copyright
detailed in the LICENSE and NOTICE files at the root of the source
tree and available online at
http://www.dspace.org/license/
-->
<p>Showing records {{shownStart}}-{{shownCount}} of {{total}}</p>
<ul class="publication-records-modal">
<li>
<ul>
{{#each records}}
<li {{#if record.[imported]}}class="imported"{{/if}}>
{{#each record.[dc.title]}}
{{#ifCond @index "==" 0}}<span class="bold">{{this}}</span> {{/ifCond}}
{{/each}}
</li>
<li {{#if record.[imported]}}class="imported"{{/if}}>
{{#each record.[dc.contributor.author]}}
{{#ifCond @index "<" 5}} <span>{{this}}{{#unless @last}}, {{/unless}} </span>{{/ifCond}}
{{#ifCond @index "==" 5}}...{{/ifCond}}
{{/each}}
</li>
<li {{#if record.[imported]}}class="imported"{{/if}}>
<button id="publication-records-import-{{record.[dc.identifier.other]}}" class="ds-button-field btn btn-default publication-records-import-btn float-right" name="import" type="submit">Import</button>
</li>
{{/each}}
</ul>
</li>
</ul>

View File

@@ -197,7 +197,16 @@
<xmlui-binding>org.dspace.app.xmlui.aspect.submission.submit.InitialQuestionsStep</xmlui-binding>
<workflow-editable>true</workflow-editable>
</step> -->
<!-- Find publications based on ID/DOI/Title/Author to pre-fill the submission
<step>
<heading>submit.progressbar.lookup</heading>
<processing-class>org.dspace.submit.step.XMLUIStartSubmissionLookupStep</processing-class>
<jspui-binding>org.dspace.app.webui.submit.step.JSPStartSubmissionLookupStep</jspui-binding>
<xmlui-binding>org.dspace.app.xmlui.aspect.submission.submit.StartSubmissionLookupStep</xmlui-binding>
<workflow-editable>true</workflow-editable>
</step>
-->
<!--Step 2 will be to Describe the item.-->
<step>
<heading>submit.progressbar.describe</heading>

View File

@@ -0,0 +1 @@
publication.url = ${publication.url}

View File

@@ -598,4 +598,5 @@
<qualifier>license</qualifier>
<scope_note></scope_note>
</dc-type>
</dspace-dc-types>

View File

@@ -0,0 +1,161 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
default-autowire-candidates="*Service,*DAO,javax.sql.DataSource">
<context:annotation-config/>
<!-- allows us to use spring annotations in beans -->
<util:map id="pubmedMetadataFieldMap" key-type="org.dspace.importer.external.metadatamapping.MetadataFieldConfig"
value-type="org.dspace.importer.external.metadatamapping.contributor.MetadataContributor">
<description>Defines which metadatum is mapped on which metadatum. Note that while the key must be unique it
only matters here for postprocessing of the value. The mapped MetadatumContributor has full control over
what metadatafield is generated.
</description>
<entry key-ref="dc.title" value-ref="titleContrib"/>
<entry key-ref="dc.description.abstract" value-ref="abstractContrib"/>
<entry key-ref="dc.identifier.other" value-ref="pubmedContrib"/>
<entry key-ref="dc.contributor.author" value-ref="authorContrib"/>
<entry key-ref="dc.date.issued" value-ref="dateContrib"/>
<entry key-ref="dc.language.iso" value-ref="pubmedLanguageContrib"/>
<entry key-ref="dc.subject" value-ref="keywordContrib"/>
</util:map>
<bean id="pubmedLanguageContrib" class="org.dspace.importer.external.pubmed.metadatamapping.PubmedLanguageMetadatumContributor">
<property name="field" ref="dc.language.iso"/>
<property name="language" ref="languageContrib"/>
</bean>
<bean id="dateContrib" class="org.dspace.importer.external.pubmed.metadatamapping.PubmedDateMetadatumContributor">
<property name="dateFormatsToAttempt">
<list>
<value>yyyy-MMM-dd</value>
<value>yyyy-MM-dd</value>
</list>
</property>
<property name="year" ref="yearContrib"/>
<property name="month" ref="monthContrib"/>
<property name="day" ref="dayContrib"/>
<property name="field" ref="dc.date.issued"/>
</bean>
<bean id="pubmedContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleXpathMetadatumContributor">
<property name="field" ref="dc.identifier.other"/>
<property name="query" value="descendant::MedlineCitation/PMID"/>
<property name="prefixToNamespaceMapping" ref="prefixToNamespaceMapping"/>
</bean>
<bean id="titleContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleXpathMetadatumContributor">
<property name="field" ref="dc.title"/>
<property name="query" value="descendant::ArticleTitle"/>
<property name="prefixToNamespaceMapping" ref="prefixToNamespaceMapping"/>
</bean>
<bean id="abstractContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleXpathMetadatumContributor">
<property name="field" ref="dc.description.abstract"/>
<property name="query" value="descendant::AbstractText"/>
<property name="prefixToNamespaceMapping" ref="prefixToNamespaceMapping"/>
</bean>
<bean id="authorContrib" class="org.dspace.importer.external.metadatamapping.contributor.CombinedMetadatumContributor">
<property name="separator" value=", "/>
<property name="metadatumContributors" ref="combinedauthorList"/>
<property name="field" ref="dc.contributor.author"/>
</bean>
<util:list id="combinedauthorList" value-type="org.dspace.importer.external.metadatamapping.contributor.MetadataContributor" list-class="java.util.LinkedList">
<ref bean="lastNameContrib"/>
<ref bean="firstNameContrib"/>
</util:list>
<bean id="lastNameContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleXpathMetadatumContributor">
<property name="field" ref="dc.contributor.author"/>
<property name="query" value="descendant::Author/LastName"/>
<property name="prefixToNamespaceMapping" ref="prefixToNamespaceMapping"/>
</bean>
<bean id="firstNameContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleXpathMetadatumContributor">
<property name="field" ref="dc.contributor.author"/>
<property name="query" value="descendant::Author/ForeName"/>
<property name="prefixToNamespaceMapping" ref="prefixToNamespaceMapping"/>
</bean>
<bean id="keywordContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleXpathMetadatumContributor">
<property name="field" ref="dc.subject"/>
<property name="query" value="descendant::Keyword"/>
<property name="prefixToNamespaceMapping" ref="prefixToNamespaceMapping"/>
</bean>
<bean id="yearContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleXpathMetadatumContributor">
<property name="field" ref="dc.date.issued"/>
<property name="query" value="descendant::PubDate/Year"/>
<property name="prefixToNamespaceMapping" ref="prefixToNamespaceMapping"/>
</bean>
<bean id="monthContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleXpathMetadatumContributor">
<property name="field" ref="dc.date.issued"/>
<property name="query" value="descendant::PubDate/Month"/>
<property name="prefixToNamespaceMapping" ref="prefixToNamespaceMapping"/>
</bean>
<bean id="dayContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleXpathMetadatumContributor">
<property name="field" ref="dc.date.issued"/>
<property name="query" value="descendant::PubDate/Day"/>
<property name="prefixToNamespaceMapping" ref="prefixToNamespaceMapping"/>
</bean>
<bean id="languageContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleXpathMetadatumContributor">
<property name="field" ref="dc.language.iso"/>
<property name="query" value="descendant::Language"/>
<property name="prefixToNamespaceMapping" ref="prefixToNamespaceMapping"/>
</bean>
<bean id="dc.title" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.title"/>
</bean>
<bean id="dc.description.abstract" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.description.abstract"/>
</bean>
<bean id="dc.contributor.author" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.contributor.author"/>
</bean>
<bean id="dc.date.issued" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.date.issued"/>
</bean>
<bean id="dc.language.iso" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.language.iso"/>
</bean>
<bean id="dc.subject" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.subject"/>
</bean>
<bean id="dc.identifier.other" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
<constructor-arg value="dc.identifier.other"/>
</bean>
<util:map id="prefixToNamespaceMapping">
</util:map>
<bean class="java.lang.Integer" id="maxRetry">
<constructor-arg value="2"/>
</bean>
<bean class="org.dspace.importer.external.pubmed.metadatamapping.service.GeneratePubmedQueryService" id="pubmedService">
<description>Defines how an org.dspace.content.Item is mapped to a query in scopus. Please note that exactly one of
these must be present. If multiple are present the result is undefined.
</description>
</bean>
</beans>

View File

@@ -20,4 +20,42 @@
@include selection {
color: white;
background: hotpink;
}
.publication-records-modal, .publication-records-modal ul {
list-style-type: none;
padding-left: 0px;
}
.publication-records-import-btn {
margin: 5px 0px 15px 0px;
}
.bold {
font-weight: bold;
}
.imported {
background-color: #E2E2E2;
}
#aspect_submission_StepTransformer_div_StartSubmissionLookupStep {
#aspect_submission_StepTransformer_field_search {
width: 81%;
display: inline;
}
#aspect_submission_StepTransformer_field_lookup {
width:19%
}
.modal .modal-body {
max-height: 500px;
overflow-y: auto;
}
#aspect_submission_StepTransformer_item_publication-title{
margin-bottom:5px;
}
}