Merge branch 'main' into 3190

This commit is contained in:
Mark H. Wood
2021-04-07 10:12:28 -04:00
312 changed files with 11449 additions and 11214 deletions

View File

@@ -54,7 +54,7 @@ services:
dspacesolr:
container_name: dspacesolr
# Uses official Solr image at https://hub.docker.com/_/solr/
image: solr:8.7
image: solr:8.8
networks:
dspacenet:
ports:

View File

@@ -466,6 +466,10 @@
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
@@ -529,8 +533,15 @@
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
<exclusions>
<!-- Different version provided by hibernate-ehcache -->
<exclusion>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
@@ -544,19 +555,9 @@
<version>1.0</version>
</dependency>
<dependency>
<groupId>gr.ekt.bte</groupId>
<artifactId>bte-io</artifactId>
<version>0.9.3.5</version>
<exclusions>
<exclusion>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
<groupId>org.jbibtex</groupId>
<artifactId>jbibtex</artifactId>
<version>1.0.10</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>

View File

@@ -0,0 +1,115 @@
/**
* 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.bulkedit;
import java.sql.SQLException;
import org.apache.commons.cli.ParseException;
import org.apache.commons.lang3.ArrayUtils;
import org.dspace.content.MetadataField;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.MetadataFieldService;
import org.dspace.content.service.MetadataValueService;
import org.dspace.core.Context;
import org.dspace.scripts.DSpaceRunnable;
import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.utils.DSpace;
/**
* {@link DSpaceRunnable} implementation to delete all the values of the given
* metadata field.
*
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
*
*/
public class MetadataDeletion extends DSpaceRunnable<MetadataDeletionScriptConfiguration<MetadataDeletion>> {
private MetadataValueService metadataValueService;
private MetadataFieldService metadataFieldService;
private ConfigurationService configurationService;
private String metadataField;
private boolean list;
@Override
public void internalRun() throws Exception {
if (list) {
listErasableMetadata();
return;
}
Context context = new Context();
try {
context.turnOffAuthorisationSystem();
performMetadataValuesDeletion(context);
} finally {
context.restoreAuthSystemState();
context.complete();
}
}
private void listErasableMetadata() {
String[] erasableMetadata = getErasableMetadata();
if (ArrayUtils.isEmpty(erasableMetadata)) {
handler.logInfo("No fields has been configured to be cleared via bulk deletion");
} else {
handler.logInfo("The fields that can be bulk deleted are: " + String.join(", ", erasableMetadata));
}
}
private void performMetadataValuesDeletion(Context context) throws SQLException {
MetadataField field = metadataFieldService.findByString(context, metadataField, '.');
if (field == null) {
throw new IllegalArgumentException("No metadata field found with name " + metadataField);
}
if (!ArrayUtils.contains(getErasableMetadata(), metadataField)) {
throw new IllegalArgumentException("The given metadata field cannot be bulk deleted");
}
handler.logInfo(String.format("Deleting the field '%s' from all objects", metadataField));
metadataValueService.deleteByMetadataField(context, field);
}
private String[] getErasableMetadata() {
return configurationService.getArrayProperty("bulkedit.allow-bulk-deletion");
}
@Override
@SuppressWarnings("unchecked")
public MetadataDeletionScriptConfiguration<MetadataDeletion> getScriptConfiguration() {
return new DSpace().getServiceManager()
.getServiceByName("metadata-deletion", MetadataDeletionScriptConfiguration.class);
}
@Override
public void setup() throws ParseException {
metadataValueService = ContentServiceFactory.getInstance().getMetadataValueService();
metadataFieldService = ContentServiceFactory.getInstance().getMetadataFieldService();
configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
metadataField = commandLine.getOptionValue('m');
list = commandLine.hasOption('l');
if (!list && metadataField == null) {
throw new ParseException("One of the following parameters is required: -m or -l");
}
}
}

View File

@@ -0,0 +1,18 @@
/**
* 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.bulkedit;
/**
* The {@link MetadataDeletion} for CLI.
*
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
*
*/
public class MetadataDeletionCli extends MetadataDeletion {
}

View File

@@ -0,0 +1,18 @@
/**
* 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.bulkedit;
/**
* Script configuration for {@link MetadataDeletionCli}.
*
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
*
*/
public class MetadataDeletionCliScriptConfiguration extends MetadataDeletionScriptConfiguration<MetadataDeletionCli> {
}

View File

@@ -0,0 +1,68 @@
/**
* 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.bulkedit;
import java.sql.SQLException;
import org.apache.commons.cli.Options;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.core.Context;
import org.dspace.scripts.configuration.ScriptConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
/**
* The {@link ScriptConfiguration} for the {@link MetadataDeletion} script.
*/
public class MetadataDeletionScriptConfiguration<T extends MetadataDeletion> extends ScriptConfiguration<T> {
@Autowired
private AuthorizeService authorizeService;
private Class<T> dspaceRunnableClass;
@Override
public boolean isAllowedToExecute(Context context) {
try {
return authorizeService.isAdmin(context);
} catch (SQLException e) {
throw new RuntimeException("SQLException occurred when checking if the current user is an admin", e);
}
}
@Override
public Options getOptions() {
if (options == null) {
Options options = new Options();
options.addOption("m", "metadata", true, "metadata field name");
options.getOption("m").setType(String.class);
options.addOption("l", "list", false, "lists the metadata fields that can be deleted");
options.getOption("l").setType(boolean.class);
super.options = options;
}
return options;
}
@Override
public Class<T> getDspaceRunnableClass() {
return dspaceRunnableClass;
}
/**
* Generic setter for the dspaceRunnableClass
* @param dspaceRunnableClass The dspaceRunnableClass to be set on this MetadataDeletionScriptConfiguration
*/
@Override
public void setDspaceRunnableClass(Class<T> dspaceRunnableClass) {
this.dspaceRunnableClass = dspaceRunnableClass;
}
}

View File

@@ -890,10 +890,10 @@ public class MetadataImport extends DSpaceRunnable<MetadataImportScriptConfigura
Entity relationEntity = getEntity(c, value);
// Get relationship type of entity and item
String relationEntityRelationshipType = itemService.getMetadata(relationEntity.getItem(),
"relationship", "type",
null, Item.ANY).get(0).getValue();
String itemRelationshipType = itemService.getMetadata(item, "relationship", "type",
null, Item.ANY).get(0).getValue();
"dspace", "entity",
"type", Item.ANY).get(0).getValue();
String itemRelationshipType = itemService.getMetadata(item, "dspace", "entity",
"type", Item.ANY).get(0).getValue();
// Get the correct RelationshipType based on typeName
List<RelationshipType> relType = relationshipTypeService.findByLeftwardOrRightwardTypeName(c, typeName);
@@ -1487,7 +1487,7 @@ public class MetadataImport extends DSpaceRunnable<MetadataImportScriptConfigura
}
}
//Populate entityTypeMap
if (key.equalsIgnoreCase("relationship.type") && line.get(key).size() > 0) {
if (key.equalsIgnoreCase("dspace.entity.type") && line.get(key).size() > 0) {
if (uuid == null) {
entityTypeMap.put(new UUID(0, rowCount), line.get(key).get(0));
} else {
@@ -1651,8 +1651,8 @@ public class MetadataImport extends DSpaceRunnable<MetadataImportScriptConfigura
if (itemService.find(c, UUID.fromString(targetUUID)) != null) {
targetItem = itemService.find(c, UUID.fromString(targetUUID));
List<MetadataValue> relTypes = itemService.
getMetadata(targetItem, "relationship", "type",
null, Item.ANY);
getMetadata(targetItem, "dspace", "entity",
"type", Item.ANY);
String relTypeValue = null;
if (relTypes.size() > 0) {
relTypeValue = relTypes.get(0).getValue();
@@ -1696,9 +1696,9 @@ public class MetadataImport extends DSpaceRunnable<MetadataImportScriptConfigura
if (itemService.find(c, UUID.fromString(targetUUID)) != null) {
DSpaceCSVLine dSpaceCSVLine = this.csv.getCSVLines()
.get(Integer.valueOf(originRow) - 1);
List<String> relTypes = dSpaceCSVLine.get("relationship.type");
List<String> relTypes = dSpaceCSVLine.get("dspace.entity.type");
if (relTypes == null || relTypes.isEmpty()) {
dSpaceCSVLine.get("relationship.type[]");
dSpaceCSVLine.get("dspace.entity.type[]");
}
if (relTypes != null && relTypes.size() > 0) {
@@ -1710,8 +1710,8 @@ public class MetadataImport extends DSpaceRunnable<MetadataImportScriptConfigura
originItem = itemService.find(c, UUID.fromString(originRefererUUID));
if (originItem != null) {
List<MetadataValue> mdv = itemService.getMetadata(originItem,
"relationship",
"type", null,
"dspace",
"entity", "type",
Item.ANY);
if (!mdv.isEmpty()) {
String relTypeValue = mdv.get(0).getValue();

View File

@@ -1,106 +0,0 @@
/**
* 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.itemimport;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import gr.ekt.bte.core.DataLoader;
import gr.ekt.bte.core.TransformationEngine;
import gr.ekt.bte.dataloader.FileDataLoader;
/**
* This class acts as a Service in the procedure to batch import using the Biblio-Transformation-Engine
*/
public class BTEBatchImportService {
TransformationEngine transformationEngine;
Map<String, DataLoader> dataLoaders = new HashMap<String, DataLoader>();
Map<String, String> outputMap = new HashMap<String, String>();
/**
* Default constructor
*/
public BTEBatchImportService() {
super();
}
/**
* Setter method for dataLoaders parameter
*
* @param dataLoaders map of data loaders
*/
public void setDataLoaders(Map<String, DataLoader> dataLoaders) {
this.dataLoaders = dataLoaders;
}
/**
* Get data loaders
*
* @return the map of DataLoaders
*/
public Map<String, DataLoader> getDataLoaders() {
return dataLoaders;
}
/**
* Get output map
*
* @return the outputMapping
*/
public Map<String, String> getOutputMap() {
return outputMap;
}
/**
* Setter method for the outputMapping
*
* @param outputMap the output mapping
*/
public void setOutputMap(Map<String, String> outputMap) {
this.outputMap = outputMap;
}
/**
* Get transformation engine
*
* @return transformation engine
*/
public TransformationEngine getTransformationEngine() {
return transformationEngine;
}
/**
* set transformation engine
*
* @param transformationEngine transformation engine
*/
public void setTransformationEngine(TransformationEngine transformationEngine) {
this.transformationEngine = transformationEngine;
}
/**
* Getter of file data loaders
*
* @return List of file data loaders
*/
public List<String> getFileDataLoaders() {
List<String> result = new ArrayList<String>();
for (String key : dataLoaders.keySet()) {
DataLoader dl = dataLoaders.get(key);
if (dl instanceof FileDataLoader) {
result.add(key);
}
}
return result;
}
}

View File

@@ -73,7 +73,6 @@ public class ItemImportCLITool {
Options options = new Options();
options.addOption("a", "add", false, "add items to DSpace");
options.addOption("b", "add-bte", false, "add items to DSpace via Biblio-Transformation-Engine (BTE)");
options.addOption("r", "replace", false, "replace items in mapfile");
options.addOption("d", "delete", false,
"delete items listed in mapfile");
@@ -388,8 +387,6 @@ public class ItemImportCLITool {
myloader.replaceItems(c, mycollections, sourcedir, mapfile, template);
} else if ("delete".equals(command)) {
myloader.deleteItems(c, mapfile);
} else if ("add-bte".equals(command)) {
myloader.addBTEItems(c, mycollections, sourcedir, mapfile, template, bteInputType, null);
}
// complete all transactions

View File

@@ -45,13 +45,6 @@ import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import gr.ekt.bte.core.DataLoader;
import gr.ekt.bte.core.TransformationEngine;
import gr.ekt.bte.core.TransformationResult;
import gr.ekt.bte.core.TransformationSpec;
import gr.ekt.bte.dataloader.FileDataLoader;
import gr.ekt.bteio.generators.DSpaceOutputGenerator;
import gr.ekt.bteio.loaders.OAIPMHDataLoader;
import org.apache.commons.collections4.ComparatorUtils;
import org.apache.commons.io.FileDeleteStrategy;
import org.apache.commons.io.FileUtils;
@@ -96,7 +89,6 @@ import org.dspace.eperson.service.EPersonService;
import org.dspace.eperson.service.GroupService;
import org.dspace.handle.service.HandleService;
import org.dspace.services.ConfigurationService;
import org.dspace.utils.DSpace;
import org.dspace.workflow.WorkflowItem;
import org.dspace.workflow.WorkflowService;
import org.springframework.beans.factory.InitializingBean;
@@ -200,100 +192,6 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
}
/**
* In this method, the BTE is instantiated. THe workflow generates the DSpace files
* necessary for the upload, and the default item import method is called
*
* @param c The contect
* @param mycollections The collections the items are inserted to
* @param sourceDir The filepath to the file to read data from
* @param mapFile The filepath to mapfile to be generated
* @param template whether to use collection template item as starting point
* @param inputType The type of the input data (bibtex, csv, etc.)
* @param workingDir The path to create temporary files (for command line or UI based)
* @throws Exception if error occurs
*/
@Override
public void addBTEItems(Context c, List<Collection> mycollections,
String sourceDir, String mapFile, boolean template, String inputType, String workingDir)
throws Exception {
//Determine the folder where BTE will output the results
String outputFolder = null;
if (workingDir == null) { //This indicates a command line import, create a random path
File importDir = new File(configurationService.getProperty("org.dspace.app.batchitemimport.work.dir"));
if (!importDir.exists()) {
boolean success = importDir.mkdir();
if (!success) {
log.info("Cannot create batch import directory!");
throw new Exception("Cannot create batch import directory!");
}
}
//Get a random folder in case two admins batch import data at the same time
outputFolder = importDir + File.separator + generateRandomFilename(true);
} else { //This indicates a UI import, working dir is preconfigured
outputFolder = workingDir;
}
BTEBatchImportService dls = new DSpace().getSingletonService(BTEBatchImportService.class);
DataLoader dataLoader = dls.getDataLoaders().get(inputType);
Map<String, String> outputMap = dls.getOutputMap();
TransformationEngine te = dls.getTransformationEngine();
if (dataLoader == null) {
System.out.println(
"ERROR: The key used in -i parameter must match a valid DataLoader in the BTE Spring XML " +
"configuration file!");
return;
}
if (outputMap == null) {
System.out.println(
"ERROR: The key used in -i parameter must match a valid outputMapping in the BTE Spring XML " +
"configuration file!");
return;
}
if (dataLoader instanceof FileDataLoader) {
FileDataLoader fdl = (FileDataLoader) dataLoader;
if (!StringUtils.isBlank(sourceDir)) {
System.out.println(
"INFO: Dataloader will load data from the file specified in the command prompt (and not from the " +
"Spring XML configuration file)");
fdl.setFilename(sourceDir);
}
} else if (dataLoader instanceof OAIPMHDataLoader) {
OAIPMHDataLoader fdl = (OAIPMHDataLoader) dataLoader;
System.out.println(sourceDir);
if (!StringUtils.isBlank(sourceDir)) {
System.out.println(
"INFO: Dataloader will load data from the address specified in the command prompt (and not from " +
"the Spring XML configuration file)");
fdl.setServerAddress(sourceDir);
}
}
if (dataLoader != null) {
System.out.println("INFO: Dataloader " + dataLoader.toString() + " will be used for the import!");
te.setDataLoader(dataLoader);
DSpaceOutputGenerator outputGenerator = new DSpaceOutputGenerator(outputMap);
outputGenerator.setOutputDirectory(outputFolder);
te.setOutputGenerator(outputGenerator);
try {
TransformationResult res = te.transform(new TransformationSpec());
List<String> output = res.getOutput();
outputGenerator.writeOutput(output);
} catch (Exception e) {
System.err.println("Exception");
e.printStackTrace();
throw e;
}
addItems(c, mycollections, outputFolder, mapFile, template);
}
}
@Override
public void addItemsAtomic(Context c, List<Collection> mycollections, String sourceDir, String mapFile,
boolean template) throws Exception {
@@ -1739,9 +1637,6 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
if (theInputType.equals("saf") || theInputType
.equals("safupload")) { //In case of Simple Archive Format import
addItems(context, finalCollections, dataDir, mapFilePath, template);
} else { // For all other imports (via BTE)
addBTEItems(context, finalCollections, theFilePath, mapFilePath, useTemplateItem, theInputType,
dataDir);
}
// email message letting user know the file is ready for

View File

@@ -183,21 +183,6 @@ public interface ItemImportService {
*/
public void deleteItems(Context c, String mapfile) throws Exception;
/**
* Add items
*
* @param c DSpace Context
* @param mycollections List of Collections
* @param sourcedir source directory
* @param mapfile map file
* @param template whether to use template item
* @param bteInputType The input type of the data (bibtex, csv, etc.), in case of local file
* @param workingDir working directory
* @throws Exception if error
*/
public void addBTEItems(Context c, List<Collection> mycollections, String sourcedir, String mapfile,
boolean template, String bteInputType, String workingDir) throws Exception;
/**
* Get temporary work directory
*

View File

@@ -12,6 +12,7 @@ import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import javax.annotation.PostConstruct;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
@@ -23,12 +24,12 @@ import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.app.sherpa.v2.SHERPAPublisherResponse;
import org.dspace.app.sherpa.v2.SHERPAResponse;
import org.dspace.app.sherpa.v2.SHERPAUtils;
import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.springframework.beans.factory.annotation.Autowired;
/**
@@ -47,11 +48,11 @@ public class SHERPAService {
private int maxNumberOfTries;
private long sleepBetweenTimeouts;
private int timeout = 5000;
private String endpoint = "https://v2.sherpa.ac.uk/cgi/retrieve";
private String endpoint = null;
private String apiKey = null;
/** log4j category */
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(SHERPAService.class);
private static final Logger log = LogManager.getLogger(SHERPAService.class);
@Autowired
ConfigurationService configurationService;
@@ -60,14 +61,6 @@ public class SHERPAService {
* Create a new HTTP builder with sensible defaults in constructor
*/
public SHERPAService() {
// Set configuration service
configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
// Get endoint and API key from configuration
endpoint = configurationService.getProperty("sherpa.romeo.url",
"https://v2.sherpa.ac.uk/cgi/retrieve");
apiKey = configurationService.getProperty("sherpa.romeo.apikey");
HttpClientBuilder builder = HttpClientBuilder.create();
// httpclient 4.3+ doesn't appear to have any sensible defaults any more. Setting conservative defaults as
// not to hammer the SHERPA service too much.
@@ -77,6 +70,17 @@ public class SHERPAService {
.build();
}
/**
* Complete initialization of the Bean.
*/
@PostConstruct
private void init() {
// Get endoint and API key from configuration
endpoint = configurationService.getProperty("sherpa.romeo.url",
"https://v2.sherpa.ac.uk/cgi/retrieve");
apiKey = configurationService.getProperty("sherpa.romeo.apikey");
}
/**
* Search the SHERPA v2 API for a journal policy data using the supplied ISSN.
* If the API key is missing, or the HTTP response is non-OK or does not complete

View File

@@ -30,9 +30,6 @@ public class SHERPAPermittedVersion {
// Version (submitted, accepted, published)
private String articleVersion;
// Version label
private String articleVersionLabel;
// Option number
private int option;
@@ -108,11 +105,4 @@ public class SHERPAPermittedVersion {
this.option = option;
}
public String getArticleVersionLabel() {
return articleVersionLabel;
}
public void setArticleVersionLabel(String articleVersionLabel) {
this.articleVersionLabel = articleVersionLabel;
}
}

View File

@@ -91,7 +91,7 @@ public class SHERPAPublisherResponse {
for (int itemIndex = 0; itemIndex < items.length(); itemIndex++) {
SHERPAPublisher sherpaPublisher = new SHERPAPublisher();
JSONObject item = items.getJSONObject(0);
JSONObject item = items.getJSONObject(itemIndex);
// Parse system metadata (per-item / result information)
if (item.has("system_metadata")) {

View File

@@ -18,7 +18,6 @@ import java.util.TreeMap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.core.I18nUtil;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -99,7 +98,7 @@ public class SHERPAResponse {
SHERPAPublisher sherpaPublisher = new SHERPAPublisher();
SHERPAJournal sherpaJournal = new SHERPAJournal();
JSONObject item = items.getJSONObject(0);
JSONObject item = items.getJSONObject(itemIndex);
// Parse system metadata (per-item / result information)
if (item.has("system_metadata")) {
@@ -417,17 +416,6 @@ public class SHERPAResponse {
log.debug("Added allowed version: " + articleVersion + " to list");
}
// Add labels for this particular article version
if ("submitted".equals(articleVersion)) {
versionLabel = I18nUtil.getMessage("jsp.sherpa.submitted-version-label");
} else if ("accepted".equals(articleVersion)) {
versionLabel = I18nUtil.getMessage("jsp.sherpa.accepted-version-label");
} else if ("published".equals(articleVersion)) {
versionLabel = I18nUtil.getMessage("jsp.sherpa.published-version-label");
}
// Set the article version label based on the i18n text set above
permittedVersion.setArticleVersionLabel(versionLabel);
// These are now child arrays, in old API they were explicit like
// "preprint restrictions", etc., and just contained text rather than data
if (permitted.has("conditions")) {

View File

@@ -141,6 +141,15 @@ public class LDAPAuthentication
// Prevents anonymous users from being added to this group, and the second check
// ensures they are LDAP users
try {
// without a logged in user, this method should return an empty list
if (context.getCurrentUser() == null) {
return Collections.EMPTY_LIST;
}
// if the logged in user does not have a netid, it's not an LDAP user
// and this method should return an empty list
if (context.getCurrentUser().getNetid() == null) {
return Collections.EMPTY_LIST;
}
if (!context.getCurrentUser().getNetid().equals("")) {
String groupName = configurationService.getProperty("authentication-ldap.login.specialgroup");
if ((groupName != null) && (!groupName.trim().equals(""))) {
@@ -681,7 +690,7 @@ public class LDAPAuthentication
if (StringUtils.isNotBlank(dn)) {
System.out.println("dn:" + dn);
int i = 1;
String groupMap = configurationService.getProperty("authentication-ldap", "login.groupmap." + i);
String groupMap = configurationService.getProperty("authentication-ldap.login.groupmap." + i);
boolean cmp;
@@ -721,7 +730,7 @@ public class LDAPAuthentication
}
}
groupMap = configurationService.getProperty("authentication-ldap", "login.groupmap." + ++i);
groupMap = configurationService.getProperty("authentication-ldap.login.groupmap." + ++i);
}
}
}

View File

@@ -0,0 +1,365 @@
/**
* 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.authority.orcid;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrInputDocument;
import org.dspace.authority.AuthorityValue;
import org.dspace.authority.AuthorityValueServiceImpl;
import org.dspace.authority.PersonAuthorityValue;
import org.dspace.utils.DSpace;
import org.orcid.jaxb.model.v3.release.record.Keyword;
import org.orcid.jaxb.model.v3.release.record.Name;
import org.orcid.jaxb.model.v3.release.record.Person;
import org.orcid.jaxb.model.v3.release.record.PersonExternalIdentifier;
import org.orcid.jaxb.model.v3.release.record.PersonExternalIdentifiers;
import org.orcid.jaxb.model.v3.release.record.ResearcherUrl;
/**
* An {@link AuthorityValue} encapsulating information retrieved from ORCID
*
* @author Jonas Van Goolen (jonas at atmire dot com)
*/
public class Orcidv3AuthorityValue extends PersonAuthorityValue {
/*
* The ORCID identifier
*/
private String orcid_id;
/*
* Map containing key-value pairs filled in by "setValues(Person person)".
* This represents all dynamic information of the object.
*/
private Map<String, List<String>> otherMetadata = new HashMap<String, List<String>>();
/**
* The syntax that the ORCID id needs to conform to
*/
public static final String ORCID_ID_SYNTAX = "\\d{4}-\\d{4}-\\d{4}-(\\d{3}X|\\d{4})";
/**
* Creates an instance of Orcidv3AuthorityValue with only uninitialized fields.
* This is meant to be filled in with values from an existing record.
* To create a brand new Orcidv3AuthorityValue, use create()
*/
public Orcidv3AuthorityValue() {
}
public Orcidv3AuthorityValue(SolrDocument document) {
super(document);
}
public String getOrcid_id() {
return orcid_id;
}
public void setOrcid_id(String orcid_id) {
this.orcid_id = orcid_id;
}
/**
* Create an empty authority.
* @return OrcidAuthorityValue
*/
public static Orcidv3AuthorityValue create() {
Orcidv3AuthorityValue orcidAuthorityValue = new Orcidv3AuthorityValue();
orcidAuthorityValue.setId(UUID.randomUUID().toString());
orcidAuthorityValue.updateLastModifiedDate();
orcidAuthorityValue.setCreationDate(new Date());
return orcidAuthorityValue;
}
/**
* Create an authority based on a given orcid bio
* @return OrcidAuthorityValue
*/
public static Orcidv3AuthorityValue create(Person person) {
if (person == null) {
return null;
}
Orcidv3AuthorityValue authority = Orcidv3AuthorityValue.create();
authority.setValues(person);
return authority;
}
/**
* Initialize this instance based on a Person object
* @param person Person
*/
protected void setValues(Person person) {
Name name = person.getName();
if (!StringUtils.equals(name.getPath(), this.getOrcid_id())) {
this.setOrcid_id(name.getPath());
}
if (!StringUtils.equals(name.getFamilyName().getContent(), this.getLastName())) {
this.setLastName(name.getFamilyName().getContent());
}
if (!StringUtils.equals(name.getGivenNames().getContent(), this.getFirstName())) {
this.setFirstName(name.getGivenNames().getContent());
}
if (name.getCreditName() != null && StringUtils.isNotBlank(name.getCreditName().getContent())) {
if (!this.getNameVariants().contains(name.getCreditName().getContent())) {
this.addNameVariant(name.getCreditName().getContent());
}
}
if (person.getKeywords() != null) {
for (Keyword keyword : person.getKeywords().getKeywords()) {
if (this.isNewMetadata("keyword", keyword.getContent())) {
this.addOtherMetadata("keyword", keyword.getContent());
}
}
}
PersonExternalIdentifiers externalIdentifiers = person.getExternalIdentifiers();
if (externalIdentifiers != null) {
for (PersonExternalIdentifier externalIdentifier : externalIdentifiers.getExternalIdentifiers()) {
if (this.isNewMetadata("external_identifier", externalIdentifier.getValue())) {
this.addOtherMetadata("external_identifier", externalIdentifier.getValue());
}
}
}
if (person.getResearcherUrls() != null) {
for (ResearcherUrl researcherUrl : person.getResearcherUrls().getResearcherUrls()) {
if (this.isNewMetadata("researcher_url", researcherUrl.getUrl().getValue())) {
this.addOtherMetadata("researcher_url", researcherUrl.getUrl().getValue());
}
}
}
if (person.getBiography() != null) {
if (this.isNewMetadata("biography", person.getBiography().getContent())) {
this.addOtherMetadata("biography", person.getBiography().getContent());
}
}
this.setValue(this.getName());
}
/**
* Makes an instance of the AuthorityValue with the given information.
* @param info string info
* @return AuthorityValue
*/
@Override
public AuthorityValue newInstance(String info) {
AuthorityValue authorityValue = null;
if (StringUtils.isNotBlank(info)) {
Orcidv3SolrAuthorityImpl orcid = new DSpace().getServiceManager().getServiceByName("AuthoritySource",
Orcidv3SolrAuthorityImpl.class);
authorityValue = orcid.queryAuthorityID(info);
} else {
authorityValue = this.create();
}
return authorityValue;
}
@Override
public void setValue(String value) {
super.setValue(value);
}
/**
* Check to see if the provided label / data pair is already present in the "otherMetadata" or not
* */
public boolean isNewMetadata(String label, String data) {
List<String> strings = getOtherMetadata().get(label);
boolean update;
if (strings == null) {
update = StringUtils.isNotBlank(data);
} else {
update = !strings.contains(data);
}
return update;
}
/**
* Add additional metadata to the otherMetadata map*/
public void addOtherMetadata(String label, String data) {
List<String> strings = otherMetadata.get(label);
if (strings == null) {
strings = new ArrayList<>();
}
strings.add(data);
otherMetadata.put(label, strings);
}
public Map<String, List<String>> getOtherMetadata() {
return otherMetadata;
}
/**
* Generate a solr record from this instance
* @return SolrInputDocument
*/
@Override
public SolrInputDocument getSolrInputDocument() {
SolrInputDocument doc = super.getSolrInputDocument();
if (StringUtils.isNotBlank(getOrcid_id())) {
doc.addField("orcid_id", getOrcid_id());
}
for (String t : otherMetadata.keySet()) {
List<String> data = otherMetadata.get(t);
for (String data_entry : data) {
doc.addField("label_" + t, data_entry);
}
}
return doc;
}
/**
* Information that can be used the choice ui
* @return map
*/
@Override
public Map<String, String> choiceSelectMap() {
Map<String, String> map = super.choiceSelectMap();
String orcid_id = getOrcid_id();
if (StringUtils.isNotBlank(orcid_id)) {
map.put("orcid", orcid_id);
}
return map;
}
@Override
public String getAuthorityType() {
return "orcid";
}
/**
* Provides a string that will allow this AuthorityType to be recognized and
* provides information to create a new instance to be created using public
* Orcidv3AuthorityValue newInstance(String info).
*
* @return see
* {@link org.dspace.authority.service.AuthorityValueService#GENERATE
* AuthorityValueService.GENERATE}
*/
@Override
public String generateString() {
String generateString = AuthorityValueServiceImpl.GENERATE + getAuthorityType()
+ AuthorityValueServiceImpl.SPLIT;
if (StringUtils.isNotBlank(getOrcid_id())) {
generateString += getOrcid_id();
}
return generateString;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Orcidv3AuthorityValue that = (Orcidv3AuthorityValue) o;
if (orcid_id != null ? !orcid_id.equals(that.orcid_id) : that.orcid_id != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
return orcid_id != null ? orcid_id.hashCode() : 0;
}
/**
* The regular equals() only checks if both AuthorityValues describe the same authority.
* This method checks if the AuthorityValues have different information
* E.g. it is used to decide when lastModified should be updated.
* @param o object
* @return true or false
*/
@Override
public boolean hasTheSameInformationAs(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.hasTheSameInformationAs(o)) {
return false;
}
Orcidv3AuthorityValue that = (Orcidv3AuthorityValue) o;
if (orcid_id != null ? !orcid_id.equals(that.orcid_id) : that.orcid_id != null) {
return false;
}
for (String key : otherMetadata.keySet()) {
if (otherMetadata.get(key) != null) {
List<String> metadata = otherMetadata.get(key);
List<String> otherMetadata = that.otherMetadata.get(key);
if (otherMetadata == null) {
return false;
} else {
HashSet<String> metadataSet = new HashSet<String>(metadata);
HashSet<String> otherMetadataSet = new HashSet<String>(otherMetadata);
if (!metadataSet.equals(otherMetadataSet)) {
return false;
}
}
} else {
if (that.otherMetadata.get(key) != null) {
return false;
}
}
}
return true;
}
@Override
public void setValues(SolrDocument document) {
super.setValues(document);
this.orcid_id = ObjectUtils.toString(document.getFieldValue("orcid_id"));
for (String key : document.getFieldNames()) {
if (key.startsWith("label_")) {
String keyInternalMap = key.substring(key.indexOf("_") + 1);
Collection<Object> valuesSolr = document.getFieldValues(key);
for (Object valueInternal : valuesSolr) {
addOtherMetadata(keyInternalMap, (String) valueInternal);
}
}
}
}
}

View File

@@ -0,0 +1,217 @@
/**
* 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.authority.orcid;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.log4j.Logger;
import org.dspace.authority.AuthorityValue;
import org.dspace.authority.SolrAuthorityInterface;
import org.dspace.external.OrcidRestConnector;
import org.dspace.external.provider.orcid.xml.XMLtoBio;
import org.json.JSONObject;
import org.orcid.jaxb.model.v3.release.common.OrcidIdentifier;
import org.orcid.jaxb.model.v3.release.record.Person;
import org.orcid.jaxb.model.v3.release.search.Result;
/**
* This class contains all methods for retrieving "Person" objects calling the ORCID (version 3) endpoints.
* Additionally, this can also create AuthorityValues based on these returned Person objects
*
* @author Jonas Van Goolen (jonas at atmire dot com)
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
public class Orcidv3SolrAuthorityImpl implements SolrAuthorityInterface {
private static Logger log = Logger.getLogger(Orcidv3SolrAuthorityImpl.class);
private OrcidRestConnector orcidRestConnector;
private String OAUTHUrl;
private String clientId;
private String clientSecret;
private String accessToken;
public void setOAUTHUrl(String oAUTHUrl) {
OAUTHUrl = oAUTHUrl;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
/**
* Initialize the accessToken that is required for all subsequent calls to ORCID
*/
public void init() {
if (StringUtils.isBlank(accessToken)
&& StringUtils.isNotBlank(clientSecret)
&& StringUtils.isNotBlank(clientId)
&& StringUtils.isNotBlank(OAUTHUrl)) {
String authenticationParameters = "?client_id=" + clientId +
"&client_secret=" + clientSecret +
"&scope=/read-public&grant_type=client_credentials";
try {
HttpPost httpPost = new HttpPost(OAUTHUrl + authenticationParameters);
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
HttpClient httpClient = HttpClientBuilder.create().build();
HttpResponse getResponse = httpClient.execute(httpPost);
JSONObject responseObject = null;
try (InputStream is = getResponse.getEntity().getContent();
BufferedReader streamReader = new BufferedReader(new InputStreamReader(is, "UTF-8"))) {
String inputStr;
while ((inputStr = streamReader.readLine()) != null && responseObject == null) {
if (inputStr.startsWith("{") && inputStr.endsWith("}") && inputStr.contains("access_token")) {
try {
responseObject = new JSONObject(inputStr);
} catch (Exception e) {
//Not as valid as I'd hoped, move along
responseObject = null;
}
}
}
}
if (responseObject != null && responseObject.has("access_token")) {
accessToken = (String) responseObject.get("access_token");
}
} catch (Exception e) {
throw new RuntimeException("Error during initialization of the Orcid connector", e);
}
}
}
public void setOrcidRestConnector(OrcidRestConnector orcidRestConnector) {
this.orcidRestConnector = orcidRestConnector;
}
/**
* Makes an instance of the AuthorityValue with the given information.
* @param text search string
* @return List<AuthorityValue>
*/
@Override
public List<AuthorityValue> queryAuthorities(String text, int max) {
init();
List<Person> bios = queryBio(text, max);
List<AuthorityValue> result = new ArrayList<>();
for (Person person : bios) {
AuthorityValue orcidAuthorityValue = Orcidv3AuthorityValue.create(person);
if (orcidAuthorityValue != null) {
result.add(orcidAuthorityValue);
}
}
return result;
}
/**
* Create an AuthorityValue from a Person retrieved using the given orcid identifier.
* @param id orcid identifier
* @return AuthorityValue
*/
@Override
public AuthorityValue queryAuthorityID(String id) {
init();
Person person = getBio(id);
AuthorityValue valueFromPerson = Orcidv3AuthorityValue.create(person);
return valueFromPerson;
}
/**
* Retrieve a Person object based on a given orcid identifier
* @param id orcid identifier
* @return Person
*/
public Person getBio(String id) {
log.debug("getBio called with ID=" + id);
if (!isValid(id)) {
return null;
}
init();
InputStream bioDocument = orcidRestConnector.get(id + ((id.endsWith("/person")) ? "" : "/person"), accessToken);
XMLtoBio converter = new XMLtoBio();
Person person = converter.convertSinglePerson(bioDocument);
return person;
}
/**
* Retrieve a list of Person objects.
* @param text search string
* @param start offset to use
* @param rows how many rows to return
* @return List<Person>
*/
public List<Person> queryBio(String text, int start, int rows) {
init();
if (rows > 100) {
throw new IllegalArgumentException("The maximum number of results to retrieve cannot exceed 100.");
}
String searchPath = "search?q=" + URLEncoder.encode(text) + "&start=" + start + "&rows=" + rows;
log.debug("queryBio searchPath=" + searchPath + " accessToken=" + accessToken);
InputStream bioDocument = orcidRestConnector.get(searchPath, accessToken);
XMLtoBio converter = new XMLtoBio();
List<Result> results = converter.convert(bioDocument);
List<Person> bios = new LinkedList<>();
for (Result result : results) {
OrcidIdentifier orcidIdentifier = result.getOrcidIdentifier();
if (orcidIdentifier != null) {
log.debug("Found OrcidId=" + orcidIdentifier.toString());
String orcid = orcidIdentifier.getPath();
Person bio = getBio(orcid);
if (bio != null) {
bios.add(bio);
}
}
}
try {
bioDocument.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
return bios;
}
/**
* Retrieve a list of Person objects.
* @param text search string
* @param max how many rows to return
* @return List<Person>
*/
public List<Person> queryBio(String text, int max) {
return queryBio(text, 0, max);
}
/**
* Check to see if the provided text has the correct ORCID syntax. Since only
* searching on ORCID id is allowed, this way, we filter out any queries that
* would return a blank result anyway
*/
private boolean isValid(String text) {
return StringUtils.isNotBlank(text) && text.matches(Orcidv3AuthorityValue.ORCID_ID_SYNTAX);
}
}

View File

@@ -17,6 +17,8 @@ import java.util.UUID;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.authorize.service.ResourcePolicyService;
import org.dspace.content.Bitstream;
@@ -30,6 +32,13 @@ import org.dspace.content.service.BitstreamService;
import org.dspace.content.service.WorkspaceItemService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.discovery.DiscoverQuery;
import org.dspace.discovery.DiscoverResult;
import org.dspace.discovery.IndexableObject;
import org.dspace.discovery.SearchService;
import org.dspace.discovery.SearchServiceException;
import org.dspace.discovery.indexobject.IndexableCollection;
import org.dspace.discovery.indexobject.IndexableCommunity;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.eperson.service.GroupService;
@@ -52,6 +61,9 @@ import org.springframework.beans.factory.annotation.Autowired;
* group 0, which is anonymous - all EPeople are members of group 0.
*/
public class AuthorizeServiceImpl implements AuthorizeService {
private static Logger log = LogManager.getLogger(AuthorizeServiceImpl.class);
@Autowired(required = true)
protected BitstreamService bitstreamService;
@Autowired(required = true)
@@ -64,6 +76,9 @@ public class AuthorizeServiceImpl implements AuthorizeService {
protected WorkspaceItemService workspaceItemService;
@Autowired(required = true)
protected WorkflowItemService workflowItemService;
@Autowired(required = true)
private SearchService searchService;
protected AuthorizeServiceImpl() {
@@ -428,46 +443,6 @@ public class AuthorizeServiceImpl implements AuthorizeService {
}
}
public boolean isCommunityAdmin(Context c) throws SQLException {
EPerson e = c.getCurrentUser();
return isCommunityAdmin(c, e);
}
@Override
public boolean isCommunityAdmin(Context c, EPerson e) throws SQLException {
if (e != null) {
List<ResourcePolicy> policies = resourcePolicyService.find(c, e,
groupService.allMemberGroups(c, e),
Constants.ADMIN, Constants.COMMUNITY);
if (CollectionUtils.isNotEmpty(policies)) {
return true;
}
}
return false;
}
public boolean isCollectionAdmin(Context c) throws SQLException {
EPerson e = c.getCurrentUser();
return isCollectionAdmin(c, e);
}
@Override
public boolean isCollectionAdmin(Context c, EPerson e) throws SQLException {
if (e != null) {
List<ResourcePolicy> policies = resourcePolicyService.find(c, e,
groupService.allMemberGroups(c, e),
Constants.ADMIN, Constants.COLLECTION);
if (CollectionUtils.isNotEmpty(policies) || isCommunityAdmin(c, e)) {
return true;
}
}
return false;
}
///////////////////////////////////////////////
// policy manipulation methods
///////////////////////////////////////////////
@@ -787,4 +762,191 @@ public class AuthorizeServiceImpl implements AuthorizeService {
return resourcePolicyService.findExceptRpType(c, o, actionID, rpType);
}
/**
* Checks that the context's current user is a community admin in the site by querying the solr database.
*
* @param context context with the current user
* @return true if the current user is a community admin in the site
* false when this is not the case, or an exception occurred
*/
@Override
public boolean isCommunityAdmin(Context context) throws SQLException {
return performCheck(context, "search.resourcetype:" + IndexableCommunity.TYPE);
}
/**
* Checks that the context's current user is a collection admin in the site by querying the solr database.
*
* @param context context with the current user
* @return true if the current user is a collection admin in the site
* false when this is not the case, or an exception occurred
*/
@Override
public boolean isCollectionAdmin(Context context) throws SQLException {
return performCheck(context, "search.resourcetype:" + IndexableCollection.TYPE);
}
/**
* Checks that the context's current user is a community or collection admin in the site.
*
* @param context context with the current user
* @return true if the current user is a community or collection admin in the site
* false when this is not the case, or an exception occurred
*/
@Override
public boolean isComColAdmin(Context context) throws SQLException {
return performCheck(context,
"(search.resourcetype:" + IndexableCommunity.TYPE + " OR search.resourcetype:" +
IndexableCollection.TYPE + ")");
}
/**
* Finds communities for which the logged in user has ADMIN rights.
*
* @param context the context whose user is checked against
* @param query the optional extra query
* @param offset the offset for pagination
* @param limit the amount of dso's to return
* @return a list of communities for which the logged in user has ADMIN rights.
* @throws SearchServiceException
*/
@Override
public List<Community> findAdminAuthorizedCommunity(Context context, String query, int offset, int limit)
throws SearchServiceException, SQLException {
List<Community> communities = new ArrayList<>();
query = formatCustomQuery(query);
DiscoverResult discoverResult = getDiscoverResult(context, query + "search.resourcetype:" +
IndexableCommunity.TYPE,
offset, limit);
for (IndexableObject solrCollections : discoverResult.getIndexableObjects()) {
Community community = ((IndexableCommunity) solrCollections).getIndexedObject();
communities.add(community);
}
return communities;
}
/**
* Finds the amount of communities for which the logged in user has ADMIN rights.
*
* @param context the context whose user is checked against
* @param query the optional extra query
* @return the number of communities for which the logged in user has ADMIN rights.
* @throws SearchServiceException
*/
@Override
public long countAdminAuthorizedCommunity(Context context, String query)
throws SearchServiceException, SQLException {
query = formatCustomQuery(query);
DiscoverResult discoverResult = getDiscoverResult(context, query + "search.resourcetype:" +
IndexableCommunity.TYPE,
null, null);
return discoverResult.getTotalSearchResults();
}
/**
* Finds collections for which the logged in user has ADMIN rights.
*
* @param context the context whose user is checked against
* @param query the optional extra query
* @param offset the offset for pagination
* @param limit the amount of dso's to return
* @return a list of collections for which the logged in user has ADMIN rights.
* @throws SearchServiceException
*/
@Override
public List<Collection> findAdminAuthorizedCollection(Context context, String query, int offset, int limit)
throws SearchServiceException, SQLException {
List<Collection> collections = new ArrayList<>();
if (context.getCurrentUser() == null) {
return collections;
}
query = formatCustomQuery(query);
DiscoverResult discoverResult = getDiscoverResult(context, query + "search.resourcetype:" +
IndexableCollection.TYPE,
offset, limit);
for (IndexableObject solrCollections : discoverResult.getIndexableObjects()) {
Collection collection = ((IndexableCollection) solrCollections).getIndexedObject();
collections.add(collection);
}
return collections;
}
/**
* Finds the amount of collections for which the logged in user has ADMIN rights.
*
* @param context the context whose user is checked against
* @param query the optional extra query
* @return the number of collections for which the logged in user has ADMIN rights.
* @throws SearchServiceException
*/
@Override
public long countAdminAuthorizedCollection(Context context, String query)
throws SearchServiceException, SQLException {
query = formatCustomQuery(query);
DiscoverResult discoverResult = getDiscoverResult(context, query + "search.resourcetype:" +
IndexableCollection.TYPE,
null, null);
return discoverResult.getTotalSearchResults();
}
private boolean performCheck(Context context, String query) throws SQLException {
if (context.getCurrentUser() == null) {
return false;
}
try {
DiscoverResult discoverResult = getDiscoverResult(context, query, null, null);
if (discoverResult.getTotalSearchResults() > 0) {
return true;
}
} catch (SearchServiceException e) {
log.error("Failed getting getting community/collection admin status for "
+ context.getCurrentUser().getEmail() + " The search error is: " + e.getMessage()
+ " The search resourceType filter was: " + query);
}
return false;
}
private DiscoverResult getDiscoverResult(Context context, String query, Integer offset, Integer limit)
throws SearchServiceException, SQLException {
String groupQuery = getGroupToQuery(groupService.allMemberGroups(context, context.getCurrentUser()));
DiscoverQuery discoverQuery = new DiscoverQuery();
if (!this.isAdmin(context)) {
query = query + " AND (" +
"admin:e" + context.getCurrentUser().getID() + groupQuery + ")";
}
discoverQuery.setQuery(query);
if (offset != null) {
discoverQuery.setStart(offset);
}
if (limit != null) {
discoverQuery.setMaxResults(limit);
}
return searchService.search(context, discoverQuery);
}
private String getGroupToQuery(List<Group> groups) {
StringBuilder groupQuery = new StringBuilder();
if (groups != null) {
for (Group group: groups) {
groupQuery.append(" OR admin:g");
groupQuery.append(group.getID());
}
}
return groupQuery.toString();
}
private String formatCustomQuery(String query) {
if (StringUtils.isBlank(query)) {
return "";
} else {
return query + " AND ";
}
}
}

View File

@@ -14,8 +14,10 @@ import java.util.List;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.DSpaceObject;
import org.dspace.core.Context;
import org.dspace.discovery.SearchServiceException;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
@@ -209,30 +211,6 @@ public interface AuthorizeService {
*/
public boolean isAdmin(Context c, EPerson e) throws SQLException;
public boolean isCommunityAdmin(Context c) throws SQLException;
public boolean isCollectionAdmin(Context c) throws SQLException;
/**
* Check to see if a specific user is Community admin
*
* @param c current context
* @param e the user to check
* @return true if user is an admin of some community
* @throws SQLException
*/
public boolean isCommunityAdmin(Context c, EPerson e) throws SQLException;
/**
* Check to see if a specific user is Collection admin
*
* @param c current context
* @param e the user to check
* @return true if user is an admin of some collection
* @throws SQLException if database error
*/
public boolean isCollectionAdmin(Context c, EPerson e) throws SQLException;
///////////////////////////////////////////////
// policy manipulation methods
///////////////////////////////////////////////
@@ -536,4 +514,82 @@ public interface AuthorizeService {
void switchPoliciesAction(Context context, DSpaceObject dso, int fromAction, int toAction)
throws SQLException, AuthorizeException;
/**
* Checks that the context's current user is a community admin in the site by querying the solr database.
*
* @param context context with the current user
* @return true if the current user is a community admin in the site
* false when this is not the case, or an exception occurred
*/
boolean isCommunityAdmin(Context context) throws SQLException;
/**
* Checks that the context's current user is a collection admin in the site by querying the solr database.
*
* @param context context with the current user
* @return true if the current user is a collection admin in the site
* false when this is not the case, or an exception occurred
*/
boolean isCollectionAdmin(Context context) throws SQLException;
/**
* Checks that the context's current user is a community or collection admin in the site.
*
* @param context context with the current user
* @return true if the current user is a community or collection admin in the site
* false when this is not the case, or an exception occurred
*/
boolean isComColAdmin(Context context) throws SQLException;
/**
* Finds communities for which the current user is admin, AND which match the query.
*
* @param context context with the current user
* @param query the query for which to filter the results more
* @param offset used for pagination of the results
* @param limit used for pagination of the results
* @return the number of matching communities
* @throws SearchServiceException
* @throws SQLException
*/
List<Community> findAdminAuthorizedCommunity(Context context, String query, int offset, int limit)
throws SearchServiceException, SQLException;
/**
* Counts communities for which the current user is admin, AND which match the query.
*
* @param context context with the current user
* @param query the query for which to filter the results more
* @return the matching communities
* @throws SearchServiceException
* @throws SQLException
*/
long countAdminAuthorizedCommunity(Context context, String query)
throws SearchServiceException, SQLException;
/**
* Finds collections for which the current user is admin, AND which match the query.
*
* @param context context with the current user
* @param query the query for which to filter the results more
* @param offset used for pagination of the results
* @param limit used for pagination of the results
* @return the matching collections
* @throws SearchServiceException
* @throws SQLException
*/
List<Collection> findAdminAuthorizedCollection(Context context, String query, int offset, int limit)
throws SearchServiceException, SQLException;
/**
* Counts collections for which the current user is admin, AND which match the query.
*
* @param context context with the current user
* @param query the query for which to filter the results more
* @return the number of matching collections
* @throws SearchServiceException
* @throws SQLException
*/
long countAdminAuthorizedCollection(Context context, String query)
throws SearchServiceException, SQLException;
}

View File

@@ -305,6 +305,7 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
// metadataValueService.update(context, metadataValue);
dso.addDetails(metadataField.toString());
}
setMetadataModified(dso);
return newMetadata;
}

View File

@@ -51,7 +51,7 @@ public class EntityServiceImpl implements EntityService {
@Override
public EntityType getType(Context context, Entity entity) throws SQLException {
Item item = entity.getItem();
List<MetadataValue> list = itemService.getMetadata(item, "relationship", "type", null, Item.ANY, false);
List<MetadataValue> list = itemService.getMetadata(item, "dspace", "entity", "type", Item.ANY, false);
if (!list.isEmpty()) {
return entityTypeService.findByEntityType(context, list.get(0).getValue());
} else {

View File

@@ -113,6 +113,16 @@ public class Item extends DSpaceObject implements DSpaceObjectLegacySupport {
@Transient
private transient ItemService itemService;
/**
* True if anything else was changed since last metadata retrieval()
* (to drive metadata cache)
*/
@Transient
private boolean modifiedMetadataCache = true;
@Transient
private List<MetadataValue> cachedMetadata = new ArrayList<>();
/**
* Protected constructor, create object using:
* {@link org.dspace.content.service.ItemService#create(Context, WorkspaceItem)}
@@ -374,4 +384,23 @@ public class Item extends DSpaceObject implements DSpaceObjectLegacySupport {
}
return itemService;
}
@Override
protected void setMetadataModified() {
super.setMetadataModified();
modifiedMetadataCache = true;
}
public boolean isModifiedMetadataCache() {
return modifiedMetadataCache;
}
protected List<MetadataValue> getCachedMetadata() {
return cachedMetadata;
}
protected void setCachedMetadata(List<MetadataValue> cachedMetadata) {
this.cachedMetadata = cachedMetadata;
modifiedMetadataCache = false;
}
}

View File

@@ -1328,42 +1328,33 @@ prevent the generation of resource policy entry values with null dspace_object a
@Override
public List<MetadataValue> getMetadata(Item item, String schema, String element, String qualifier, String lang,
boolean enableVirtualMetadata) {
//Fields of the relation schema are virtual metadata
//except for relation.type which is the type of item in the model
if (StringUtils.equals(schema, MetadataSchemaEnum.RELATION.getName()) && !StringUtils.equals(element, "type")) {
List<RelationshipMetadataValue> relationMetadata = relationshipMetadataService
.getRelationshipMetadata(item, enableVirtualMetadata);
List<MetadataValue> listToReturn = new LinkedList<>();
for (MetadataValue metadataValue : relationMetadata) {
if (StringUtils.equals(metadataValue.getMetadataField().getElement(), element)) {
listToReturn.add(metadataValue);
if (!enableVirtualMetadata) {
log.debug("Called getMetadata for " + item.getID() + " without enableVirtualMetadata");
return super.getMetadata(item, schema, element, qualifier, lang);
}
}
listToReturn = sortMetadataValueList(listToReturn);
return listToReturn;
} else {
List<MetadataValue> dbMetadataValues = super.getMetadata(item, schema, element, qualifier, lang);
if (item.isModifiedMetadataCache()) {
log.debug("Called getMetadata for " + item.getID() + " with invalid cache");
//rebuild cache
List<MetadataValue> dbMetadataValues = item.getMetadata();
List<MetadataValue> fullMetadataValueList = new LinkedList<>();
if (enableVirtualMetadata) {
fullMetadataValueList.addAll(relationshipMetadataService.getRelationshipMetadata(item, true));
}
fullMetadataValueList.addAll(dbMetadataValues);
List<MetadataValue> finalList = new LinkedList<>();
for (MetadataValue metadataValue : fullMetadataValueList) {
if (match(schema, element, qualifier, lang, metadataValue)) {
finalList.add(metadataValue);
}
}
finalList = sortMetadataValueList(finalList);
return finalList;
item.setCachedMetadata(sortMetadataValueList(fullMetadataValueList));
}
log.debug("Called getMetadata for " + item.getID() + " based on cache");
// Build up list of matching values based on the cache
List<MetadataValue> values = new ArrayList<>();
for (MetadataValue dcv : item.getCachedMetadata()) {
if (match(schema, element, qualifier, lang, dcv)) {
values.add(dcv);
}
}
// Create an array of matching values
return values;
}
/**

View File

@@ -164,6 +164,7 @@ public class Relationship implements ReloadableEntity<Integer> {
*/
public void setLeftPlace(int leftPlace) {
this.leftPlace = leftPlace;
leftItem.setMetadataModified();
}
/**
@@ -180,6 +181,7 @@ public class Relationship implements ReloadableEntity<Integer> {
*/
public void setRightPlace(int rightPlace) {
this.rightPlace = rightPlace;
rightItem.setMetadataModified();
}
/**

View File

@@ -63,11 +63,9 @@ public class RelationshipMetadataServiceImpl implements RelationshipMetadataServ
public String getEntityTypeStringFromMetadata(Item item) {
List<MetadataValue> list = item.getMetadata();
for (MetadataValue mdv : list) {
if (StringUtils.equals(mdv.getMetadataField().getMetadataSchema().getName(),
"relationship")
&& StringUtils.equals(mdv.getMetadataField().getElement(),
"type")) {
if (StringUtils.equals(mdv.getMetadataField().getMetadataSchema().getName(), "dspace")
&& StringUtils.equals(mdv.getMetadataField().getElement(), "entity")
&& StringUtils.equals(mdv.getMetadataField().getQualifier(), "type")) {
return mdv.getValue();
}
}

View File

@@ -257,8 +257,8 @@ public class RelationshipServiceImpl implements RelationshipService {
}
private boolean verifyEntityTypes(Item itemToProcess, EntityType entityTypeToProcess) {
List<MetadataValue> list = itemService.getMetadata(itemToProcess, "relationship", "type",
null, Item.ANY, false);
List<MetadataValue> list = itemService.getMetadata(itemToProcess, "dspace", "entity",
"type", Item.ANY, false);
if (list.isEmpty()) {
return false;
}

View File

@@ -156,22 +156,6 @@ public final class ChoiceAuthorityServiceImpl implements ChoiceAuthorityService
return ma.getMatches(query, start, limit, locale);
}
@Override
public Choices getMatches(String fieldKey, String query, Collection collection, int start, int limit, String locale,
boolean externalInput) {
ChoiceAuthority ma = getAuthorityByFieldKeyCollection(fieldKey, collection);
if (ma == null) {
throw new IllegalArgumentException(
"No choices plugin was configured for field \"" + fieldKey
+ "\", collection=" + collection.getID().toString() + ".");
}
if (externalInput && ma instanceof SolrAuthority) {
((SolrAuthority) ma).addExternalResultsInNextMatches();
}
return ma.getMatches(query, start, limit, locale);
}
@Override
public Choices getBestMatch(String fieldKey, String query, Collection collection,
String locale) {

View File

@@ -13,6 +13,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
@@ -315,6 +316,9 @@ public class DSpaceControlledVocabulary extends SelfNamedPlugin implements Hiera
private String getNodeLabel(String key, boolean useHierarchy) {
try {
Node node = getNode(key);
if (Objects.isNull(node)) {
return null;
}
if (useHierarchy) {
return this.buildString(node);
} else {

View File

@@ -222,4 +222,12 @@ public class MetadataAuthorityServiceImpl implements MetadataAuthorityService {
}
return copy;
}
@Override
public void clearCache() {
controlled.clear();
minConfidence.clear();
isAuthorityRequired = null;
}
}

View File

@@ -0,0 +1,87 @@
/**
* 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.content.authority;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.dspace.app.sherpa.SHERPAService;
import org.dspace.app.sherpa.v2.SHERPAResponse;
import org.dspace.utils.DSpace;
/**
* Journal-name authority based on SHERPA/RoMEO v2
*
* @author Larry Stone
* @author Andrea Bollini (andrea.bollini at 4science.it)
* @version $Revision $
* @see SHERPARoMEOProtocol
*/
public class SHERPARoMEOJournalTitle implements ChoiceAuthority {
private String pluginInstanceName;
public SHERPARoMEOJournalTitle() {
super();
}
@Override
public Choices getMatches(String text, int start, int limit, String locale) {
// punt if there is no query text
if (text == null || text.trim().length() == 0) {
return new Choices(true);
}
SHERPAService sherpaService = new DSpace().getSingletonService(SHERPAService.class);
SHERPAResponse sherpaResponse = sherpaService.performRequest("publication", "title",
"contains word", text, 0, 0);
Choices result;
if (CollectionUtils.isNotEmpty(sherpaResponse.getJournals())) {
List<Choice> list = sherpaResponse
.getJournals().stream()
.skip(start)
.limit(limit)
.map(sherpaJournal -> new Choice(sherpaJournal.getIssns().get(0),
sherpaJournal.getTitles().get(0), sherpaJournal.getTitles().get(0)))
.collect(Collectors.toList());
int total = sherpaResponse.getJournals().size();
result = new Choices(list.toArray(new Choice[list.size()]), start, total, Choices.CF_ACCEPTED,
total > (start + limit));
} else {
result = new Choices(false);
}
return result;
}
@Override
public Choices getBestMatch(String text, String locale) {
return getMatches(text, 0, 1, locale);
}
@Override
public String getLabel(String key, String locale) {
SHERPAService sherpaService = new DSpace().getSingletonService(SHERPAService.class);
SHERPAResponse sherpaResponse = sherpaService.performRequest("publication", "issn",
"equals", key, 0, 1);
if (CollectionUtils.isNotEmpty(sherpaResponse.getJournals())) {
return sherpaResponse.getJournals().get(0).getTitles().get(0);
} else {
return null;
}
}
@Override
public void setPluginInstanceName(String name) {
this.pluginInstanceName = name;
}
@Override
public String getPluginInstanceName() {
return pluginInstanceName;
}
}

View File

@@ -0,0 +1,87 @@
/**
* 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.content.authority;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.dspace.app.sherpa.SHERPAService;
import org.dspace.app.sherpa.v2.SHERPAPublisherResponse;
import org.dspace.utils.DSpace;
/**
* Publisher name authority based on SHERPA/RoMEO v2
*
* @author Larry Stone
* @author Andrea Bollini (andrea.bollini at 4science.it)
* @version $Revision $
* @see SHERPARoMEOProtocol
*/
public class SHERPARoMEOPublisher implements ChoiceAuthority {
private String pluginInstanceName;
public SHERPARoMEOPublisher() {
super();
}
@Override
public Choices getMatches(String text, int start, int limit, String locale) {
// punt if there is no query text
if (text == null || text.trim().length() == 0) {
return new Choices(true);
}
SHERPAService sherpaService = new DSpace().getSingletonService(SHERPAService.class);
SHERPAPublisherResponse sherpaResponse = sherpaService.performPublisherRequest("publisher", "name",
"contains word", text, 0, 0);
Choices result;
if (CollectionUtils.isNotEmpty(sherpaResponse.getPublishers())) {
List<Choice> list = sherpaResponse
.getPublishers().stream()
.skip(start)
.limit(limit)
.map(sherpaPublisher ->
new Choice(sherpaPublisher.getIdentifier(),
sherpaPublisher.getName(), sherpaPublisher.getName()))
.collect(Collectors.toList());
int total = sherpaResponse.getPublishers().size();
result = new Choices(list.toArray(new Choice[list.size()]), start, total, Choices.CF_ACCEPTED,
total > (start + limit));
} else {
result = new Choices(false);
}
return result;
}
@Override
public Choices getBestMatch(String text, String locale) {
return getMatches(text, 0, 1, locale);
}
@Override
public String getLabel(String key, String locale) {
SHERPAService sherpaService = new DSpace().getSingletonService(SHERPAService.class);
SHERPAPublisherResponse sherpaResponse = sherpaService.performPublisherRequest("publisher", "id",
"equals", key, 0, 1);
if (CollectionUtils.isNotEmpty(sherpaResponse.getPublishers())) {
return sherpaResponse.getPublishers().get(0).getName();
} else {
return null;
}
}
@Override
public void setPluginInstanceName(String name) {
this.pluginInstanceName = name;
}
@Override
public String getPluginInstanceName() {
return pluginInstanceName;
}
}

View File

@@ -53,8 +53,6 @@ public class SolrAuthority implements ChoiceAuthority {
private static final Logger log = LogManager.getLogger(SolrAuthority.class);
protected boolean externalResults = false;
protected final AuthorityValueService authorityValueService
= AuthorityServiceFactory.getInstance().getAuthorityValueService();
@@ -95,9 +93,6 @@ public class SolrAuthority implements ChoiceAuthority {
queryArgs.set(CommonParams.START, start);
//We add one to our facet limit so that we know if there are more matches
int maxNumberOfSolrResults = limit + 1;
if (externalResults) {
maxNumberOfSolrResults = configurationService.getIntProperty("xmlui.lookup.select.size", 12);
}
queryArgs.set(CommonParams.ROWS, maxNumberOfSolrResults);
String sortField = "value";
@@ -135,14 +130,16 @@ public class SolrAuthority implements ChoiceAuthority {
}
}
if (externalResults && StringUtils.isNotBlank(text)) {
if (StringUtils.isNotBlank(text)) {
int sizeFromSolr = alreadyPresent.size();
int maxExternalResults = limit <= 10 ? Math.max(limit - sizeFromSolr, 2) : Math
.max(limit - 10 - sizeFromSolr, 2) + limit - 10;
int maxExternalResults = sizeFromSolr < limit ? limit + 1 : sizeFromSolr + 1;
// force an upper limit for external results
if (maxExternalResults > 10) {
maxExternalResults = 10;
}
addExternalResults(text, choices, alreadyPresent, maxExternalResults);
}
// hasMore = (authDocs.size() == (limit + 1));
hasMore = true;
}
@@ -171,8 +168,9 @@ public class SolrAuthority implements ChoiceAuthority {
int max) {
if (source != null) {
try {
// max has been already adapted to consider the need to filter already found entries
List<AuthorityValue> values = source
.queryAuthorities(text, max * 2); // max*2 because results get filtered
.queryAuthorities(text, max);
// filtering loop
Iterator<AuthorityValue> iterator = values.iterator();
@@ -196,7 +194,6 @@ public class SolrAuthority implements ChoiceAuthority {
} catch (Exception e) {
log.error("Error", e);
}
this.externalResults = false;
} else {
log.warn("external source for authority not configured");
}
@@ -288,10 +285,6 @@ public class SolrAuthority implements ChoiceAuthority {
return manager.getServiceByName(AuthoritySearchService.class.getName(), AuthoritySearchService.class);
}
public void addExternalResultsInNextMatches() {
this.externalResults = true;
}
@Override
public void setPluginInstanceName(String name) {
authorityName = name;

View File

@@ -89,9 +89,6 @@ public interface ChoiceAuthorityService {
public Choices getMatches(String fieldKey, String query, Collection collection,
int start, int limit, String locale);
public Choices getMatches(String fieldKey, String query, Collection collection, int start, int limit, String locale,
boolean externalInput);
/**
* Wrapper that calls getBestMatch method of the plugin corresponding to
* the metadata field defined by single field key.

View File

@@ -112,4 +112,9 @@ public interface MetadataAuthorityService {
* @return the list of metadata field with authority control
*/
public List<String> getAuthorityMetadata();
/**
* This method has been created to have a way of clearing the cache kept inside the service
*/
public void clearCache();
}

View File

@@ -8,8 +8,10 @@
package org.dspace.content.dao.impl;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
@@ -17,6 +19,7 @@ import javax.persistence.criteria.Join;
import javax.persistence.criteria.Root;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.dspace.content.MetadataField;
import org.dspace.content.MetadataField_;
import org.dspace.content.MetadataSchema;
@@ -24,6 +27,7 @@ import org.dspace.content.MetadataSchema_;
import org.dspace.content.dao.MetadataFieldDAO;
import org.dspace.core.AbstractHibernateDAO;
import org.dspace.core.Context;
import org.hibernate.Session;
/**
* Hibernate implementation of the Database Access Object interface class for the MetadataField object.
@@ -33,6 +37,17 @@ import org.dspace.core.Context;
* @author kevinvandevelde at atmire.com
*/
public class MetadataFieldDAOImpl extends AbstractHibernateDAO<MetadataField> implements MetadataFieldDAO {
/**
* log4j logger
*/
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(MetadataFieldDAOImpl.class);
/**
* Cache for improvement the performance of searching metadata fields
* This cache only stores IDs, the actual MetadataField is retrieved from hibernate
*/
private static Map<String, Integer> cachedFields = new HashMap();
protected MetadataFieldDAOImpl() {
super();
}
@@ -79,6 +94,30 @@ public class MetadataFieldDAOImpl extends AbstractHibernateDAO<MetadataField> im
@Override
public MetadataField findByElement(Context context, String metadataSchema, String element, String qualifier)
throws SQLException {
String key = metadataSchema + "." + element + "." + qualifier;
if (cachedFields.containsKey(key)) {
Session session = getHibernateSession(context);
MetadataField metadataField = null;
try {
metadataField = session.load(MetadataField.class, cachedFields.get(key));
} catch (Throwable e) {
log.error("Failed to load metadata field " + key + " using ID " + cachedFields.get(key));
}
try {
if (metadataField != null &&
(metadataField.getMetadataSchema().getName() + "." + metadataField.getElement() +
"." + metadataField.getQualifier()).equals(key)) {
return metadataField;
} else {
cachedFields.remove(key);
}
} catch (Throwable e) {
log.error("Failed to verify consistence of metadata field " + key +
" using ID " + cachedFields.get(key));
cachedFields.clear();
}
}
Query query;
if (StringUtils.isNotBlank(qualifier)) {
@@ -103,7 +142,11 @@ public class MetadataFieldDAOImpl extends AbstractHibernateDAO<MetadataField> im
}
query.setHint("org.hibernate.cacheable", Boolean.TRUE);
return singleResult(query);
MetadataField metadataField = singleResult(query);
if (metadataField != null) {
cachedFields.put(key, metadataField.getID());
}
return metadataField;
}
@Override

View File

@@ -13,10 +13,13 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.UnknownHostException;
import java.rmi.dgc.VMID;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -453,6 +456,40 @@ public final class Utils {
}
}
/**
* Retrieve the IP address(es) of a given URI string.
* <P>
* At this time, DSpace only supports IPv4, so this method will only return IPv4 addresses.
* @param uriString URI string
* @return IP address(es) in a String array (or null if not found)
*/
public static String[] getIPAddresses(String uriString) {
String[] ipAddresses = null;
// First, get the hostname
String hostname = getHostName(uriString);
if (StringUtils.isNotEmpty(hostname)) {
try {
// Then, get the list of all IPs for that hostname
InetAddress[] inetAddresses = InetAddress.getAllByName(hostname);
// Convert array of InetAddress objects to array of IP address Strings
ipAddresses = Arrays.stream(inetAddresses)
// Filter our array to ONLY include IPv4 addresses
.filter((address) -> address instanceof Inet4Address)
// Call getHostAddress() on each to get the IPv4 address as a string
.map((address) -> ((Inet4Address) address).getHostAddress())
.toArray(String[]::new);
} catch (UnknownHostException ex) {
return null;
}
}
return ipAddresses;
}
/**
* Replaces configuration placeholders within a String with the corresponding value
* from DSpace's Configuration Service.

View File

@@ -157,6 +157,13 @@ public class IndexEventConsumer implements Consumer {
} else {
log.debug("consume() adding event to update queue: " + event.toString());
objectsToUpdate.addAll(indexObjectServiceFactory.getIndexableObjects(ctx, subject));
// If the event subject is a Collection and the event object is an Item,
// also update the object in order to index mapped/unmapped Items
if (subject != null &&
subject.getType() == Constants.COLLECTION && object.getType() == Constants.ITEM) {
objectsToUpdate.addAll(indexObjectServiceFactory.getIndexableObjects(ctx, object));
}
}
break;

View File

@@ -11,6 +11,7 @@ import static org.apache.logging.log4j.LogManager.getLogger;
import java.sql.SQLException;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.dspace.authorize.service.AuthorizeService;
@@ -37,9 +38,16 @@ public class SolrServicePrivateItemPlugin implements SolrServiceSearchPlugin {
try {
// Prevents access if user has no administrative rights on the community or collection.
// NOTE: the resource restriction plugin adds location filters for community and collection admins.
if ( !authorizeService.isAdmin(context) && !authorizeService.isCommunityAdmin(context)
&& !authorizeService.isCollectionAdmin(context)) {
if (authorizeService.isAdmin(context)) {
return;
}
if (!StringUtils.equalsIgnoreCase(discoveryQuery.getDiscoveryConfigurationName(), "administrativeView")) {
solrQuery.addFilterQuery("NOT(discoverable:false)");
return;
}
if (!authorizeService.isCommunityAdmin(context) && !authorizeService.isCollectionAdmin(context)) {
solrQuery.addFilterQuery("NOT(discoverable:false)");
}
} catch (SQLException ex) {
log.error(LogManager.getHeader(context, "Error looking up authorization rights of current user",

View File

@@ -11,6 +11,7 @@ import java.sql.SQLException;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.common.SolrInputDocument;
@@ -118,6 +119,7 @@ public class SolrServiceResourceRestrictionPlugin implements SolrServiceIndexPlu
fieldValue = "e" + resourcePolicy.getEPerson().getID();
}
document.addField("read", fieldValue);
document.addField("admin", fieldValue);
}
// remove the policy from the cache to save memory
@@ -159,14 +161,15 @@ public class SolrServiceResourceRestrictionPlugin implements SolrServiceIndexPlu
resourceQuery.append(")");
if (authorizeService.isCommunityAdmin(context)
|| authorizeService.isCollectionAdmin(context)) {
resourceQuery.append(" OR ");
resourceQuery.append(DSpaceServicesFactory.getInstance()
String locations = DSpaceServicesFactory.getInstance()
.getServiceManager()
.getServiceByName(SearchService.class.getName(),
SearchService.class)
.createLocationQueryForAdministrableItems(context));
.createLocationQueryForAdministrableItems(context);
if (StringUtils.isNotBlank(locations)) {
resourceQuery.append(" OR ");
resourceQuery.append(locations);
}
solrQuery.addFilterQuery(resourceQuery.toString());

View File

@@ -15,6 +15,7 @@ import org.apache.solr.common.SolrInputDocument;
import org.dspace.content.InProgressSubmission;
import org.dspace.content.Item;
import org.dspace.core.Context;
import org.dspace.discovery.SearchUtils;
import org.dspace.discovery.indexobject.factory.CollectionIndexFactory;
import org.dspace.discovery.indexobject.factory.InprogressSubmissionIndexFactory;
import org.dspace.discovery.indexobject.factory.ItemIndexFactory;
@@ -47,7 +48,7 @@ public abstract class InprogressSubmissionIndexFactoryImpl
@Override
public void storeInprogressItemFields(Context context, SolrInputDocument doc,
InProgressSubmission inProgressSubmission) throws SQLException {
InProgressSubmission inProgressSubmission) throws SQLException, IOException {
final Item item = inProgressSubmission.getItem();
doc.addField("lastModified", SolrUtils.getDateFormatter().format(item.getLastModified()));
EPerson submitter = inProgressSubmission.getSubmitter();
@@ -61,6 +62,9 @@ public abstract class InprogressSubmissionIndexFactoryImpl
// get the location string (for searching by collection & community)
List<String> locations = indexableCollectionService.
getCollectionLocations(context, inProgressSubmission.getCollection());
// Add item metadata
indexableItemService.addDiscoveryFields(doc, context, item, SearchUtils.getAllDiscoveryConfigurations(item));
indexableCollectionService.storeCommunityCollectionLocations(doc, locations);
}
}

View File

@@ -19,8 +19,6 @@ import org.apache.solr.common.SolrInputDocument;
import org.dspace.content.Item;
import org.dspace.core.Context;
import org.dspace.discovery.IndexableObject;
import org.dspace.discovery.SearchUtils;
import org.dspace.discovery.configuration.DiscoveryConfiguration;
import org.dspace.discovery.indexobject.factory.WorkflowItemIndexFactory;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.xmlworkflow.storedcomponents.ClaimedTask;
@@ -75,10 +73,6 @@ public class WorkflowItemIndexFactoryImpl
final SolrInputDocument doc = super.buildDocument(context, indexableObject);
final XmlWorkflowItem workflowItem = indexableObject.getIndexedObject();
final Item item = workflowItem.getItem();
// Add the item metadata as configured
List<DiscoveryConfiguration> discoveryConfigurations = SearchUtils
.getAllDiscoveryConfigurations(workflowItem);
indexableItemService.addDiscoveryFields(doc, context, item, discoveryConfigurations);
String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService()
.getProperty("discovery.facet.namedtype.workflow.item");

View File

@@ -19,8 +19,6 @@ import org.apache.solr.common.SolrInputDocument;
import org.dspace.content.WorkspaceItem;
import org.dspace.content.service.WorkspaceItemService;
import org.dspace.core.Context;
import org.dspace.discovery.SearchUtils;
import org.dspace.discovery.configuration.DiscoveryConfiguration;
import org.dspace.discovery.indexobject.factory.WorkspaceItemIndexFactory;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -71,12 +69,6 @@ public class WorkspaceItemIndexFactoryImpl
acvalue = indexableObject.getTypeText();
}
addNamedResourceTypeIndex(doc, acvalue);
final WorkspaceItem inProgressSubmission = indexableObject.getIndexedObject();
// Add the item metadata as configured
List<DiscoveryConfiguration> discoveryConfigurations = SearchUtils
.getAllDiscoveryConfigurations(inProgressSubmission);
indexableItemService.addDiscoveryFields(doc, context, inProgressSubmission.getItem(), discoveryConfigurations);
return doc;
}

View File

@@ -7,6 +7,7 @@
*/
package org.dspace.discovery.indexobject.factory;
import java.io.IOException;
import java.sql.SQLException;
import org.apache.solr.common.SolrInputDocument;
@@ -31,5 +32,5 @@ public interface InprogressSubmissionIndexFactory<T extends IndexableInProgressS
* @throws SQLException If database error
*/
void storeInprogressItemFields(Context context, SolrInputDocument doc, InProgressSubmission inProgressSubmission)
throws SQLException;
throws SQLException, IOException;
}

View File

@@ -90,7 +90,7 @@ public class SHERPAv2PublisherDataProvider implements ExternalDataProvider {
public List<ExternalDataObject> searchExternalDataObjects(String query, int start, int limit) {
// Search SHERPA for publishers with the query term in the title (name)
SHERPAPublisherResponse sherpaResponse = sherpaService.performPublisherRequest(
"publication", "title", "contains word", query, start, limit);
"publisher", "name", "contains word", query, start, limit);
// If at least one publisher was found, convert to a list of ExternalDataObjects and return
if (CollectionUtils.isNotEmpty(sherpaResponse.getPublishers())) {

View File

@@ -10,6 +10,8 @@ package org.dspace.handle;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@@ -57,6 +59,13 @@ public class HandleServiceImpl implements HandleService {
@Autowired
protected SiteService siteService;
private static final Pattern[] IDENTIFIER_PATTERNS = {
Pattern.compile("^hdl:(.*)$"),
Pattern.compile("^info:hdl/(.*)$"),
Pattern.compile("^https?://hdl\\.handle\\.net/(.*)$"),
Pattern.compile("^https?://.+/handle/(.*)$")
};
/**
* Public Constructor
*/
@@ -376,4 +385,39 @@ public class HandleServiceImpl implements HandleService {
public int countTotal(Context context) throws SQLException {
return handleDAO.countRows(context);
}
@Override
public String parseHandle(String identifier) {
if (identifier == null) {
return null;
}
if (identifier.startsWith(getPrefix() + "/")) {
// prefix is the equivalent of 123456789 in 123456789/???; don't strip
return identifier;
}
String canonicalPrefix = configurationService.getProperty("handle.canonical.prefix");
if (identifier.startsWith(canonicalPrefix + "/")) {
// prefix is the equivalent of https://hdl.handle.net/ in https://hdl.handle.net/123456789/???; strip
return StringUtils.stripStart(identifier, canonicalPrefix);
}
for (Pattern pattern : IDENTIFIER_PATTERNS) {
Matcher matcher = pattern.matcher(identifier);
if (matcher.matches()) {
return matcher.group(1);
}
}
// Check additional prefixes supported in the config file
String[] additionalPrefixes = configurationService.getArrayProperty("handle.additional.prefixes");
for (String additionalPrefix : additionalPrefixes) {
if (identifier.startsWith(additionalPrefix + "/")) {
// prefix is the equivalent of 123456789 in 123456789/???; don't strip
return identifier;
}
}
return null;
}
}

View File

@@ -181,4 +181,15 @@ public interface HandleService {
public void modifyHandleDSpaceObject(Context context, String handle, DSpaceObject newOwner) throws SQLException;
int countTotal(Context context) throws SQLException;
/**
* Format a handle ~
* - hdl:123456789/1 -> 123456789/1
* - info:hdl/123456789/1 -> 123456789/1
* - https://hdl.handle.net/123456789/1 -> 123456789/1
*
* @param identifier
* @return
*/
String parseHandle(String identifier);
}

View File

@@ -60,32 +60,7 @@ public class HandleIdentifierProvider extends IdentifierProvider {
@Override
public boolean supports(String identifier) {
String prefix = handleService.getPrefix();
String canonicalPrefix = DSpaceServicesFactory.getInstance().getConfigurationService()
.getProperty("handle.canonical.prefix");
if (identifier == null) {
return false;
}
// return true if handle has valid starting pattern
if (identifier.startsWith(prefix + "/")
|| identifier.startsWith(canonicalPrefix)
|| identifier.startsWith("hdl:")
|| identifier.startsWith("info:hdl")
|| identifier.matches("^https?://hdl\\.handle\\.net/.*")
|| identifier.matches("^https?://.+/handle/.*")) {
return true;
}
//Check additional prefixes supported in the config file
String[] additionalPrefixes = DSpaceServicesFactory.getInstance().getConfigurationService()
.getArrayProperty("handle.additional.prefixes");
for (String additionalPrefix : additionalPrefixes) {
if (identifier.startsWith(additionalPrefix + "/")) {
return true;
}
}
return false;
return handleService.parseHandle(identifier) != null;
}
@Override
@@ -161,6 +136,7 @@ public class HandleIdentifierProvider extends IdentifierProvider {
public DSpaceObject resolve(Context context, String identifier, String... attributes) {
// We can do nothing with this, return null
try {
identifier = handleService.parseHandle(identifier);
return handleService.resolveToObject(context, identifier);
} catch (IllegalStateException | SQLException e) {
log.error(LogManager.getHeader(context, "Error while resolving handle to item", "handle: " + identifier),

View File

@@ -78,33 +78,7 @@ public class VersionedHandleIdentifierProvider extends IdentifierProvider {
@Override
public boolean supports(String identifier) {
String prefix = handleService.getPrefix();
String canonicalPrefix = DSpaceServicesFactory.getInstance().getConfigurationService()
.getProperty("handle.canonical.prefix");
if (identifier == null) {
return false;
}
// return true if handle has valid starting pattern
if (identifier.startsWith(prefix + "/")
|| identifier.startsWith(canonicalPrefix)
|| identifier.startsWith("hdl:")
|| identifier.startsWith("info:hdl")
|| identifier.matches("^https?://hdl\\.handle\\.net/.*")
|| identifier.matches("^https?://.+/handle/.*")) {
return true;
}
//Check additional prefixes supported in the config file
String[] additionalPrefixes = DSpaceServicesFactory.getInstance().getConfigurationService()
.getArrayProperty("handle.additional.prefixes");
for (String additionalPrefix : additionalPrefixes) {
if (identifier.startsWith(additionalPrefix + "/")) {
return true;
}
}
// otherwise, assume invalid handle
return false;
return handleService.parseHandle(identifier) != null;
}
@Override
@@ -310,6 +284,7 @@ public class VersionedHandleIdentifierProvider extends IdentifierProvider {
public DSpaceObject resolve(Context context, String identifier, String... attributes) {
// We can do nothing with this, return null
try {
identifier = handleService.parseHandle(identifier);
return handleService.resolveToObject(context, identifier);
} catch (IllegalStateException | SQLException e) {
log.error(LogManager.getHeader(context, "Error while resolving handle to item", "handle: " + identifier),

View File

@@ -72,33 +72,7 @@ public class VersionedHandleIdentifierProviderWithCanonicalHandles extends Ident
@Override
public boolean supports(String identifier) {
String prefix = handleService.getPrefix();
String canonicalPrefix = DSpaceServicesFactory.getInstance().getConfigurationService()
.getProperty("handle.canonical.prefix");
if (identifier == null) {
return false;
}
// return true if handle has valid starting pattern
if (identifier.startsWith(prefix + "/")
|| identifier.startsWith(canonicalPrefix)
|| identifier.startsWith("hdl:")
|| identifier.startsWith("info:hdl")
|| identifier.matches("^https?://hdl\\.handle\\.net/.*")
|| identifier.matches("^https?://.+/handle/.*")) {
return true;
}
//Check additional prefixes supported in the config file
String[] additionalPrefixes = DSpaceServicesFactory.getInstance().getConfigurationService()
.getArrayProperty("handle.additional.prefixes");
for (String additionalPrefix : additionalPrefixes) {
if (identifier.startsWith(additionalPrefix + "/")) {
return true;
}
}
// otherwise, assume invalid handle
return false;
return handleService.parseHandle(identifier) != null;
}
@Override

View File

@@ -15,7 +15,11 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import au.com.bytecode.opencsv.CSVReader;
import com.opencsv.CSVParser;
import com.opencsv.CSVParserBuilder;
import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;
import com.opencsv.exceptions.CsvException;
import org.dspace.importer.external.exception.FileSourceException;
import org.dspace.importer.external.metadatamapping.MetadataFieldConfig;
import org.dspace.importer.external.metadatamapping.contributor.MetadataContributor;
@@ -24,7 +28,6 @@ import org.dspace.importer.external.service.components.MetadataSource;
import org.dspace.importer.external.service.components.dto.PlainMetadataKeyValueItem;
import org.dspace.importer.external.service.components.dto.PlainMetadataSourceDto;
/**
* This class is an implementation of {@link MetadataSource} which extends {@link AbstractPlainMetadataSource}
* in order to parse "character separated" files like csv, tsv, etc using the Live Import framework.
@@ -36,7 +39,9 @@ public class CharacterSeparatedImportMetadataSourceServiceImpl extends AbstractP
private char separator = ',';
private char escapeCharacter = '"';
private char quoteCharacter = '"';
private char escapeCharacter = '\\';
private Integer skipLines = 1;
@@ -70,6 +75,26 @@ public class CharacterSeparatedImportMetadataSourceServiceImpl extends AbstractP
this.separator = separator;
}
/**
* Method to inject the escape character, usually ". This must be the ASCII integer
* related to the char.
* In example, 9 for tab, 44 for comma
*
*/
public void setQuoteCharacter(char quoteCharacter) {
this.quoteCharacter = quoteCharacter;
}
/**
* Method to inject the escape character, usually \. This must be the ASCII integer
* related to the char.
* In example, 9 for tab, 44 for comma
*
*/
public void setEscapeCharacter(char escapeCharacter) {
this.escapeCharacter = escapeCharacter;
}
@Override
public String getImportSource() {
return importSource;
@@ -82,15 +107,6 @@ public class CharacterSeparatedImportMetadataSourceServiceImpl extends AbstractP
this.importSource = importSource;
}
/**
* Method to inject the escape character. This must be the ASCII integer
* related to the char.
* In example, 9 for tab, 44 for comma
*
*/
public void setEscapeCharacter(char escapeCharacter) {
this.escapeCharacter = escapeCharacter;
}
/**
* The method process any kind of "character separated" files, like CSV, TSV, and so on.
@@ -110,8 +126,11 @@ public class CharacterSeparatedImportMetadataSourceServiceImpl extends AbstractP
@Override
protected List<PlainMetadataSourceDto> readData(InputStream inputStream) throws FileSourceException {
List<PlainMetadataSourceDto> plainMetadataList = new ArrayList<>();
try (CSVReader csvReader = new CSVReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8),
separator, escapeCharacter);) {
CSVParser parser = new CSVParserBuilder().withSeparator(separator).withQuoteChar(quoteCharacter)
.withEscapeChar(escapeCharacter).build();
try (
InputStreamReader inputReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
CSVReader csvReader = new CSVReaderBuilder(inputReader).withCSVParser(parser).build()) {
// read all row
List<String[]> lines = csvReader.readAll();
int listSize = lines == null ? 0 : lines.size();
@@ -139,7 +158,7 @@ public class CharacterSeparatedImportMetadataSourceServiceImpl extends AbstractP
}
count++;
}
} catch (IOException e) {
} catch (IOException | CsvException e) {
throw new FileSourceException("Error reading file", e);
}
return plainMetadataList;

View File

@@ -8,17 +8,22 @@
package org.dspace.importer.external.metadatamapping.contributor;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import au.com.bytecode.opencsv.CSVReader;
import com.opencsv.CSVParser;
import com.opencsv.CSVParserBuilder;
import com.opencsv.CSVReaderBuilder;
import com.opencsv.exceptions.CsvException;
import org.dspace.importer.external.metadatamapping.MetadatumDTO;
import org.dspace.importer.external.service.components.dto.PlainMetadataKeyValueItem;
import org.dspace.importer.external.service.components.dto.PlainMetadataSourceDto;
/**
* This class implements functionalities to handle common situation regarding plain metadata.
* In some scenario, like csv or tsv, the format don't allow lists.
@@ -33,7 +38,9 @@ public class EnhancedSimpleMetadataContributor extends SimpleMetadataContributor
private char delimiter = ',';
private char escape = '"';
private char quote = '"';
private char escape = '\\';
/**
* This method could be used to set the delimiter used during parse
@@ -51,11 +58,24 @@ public class EnhancedSimpleMetadataContributor extends SimpleMetadataContributor
}
/**
* Method to inject the escape character.
* This must be the ASCII integer
* related to the char.
* In example, 9 for tab, 44 for comma
* If no escape is set, double quote will be used
* This method could be used to get the quote char used in this class
*/
public char getQuote() {
return quote;
}
/**
* This method could be used to set the quote char used during parse
* If no quote char is set, " will be used
*/
public void setQuote(char quote) {
this.quote = quote;
}
/**
* Method to inject the escape character, usually the ". This must be the ASCII
* integer related to the char.
* In example, 9 for tab, 44 for comma If no escape is set, double quote will be used
*/
public void setEscape(char escape) {
this.escape = escape;
@@ -94,10 +114,12 @@ public class EnhancedSimpleMetadataContributor extends SimpleMetadataContributor
// For example, list of author must be: Author 1, author 2, author 3
// if author name contains comma, is important to escape its in
// this way: Author 1, \"Author 2, something\", Author 3
try (CSVReader csvReader = new CSVReader(new StringReader(value),
delimiter, escape);) {
CSVParser parser = new CSVParserBuilder().withSeparator(delimiter).withQuoteChar(quote).withEscapeChar(escape)
.build();
try ( Reader inputReader = new StringReader(value);
com.opencsv.CSVReader csvReader = new CSVReaderBuilder(inputReader).withCSVParser(parser).build()) {
rows = csvReader.readAll();
} catch (IOException e) {
} catch (IOException | CsvException e) {
//fallback, use the inpu as value
return new String[] { value };
}

View File

@@ -130,15 +130,18 @@ public class PubmedDateMetadatumContributor<T> implements MetadataContributor<T>
} catch (ParseException e) {
// Multiple dateformats can be configured, we don't want to print the entire stacktrace every
// time one of those formats fails.
log.info(
log.debug(
"Failed parsing " + dateString + " using the following format: " + dateFormat + ", check " +
"the configured dataformats in config/spring/api/pubmed-integration.xml");
}
j++;
}
if (dcDate != null) {
values.add(metadataFieldMapping.toDCValue(field, dcDate.toString()));
} else {
log.info(
"Failed parsing " + dateString + ", check " +
"the configured dataformats in config/spring/api/pubmed-integration.xml");
}
}
} catch (Exception e) {

View File

@@ -51,7 +51,8 @@ public class PubmedImportMetadataSourceServiceImpl extends AbstractImportMetadat
private String baseAddress;
private WebTarget pubmedWebTarget;
// it is protected so that subclass can mock it for testing
protected WebTarget pubmedWebTarget;
private List<String> supportedExtensions;

View File

@@ -11,6 +11,7 @@ import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.dspace.core.Utils;
import org.dspace.service.ClientInfoService;
import org.dspace.services.ConfigurationService;
import org.dspace.statistics.util.IPTable;
@@ -41,8 +42,7 @@ public class ClientInfoServiceImpl implements ClientInfoService {
@Autowired(required = true)
public ClientInfoServiceImpl(ConfigurationService configurationService) {
this.configurationService = configurationService;
this.trustedProxies = parseTrustedProxyRanges(
configurationService.getArrayProperty("proxies.trusted.ipranges"));
this.trustedProxies = parseTrustedProxyRanges();
}
@Override
@@ -62,9 +62,8 @@ public class ClientInfoServiceImpl implements ClientInfoService {
}
} else if (StringUtils.isNotBlank(xForwardedForHeaderValue)) {
log.warn(
"X-Forwarded-For header detected but useProxiesEnabled is not enabled. " +
"If your dspace is behind a proxy set it to true");
log.warn("X-Forwarded-For header sent from client, but useProxies is not enabled. " +
"To trust X-Forwarded-For headers, set useProxies=true.");
}
return ip;
@@ -74,55 +73,120 @@ public class ClientInfoServiceImpl implements ClientInfoService {
public boolean isUseProxiesEnabled() {
if (useProxiesEnabled == null) {
useProxiesEnabled = configurationService.getBooleanProperty("useProxies", true);
log.info("useProxies=" + useProxiesEnabled);
log.info("Proxies (useProxies) enabled? " + useProxiesEnabled);
}
return useProxiesEnabled;
}
private IPTable parseTrustedProxyRanges(String[] proxyProperty) {
if (ArrayUtils.isEmpty(proxyProperty)) {
return null;
} else {
//Load all supplied proxy IP ranges into the IP table
/**
* Parse / Determine trusted proxies based on configuration. "Trusted" proxies are the IP addresses from which we'll
* allow the X-FORWARDED-FOR header. We don't accept that header from any IP address, as the header could be used
* to spoof/fake your IP address.
* <P>
* If "proxies.trusted.include_ui_ip = true" (which is the default), then we lookup the IP address(es) associated
* with ${dspace.ui.url}, and append them to the list of trusted proxies. This is necessary to allow the Angular
* UI server-side rendering (SSR) to send us the X-FORWARDED-FOR header, which it usually uses to specify the
* original client IP address.
* <P>
* If "proxies.trusted.ipranges" configuration is specified, those IP addresses/ranges are also included in the
* list of trusted proxies.
* <P>
* Localhost (127.0.0.1) is ALWAYS included in the list of trusted proxies
*
* @return IPTable of trusted IP addresses/ranges, or null if none could be found.
*/
private IPTable parseTrustedProxyRanges() {
String localhostIP = "127.0.0.1";
IPTable ipTable = new IPTable();
// Get list of trusted proxy IP ranges
String[] trustedIpRanges = configurationService.getArrayProperty("proxies.trusted.ipranges");
// Always append localhost (127.0.0.1) to the list of trusted proxies, if not already included
if (!ArrayUtils.contains(trustedIpRanges, localhostIP)) {
trustedIpRanges = ArrayUtils.add(trustedIpRanges, localhostIP);
}
try {
for (String proxyRange : proxyProperty) {
ipTable.add(proxyRange);
// Load all IPs into our IP Table
for (String ipRange : trustedIpRanges) {
ipTable.add(ipRange);
}
} catch (IPTable.IPFormatException e) {
log.error("Property proxies.trusted.ipranges contains an invalid IP range", e);
ipTable = null;
log.error("Property 'proxies.trusted.ipranges' contains an invalid IP range", e);
}
// Is the UI IP address always trusted (default = true)
boolean uiIsTrustedProxy = configurationService.getBooleanProperty("proxies.trusted.include_ui_ip", true);
// As long as the UI is a trusted proxy, determine IP(s) of ${dspace.ui.url}
if (uiIsTrustedProxy) {
String uiUrl = configurationService.getProperty("dspace.ui.url");
// Get any IP address(es) associated with our UI
String[] uiIpAddresses = Utils.getIPAddresses(uiUrl);
if (ArrayUtils.isNotEmpty(uiIpAddresses)) {
try {
// Load all UI IPs into our IP Table
for (String ipRange : uiIpAddresses) {
ipTable.add(ipRange);
}
} catch (IPTable.IPFormatException e) {
log.error("IP address lookup for dspace.ui.url={} was invalid and could not be added to trusted" +
" proxies", uiUrl, e);
}
}
}
// If our IPTable is not empty, log the trusted proxies and return it
if (!ipTable.isEmpty()) {
log.info("Trusted proxies (configure via 'proxies.trusted.ipranges'): {}", ipTable.toSet().toString());
return ipTable;
} else {
return null;
}
}
/**
* Whether a request is from a trusted proxy or not. Only returns true if trusted proxies are specified
* and the ipAddress is contained in those proxies. False in all other cases
* @param ipAddress IP address to check for
* @return true if trusted, false otherwise
*/
private boolean isRequestFromTrustedProxy(String ipAddress) {
try {
return trustedProxies == null || trustedProxies.contains(ipAddress);
return trustedProxies != null && trustedProxies.contains(ipAddress);
} catch (IPTable.IPFormatException e) {
log.error("Request contains invalid remote address", e);
return false;
}
}
/**
* Get the first X-FORWARDED-FOR header value which does not match the IP or another proxy IP. This is the most
* likely client IP address when proxies are in use.
* <P>
* NOTE: This method does NOT validate the X-FORWARDED-FOR header value is accurate, so be aware this header
* could contain a spoofed value. Therefore, any code calling this method should verify the source is somehow
* trusted, e.g. by using isRequestFromTrustedProxy() or similar.
* @param remoteIp remote IP address
* @param xForwardedForValue X-FORWARDED-FOR header value passed by that address
* @return likely client IP address from X-FORWARDED-FOR header
*/
private String getXForwardedForIpValue(String remoteIp, String xForwardedForValue) {
String ip = null;
/* This header is a comma delimited list */
String headerValue = StringUtils.trimToEmpty(xForwardedForValue);
for (String xfip : headerValue.split(",")) {
xfip = xfip.trim();
/* proxy itself will sometime populate this header with the same value in
remote address. ordering in spec is vague, we'll just take the last
not equal to the proxy
*/
if (!StringUtils.equals(remoteIp, xfip) && StringUtils.isNotBlank(xfip)
// if we have trusted proxies, we'll assume that they are not the client IP
&& (trustedProxies == null || !isRequestFromTrustedProxy(xfip))) {
ip = xfip.trim();
&& !isRequestFromTrustedProxy(xfip)) {
ip = xfip;
}
}

View File

@@ -17,7 +17,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import au.com.bytecode.opencsv.CSVWriter;
import com.opencsv.CSVWriterBuilder;
import com.opencsv.ICSVWriter;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
@@ -232,7 +233,7 @@ public class Dataset {
public ByteArrayOutputStream exportAsCSV() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
CSVWriter ecsvp = new CSVWriter(new OutputStreamWriter(baos), ';');
ICSVWriter ecsvp = new CSVWriterBuilder(new OutputStreamWriter(baos)).withSeparator(';').build();
//Generate the item row
List<String> colLabels = getColLabels();
colLabels.add(0, "");

View File

@@ -37,11 +37,11 @@ import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import au.com.bytecode.opencsv.CSVReader;
import au.com.bytecode.opencsv.CSVWriter;
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.exception.GeoIp2Exception;
import com.maxmind.geoip2.model.CityResponse;
import com.opencsv.CSVReader;
import com.opencsv.CSVWriter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

View File

@@ -200,6 +200,13 @@ public class IPTable {
return set;
}
/**
* Return whether IPTable is empty (having no entries)
* @return true if empty, false otherwise
*/
public boolean isEmpty() {
return map.isEmpty();
}
/**
* Exception Class to deal with IPFormat errors.

View File

@@ -1,54 +0,0 @@
/**
* 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.extraction;
import java.util.List;
import gr.ekt.bte.dataloader.FileDataLoader;
import org.dspace.services.ConfigurationService;
/**
* Configuration bean to associate a BTE FileDataLoader with a specific list of format identified by the file
* extensions. See config/spring/api/metadata-extractor.xml
*
* @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it)
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
public class MetadataExtractor {
private List<String> extensions;
private FileDataLoader dataLoader;
private ConfigurationService configurationService;
public List<String> getExtensions() {
return extensions;
}
public void setExtensions(List<String> mime) {
this.extensions = mime;
}
public FileDataLoader getDataLoader() {
return dataLoader;
}
public void setDataLoader(FileDataLoader dataLoader) {
this.dataLoader = dataLoader;
}
public ConfigurationService getConfigurationService() {
return configurationService;
}
public void setConfigurationService(ConfigurationService configurationService) {
this.configurationService = configurationService;
}
}

View File

@@ -7,55 +7,37 @@
*/
package org.dspace.submit.listener;
import java.util.Map;
import java.util.Set;
import gr.ekt.bte.core.DataLoader;
import org.dspace.services.ConfigurationService;
import org.dspace.content.Item;
import org.dspace.core.Context;
import org.dspace.external.model.ExternalDataObject;
/**
* Configuration bean to map metadata to identifiers (i.e dc.identifier.doi -> doi, dc.identifier.isbn -> isbn) and
* alias to BTE Data Loader. See config/spring/api/step-processing.xml
* The interface to implement to support the ExtractMetadata enrichment step
*
* @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it)
* @author Andrea Bollini (andrea.bollini at 4science.it)
*
*/
public class MetadataListener {
public interface MetadataListener {
/**
* Return the list of metadata that should be monitored as change to them could
* allow the service to retrieve an ExternalDataObject to enrich the current
* item
*
* @return the list of metadata to monitor
*/
public Set<String> getMetadataToListen();
/**
* Metadata to identifier map
* Retrieve an ExternalDataObject to enrich the current item using the current
* metadata and the information about which listened metadata are changed
*
* @param context the DSpace Context Object
* @param item the item in its current status
* @param changedMetadata the list of listened metadata that are changed
* @return an ExternalDataObject that can be used to enrich the current item
*/
private Map<String, String> metadata;
private ConfigurationService configurationService;
/**
* Alias to data loader map
*/
private Map<String, DataLoader> dataloadersMap;
public ConfigurationService getConfigurationService() {
return configurationService;
}
public void setConfigurationService(ConfigurationService configurationService) {
this.configurationService = configurationService;
}
public Map<String, String> getMetadata() {
return metadata;
}
public void setMetadata(Map<String, String> metadata) {
this.metadata = metadata;
}
public Map<String, DataLoader> getDataloadersMap() {
return dataloadersMap;
}
public void setDataloadersMap(Map<String, DataLoader> dataloadersMap) {
this.dataloadersMap = dataloadersMap;
}
public ExternalDataObject getExternalDataObject(Context context, Item item, Set<String> changedMetadata);
}

View File

@@ -0,0 +1,99 @@
/**
* 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.listener;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
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.Context;
import org.dspace.external.model.ExternalDataObject;
import org.dspace.external.provider.ExternalDataProvider;
/**
* This is the basic implementation for the MetadataListener interface.
*
* It got the a map of metadata and related External Data Provider that can be
* used to retrieve further information using the updated metadata in the item
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*
*/
public class SimpleMetadataListener implements MetadataListener {
/**
* A map to link a specific metadata with an ExternalDataProvider
*/
private Map<String, List<ExternalDataProvider>> externalDataProvidersMap;
private ItemService itemService = ContentServiceFactory.getInstance().getItemService();
public Map<String, List<ExternalDataProvider>> getExternalDataProvidersMap() {
return externalDataProvidersMap;
}
public void setExternalDataProvidersMap(Map<String, List<ExternalDataProvider>> externalDataProvidersMap) {
this.externalDataProvidersMap = externalDataProvidersMap;
}
@Override
public Set<String> getMetadataToListen() {
return externalDataProvidersMap.keySet();
}
@Override
public ExternalDataObject getExternalDataObject(Context context, Item item, Set<String> changedMetadata) {
// we loop over the available provider and return the first found object
for (String m : changedMetadata) {
List<ExternalDataProvider> providers = externalDataProvidersMap.get(m);
for (ExternalDataProvider prov : providers) {
String id = generateExternalId(context, prov, item, changedMetadata, m);
if (StringUtils.isNotBlank(id)) {
Optional<ExternalDataObject> result = prov.getExternalDataObject(id);
if (result.isPresent()) {
return result.get();
}
}
}
}
return null;
}
/**
* This is the simpler implementation, it assumes that the value of the metadata
* listened by the DataProvider can be used directly as identifier. Subclass may
* extend it to add support for identifier normalization or combine multiple
* information to build the identifier
*
* @param context the DSpace Context Object
* @param prov the ExternalDataProvider that need to received an Id
* @param item the item
* @param changedMetadata the metadata that are recently changed
* @param m the changed metadata that lead to the selected
* ExternalDataProvider
* @return an Id if any that can be used to query the {@link ExternalDataProvider}
*/
protected String generateExternalId(Context context, ExternalDataProvider prov, Item item,
Set<String> changedMetadata, String m) {
List<MetadataValue> metadataByMetadataString = itemService.getMetadataByMetadataString(item, m);
// only suggest an identifier if there is exactly one value for the metadata. If
// there are more values it is highly probable that a lookup was already
// performed when the first value was added
if (metadataByMetadataString != null && metadataByMetadataString.size() == 1) {
return metadataByMetadataString.get(0).getValue();
}
return null;
}
}

View File

@@ -1,144 +0,0 @@
/**
* 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.lookup;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import gr.ekt.bte.core.DataLoadingSpec;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.RecordSet;
import gr.ekt.bte.core.Value;
import gr.ekt.bte.dataloader.FileDataLoader;
import gr.ekt.bte.exceptions.MalformedSourceException;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
/**
* Load metadata from CiNii formated file
*
* @author Keiji Suzuki
*/
public class CiNiiFileDataLoader extends FileDataLoader {
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(CiNiiFileDataLoader.class);
Map<String, String> fieldMap; // mapping between service fields and local
// intermediate fields
/**
* Empty constructor
*/
public CiNiiFileDataLoader() {
}
/**
* @param filename Name of file to load CiNii data from.
*/
public CiNiiFileDataLoader(String filename) {
super(filename);
}
/*
* {@see gr.ekt.bte.core.DataLoader#getRecords()}
*
* @throws MalformedSourceException
*/
@Override
public RecordSet getRecords() throws MalformedSourceException {
RecordSet recordSet = new RecordSet();
try {
InputStream inputStream = new FileInputStream(new File(filename));
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(true);
DocumentBuilder db = factory.newDocumentBuilder();
Document inDoc = db.parse(inputStream);
Element xmlRoot = inDoc.getDocumentElement();
// There is no element to represent an record, so we can not process
// multi records at once.
Record record = CiNiiUtils.convertCiNiiDomToRecord(xmlRoot);
if (record != null) {
recordSet.addRecord(convertFields(record));
}
} catch (FileNotFoundException e) {
log.error(e.getMessage(), e);
} catch (ParserConfigurationException e) {
log.error(e.getMessage(), e);
} catch (SAXException e) {
log.error(e.getMessage(), e);
} catch (IOException e) {
log.error(e.getMessage(), e);
}
return recordSet;
}
/*
* (non-Javadoc)
*
* @see
* gr.ekt.bte.core.DataLoader#getRecords(gr.ekt.bte.core.DataLoadingSpec)
*/
@Override
public RecordSet getRecords(DataLoadingSpec spec)
throws MalformedSourceException {
if (spec.getOffset() > 0) {
return new RecordSet();
}
return getRecords();
}
public Record convertFields(Record publication) {
for (String fieldName : fieldMap.keySet()) {
String md = null;
if (fieldMap != null) {
md = this.fieldMap.get(fieldName);
}
if (StringUtils.isBlank(md)) {
continue;
} else {
md = md.trim();
}
if (publication.isMutable()) {
List<Value> values = publication.getValues(fieldName);
publication.makeMutable().removeField(fieldName);
publication.makeMutable().addField(md, values);
}
}
return publication;
}
public void setFieldMap(Map<String, String> fieldMap) {
this.fieldMap = fieldMap;
}
}

View File

@@ -1,107 +0,0 @@
/**
* 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.lookup;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import gr.ekt.bte.core.Record;
import org.apache.http.HttpException;
import org.dspace.core.Context;
/**
* Load metadata from CiNii RDF API
*
* @author Keiji Suzuki
*/
public class CiNiiOnlineDataLoader extends NetworkSubmissionLookupDataLoader {
protected CiNiiService ciniiService = new CiNiiService();
protected boolean searchProvider = true;
/**
* Application id to use CiNii
*/
protected String appId = null;
/**
* max result number to return
*/
protected int maxResults = 10;
public void setCiNiiService(CiNiiService ciniiService) {
this.ciniiService = ciniiService;
}
@Override
public List<String> getSupportedIdentifiers() {
return Arrays.asList(new String[] {CINII});
}
public void setSearchProvider(boolean searchProvider) {
this.searchProvider = searchProvider;
}
@Override
public boolean isSearchProvider() {
return searchProvider;
}
@Override
public List<Record> getByIdentifier(Context context,
Map<String, Set<String>> keys) throws HttpException, IOException {
if (appId == null) {
throw new RuntimeException("No CiNii Application ID is specified!");
}
List<Record> results = new ArrayList<Record>();
if (keys != null) {
Set<String> ciniiids = keys.get(CINII);
if (ciniiids != null && ciniiids.size() > 0) {
for (String ciniiid : ciniiids) {
Record record = ciniiService.getByCiNiiID(ciniiid, getAppId());
if (record != null) {
results.add(convertFields(record));
}
}
}
}
return results;
}
@Override
public List<Record> search(Context context, String title, String author, int year)
throws HttpException, IOException {
if (appId == null) {
throw new RuntimeException("No CiNii Application ID is specified!");
}
return ciniiService.searchByTerm(title, author, year,
getMaxResults(), getAppId());
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public int getMaxResults() {
return maxResults;
}
public void setMaxResults(int maxResults) {
this.maxResults = maxResults;
}
}

View File

@@ -1,221 +0,0 @@
/**
* 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.lookup;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import gr.ekt.bte.core.Record;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.app.util.XMLUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* @author Keiji Suzuki
*/
public class CiNiiService {
/**
* log4j category
*/
private static final Logger log = LogManager.getLogger(CiNiiService.class);
protected int timeout = 1000;
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public Record getByCiNiiID(String id, String appId) throws HttpException,
IOException {
return search(id, appId);
}
public List<Record> searchByTerm(String title, String author, int year,
int maxResults, String appId)
throws HttpException, IOException {
List<Record> records = new ArrayList<>();
List<String> ids = getCiNiiIDs(title, author, year, maxResults, appId);
if (ids != null && ids.size() > 0) {
for (String id : ids) {
Record record = search(id, appId);
if (record != null) {
records.add(record);
}
}
}
return records;
}
/**
* Get metadata by searching CiNii RDF API with CiNii NAID
*
* @param id CiNii NAID to search by
* @param appId registered application identifier for the API
* @return record metadata
* @throws IOException A general class of exceptions produced by failed or interrupted I/O operations.
* @throws HttpException Represents a XML/HTTP fault and provides access to the HTTP status code.
*/
protected Record search(String id, String appId)
throws IOException, HttpException {
HttpGet method = null;
try ( CloseableHttpClient client = HttpClientBuilder.create().build(); ) {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(timeout)
.build();
method = new HttpGet("http://ci.nii.ac.jp/naid/" + id + ".rdf?appid=" + appId);
method.setConfig(requestConfig);
// Execute the method.
HttpResponse response = client.execute(method);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
if (statusCode == HttpStatus.SC_BAD_REQUEST) {
throw new RuntimeException("CiNii RDF is not valid");
} else {
throw new RuntimeException("CiNii RDF Http call failed: "
+ statusLine);
}
}
try {
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(true);
// disallow DTD parsing to ensure no XXE attacks can occur.
// See https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
DocumentBuilder db = factory.newDocumentBuilder();
Document inDoc = db.parse(response.getEntity().getContent());
Element xmlRoot = inDoc.getDocumentElement();
return CiNiiUtils.convertCiNiiDomToRecord(xmlRoot);
} catch (Exception e) {
throw new RuntimeException(
"CiNii RDF identifier is not valid or not exist");
}
} finally {
if (method != null) {
method.releaseConnection();
}
}
}
/**
* Get CiNii NAIDs by searching CiNii OpenURL API with title, author and year
*
* @param title record title
* @param author record author
* @param year record year
* @param maxResults maximum number of results returned
* @param appId registered application identifier for the API
* @return matching NAIDs
* @throws IOException A general class of exceptions produced by failed or interrupted I/O operations.
* @throws HttpException Represents a XML/HTTP fault and provides access to the HTTP status code.
*/
protected List<String> getCiNiiIDs(String title, String author, int year,
int maxResults, String appId)
throws IOException, HttpException {
// Need at least one query term
if (title == null && author == null && year == -1) {
return null;
}
HttpGet method = null;
List<String> ids = new ArrayList<>();
try ( CloseableHttpClient client = HttpClientBuilder.create().build(); ) {
StringBuilder query = new StringBuilder();
query.append("format=rss&appid=").append(appId)
.append("&count=").append(maxResults);
if (title != null) {
query.append("&title=").append(URLEncoder.encode(title, "UTF-8"));
}
if (author != null) {
query.append("&author=").append(URLEncoder.encode(author, "UTF-8"));
}
if (year != -1) {
query.append("&year_from=").append(String.valueOf(year));
query.append("&year_to=").append(String.valueOf(year));
}
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(timeout)
.build();
method = new HttpGet("http://ci.nii.ac.jp/opensearch/search?" + query.toString());
method.setConfig(requestConfig);
// Execute the method.
HttpResponse response = client.execute(method);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
if (statusCode == HttpStatus.SC_BAD_REQUEST) {
throw new RuntimeException("CiNii OpenSearch query is not valid");
} else {
throw new RuntimeException("CiNii OpenSearch call failed: "
+ statusLine);
}
}
try {
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(true);
// disallow DTD parsing to ensure no XXE attacks can occur.
// See https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
DocumentBuilder db = factory.newDocumentBuilder();
Document inDoc = db.parse(response.getEntity().getContent());
Element xmlRoot = inDoc.getDocumentElement();
List<Element> items = XMLUtils.getElementList(xmlRoot, "item");
int url_len = "http://ci.nii.ac.jp/naid/".length();
for (Element item : items) {
String about = item.getAttribute("rdf:about");
if (about.length() > url_len) {
ids.add(about.substring(url_len));
}
}
return ids;
} catch (Exception e) {
throw new RuntimeException(
"CiNii OpenSearch results is not valid or not exist");
}
} finally {
if (method != null) {
method.releaseConnection();
}
}
}
}

View File

@@ -1,225 +0,0 @@
/**
* 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.lookup;
import java.util.LinkedList;
import java.util.List;
import gr.ekt.bte.core.MutableRecord;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.StringValue;
import gr.ekt.bte.core.Value;
import org.apache.commons.lang3.StringUtils;
import org.dspace.app.util.XMLUtils;
import org.dspace.submit.util.SubmissionLookupPublication;
import org.w3c.dom.Element;
/**
* @author Keiji Suzuki
*/
public class CiNiiUtils {
/**
* Default constructor
*/
private CiNiiUtils() { }
public static Record convertCiNiiDomToRecord(Element xmlRoot) {
MutableRecord record = new SubmissionLookupPublication("");
List<Element> list = XMLUtils.getElementList(xmlRoot, "rdf:Description");
// Valid CiNii record should have three rdf:Description elements
if (list.size() < 3) {
return record;
}
Element description_ja = list.get(0); // Japanese description
Element description_en = list.get(1); // English description
// Element description3 = list.get(2); // Authors information: NOT USE here
String language = XMLUtils.getElementValue(description_ja, "dc:language");
language = language != null ? language.toLowerCase() : "ja";
record.addValue("language", new StringValue(language));
if ("ja".equals(language) || "jpn".equals(language)) {
String title = XMLUtils.getElementValue(description_ja, "dc:title");
if (title != null) {
record.addValue("title", new StringValue(title));
}
String titleAlternative = XMLUtils.getElementValue(description_en, "dc:title");
if (titleAlternative != null) {
record.addValue("titleAlternative", new StringValue(titleAlternative));
}
List<Value> authors = getAuthors(description_ja);
if (authors.size() > 0) {
record.addField("authors", authors);
}
List<Value> authorAlternative = getAuthors(description_en);
if (authorAlternative.size() > 0) {
record.addField("auhtorAlternative", authorAlternative);
}
String publisher = XMLUtils.getElementValue(description_ja, "dc:publisher");
if (publisher != null) {
record.addValue("publisher", new StringValue(publisher));
}
} else {
String title = XMLUtils.getElementValue(description_en, "dc:title");
if (title != null) {
record.addValue("title", new StringValue(title));
}
String titleAlternative = XMLUtils.getElementValue(description_ja, "dc:title");
if (titleAlternative != null) {
record.addValue("titleAlternative", new StringValue(titleAlternative));
}
List<Value> authors = getAuthors(description_en);
if (authors.size() > 0) {
record.addField("authors", authors);
}
List<Value> authorAlternative = getAuthors(description_ja);
if (authorAlternative.size() > 0) {
record.addField("authorAlternative", authorAlternative);
}
String publisher = XMLUtils.getElementValue(description_en, "dc:publisher");
if (publisher != null) {
record.addValue("publisher", new StringValue(publisher));
}
}
String abstract_ja = XMLUtils.getElementValue(description_ja, "dc:description");
String abstract_en = XMLUtils.getElementValue(description_en, "dc:description");
if (abstract_ja != null && abstract_en != null) {
List<Value> description = new LinkedList<Value>();
description.add(new StringValue(abstract_ja));
description.add(new StringValue(abstract_en));
record.addField("description", description);
} else if (abstract_ja != null) {
record.addValue("description", new StringValue(abstract_ja));
} else if (abstract_en != null) {
record.addValue("description", new StringValue(abstract_en));
}
List<Value> subjects = getSubjects(description_ja);
subjects.addAll(getSubjects(description_en));
if (subjects.size() > 0) {
record.addField("subjects", subjects);
}
String journal_j = XMLUtils.getElementValue(description_ja, "prism:publicationName");
String journal_e = XMLUtils.getElementValue(description_en, "prism:publicationName");
if (journal_j != null && journal_e != null) {
record.addValue("journal", new StringValue(journal_j + " = " + journal_e));
} else if (journal_j != null) {
record.addValue("journal", new StringValue(journal_j));
} else if (journal_e != null) {
record.addValue("journal", new StringValue(journal_e));
}
String volume = XMLUtils.getElementValue(description_ja, "prism:volume");
if (volume != null) {
record.addValue("volume", new StringValue(volume));
}
String issue = XMLUtils.getElementValue(description_ja, "prism:number");
if (issue != null) {
record.addValue("issue", new StringValue(issue));
}
String spage = XMLUtils.getElementValue(description_ja, "prism:startingPage");
if (spage != null) {
record.addValue("spage", new StringValue(spage));
}
String epage = XMLUtils.getElementValue(description_ja, "prism:endingPage");
if (epage != null) {
record.addValue("epage", new StringValue(epage));
}
String pages = XMLUtils.getElementValue(description_ja, "prism:pageRange");
if (pages != null && spage == null) {
int pos = pages.indexOf("-");
if (pos > -1) {
spage = pages.substring(0, pos);
epage = pages.substring(pos + 1, pages.length() - pos);
if (!epage.equals("") && spage.length() > epage.length()) {
epage = spage.substring(0, spage.length() - epage.length()) + epage;
}
} else {
spage = pages;
epage = "";
}
record.addValue("spage", new StringValue(spage));
if (!epage.equals("") && epage == null) {
record.addValue("epage", new StringValue(epage));
}
}
String issn = XMLUtils.getElementValue(description_ja, "prism:issn");
if (issn != null) {
record.addValue("issn", new StringValue(issn));
}
String issued = XMLUtils.getElementValue(description_ja, "prism:publicationDate");
if (issued != null) {
record.addValue("issued", new StringValue(issued));
}
String ncid = XMLUtils.getElementValue(description_ja, "cinii:ncid");
if (ncid != null) {
record.addValue("ncid", new StringValue(ncid));
}
String naid = XMLUtils.getElementValue(description_ja, "cinii:naid");
if (naid != null) {
record.addValue("naid", new StringValue(naid));
}
return record;
}
private static List<Value> getAuthors(Element element) {
List<Value> authors = new LinkedList<Value>();
List<String> authorList = XMLUtils.getElementValueList(element, "dc:creator");
if (authorList != null && authorList.size() > 0) {
for (String author : authorList) {
int pos = author.indexOf(" ");
if (pos > -1) {
author = author.substring(0, pos) + "," + author.substring(pos);
}
authors.add(new StringValue(author));
}
}
return authors;
}
private static List<Value> getSubjects(Element element) {
List<Value> subjects = new LinkedList<Value>();
List<Element> topicList = XMLUtils.getElementList(element, "foaf:topic");
String attrValue = null;
for (Element topic : topicList) {
attrValue = topic.getAttribute("dc:title");
if (StringUtils.isNotBlank(attrValue)) {
subjects.add(new StringValue(attrValue.trim()));
}
}
return subjects;
}
}

View File

@@ -1,142 +0,0 @@
/**
* 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.lookup;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import gr.ekt.bte.core.DataLoadingSpec;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.RecordSet;
import gr.ekt.bte.core.Value;
import gr.ekt.bte.dataloader.FileDataLoader;
import gr.ekt.bte.exceptions.MalformedSourceException;
import org.apache.commons.lang3.StringUtils;
import org.dspace.app.util.XMLUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class CrossRefFileDataLoader extends FileDataLoader {
Map<String, String> fieldMap; // mapping between service fields and local
// intermediate fields
/**
*
*/
public CrossRefFileDataLoader() {
}
/**
* @param filename Name of file to load ArXiv data from.
*/
public CrossRefFileDataLoader(String filename) {
super(filename);
}
/*
* (non-Javadoc)
*
* @see gr.ekt.bte.core.DataLoader#getRecords()
*/
@Override
public RecordSet getRecords() throws MalformedSourceException {
RecordSet recordSet = new RecordSet();
try {
InputStream inputStream = new FileInputStream(new File(filename));
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(true);
DocumentBuilder db = factory.newDocumentBuilder();
Document inDoc = db.parse(inputStream);
Element xmlRoot = inDoc.getDocumentElement();
Element queryResult = XMLUtils.getSingleElement(xmlRoot, "query_result");
Element body = XMLUtils.getSingleElement(queryResult, "body");
Element dataRoot = XMLUtils.getSingleElement(body, "query");
Record record = CrossRefUtils.convertCrossRefDomToRecord(dataRoot);
recordSet.addRecord(convertFields(record));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return recordSet;
}
/*
* (non-Javadoc)
*
* @see
* gr.ekt.bte.core.DataLoader#getRecords(gr.ekt.bte.core.DataLoadingSpec)
*/
@Override
public RecordSet getRecords(DataLoadingSpec spec)
throws MalformedSourceException {
if (spec.getOffset() > 0) {
return new RecordSet();
}
return getRecords();
}
public Record convertFields(Record publication) {
for (String fieldName : fieldMap.keySet()) {
String md = null;
if (fieldMap != null) {
md = this.fieldMap.get(fieldName);
}
if (StringUtils.isBlank(md)) {
continue;
} else {
md = md.trim();
}
if (publication.isMutable()) {
List<Value> values = publication.getValues(fieldName);
publication.makeMutable().removeField(fieldName);
publication.makeMutable().addField(md, values);
}
}
return publication;
}
public void setFieldMap(Map<String, String> fieldMap) {
this.fieldMap = fieldMap;
}
}

View File

@@ -1,112 +0,0 @@
/**
* 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.lookup;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.ParserConfigurationException;
import gr.ekt.bte.core.Record;
import org.apache.http.HttpException;
import org.dspace.core.Context;
import org.jdom.JDOMException;
import org.xml.sax.SAXException;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class CrossRefOnlineDataLoader extends NetworkSubmissionLookupDataLoader {
protected CrossRefService crossrefService = new CrossRefService();
protected boolean searchProvider = true;
protected String apiKey = null;
protected int maxResults = 10;
public void setSearchProvider(boolean searchProvider) {
this.searchProvider = searchProvider;
}
public void setCrossrefService(CrossRefService crossrefService) {
this.crossrefService = crossrefService;
}
@Override
public List<String> getSupportedIdentifiers() {
return Arrays.asList(new String[] {DOI});
}
@Override
public List<Record> getByIdentifier(Context context,
Map<String, Set<String>> keys) throws HttpException, IOException {
if (keys != null && keys.containsKey(DOI)) {
Set<String> dois = keys.get(DOI);
List<Record> items = null;
List<Record> results = new ArrayList<Record>();
if (getApiKey() == null) {
throw new RuntimeException("No CrossRef API key is specified!");
}
try {
items = crossrefService.search(context, dois, getApiKey());
} catch (JDOMException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (ParserConfigurationException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (SAXException e) {
throw new RuntimeException(e.getMessage(), e);
}
for (Record record : items) {
results.add(convertFields(record));
}
return results;
}
return null;
}
@Override
public List<Record> search(Context context, String title, String author,
int year) throws HttpException, IOException {
if (getApiKey() == null) {
throw new RuntimeException("No CrossRef API key is specified!");
}
List<Record> items = crossrefService.search(context, title, author,
year, getMaxResults(), getApiKey());
return items;
}
@Override
public boolean isSearchProvider() {
return searchProvider;
}
public String getApiKey() {
return apiKey;
}
public void setApiKey(String apiKey) {
this.apiKey = apiKey;
}
public int getMaxResults() {
return maxResults;
}
public void setMaxResults(int maxResults) {
this.maxResults = maxResults;
}
}

View File

@@ -1,204 +0,0 @@
/**
* 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.lookup;
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import gr.ekt.bte.core.Record;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.logging.log4j.Logger;
import org.dspace.app.util.XMLUtils;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.jdom.JDOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class CrossRefService {
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(CrossRefService.class);
protected int timeout = 1000;
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public List<Record> search(Context context, Set<String> dois, String apiKey)
throws HttpException, IOException, JDOMException,
ParserConfigurationException, SAXException {
List<Record> results = new ArrayList<>();
if (dois != null && dois.size() > 0) {
for (String record : dois) {
try {
HttpGet method = null;
try {
HttpClient client = HttpClientBuilder.create().build();
try {
URIBuilder uriBuilder = new URIBuilder(
"http://www.crossref.org/openurl/");
uriBuilder.addParameter("pid", apiKey);
uriBuilder.addParameter("noredirect", "true");
uriBuilder.addParameter("id", record);
method = new HttpGet(uriBuilder.build());
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(timeout)
.build();
method.setConfig(requestConfig);
} catch (URISyntaxException ex) {
throw new HttpException("Request not sent", ex);
}
// Execute the method.
HttpResponse response = client.execute(method);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
throw new RuntimeException("Http call failed: "
+ statusLine);
}
Record crossitem;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(true);
// disallow DTD parsing to ensure no XXE attacks can occur.
// See https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
DocumentBuilder db = factory
.newDocumentBuilder();
Document inDoc = db.parse(response.getEntity().getContent());
Element xmlRoot = inDoc.getDocumentElement();
Element queryResult = XMLUtils.getSingleElement(xmlRoot, "query_result");
Element body = XMLUtils.getSingleElement(queryResult, "body");
Element dataRoot = XMLUtils.getSingleElement(body, "query");
crossitem = CrossRefUtils
.convertCrossRefDomToRecord(dataRoot);
results.add(crossitem);
} catch (Exception e) {
log.warn(LogManager
.getHeader(
context,
"retrieveRecordDOI",
record
+ " DOI is not valid or not exist: "
+ e.getMessage()));
}
} finally {
if (method != null) {
method.releaseConnection();
}
}
} catch (RuntimeException rt) {
log.error(rt.getMessage(), rt);
}
}
}
return results;
}
public List<Record> search(Context context, String title, String authors,
int year, int count, String apiKey) throws IOException, HttpException {
HttpGet method = null;
try ( CloseableHttpClient client = HttpClientBuilder.create().build(); ) {
URIBuilder uriBuilder = new URIBuilder("http://search.labs.crossref.org/dois");
StringBuilder sb = new StringBuilder();
if (StringUtils.isNotBlank(title)) {
sb.append(title);
}
sb.append(" ");
if (StringUtils.isNotBlank(authors)) {
sb.append(authors);
}
String q = sb.toString().trim();
uriBuilder.addParameter("q", q);
uriBuilder.addParameter("year", year != -1 ? String.valueOf(year) : "");
uriBuilder.addParameter("rows", count != -1 ? String.valueOf(count) : "");
method = new HttpGet(uriBuilder.build());
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(timeout)
.build();
method.setConfig(requestConfig);
// Execute the method.
HttpResponse response = client.execute(method);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
throw new RuntimeException("Http call failed:: "
+ statusLine);
}
Gson gson = new Gson();
Type listType = new TypeToken<ArrayList<Map>>() {
}.getType();
List<Map> json = gson.fromJson(
IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8),
listType);
Set<String> dois = new HashSet<>();
for (Map r : json) {
dois.add(SubmissionLookupUtils.normalizeDOI((String) r
.get("doi")));
}
method.releaseConnection();
return search(context, dois, apiKey);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
if (method != null) {
method.releaseConnection();
}
}
}
}

View File

@@ -1,216 +0,0 @@
/**
* 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.lookup;
import java.util.LinkedList;
import java.util.List;
import gr.ekt.bte.core.MutableRecord;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.StringValue;
import gr.ekt.bte.core.Value;
import org.apache.commons.lang3.StringUtils;
import org.dspace.app.util.XMLUtils;
import org.dspace.submit.util.SubmissionLookupPublication;
import org.w3c.dom.Element;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class CrossRefUtils {
/**
* Default constructor
*/
private CrossRefUtils() { }
public static Record convertCrossRefDomToRecord(Element dataRoot) {
MutableRecord record = new SubmissionLookupPublication("");
String status = dataRoot.getAttribute("status");
if (!"resolved".equals(status)) {
String msg = XMLUtils.getElementValue(dataRoot, "msg");
String exMsg = status + " - " + msg;
throw new RuntimeException(exMsg);
}
String doi = XMLUtils.getElementValue(dataRoot, "doi");
if (doi != null) {
record.addValue("doi", new StringValue(doi));
}
String itemType = doi != null ? XMLUtils.getElementAttribute(dataRoot,
"doi", "type") : "unspecified";
if (itemType != null) {
record.addValue("doiType", new StringValue(itemType));
}
List<Element> identifier = XMLUtils.getElementList(dataRoot, "issn");
for (Element ident : identifier) {
if ("print".equalsIgnoreCase(ident.getAttribute("type"))
|| StringUtils.isNotBlank(ident.getAttribute("type"))) {
String issn = ident.getTextContent().trim();
if (issn != null) {
record.addValue("printISSN", new StringValue(issn));
}
} else {
String eissn = ident.getTextContent().trim();
if (eissn != null) {
record.addValue("electronicISSN", new StringValue(eissn));
}
}
}
List<Element> identifierisbn = XMLUtils.getElementList(dataRoot, "isbn");
for (Element ident : identifierisbn) {
if ("print".equalsIgnoreCase(ident.getAttribute("type"))
|| StringUtils.isNotBlank(ident.getAttribute("type"))) {
String issn = ident.getTextContent().trim();
if (issn != null) {
record.addValue("printISBN", new StringValue(issn));
}
} else {
String eissn = ident.getTextContent().trim();
if (eissn != null) {
record.addValue("electronicISBN", new StringValue(eissn));
}
}
}
String editionNumber = XMLUtils.getElementValue(dataRoot,
"editionNumber");
if (editionNumber != null) {
record.addValue("editionNumber", new StringValue(editionNumber));
}
String volume = XMLUtils.getElementValue(dataRoot, "volume");
if (volume != null) {
record.addValue("volume", new StringValue(volume));
}
String issue = XMLUtils.getElementValue(dataRoot, "issue");
if (issue != null) {
record.addValue("issue", new StringValue(issue));
}
String year = XMLUtils.getElementValue(dataRoot, "year");
if (year != null) {
record.addValue("year", new StringValue(year));
}
String firstPage = XMLUtils.getElementValue(dataRoot, "first_page");
if (firstPage != null) {
record.addValue("firstPage", new StringValue(firstPage));
}
String lastPage = XMLUtils.getElementValue(dataRoot, "last_page");
if (lastPage != null) {
record.addValue("lastPage", new StringValue(lastPage));
}
String seriesTitle = XMLUtils.getElementValue(dataRoot, "series_title");
if (seriesTitle != null) {
record.addValue("seriesTitle", new StringValue(seriesTitle));
}
String journalTitle = XMLUtils.getElementValue(dataRoot,
"journal_title");
if (journalTitle != null) {
record.addValue("journalTitle", new StringValue(journalTitle));
}
String volumeTitle = XMLUtils.getElementValue(dataRoot, "volume_title");
if (volumeTitle != null) {
record.addValue("volumeTitle", new StringValue(volumeTitle));
}
String articleTitle = XMLUtils.getElementValue(dataRoot,
"article_title");
if (articleTitle != null) {
record.addValue("articleTitle", new StringValue(articleTitle));
}
String publicationType = XMLUtils.getElementValue(dataRoot,
"pubblication_type");
if (publicationType != null) {
record.addValue("publicationType", new StringValue(publicationType));
}
List<String[]> authors = new LinkedList<String[]>();
List<String[]> editors = new LinkedList<String[]>();
List<String[]> translators = new LinkedList<String[]>();
List<String[]> chairs = new LinkedList<String[]>();
List<Element> contributors = XMLUtils.getElementList(dataRoot,
"contributors");
List<Element> contributor = null;
if (contributors != null && contributors.size() > 0) {
contributor = XMLUtils.getElementList(contributors.get(0),
"contributor");
for (Element contrib : contributor) {
String givenName = XMLUtils.getElementValue(contrib,
"given_name");
String surname = XMLUtils.getElementValue(contrib, "surname");
if ("editor".equalsIgnoreCase(contrib
.getAttribute("contributor_role"))) {
editors.add(new String[] {givenName, surname});
} else if ("chair".equalsIgnoreCase(contrib
.getAttribute("contributor_role"))) {
chairs.add(new String[] {givenName, surname});
} else if ("translator".equalsIgnoreCase(contrib
.getAttribute("contributor_role"))) {
translators.add(new String[] {givenName, surname});
} else {
authors.add(new String[] {givenName, surname});
}
}
}
if (authors.size() > 0) {
List<Value> values = new LinkedList<Value>();
for (String[] sArray : authors) {
values.add(new StringValue(sArray[1] + ", " + sArray[0]));
}
record.addField("authors", values);
}
if (editors.size() > 0) {
List<Value> values = new LinkedList<Value>();
for (String[] sArray : editors) {
values.add(new StringValue(sArray[1] + ", " + sArray[0]));
}
record.addField("editors", values);
}
if (translators.size() > 0) {
List<Value> values = new LinkedList<Value>();
for (String[] sArray : translators) {
values.add(new StringValue(sArray[1] + ", " + sArray[0]));
}
record.addField("translators", values);
}
if (chairs.size() > 0) {
List<Value> values = new LinkedList<Value>();
for (String[] sArray : chairs) {
values.add(new StringValue(sArray[1] + ", " + sArray[0]));
}
record.addField("chairs", values);
}
return record;
}
}

View File

@@ -1,364 +0,0 @@
/**
* 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.lookup;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import gr.ekt.bte.core.DataOutputSpec;
import gr.ekt.bte.core.OutputGenerator;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.RecordSet;
import gr.ekt.bte.core.Value;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.app.util.DCInput;
import org.dspace.app.util.DCInputSet;
import org.dspace.app.util.DCInputsReader;
import org.dspace.app.util.DCInputsReaderException;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection;
import org.dspace.content.Item;
import org.dspace.content.MetadataField;
import org.dspace.content.MetadataSchema;
import org.dspace.content.WorkspaceItem;
import org.dspace.content.service.ItemService;
import org.dspace.content.service.MetadataFieldService;
import org.dspace.content.service.MetadataSchemaService;
import org.dspace.content.service.WorkspaceItemService;
import org.dspace.core.Context;
import org.dspace.submit.util.ItemSubmissionLookupDTO;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class DSpaceWorkspaceItemOutputGenerator implements OutputGenerator {
private static Logger log = LogManager.getLogger(DSpaceWorkspaceItemOutputGenerator.class);
protected Context context;
protected String formName;
protected List<WorkspaceItem> witems;
protected ItemSubmissionLookupDTO dto;
protected Collection collection;
Map<String, String> outputMap;
protected List<String> extraMetadataToKeep;
@Autowired(required = true)
protected ItemService itemService;
@Autowired(required = true)
protected MetadataFieldService metadataFieldService;
@Autowired(required = true)
protected MetadataSchemaService metadataSchemaService;
@Autowired(required = true)
protected WorkspaceItemService workspaceItemService;
@Override
public List<String> generateOutput(RecordSet recordSet) {
log.info("BTE OutputGenerator started. Records to output: "
+ recordSet.getRecords().size());
// Printing debug message
String totalString = "";
for (Record record : recordSet.getRecords()) {
totalString += SubmissionLookupUtils.getPrintableString(record)
+ "\n";
}
log.debug("Records to output:\n" + totalString);
witems = new ArrayList<WorkspaceItem>();
for (Record rec : recordSet.getRecords()) {
try {
WorkspaceItem wi = workspaceItemService.create(context, collection,
true);
merge(formName, wi.getItem(), rec);
witems.add(wi);
} catch (AuthorizeException e) {
log.error(e.getMessage(), e);
} catch (SQLException e) {
log.error(e.getMessage(), e);
}
}
return new ArrayList<String>();
}
@Override
public List<String> generateOutput(RecordSet records, DataOutputSpec spec) {
return generateOutput(records);
}
public List<WorkspaceItem> getWitems() {
return witems;
}
public void setContext(Context context) {
this.context = context;
}
public void setFormName(String formName) {
this.formName = formName;
}
public void setDto(ItemSubmissionLookupDTO dto) {
this.dto = dto;
}
public void setOutputMap(Map<String, String> outputMap) {
// Reverse the key-value pairs
this.outputMap = new HashMap<String, String>();
for (String key : outputMap.keySet()) {
this.outputMap.put(outputMap.get(key), key);
}
}
public void setCollection(Collection collection) {
this.collection = collection;
}
public void setExtraMetadataToKeep(List<String> extraMetadataToKeep) {
this.extraMetadataToKeep = extraMetadataToKeep;
}
// Methods
public void merge(String formName, Item item, Record record) {
try {
Record itemLookup = record;
Set<String> addedMetadata = new HashSet<String>();
for (String field : itemLookup.getFields()) {
String metadata = getMetadata(formName, itemLookup, field);
if (StringUtils.isBlank(metadata)) {
continue;
}
if (itemService.getMetadataByMetadataString(item, metadata).size() == 0
|| addedMetadata.contains(metadata)) {
addedMetadata.add(metadata);
String[] md = splitMetadata(metadata);
if (isValidMetadata(formName, md)) { // if in extra metadata or in the spefific form
List<Value> values = itemLookup.getValues(field);
if (values != null && values.size() > 0) {
if (isRepeatableMetadata(formName, md)) { // if metadata is repeatable in form
for (Value value : values) {
String[] splitValue = splitValue(value
.getAsString());
if (splitValue[3] != null) {
itemService.addMetadata(context, item, md[0], md[1], md[2],
md[3], splitValue[0],
splitValue[1],
Integer.parseInt(splitValue[2]));
} else {
itemService.addMetadata(context, item, md[0], md[1], md[2],
md[3], value.getAsString());
}
}
} else {
String value = values.iterator().next()
.getAsString();
String[] splitValue = splitValue(value);
if (splitValue[3] != null) {
itemService.addMetadata(context, item, md[0], md[1], md[2], md[3],
splitValue[0], splitValue[1],
Integer.parseInt(splitValue[2]));
} else {
itemService.addMetadata(context, item, md[0], md[1], md[2], md[3],
value);
}
}
}
}
}
}
itemService.update(context, item);
} catch (SQLException e) {
log.error(e.getMessage(), e);
} catch (AuthorizeException e) {
log.error(e.getMessage(), e);
}
}
protected String getMetadata(String formName, Record itemLookup, String name) {
String type = SubmissionLookupService.getType(itemLookup);
String md = outputMap.get(type + "." + name);
if (StringUtils.isBlank(md)) {
md = outputMap.get(formName + "." + name);
if (StringUtils.isBlank(md)) {
md = outputMap.get(name);
}
}
// KSTA:ToDo: Make this a modifier
if (md != null && md.contains("|")) {
String[] cond = md.trim().split("\\|");
for (int idx = 1; idx < cond.length; idx++) {
boolean temp = itemLookup.getFields().contains(cond[idx]);
if (temp) {
return null;
}
}
return cond[0];
}
return md;
}
protected String[] splitMetadata(String metadata) {
String[] mdSplit = new String[3];
if (StringUtils.isNotBlank(metadata)) {
String tmpSplit[] = metadata.split("\\.");
if (tmpSplit.length == 4) {
mdSplit = new String[4];
mdSplit[0] = tmpSplit[0];
mdSplit[1] = tmpSplit[1];
mdSplit[2] = tmpSplit[2];
mdSplit[3] = tmpSplit[3];
} else if (tmpSplit.length == 3) {
mdSplit = new String[4];
mdSplit[0] = tmpSplit[0];
mdSplit[1] = tmpSplit[1];
mdSplit[2] = tmpSplit[2];
mdSplit[3] = null;
} else if (tmpSplit.length == 2) {
mdSplit = new String[4];
mdSplit[0] = tmpSplit[0];
mdSplit[1] = tmpSplit[1];
mdSplit[2] = null;
mdSplit[3] = null;
}
}
return mdSplit;
}
protected boolean isValidMetadata(String formName, String[] md) {
try {
if (extraMetadataToKeep != null
&& extraMetadataToKeep.contains(StringUtils.join(
Arrays.copyOfRange(md, 0, 3), "."))) {
return true;
}
return getDCInput(formName, md[0], md[1], md[2]) != null;
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return false;
}
protected DCInput getDCInput(String formName, String schema, String element,
String qualifier) throws DCInputsReaderException {
List<DCInputSet> dcinputsets = new DCInputsReader().getInputsBySubmissionName(formName);
for (DCInputSet dcinputset : dcinputsets) {
for (DCInput[] dcrow : dcinputset.getFields()) {
for (DCInput dcinput : dcrow) {
if (dcinput.getSchema().equals(schema)
&& dcinput.getElement().equals(element)
&& ((dcinput.getQualifier() != null && dcinput
.getQualifier().equals(qualifier))
|| (dcinput.getQualifier() == null && qualifier == null))) {
return dcinput;
}
}
}
}
return null;
}
protected boolean isRepeatableMetadata(String formName, String[] md) {
try {
DCInput dcinput = getDCInput(formName, md[0], md[1], md[2]);
if (dcinput != null) {
return dcinput.isRepeatable();
}
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
protected String[] splitValue(String value) {
String[] splitted = value
.split(SubmissionLookupService.SEPARATOR_VALUE_REGEX);
String[] result = new String[6];
result[0] = splitted[0];
result[2] = "-1";
result[3] = "-1";
result[4] = "-1";
if (splitted.length > 1) {
result[5] = "splitted";
if (StringUtils.isNotBlank(splitted[1])) {
result[1] = splitted[1];
}
if (splitted.length > 2) {
result[2] = String.valueOf(Integer.parseInt(splitted[2]));
if (splitted.length > 3) {
result[3] = String.valueOf(Integer.parseInt(splitted[3]));
if (splitted.length > 4) {
result[4] = String.valueOf(Integer
.parseInt(splitted[4]));
}
}
}
}
return result;
}
protected void makeSureMetadataExist(Context context, String schema,
String element, String qualifier) {
try {
context.turnOffAuthorisationSystem();
boolean create = false;
MetadataSchema mdschema = metadataSchemaService.find(context, schema);
MetadataField mdfield = null;
if (mdschema == null) {
mdschema = metadataSchemaService.create(context, schema,
SubmissionLookupService.SL_NAMESPACE_PREFIX + schema
);
create = true;
} else {
mdfield = metadataFieldService.findByElement(context,
mdschema, element, qualifier);
}
if (mdfield == null) {
metadataFieldService.create(context, mdschema, element, qualifier,
"Campo utilizzato per la cache del provider submission-lookup: "
+ schema);
create = true;
}
if (create) {
context.complete();
}
context.restoreAuthSystemState();
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -1,64 +0,0 @@
/**
* 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.lookup;
import java.util.List;
import java.util.Map;
import gr.ekt.bte.core.AbstractModifier;
import gr.ekt.bte.core.MutableRecord;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.Value;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class FieldMergeModifier extends AbstractModifier {
protected Map<String, List<String>> mergeFieldMap;
public FieldMergeModifier() {
super("FieldMergeModifier");
}
@Override
public Record modify(MutableRecord rec) {
if (mergeFieldMap != null) {
for (String target_field : mergeFieldMap.keySet()) {
List<String> source_fields = mergeFieldMap.get(target_field);
for (String source_field : source_fields) {
List<Value> values = rec.getValues(source_field);
if (values != null && values.size() > 0) {
for (Value value : values) {
rec.addValue(target_field, value);
}
}
// rec.removeField(source_field);
}
}
}
return rec;
}
/**
* @return the merge_field_map
*/
public Map<String, List<String>> getMergeFieldMap() {
return mergeFieldMap;
}
/**
* @param merge_field_map the merge_field_map to set
*/
public void setMergeFieldMap(Map<String, List<String>> merge_field_map) {
this.mergeFieldMap = merge_field_map;
}
}

View File

@@ -1,78 +0,0 @@
/**
* 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.lookup;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import gr.ekt.bte.core.AbstractModifier;
import gr.ekt.bte.core.MutableRecord;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.StringValue;
import gr.ekt.bte.core.Value;
import org.springframework.beans.factory.InitializingBean;
/**
* Modifier to covert ISO 639-2 alpha-3 code to ISO 639-1 alpha-2 code
*
* @author Keiji Suzuki
*/
public class LanguageCodeModifier extends AbstractModifier implements InitializingBean {
protected static Map<String, String> lang3to2 = null;
@Override
public void afterPropertiesSet() throws Exception {
lang3to2 = new HashMap<String, String>();
for (Locale locale : Locale.getAvailableLocales()) {
try {
lang3to2.put(locale.getISO3Language(), locale.getLanguage());
} catch (MissingResourceException e) {
continue;
}
}
}
public LanguageCodeModifier() {
super("LanguageCodeModifier");
}
@Override
public Record modify(MutableRecord rec) {
List<Value> old_values = rec.getValues("language");
if (old_values == null || old_values.size() == 0) {
return rec;
}
List<Value> new_values = new ArrayList<Value>();
for (Value value : old_values) {
String lang3 = value.getAsString();
String lang2 = lang3.length() == 3 ? getLang2(lang3) : lang3;
new_values.add(new StringValue(lang2));
}
rec.updateField("language", new_values);
return rec;
}
/**
* Covert ISO 639-2 alpha-3 code to ISO 639-1 alpha-2 code
*
* @param lang3 ISO 639-1 alpha-3 language code
* @return String ISO 639-1 alpha-2 language code ("other" if code is not alpha-2)
*/
protected String getLang2(String lang3) {
return lang3to2.containsKey(lang3) ? lang3to2.get(lang3) : "other";
}
}

View File

@@ -1,40 +0,0 @@
/**
* 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.lookup;
import java.util.ArrayList;
import java.util.List;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class LookupProvidersCheck {
private List<String> providersOk = new ArrayList<String>();
private List<String> providersErr = new ArrayList<String>();
public List<String> getProvidersOk() {
return providersOk;
}
public void setProvidersOk(List<String> providersOk) {
this.providersOk = providersOk;
}
public List<String> getProvidersErr() {
return providersErr;
}
public void setProvidersErr(List<String> providersErr) {
this.providersErr = providersErr;
}
}

View File

@@ -1,181 +0,0 @@
/**
* 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.lookup;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import gr.ekt.bte.core.AbstractModifier;
import gr.ekt.bte.core.MutableRecord;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.StringValue;
import gr.ekt.bte.core.Value;
import org.apache.commons.lang3.StringUtils;
import org.dspace.services.ConfigurationService;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class MapConverterModifier extends AbstractModifier {
protected String mappingFile; //The properties absolute filename
protected String converterNameFile; //The properties filename
protected ConfigurationService configurationService;
protected Map<String, String> mapping;
protected String defaultValue = "";
protected List<String> fieldKeys;
protected Map<String, String> regexConfig = new HashMap<String, String>();
public final String REGEX_PREFIX = "regex.";
public void init() {
this.mappingFile = configurationService.getProperty(
"dspace.dir") + File.separator + "config" + File.separator + "crosswalks" + File.separator +
converterNameFile;
this.mapping = new HashMap<String, String>();
FileInputStream fis = null;
try {
fis = new FileInputStream(new File(mappingFile));
Properties mapConfig = new Properties();
mapConfig.load(fis);
fis.close();
for (Object key : mapConfig.keySet()) {
String keyS = (String) key;
if (keyS.startsWith(REGEX_PREFIX)) {
String regex = keyS.substring(REGEX_PREFIX.length());
String regReplace = mapping.get(keyS);
if (regReplace == null) {
regReplace = "";
} else if (regReplace.equalsIgnoreCase("@ident@")) {
regReplace = "$0";
}
regexConfig.put(regex, regReplace);
}
if (mapConfig.getProperty(keyS) != null) {
mapping.put(keyS, mapConfig.getProperty(keyS));
} else {
mapping.put(keyS, "");
}
}
} catch (Exception e) {
throw new IllegalArgumentException("", e);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException ioe) {
// ...
}
}
}
for (String keyS : mapping.keySet()) {
if (keyS.startsWith(REGEX_PREFIX)) {
String regex = keyS.substring(REGEX_PREFIX.length());
String regReplace = mapping.get(keyS);
if (regReplace == null) {
regReplace = "";
} else if (regReplace.equalsIgnoreCase("@ident@")) {
regReplace = "$0";
}
regexConfig.put(regex, regReplace);
}
}
}
/**
* @param name Name of file to load ArXiv data from.
*/
public MapConverterModifier(String name) {
super(name);
}
/*
* (non-Javadoc)
*
* @see
* gr.ekt.bte.core.AbstractModifier#modify(gr.ekt.bte.core.MutableRecord)
*/
@Override
public Record modify(MutableRecord record) {
if (mapping != null && fieldKeys != null) {
for (String key : fieldKeys) {
List<Value> values = record.getValues(key);
if (values == null) {
continue;
}
List<Value> newValues = new ArrayList<Value>();
for (Value value : values) {
String stringValue = value.getAsString();
String tmp = "";
if (mapping.containsKey(stringValue)) {
tmp = mapping.get(stringValue);
} else {
tmp = defaultValue;
for (String regex : regexConfig.keySet()) {
if (stringValue != null
&& stringValue.matches(regex)) {
tmp = stringValue.replaceAll(regex,
regexConfig.get(regex));
}
}
}
if ("@@ident@@".equals(tmp)) {
newValues.add(new StringValue(stringValue));
} else if (StringUtils.isNotBlank(tmp)) {
newValues.add(new StringValue(tmp));
} else {
newValues.add(new StringValue(stringValue));
}
}
record.updateField(key, newValues);
}
}
return record;
}
public void setFieldKeys(List<String> fieldKeys) {
this.fieldKeys = fieldKeys;
}
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
public void setConverterNameFile(String converterNameFile) {
this.converterNameFile = converterNameFile;
}
public void setConfigurationService(ConfigurationService configurationService) {
this.configurationService = configurationService;
}
}

View File

@@ -1,291 +0,0 @@
/**
* 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.lookup;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import gr.ekt.bte.core.DataLoader;
import gr.ekt.bte.core.DataLoadingSpec;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.RecordSet;
import gr.ekt.bte.core.StringValue;
import gr.ekt.bte.dataloader.FileDataLoader;
import gr.ekt.bte.exceptions.MalformedSourceException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.core.Context;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class MultipleSubmissionLookupDataLoader implements DataLoader {
private static Logger log = LogManager.getLogger(MultipleSubmissionLookupDataLoader.class);
protected final String NOT_FOUND_DOI = "NOT-FOUND-DOI";
Map<String, DataLoader> dataloadersMap;
// Depending on these values, the multiple data loader loads data from the
// appropriate providers
Map<String, Set<String>> identifiers = null; // Searching by identifiers
// (DOI ...)
Map<String, Set<String>> searchTerms = null; // Searching by author, title,
// date
String filename = null; // Uploading file
String type = null; // the type of the upload file (bibtex, etc.)
/*
* (non-Javadoc)
*
* @see gr.ekt.bte.core.DataLoader#getRecords()
*/
@Override
public RecordSet getRecords() throws MalformedSourceException {
RecordSet recordSet = new RecordSet();
// KSTA:ToDo: Support timeout (problematic) providers
// List<String> timeoutProviders = new ArrayList<String>();
for (String providerName : filterProviders().keySet()) {
DataLoader provider = dataloadersMap.get(providerName);
RecordSet subRecordSet = provider.getRecords();
recordSet.addAll(subRecordSet);
// Add in each record the provider name... a new provider doesn't
// need to know about it!
for (Record record : subRecordSet.getRecords()) {
if (record.isMutable()) {
record.makeMutable().addValue(
SubmissionLookupService.PROVIDER_NAME_FIELD,
new StringValue(providerName));
}
}
}
// Question: Do we want that in case of file data loader?
// for each publication in the record set, if it has a DOI, try to find
// extra pubs from the other providers
if (searchTerms != null
|| (identifiers != null && !identifiers
.containsKey(SubmissionLookupDataLoader.DOI))) { // Extend
Map<String, Set<String>> provider2foundDOIs = new HashMap<String, Set<String>>();
List<String> foundDOIs = new ArrayList<String>();
for (Record publication : recordSet.getRecords()) {
String providerName = SubmissionLookupUtils.getFirstValue(
publication,
SubmissionLookupService.PROVIDER_NAME_FIELD);
String doi = null;
if (publication.getValues(SubmissionLookupDataLoader.DOI) != null
&& publication
.getValues(SubmissionLookupDataLoader.DOI)
.size() > 0) {
doi = publication.getValues(SubmissionLookupDataLoader.DOI)
.iterator().next().getAsString();
}
if (doi == null) {
doi = NOT_FOUND_DOI;
} else {
doi = SubmissionLookupUtils.normalizeDOI(doi);
if (!foundDOIs.contains(doi)) {
foundDOIs.add(doi);
}
Set<String> tmp = provider2foundDOIs.get(providerName);
if (tmp == null) {
tmp = new HashSet<String>();
provider2foundDOIs.put(providerName, tmp);
}
tmp.add(doi);
}
}
for (String providerName : dataloadersMap.keySet()) {
DataLoader genProvider = dataloadersMap.get(providerName);
if (!(genProvider instanceof SubmissionLookupDataLoader)) {
continue;
}
SubmissionLookupDataLoader provider = (SubmissionLookupDataLoader) genProvider;
// Provider must support DOI
if (!provider.getSupportedIdentifiers().contains(
SubmissionLookupDataLoader.DOI)) {
continue;
}
// if (evictProviders != null
// && evictProviders.contains(provider.getShortName())) {
// continue;
// }
Set<String> doiToSearch = new HashSet<String>();
Set<String> alreadyFoundDOIs = provider2foundDOIs
.get(providerName);
for (String doi : foundDOIs) {
if (alreadyFoundDOIs == null
|| !alreadyFoundDOIs.contains(doi)) {
doiToSearch.add(doi);
}
}
List<Record> pPublications = null;
Context context = null;
try {
if (doiToSearch.size() > 0) {
context = new Context();
pPublications = provider.getByDOIs(context, doiToSearch);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
if (context != null && context.isValid()) {
context.abort();
}
}
if (pPublications != null) {
for (Record rec : pPublications) {
recordSet.addRecord(rec);
if (rec.isMutable()) {
rec.makeMutable().addValue(
SubmissionLookupService.PROVIDER_NAME_FIELD,
new StringValue(providerName));
}
}
}
}
}
log.info("BTE DataLoader finished. Items loaded: "
+ recordSet.getRecords().size());
// Printing debug message
String totalString = "";
for (Record record : recordSet.getRecords()) {
totalString += SubmissionLookupUtils.getPrintableString(record)
+ "\n";
}
log.debug("Records loaded:\n" + totalString);
return recordSet;
}
/*
* (non-Javadoc)
*
* @see
* gr.ekt.bte.core.DataLoader#getRecords(gr.ekt.bte.core.DataLoadingSpec)
*/
@Override
public RecordSet getRecords(DataLoadingSpec loadingSpec)
throws MalformedSourceException {
// Identify the end of loading
if (loadingSpec.getOffset() > 0) {
return new RecordSet();
}
return getRecords();
}
public Map<String, DataLoader> getProvidersMap() {
return dataloadersMap;
}
public void setDataloadersMap(Map<String, DataLoader> providersMap) {
this.dataloadersMap = providersMap;
}
public void setIdentifiers(Map<String, Set<String>> identifiers) {
this.identifiers = identifiers;
this.filename = null;
this.searchTerms = null;
if (dataloadersMap != null) {
for (String providerName : dataloadersMap.keySet()) {
DataLoader provider = dataloadersMap.get(providerName);
if (provider instanceof NetworkSubmissionLookupDataLoader) {
((NetworkSubmissionLookupDataLoader) provider)
.setIdentifiers(identifiers);
}
}
}
}
public void setSearchTerms(Map<String, Set<String>> searchTerms) {
this.searchTerms = searchTerms;
this.identifiers = null;
this.filename = null;
if (dataloadersMap != null) {
for (String providerName : dataloadersMap.keySet()) {
DataLoader provider = dataloadersMap.get(providerName);
if (provider instanceof NetworkSubmissionLookupDataLoader) {
((NetworkSubmissionLookupDataLoader) provider)
.setSearchTerms(searchTerms);
}
}
}
}
public void setFile(String filename, String type) {
this.filename = filename;
this.type = type;
this.identifiers = null;
this.searchTerms = null;
if (dataloadersMap != null) {
for (String providerName : dataloadersMap.keySet()) {
DataLoader provider = dataloadersMap.get(providerName);
if (provider instanceof FileDataLoader) {
((FileDataLoader) provider).setFilename(filename);
}
}
}
}
public Map<String, DataLoader> filterProviders() {
Map<String, DataLoader> result = new HashMap<String, DataLoader>();
for (String providerName : dataloadersMap.keySet()) {
DataLoader dataLoader = dataloadersMap.get(providerName);
if (searchTerms != null && identifiers == null && filename == null) {
if (dataLoader instanceof SubmissionLookupDataLoader &&
((SubmissionLookupDataLoader) dataLoader).isSearchProvider()) {
result.put(providerName, dataLoader);
}
} else if (searchTerms == null && identifiers != null && filename == null) {
if (dataLoader instanceof SubmissionLookupDataLoader) {
result.put(providerName, dataLoader);
}
} else if (searchTerms == null && identifiers == null
&& filename != null) {
if (dataLoader instanceof FileDataLoader) {
// add only the one that we are interested in
if (providerName.endsWith(type)) {
result.put(providerName, dataLoader);
}
}
}
}
return result;
}
}

View File

@@ -1,150 +0,0 @@
/**
* 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.lookup;
import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import gr.ekt.bte.core.DataLoadingSpec;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.RecordSet;
import gr.ekt.bte.core.Value;
import gr.ekt.bte.exceptions.MalformedSourceException;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpException;
import org.dspace.core.Context;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public abstract class NetworkSubmissionLookupDataLoader implements
SubmissionLookupDataLoader {
Map<String, Set<String>> identifiers; // Searching by identifiers (DOI ...)
Map<String, Set<String>> searchTerms; // Searching by author, title, date
Map<String, String> fieldMap; // mapping between service fields and local
// intermediate fields
String providerName;
@Override
public List<Record> getByDOIs(Context context, Set<String> doiToSearch)
throws HttpException, IOException {
Map<String, Set<String>> keys = new HashMap<String, Set<String>>();
keys.put(DOI, doiToSearch);
return getByIdentifier(context, keys);
}
// BTE Data Loader interface methods
@Override
public RecordSet getRecords() throws MalformedSourceException {
RecordSet recordSet = new RecordSet();
List<Record> results = null;
try {
if (getIdentifiers() != null) { // Search by identifiers
results = getByIdentifier(null, getIdentifiers());
} else {
String title = getSearchTerms().get("title") != null ? getSearchTerms()
.get("title").iterator().next()
: null;
String authors = getSearchTerms().get("authors") != null ? getSearchTerms()
.get("authors").iterator().next()
: null;
String year = getSearchTerms().get("year") != null ? getSearchTerms()
.get("year").iterator().next()
: String.valueOf(Calendar.getInstance().get(Calendar.YEAR));
int yearInt = Integer.parseInt(year);
results = search(null, title, authors, yearInt);
}
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (results != null) {
for (Record record : results) {
recordSet.addRecord(record);
}
}
return recordSet;
}
@Override
public RecordSet getRecords(DataLoadingSpec arg0)
throws MalformedSourceException {
return getRecords();
}
public Map<String, Set<String>> getIdentifiers() {
return identifiers;
}
public void setIdentifiers(Map<String, Set<String>> identifiers) {
this.identifiers = identifiers;
}
public Map<String, Set<String>> getSearchTerms() {
return searchTerms;
}
public void setSearchTerms(Map<String, Set<String>> searchTerms) {
this.searchTerms = searchTerms;
}
public Map<String, String> getFieldMap() {
return fieldMap;
}
public void setFieldMap(Map<String, String> fieldMap) {
this.fieldMap = fieldMap;
}
public void setProviderName(String providerName) {
this.providerName = providerName;
}
public Record convertFields(Record publication) {
for (String fieldName : fieldMap.keySet()) {
String md = null;
if (fieldMap != null) {
md = this.fieldMap.get(fieldName);
}
if (StringUtils.isBlank(md)) {
continue;
} else {
md = md.trim();
}
if (publication.isMutable()) {
List<Value> values = publication.getValues(fieldName);
publication.makeMutable().removeField(fieldName);
publication.makeMutable().addField(md, values);
}
}
return publication;
}
}

View File

@@ -1,75 +0,0 @@
/**
* 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.lookup;
import java.util.ArrayList;
import java.util.List;
import gr.ekt.bte.core.AbstractModifier;
import gr.ekt.bte.core.MutableRecord;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.StringValue;
import gr.ekt.bte.core.Value;
import org.apache.commons.lang3.StringUtils;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class RemoveLastDotModifier extends AbstractModifier {
List<String> fieldKeys;
/**
* @param name modifier name
*/
public RemoveLastDotModifier(String name) {
super(name);
}
/*
* (non-Javadoc)
*
* @see
* gr.ekt.bte.core.AbstractModifier#modify(gr.ekt.bte.core.MutableRecord)
*/
@Override
public Record modify(MutableRecord record) {
if (fieldKeys != null) {
for (String key : fieldKeys) {
List<Value> values = record.getValues(key);
List<Value> newValues = new ArrayList<Value>();
if (values != null) {
for (Value value : values) {
String valueString = value.getAsString();
if (StringUtils.isNotBlank(valueString)
&& valueString.endsWith(".")) {
newValues.add(new StringValue(valueString
.substring(0, valueString.length() - 1)));
} else {
newValues.add(new StringValue(valueString));
}
}
record.updateField(key, newValues);
}
}
}
return record;
}
public void setFieldKeys(List<String> fieldKeys) {
this.fieldKeys = fieldKeys;
}
}

View File

@@ -1,103 +0,0 @@
/**
* 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.lookup;
import java.util.List;
import gr.ekt.bte.core.DataLoader;
import gr.ekt.bte.core.DataLoadingSpec;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.RecordSet;
import gr.ekt.bte.exceptions.MalformedSourceException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.submit.util.ItemSubmissionLookupDTO;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class SubmissionItemDataLoader implements DataLoader {
protected List<ItemSubmissionLookupDTO> dtoList;
List<DataLoader> providers;
private static Logger log = LogManager.getLogger(SubmissionItemDataLoader.class);
public SubmissionItemDataLoader() {
dtoList = null;
providers = null;
}
@Override
public RecordSet getRecords() throws MalformedSourceException {
if (dtoList == null) {
throw new MalformedSourceException("dtoList not initialized");
}
RecordSet ret = new RecordSet();
for (ItemSubmissionLookupDTO dto : dtoList) {
Record rec = dto.getTotalPublication(providers);
ret.addRecord(rec);
}
log.info("BTE DataLoader finished. Items loaded: "
+ ret.getRecords().size());
// Printing debug message
String totalString = "";
for (Record record : ret.getRecords()) {
totalString += SubmissionLookupUtils.getPrintableString(record)
+ "\n";
}
log.debug("Records loaded:\n" + totalString);
return ret;
}
@Override
public RecordSet getRecords(DataLoadingSpec spec)
throws MalformedSourceException {
if (spec.getOffset() > 0) {
return new RecordSet();
}
return getRecords();
}
/**
* @return the dtoList
*/
public List<ItemSubmissionLookupDTO> getDtoList() {
return dtoList;
}
/**
* @param dtoList the dtoList to set
*/
public void setDtoList(List<ItemSubmissionLookupDTO> dtoList) {
this.dtoList = dtoList;
}
/**
* @return the providers
*/
public List<DataLoader> getProviders() {
return providers;
}
/**
* @param providers the providers to set
*/
public void setProviders(List<DataLoader> providers) {
this.providers = providers;
}
}

View File

@@ -1,55 +0,0 @@
/**
* 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.lookup;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import gr.ekt.bte.core.DataLoader;
import gr.ekt.bte.core.Record;
import org.apache.http.HttpException;
import org.dspace.core.Context;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public interface SubmissionLookupDataLoader extends DataLoader {
public final static String DOI = "doi";
public final static String PUBMED = "pubmed";
public final static String ARXIV = "arxiv";
public final static String REPEC = "repec";
public final static String SCOPUSEID = "scopuseid";
public final static String CINII = "cinii";
public final static String TYPE = "type";
List<String> getSupportedIdentifiers();
boolean isSearchProvider();
List<Record> search(Context context, String title, String author, int year)
throws HttpException, IOException;
List<Record> getByIdentifier(Context context, Map<String, Set<String>> keys)
throws HttpException, IOException;
List<Record> getByDOIs(Context context, Set<String> doiToSearch)
throws HttpException, IOException;
}

View File

@@ -1,91 +0,0 @@
/**
* 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.lookup;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import gr.ekt.bte.core.DataOutputSpec;
import gr.ekt.bte.core.OutputGenerator;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.RecordSet;
import gr.ekt.bte.core.Value;
import org.dspace.submit.util.ItemSubmissionLookupDTO;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class SubmissionLookupOutputGenerator implements OutputGenerator {
protected List<ItemSubmissionLookupDTO> dtoList;
protected final String DOI_FIELD = "doi";
protected final String NOT_FOUND_DOI = "NOT-FOUND-DOI";
public SubmissionLookupOutputGenerator() {
}
@Override
public List<String> generateOutput(RecordSet records) {
dtoList = new ArrayList<ItemSubmissionLookupDTO>();
Map<String, List<Record>> record_sets = new HashMap<String, List<Record>>();
int counter = 0;
for (Record rec : records) {
String current_doi = NOT_FOUND_DOI;
List<Value> values = rec.getValues(DOI_FIELD);
if (values != null && values.size() > 0) {
current_doi = values.get(0).getAsString();
} else {
current_doi = NOT_FOUND_DOI + "_" + counter;
}
if (record_sets.keySet().contains(current_doi)) {
record_sets.get(current_doi).add(rec);
} else {
ArrayList<Record> publication = new ArrayList<Record>();
publication.add(rec);
record_sets.put(current_doi, publication);
}
counter++;
}
for (Map.Entry<String, List<Record>> entry : record_sets.entrySet()) {
ItemSubmissionLookupDTO dto = new ItemSubmissionLookupDTO(
entry.getValue());
dtoList.add(dto);
}
return new ArrayList<String>();
}
@Override
public List<String> generateOutput(RecordSet records, DataOutputSpec spec) {
return generateOutput(records);
}
/**
* @return the items
*/
public List<ItemSubmissionLookupDTO> getDtoList() {
return dtoList;
}
/**
* @param items the items to set
*/
public void setDtoList(List<ItemSubmissionLookupDTO> items) {
this.dtoList = items;
}
}

View File

@@ -1,194 +0,0 @@
/**
* 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.lookup;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import gr.ekt.bte.core.DataLoader;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.TransformationEngine;
import gr.ekt.bte.dataloader.FileDataLoader;
import org.apache.logging.log4j.Logger;
import org.dspace.submit.util.SubmissionLookupDTO;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class SubmissionLookupService {
public static final String CFG_MODULE = "submission-lookup";
public static final String SL_NAMESPACE_PREFIX = "http://www.dspace.org/sl/";
public static final String MANUAL_USER_INPUT = "manual";
public static final String PROVIDER_NAME_FIELD = "provider_name_field";
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(SubmissionLookupService.class);
public static final String SEPARATOR_VALUE = "#######";
public static final String SEPARATOR_VALUE_REGEX = SEPARATOR_VALUE;
protected List<DataLoader> providers;
protected Map<String, List<String>> idents2provs;
protected List<String> searchProviders;
protected List<String> fileProviders;
protected TransformationEngine phase1TransformationEngine;
protected TransformationEngine phase2TransformationEngine;
protected List<String> detailFields = null;
public void setPhase2TransformationEngine(
TransformationEngine phase2TransformationEngine) {
this.phase2TransformationEngine = phase2TransformationEngine;
}
public void setPhase1TransformationEngine(
TransformationEngine phase1TransformationEngine) {
this.phase1TransformationEngine = phase1TransformationEngine;
MultipleSubmissionLookupDataLoader dataLoader = (MultipleSubmissionLookupDataLoader) phase1TransformationEngine
.getDataLoader();
this.idents2provs = new HashMap<String, List<String>>();
this.searchProviders = new ArrayList<String>();
this.fileProviders = new ArrayList<String>();
if (providers == null) {
this.providers = new ArrayList<DataLoader>();
for (String providerName : dataLoader.getProvidersMap().keySet()) {
DataLoader p = dataLoader.getProvidersMap().get(providerName);
this.providers.add(p);
// Do not do that for file providers
if (p instanceof FileDataLoader) {
this.fileProviders.add(providerName);
} else if (p instanceof NetworkSubmissionLookupDataLoader) {
NetworkSubmissionLookupDataLoader p2 = (NetworkSubmissionLookupDataLoader) p;
p2.setProviderName(providerName);
if (p2.isSearchProvider()) {
searchProviders.add(providerName);
}
List<String> suppIdentifiers = p2.getSupportedIdentifiers();
if (suppIdentifiers != null) {
for (String ident : suppIdentifiers) {
List<String> tmp = idents2provs.get(ident);
if (tmp == null) {
tmp = new ArrayList<String>();
idents2provs.put(ident, tmp);
}
tmp.add(providerName);
}
}
}
}
}
}
public TransformationEngine getPhase1TransformationEngine() {
return phase1TransformationEngine;
}
public TransformationEngine getPhase2TransformationEngine() {
return phase2TransformationEngine;
}
public List<String> getIdentifiers() {
List<String> allSupportedIdentifiers = new ArrayList<String>();
MultipleSubmissionLookupDataLoader dataLoader = (MultipleSubmissionLookupDataLoader) phase1TransformationEngine
.getDataLoader();
for (String providerName : dataLoader.getProvidersMap().keySet()) {
DataLoader provider = dataLoader.getProvidersMap()
.get(providerName);
if (provider instanceof SubmissionLookupDataLoader) {
for (String identifier : ((SubmissionLookupDataLoader) provider)
.getSupportedIdentifiers()) {
if (!allSupportedIdentifiers.contains(identifier)) {
allSupportedIdentifiers.add(identifier);
}
}
}
}
return allSupportedIdentifiers;
}
public Map<String, List<String>> getProvidersIdentifiersMap() {
return idents2provs;
}
public SubmissionLookupDTO getSubmissionLookupDTO(
HttpServletRequest request, String uuidSubmission) {
SubmissionLookupDTO dto = (SubmissionLookupDTO) request.getSession()
.getAttribute("submission_lookup_" + uuidSubmission);
if (dto == null) {
dto = new SubmissionLookupDTO();
storeDTOs(request, uuidSubmission, dto);
}
return dto;
}
public void invalidateDTOs(HttpServletRequest request, String uuidSubmission) {
request.getSession().removeAttribute(
"submission_lookup_" + uuidSubmission);
}
public void storeDTOs(HttpServletRequest request, String uuidSubmission,
SubmissionLookupDTO dto) {
request.getSession().setAttribute(
"submission_lookup_" + uuidSubmission, dto);
}
public List<String> getSearchProviders() {
return searchProviders;
}
public List<DataLoader> getProviders() {
return providers;
}
public static String getProviderName(Record rec) {
return SubmissionLookupUtils.getFirstValue(rec,
SubmissionLookupService.PROVIDER_NAME_FIELD);
}
public static String getType(Record rec) {
return SubmissionLookupUtils.getFirstValue(rec,
SubmissionLookupDataLoader.TYPE);
}
public List<String> getFileProviders() {
return this.fileProviders;
}
public List<String> getDetailFields() {
return detailFields;
}
public void setDetailFields(List<String> detailFields) {
this.detailFields = detailFields;
}
}

View File

@@ -1,156 +0,0 @@
/**
* 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.lookup;
import java.io.File;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.Value;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.content.Item;
import org.dspace.content.MetadataSchema;
import org.dspace.content.MetadataValue;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.ItemService;
import org.dspace.content.service.MetadataSchemaService;
import org.dspace.core.Context;
import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class SubmissionLookupUtils {
private static final Logger log = LogManager.getLogger(SubmissionLookupUtils.class);
/**
* Default constructor
*/
private SubmissionLookupUtils() { }
private static final ConfigurationService configurationService
= DSpaceServicesFactory.getInstance().getConfigurationService();
/**
* Location of config file
*/
private static final String configFilePath = configurationService
.getProperty("dspace.dir")
+ File.separator
+ "config"
+ File.separator + "crosswalks" + File.separator;
// Patter to extract the converter name if any
private static final Pattern converterPattern = Pattern.compile(".*\\((.*)\\)");
protected static final MetadataSchemaService metadataSchemaService =
ContentServiceFactory.getInstance().getMetadataSchemaService();
protected static final ItemService itemService = ContentServiceFactory.getInstance().getItemService();
public static LookupProvidersCheck getProvidersCheck(Context context,
Item item, String dcSchema, String dcElement,
String dcQualifier) {
try {
LookupProvidersCheck check = new LookupProvidersCheck();
List<MetadataSchema> schemas = metadataSchemaService.findAll(context);
List<MetadataValue> values = itemService.getMetadata(item, dcSchema, dcElement,
dcQualifier, Item.ANY);
for (MetadataSchema schema : schemas) {
boolean error = false;
if (schema.getNamespace().startsWith(
SubmissionLookupService.SL_NAMESPACE_PREFIX)) {
List<MetadataValue> slCache = itemService.getMetadata(item, schema.getName(),
dcElement, dcQualifier, Item.ANY);
if (slCache.isEmpty()) {
continue;
}
if (slCache.size() != values.size()) {
error = true;
} else {
for (int idx = 0; idx < values.size(); idx++) {
MetadataValue v = values.get(idx);
MetadataValue sl = slCache.get(idx);
// FIXME gestire authority e possibilita' multiple:
// match non sicuri, affiliation, etc.
if (!v.getValue().equals(sl.getValue())) {
error = true;
break;
}
}
}
if (error) {
check.getProvidersErr().add(schema.getName());
} else {
check.getProvidersOk().add(schema.getName());
}
}
}
return check;
} catch (SQLException e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e.getMessage(), e);
}
}
public static String normalizeDOI(String doi) {
if (doi != null) {
return doi.trim().replaceAll("^http://dx.doi.org/", "")
.replaceAll("^doi:", "");
}
return null;
}
public static String getFirstValue(Record rec, String field) {
List<Value> values = rec.getValues(field);
String value = null;
if (values != null && values.size() > 0) {
value = values.get(0).getAsString();
}
return value;
}
public static List<String> getValues(Record rec, String field) {
List<String> result = new ArrayList<>();
List<Value> values = rec.getValues(field);
if (values != null && values.size() > 0) {
for (Value value : values) {
result.add(value.getAsString());
}
}
return result;
}
public static String getPrintableString(Record record) {
StringBuilder result = new StringBuilder();
result.append("\nPublication {\n");
for (String field : record.getFields()) {
result.append("--").append(field).append(":\n");
List<Value> values = record.getValues(field);
for (Value value : values) {
result.append("\t").append(value.getAsString()).append("\n");
}
}
result.append("}\n");
return result.toString();
}
}

View File

@@ -1,97 +0,0 @@
/**
* 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.lookup;
import java.util.ArrayList;
import java.util.List;
import gr.ekt.bte.core.AbstractModifier;
import gr.ekt.bte.core.MutableRecord;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.StringValue;
import gr.ekt.bte.core.Value;
import org.apache.commons.lang3.StringUtils;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class ValueConcatenationModifier extends AbstractModifier {
private String field;
private String separator = ",";
private boolean whitespaceAfter = true;
public ValueConcatenationModifier() {
super("ValueConcatenationModifier");
}
@Override
public Record modify(MutableRecord rec) {
List<Value> values = rec.getValues(field);
if (values != null) {
List<String> converted_values = new ArrayList<String>();
for (Value val : values) {
converted_values.add(val.getAsString());
}
List<Value> final_value = new ArrayList<Value>();
String v = StringUtils.join(converted_values.iterator(), separator
+ (whitespaceAfter ? " " : ""));
final_value.add(new StringValue(v));
rec.updateField(field, final_value);
}
return rec;
}
/**
* @return the field
*/
public String getField() {
return field;
}
/**
* @param field the field to set
*/
public void setField(String field) {
this.field = field;
}
/**
* @return the separator
*/
public String getSeparator() {
return separator;
}
/**
* @param separator the separator to set
*/
public void setSeparator(String separator) {
this.separator = separator;
}
/**
* @return the whiteSpaceAfter
*/
public boolean isWhitespaceAfter() {
return whitespaceAfter;
}
/**
* @param whiteSpaceAfter the whiteSpaceAfter to set
*/
public void setWhitespaceAfter(boolean whiteSpaceAfter) {
this.whitespaceAfter = whiteSpaceAfter;
}
}

View File

@@ -1,34 +0,0 @@
/**
* 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.logging.log4j.Logger;
import org.dspace.content.InProgressSubmission;
import org.dspace.core.Context;
import org.dspace.submit.AbstractProcessingStep;
public class AccessStep extends AbstractProcessingStep {
/**
* log4j logger
*/
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(AccessStep.class);
@Override
public void doPreProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
@Override
public void doPostProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
}

View File

@@ -1,38 +0,0 @@
/**
* 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.logging.log4j.Logger;
import org.dspace.content.InProgressSubmission;
import org.dspace.core.Context;
import org.dspace.license.factory.LicenseServiceFactory;
import org.dspace.license.service.CreativeCommonsService;
import org.dspace.submit.AbstractProcessingStep;
public class CCLicenseStep extends AbstractProcessingStep {
/**
* log4j logger
*/
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(CCLicenseStep.class);
protected final CreativeCommonsService creativeCommonsService = LicenseServiceFactory.getInstance()
.getCreativeCommonsService();
@Override
public void doPreProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
@Override
public void doPostProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
}

View File

@@ -1,32 +0,0 @@
/**
* 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.logging.log4j.Logger;
import org.dspace.content.InProgressSubmission;
import org.dspace.core.Context;
import org.dspace.submit.AbstractProcessingStep;
public class CompleteStep extends AbstractProcessingStep {
/**
* log4j logger
*/
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(CompleteStep.class);
@Override
public void doPreProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
@Override
public void doPostProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
}

View File

@@ -1,22 +0,0 @@
/**
* 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.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it)
*/
public class DescribeStep extends MetadataStep {
/**
* log4j logger
*/
private static final Logger log = LogManager.getLogger();
}

View File

@@ -1,22 +0,0 @@
/**
* 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.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it)
*/
public class ExtractionStep extends MetadataStep {
/**
* log4j logger
*/
private static final Logger log = LogManager.getLogger();
}

View File

@@ -1,27 +0,0 @@
/**
* 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.dspace.content.InProgressSubmission;
import org.dspace.core.Context;
import org.dspace.submit.AbstractProcessingStep;
public class InitialQuestionsStep extends AbstractProcessingStep {
@Override
public void doPreProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
@Override
public void doPostProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
}

View File

@@ -1,33 +0,0 @@
/**
* 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.logging.log4j.Logger;
import org.dspace.content.InProgressSubmission;
import org.dspace.core.Context;
import org.dspace.submit.AbstractProcessingStep;
public class LicenseStep extends AbstractProcessingStep {
/**
* log4j logger
*/
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(LicenseStep.class);
@Override
public void doPreProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
@Override
public void doPostProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
}

View File

@@ -1,198 +0,0 @@
/**
* 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 java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import gr.ekt.bte.core.DataLoader;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.Value;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.InProgressSubmission;
import org.dspace.content.Item;
import org.dspace.content.MetadataValue;
import org.dspace.core.Context;
import org.dspace.core.Utils;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.submit.AbstractProcessingStep;
import org.dspace.submit.listener.MetadataListener;
import org.dspace.submit.lookup.SubmissionLookupDataLoader;
//FIXME move to the ExtractionStep
/**
* @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it)
*/
public class MetadataStep extends AbstractProcessingStep {
/**
* log4j logger
*/
private static final Logger log = LogManager.getLogger();
protected List<MetadataListener> listeners = DSpaceServicesFactory.getInstance().getServiceManager()
.getServicesByType(MetadataListener.class);
protected Map<String, List<MetadataValue>> metadataMap = new HashMap<>();
private final Map<String, Set<String>> results = new HashMap<>();
private final Map<String, String> mappingIdentifier = new HashMap<>();
@Override
public void doPreProcessing(Context context, InProgressSubmission wsi) {
for (MetadataListener listener : listeners) {
for (String metadata : listener.getMetadata().keySet()) {
String[] tokenized = Utils.tokenize(metadata);
List<MetadataValue> mm = itemService.getMetadata(wsi.getItem(), tokenized[0], tokenized[1],
tokenized[2], Item.ANY);
if (mm != null && !mm.isEmpty()) {
metadataMap.put(metadata, mm);
} else {
metadataMap.put(metadata, new ArrayList<>());
}
mappingIdentifier.put(metadata, listener.getMetadata().get(metadata));
}
}
}
@Override
public void doPostProcessing(Context context, InProgressSubmission wsi) {
external:
for (String metadata : metadataMap.keySet()) {
String[] tokenized = Utils.tokenize(metadata);
List<MetadataValue> currents = itemService.getMetadata(wsi.getItem(), tokenized[0], tokenized[1],
tokenized[2], Item.ANY);
if (currents != null && !currents.isEmpty()) {
List<MetadataValue> olds = metadataMap.get(metadata);
if (olds.isEmpty()) {
process(context, metadata, currents);
continue external;
}
internal:
for (MetadataValue current : currents) {
boolean found = false;
for (MetadataValue old : olds) {
if (old.getValue().equals(current.getValue())) {
found = true;
}
}
if (!found) {
process(context, metadata, current);
}
}
}
}
if (!results.isEmpty()) {
for (MetadataListener listener : listeners) {
for (DataLoader dataLoader : listener.getDataloadersMap().values()) {
SubmissionLookupDataLoader submissionLookupDataLoader = (SubmissionLookupDataLoader) dataLoader;
try {
List<Record> recordSet = submissionLookupDataLoader.getByIdentifier(context, results);
List<Record> resultSet = convertFields(recordSet, bteBatchImportService.getOutputMap());
enrichItem(context, resultSet, wsi.getItem());
} catch (HttpException | IOException | SQLException | AuthorizeException e) {
log.error(e.getMessage(), e);
}
}
}
}
}
protected void enrichItem(Context context, List<Record> rset, Item item) throws SQLException, AuthorizeException {
for (Record record : rset) {
for (String field : record.getFields()) {
try {
String[] tfield = Utils.tokenize(field);
List<MetadataValue> mdvs = itemService
.getMetadata(item, tfield[0], tfield[1], tfield[2], Item.ANY);
if (mdvs == null || mdvs.isEmpty()) {
for (Value value : record.getValues(field)) {
itemService.addMetadata(context, item, tfield[0], tfield[1], tfield[2], null,
value.getAsString());
}
} else {
external:
for (Value value : record.getValues(field)) {
boolean found = false;
for (MetadataValue mdv : mdvs) {
if (mdv.getValue().equals(value.getAsString())) {
found = true;
continue external;
}
}
if (!found) {
itemService.addMetadata(context, item, tfield[0], tfield[1], tfield[2], null,
value.getAsString());
}
}
}
} catch (SQLException e) {
log.error(e.getMessage(), e);
}
}
}
itemService.update(context, item);
}
private void process(Context context, String metadata, List<MetadataValue> currents) {
for (MetadataValue current : currents) {
process(context, metadata, current);
}
}
private void process(Context context, String metadata, MetadataValue current) {
String key = mappingIdentifier.get(metadata);
Set<String> identifiers = null;
if (!results.containsKey(key)) {
identifiers = new HashSet<>();
} else {
identifiers = results.get(key);
}
identifiers.add(current.getValue());
results.put(key, identifiers);
}
public List<Record> convertFields(List<Record> recordSet, Map<String, String> fieldMap) {
List<Record> result = new ArrayList<>();
for (Record publication : recordSet) {
for (String fieldName : fieldMap.keySet()) {
String md = null;
if (fieldMap != null) {
md = fieldMap.get(fieldName);
}
if (StringUtils.isBlank(md)) {
continue;
} else {
md = md.trim();
}
if (publication.isMutable()) {
List<Value> values = publication.getValues(md);
publication.makeMutable().removeField(md);
publication.makeMutable().addField(fieldName, values);
}
}
result.add(publication);
}
return result;
}
}

View File

@@ -1,28 +0,0 @@
/**
* 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.dspace.content.InProgressSubmission;
import org.dspace.core.Context;
import org.dspace.submit.AbstractProcessingStep;
public class SampleStep extends AbstractProcessingStep {
@Override
public void doPreProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
@Override
public void doPostProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
}

View File

@@ -1,30 +0,0 @@
/**
* 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.logging.log4j.Logger;
import org.dspace.content.InProgressSubmission;
import org.dspace.core.Context;
import org.dspace.submit.AbstractProcessingStep;
public class SelectCollectionStep extends AbstractProcessingStep {
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(SelectCollectionStep.class);
@Override
public void doPreProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
@Override
public void doPostProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
}

View File

@@ -1,33 +0,0 @@
/**
* 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.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dspace.content.InProgressSubmission;
import org.dspace.core.Context;
import org.dspace.submit.AbstractProcessingStep;
public class StartSubmissionLookupStep extends AbstractProcessingStep {
/**
* log4j logger
*/
private static Logger log = LogManager.getLogger(StartSubmissionLookupStep.class);
@Override
public void doPreProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
@Override
public void doPostProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
}

View File

@@ -1,33 +0,0 @@
/**
* 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.logging.log4j.Logger;
import org.dspace.content.InProgressSubmission;
import org.dspace.core.Context;
import org.dspace.submit.AbstractProcessingStep;
public class UploadStep extends AbstractProcessingStep {
/**
* log4j logger
*/
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(UploadStep.class);
@Override
public void doPreProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
@Override
public void doPostProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
}

View File

@@ -1,18 +0,0 @@
/**
* 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.logging.log4j.Logger;
public class UploadWithEmbargoStep extends UploadStep {
/**
* log4j logger
*/
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(UploadWithEmbargoStep.class);
}

View File

@@ -1,27 +0,0 @@
/**
* 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.dspace.content.InProgressSubmission;
import org.dspace.core.Context;
import org.dspace.submit.AbstractProcessingStep;
public class VerifyStep extends AbstractProcessingStep {
@Override
public void doPreProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
@Override
public void doPostProcessing(Context context, InProgressSubmission wsi) {
// TODO Auto-generated method stub
}
}

View File

@@ -1,91 +0,0 @@
/**
* 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.util;
import java.io.Serializable;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import gr.ekt.bte.core.DataLoader;
import gr.ekt.bte.core.MutableRecord;
import gr.ekt.bte.core.Record;
import gr.ekt.bte.core.Value;
import org.dspace.submit.lookup.SubmissionLookupService;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class ItemSubmissionLookupDTO implements Serializable {
private static final long serialVersionUID = 1;
private static final String MERGED_PUBLICATION_PROVIDER = "merged";
private static final String UNKNOWN_PROVIDER_STRING = "UNKNOWN-PROVIDER";
private List<Record> publications;
private String uuid;
public ItemSubmissionLookupDTO(List<Record> publications) {
this.uuid = UUID.randomUUID().toString();
this.publications = publications;
}
public List<Record> getPublications() {
return publications;
}
public Set<String> getProviders() {
Set<String> orderedProviders = new LinkedHashSet<String>();
for (Record p : publications) {
orderedProviders.add(SubmissionLookupService.getProviderName(p));
}
return orderedProviders;
}
public String getUUID() {
return uuid;
}
public Record getTotalPublication(List<DataLoader> providers) {
if (publications == null) {
return null;
} else if (publications.size() == 1) {
return publications.get(0);
} else {
MutableRecord pub = new SubmissionLookupPublication(
MERGED_PUBLICATION_PROVIDER);
// for (SubmissionLookupProvider prov : providers)
// {
for (Record p : publications) {
// if
// (!SubmissionLookupService.getProviderName(p).equals(prov.getShortName()))
// {
// continue;
// }
for (String field : p.getFields()) {
List<Value> values = p.getValues(field);
if (values != null && values.size() > 0) {
if (!pub.getFields().contains(field)) {
for (Value v : values) {
pub.addValue(field, v);
}
}
}
}
}
// }
return pub;
}
}
}

View File

@@ -1,45 +0,0 @@
/**
* 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.util;
import java.io.Serializable;
import java.util.List;
import java.util.UUID;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class SubmissionLookupDTO implements Serializable {
private static final long serialVersionUID = 1;
private String uuid;
private List<ItemSubmissionLookupDTO> items;
public SubmissionLookupDTO() {
this.uuid = UUID.randomUUID().toString();
}
public void setItems(List<ItemSubmissionLookupDTO> items) {
this.items = items;
}
public ItemSubmissionLookupDTO getLookupItem(String uuidLookup) {
if (items != null) {
for (ItemSubmissionLookupDTO item : items) {
if (item.getUUID().equals(uuidLookup)) {
return item;
}
}
}
return null;
}
}

View File

@@ -1,189 +0,0 @@
/**
* 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.util;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import gr.ekt.bte.core.MutableRecord;
import gr.ekt.bte.core.StringValue;
import gr.ekt.bte.core.Value;
import org.apache.commons.lang3.StringUtils;
import org.dspace.submit.lookup.SubmissionLookupDataLoader;
/**
* @author Andrea Bollini
* @author Kostas Stamatis
* @author Luigi Andrea Pascarelli
* @author Panagiotis Koutsourakis
*/
public class SubmissionLookupPublication implements MutableRecord, Serializable {
private String providerName;
private Map<String, List<String>> storage = new HashMap<String, List<String>>();
public SubmissionLookupPublication(String providerName) {
this.providerName = providerName;
}
// needed to serialize it with JSON
public Map<String, List<String>> getStorage() {
return storage;
}
@Override
public Set<String> getFields() {
return storage.keySet();
}
public List<String> remove(String md) {
return storage.remove(md);
}
public void add(String md, String nValue) {
if (StringUtils.isNotBlank(nValue)) {
List<String> tmp = storage.get(md);
if (tmp == null) {
tmp = new ArrayList<String>();
storage.put(md, tmp);
}
tmp.add(nValue);
}
}
public String getFirstValue(String md) {
List<String> tmp = storage.get(md);
if (tmp == null || tmp.size() == 0) {
return null;
}
return tmp.get(0);
}
public String getProviderName() {
return providerName;
}
public String getType() {
return getFirstValue(SubmissionLookupDataLoader.TYPE);
}
// BTE Record interface methods
@Override
public boolean hasField(String md) {
return storage.containsKey(md);
}
@Override
public List<Value> getValues(String md) {
List<String> stringValues = storage.get(md);
if (stringValues == null) {
return null;
}
List<Value> values = new ArrayList<Value>();
for (String value : stringValues) {
values.add(new StringValue(value));
}
return values;
}
@Override
public boolean isMutable() {
return true;
}
@Override
public MutableRecord makeMutable() {
return this;
}
@Override
public boolean addField(String md, List<Value> values) {
if (storage.containsKey(md)) {
List<String> stringValues = storage.get(md);
if (values != null) {
for (Value value : values) {
stringValues.add(value.getAsString());
}
}
} else {
List<String> tmp = new ArrayList<String>();
if (values != null) {
for (Value value : values) {
tmp.add(value.getAsString());
}
}
storage.put(md, tmp);
}
return true;
}
@Override
public boolean addValue(String md, Value value) {
if (storage.containsKey(md)) {
List<String> stringValues = storage.get(md);
stringValues.add(value.getAsString());
} else {
List<String> tmp = new ArrayList<String>();
tmp.add(value.getAsString());
storage.put(md, tmp);
}
return true;
}
@Override
public boolean removeField(String md) {
if (storage.containsKey(md)) {
storage.remove(md);
}
return false;
}
@Override
public boolean removeValue(String md, Value value) {
if (storage.containsKey(md)) {
List<String> stringValues = storage.get(md);
stringValues.remove(value.getAsString());
}
return true;
}
@Override
public boolean updateField(String md, List<Value> values) {
List<String> stringValues = new ArrayList<String>();
for (Value value : values) {
stringValues.add(value.getAsString());
}
storage.put(md, stringValues);
return true;
}
@Override
public boolean updateValue(String md, Value valueOld, Value valueNew) {
if (storage.containsKey(md)) {
List<String> stringValues = storage.get(md);
List<String> newStringValues = storage.get(md);
for (String s : stringValues) {
if (s.equals(valueOld.getAsString())) {
newStringValues.add(valueNew.getAsString());
} else {
newStringValues.add(s);
}
}
storage.put(md, newStringValues);
}
return true;
}
}

Some files were not shown because too many files have changed in this diff Show More