From 7811bb8966db5564d953eba6d3b86aef54c50c23 Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Sat, 24 Aug 2019 07:06:29 -0400 Subject: [PATCH 001/125] [DS-2378] First pass: collapse loops to single SpringServiceManager. Also tidy the code, make better use of logger. --- .../servicemanager/DSpaceServiceManager.java | 224 ++++++++---------- .../spring/SpringServiceManager.java | 17 +- 2 files changed, 109 insertions(+), 132 deletions(-) diff --git a/dspace-services/src/main/java/org/dspace/servicemanager/DSpaceServiceManager.java b/dspace-services/src/main/java/org/dspace/servicemanager/DSpaceServiceManager.java index a4520de0df..2c8dc01eb7 100644 --- a/dspace-services/src/main/java/org/dspace/servicemanager/DSpaceServiceManager.java +++ b/dspace-services/src/main/java/org/dspace/servicemanager/DSpaceServiceManager.java @@ -47,6 +47,8 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { protected boolean running = false; + private ServiceManagerSystem serviceManagerSystem; + /** * @return true if the service manager is running */ @@ -65,13 +67,10 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { } } - private List serviceManagers = Collections - .synchronizedList(new ArrayList()); - private SpringServiceManager primaryServiceManager = null; /** * This holds the stack of activators. It is randomly ordered. */ - private List activators = Collections.synchronizedList(new ArrayList()); + private final List activators = Collections.synchronizedList(new ArrayList<>()); protected boolean developing = false; @@ -114,11 +113,11 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { try { activator.start(this); activators.add(activator); - log.info("Started and registered activator: " + activator.getClass().getName()); + log.info("Started and registered activator: {}", activator.getClass().getName()); } catch (Exception e1) { log.error( - "ERROR: Failed to start activator (" + activator.getClass().getName() + "): " + e1.getMessage(), - e1); + "ERROR: Failed to start activator ({}): {}", + activator.getClass().getName(), e1.getMessage(), e1); } } } @@ -133,9 +132,10 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { // succeeded creating the activator try { activator.stop(this); - log.info("Stopped and unregistered activator: " + activatorClassName); + log.info("Stopped and unregistered activator: {}", activatorClassName); } catch (Exception e1) { - log.error("ERROR: Failed to stop activator (" + activatorClassName + "): " + e1.getMessage(), e1); + log.error("ERROR: Failed to stop activator ({}): {}", + activatorClassName, e1.getMessage(), e1); } } } @@ -146,14 +146,14 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { * This will call all the services which want to be notified when the service manager is ready */ public void notifyServiceManagerReady() { - for (ServiceManagerSystem sms : serviceManagers) { - List services = sms.getServicesByType(ServiceManagerReadyAware.class); - for (ServiceManagerReadyAware serviceManagerReadyAware : services) { - try { - serviceManagerReadyAware.serviceManagerReady(this); - } catch (Exception e) { - log.error("ERROR: Failure in service when calling serviceManagerReady: " + e.getMessage(), e); - } + List services + = serviceManagerSystem.getServicesByType(ServiceManagerReadyAware.class); + for (ServiceManagerReadyAware serviceManagerReadyAware : services) { + try { + serviceManagerReadyAware.serviceManagerReady(this); + } catch (Exception e) { + log.error("ERROR: Failure in service when calling serviceManagerReady: {}", + e.getMessage(), e); } } } @@ -190,17 +190,15 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { @Override public void shutdown() { unregisterActivators(); - for (ServiceManagerSystem sms : serviceManagers) { - try { - sms.shutdown(); - } catch (Exception e) { - // shutdown failures are not great but should NOT cause an interruption of processing - log.error("Failure shutting down service manager (" + sms + "): " + e.getMessage(), e); - } + try { + serviceManagerSystem.shutdown(); + } catch (Exception e) { + // shutdown failures are not great but should NOT cause an interruption of processing + log.error("Failure shutting down service manager ({}): {}", + serviceManagerSystem, e.getMessage(), e); } this.running = false; // wait til the end - this.serviceManagers.clear(); - this.primaryServiceManager = null; + this.serviceManagerSystem = null; log.info("Shutdown DSpace core service manager"); } @@ -224,7 +222,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { try { // have to put this at the top because otherwise initializing beans will die when they try to use the SMS this.running = true; - // create the primary SMS and start it + // create the SMS and start it SpringServiceManager springSMS = new SpringServiceManager(this, configurationService, testing, developing, springXmlConfigFiles); try { @@ -234,8 +232,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { throw new IllegalStateException("failure starting up spring service manager: " + e.getMessage(), e); } // add it to the list of service managers - this.serviceManagers.add(springSMS); - this.primaryServiceManager = springSMS; + this.serviceManagerSystem = springSMS; // now startup the activators registerActivators(); @@ -243,7 +240,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { // now we call the ready mixins notifyServiceManagerReady(); - } catch (Exception e) { + } catch (IllegalStateException e) { shutdown(); // execute the shutdown String message = "Failed to startup the DSpace Service Manager: " + e.getMessage(); log.error(message, e); @@ -251,15 +248,14 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { } } + @Override public void registerService(String name, Object service) { checkRunning(); if (name == null || service == null) { throw new IllegalArgumentException("name and service cannot be null"); } - // register service/provider with all - for (ServiceManagerSystem sms : serviceManagers) { - sms.registerService(name, service); - } + // register service/provider + serviceManagerSystem.registerService(name, service); } @Override @@ -268,131 +264,110 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { if (name == null || service == null) { throw new IllegalArgumentException("name and service cannot be null"); } - // register service/provider with all - for (ServiceManagerSystem sms : serviceManagers) { - sms.registerServiceNoAutowire(name, service); - } + // register service/provider + serviceManagerSystem.registerServiceNoAutowire(name, service); } + @Override public T registerServiceClass(String name, Class type) { checkRunning(); if (name == null || type == null) { throw new IllegalArgumentException("name and type cannot be null"); } - // we only register with the primary - return primaryServiceManager.registerServiceClass(name, type); + + return serviceManagerSystem.registerServiceClass(name, type); } + @Override public void unregisterService(String name) { checkRunning(); if (name == null) { throw new IllegalArgumentException("name cannot be null"); } - // only unregister with the primary - primaryServiceManager.unregisterService(name); + + serviceManagerSystem.unregisterService(name); } + @Override public T getServiceByName(String name, Class type) { checkRunning(); if (type == null) { throw new IllegalArgumentException("type cannot be null"); } T service = null; - for (ServiceManagerSystem sms : serviceManagers) { - try { - service = sms.getServiceByName(name, type); - if (service != null) { - break; - } - } catch (Exception e) { - // keep going - } - } - // need to check the service mixin manager if not found - if (service == null - && name != null) { - for (ServiceManagerSystem sms : serviceManagers) { - if (service == null) { - service = sms.getServiceByName(name, type); - } - } + try { + service = serviceManagerSystem.getServiceByName(name, type); + } catch (Exception e) { + // keep going } return service; } @Override public ConfigurableApplicationContext getApplicationContext() { - return primaryServiceManager.getApplicationContext(); + return serviceManagerSystem.getApplicationContext(); } + @Override public List getServicesByType(Class type) { checkRunning(); if (type == null) { throw new IllegalArgumentException("type cannot be null"); } - HashSet set = new HashSet(); - for (ServiceManagerSystem sms : serviceManagers) { - try { - set.addAll(sms.getServicesByType(type)); - } catch (Exception e) { - // keep going - } + HashSet set = new HashSet<>(); + try { + set.addAll(serviceManagerSystem.getServicesByType(type)); + } catch (Exception e) { + // keep going } // put the set into a list for easier access and sort it - List services = new ArrayList(set); + List services = new ArrayList<>(set); Collections.sort(services, new ServiceManagerUtils.ServiceComparator()); return services; } + @Override public List getServicesNames() { checkRunning(); - List names = new ArrayList(); - for (ServiceManagerSystem sms : serviceManagers) { - try { - names.addAll(sms.getServicesNames()); - } catch (Exception e) { - // keep going - } + List names = new ArrayList<>(); + try { + names.addAll(serviceManagerSystem.getServicesNames()); + } catch (Exception e) { + // keep going } Collections.sort(names); return names; } + @Override public boolean isServiceExists(String name) { checkRunning(); if (name == null) { throw new IllegalArgumentException("name cannot be null"); } boolean exists = false; - for (ServiceManagerSystem sms : serviceManagers) { - try { - exists = sms.isServiceExists(name); - if (exists) { - break; - } - } catch (Exception e) { - // keep going - } + try { + exists = serviceManagerSystem.isServiceExists(name); + } catch (Exception e) { + // keep going } return exists; } + @Override public Map getServices() { checkRunning(); - Map services = new HashMap(); - for (ServiceManagerSystem sms : serviceManagers) { - try { - for (Entry entry : sms.getServices().entrySet()) { - if (!services.containsKey(entry.getKey())) { - services.put(entry.getKey(), entry.getValue()); - } + Map services = new HashMap<>(); + try { + for (Entry entry : serviceManagerSystem.getServices().entrySet()) { + if (!services.containsKey(entry.getKey())) { + services.put(entry.getKey(), entry.getValue()); } - } catch (Exception e) { - // keep going if it fails for one - log.error( - "Failed to get list of services from service manager (" + sms.getClass() + "): " + e.getMessage(), - e); } + } catch (Exception e) { + log.error( + "Failed to get list of services from service manager ({}): {}", + serviceManagerSystem.getClass(), e.getMessage(), e); } return services; } @@ -402,6 +377,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { * Every service gets called to notify them of the config change * depending on the the listener they are using. */ + @Override public void pushConfig(Map properties) { checkRunning(); if (properties != null && !properties.isEmpty()) { @@ -410,43 +386,41 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { if (changedNames.length > 0) { // some configs changed so push the changes to the listeners in all known services and providers // make the list of changed setting names and map of changed settings - ArrayList changedSettingNames = new ArrayList(); - Map changedSettings = new LinkedHashMap(); + ArrayList changedSettingNames = new ArrayList<>(); + Map changedSettings = new LinkedHashMap<>(); for (String configName : changedNames) { changedSettingNames.add(configName); changedSettings.put(configName, configurationService.getProperty(configName)); } // notify the services that implement the mixin - for (ServiceManagerSystem sms : serviceManagers) { - List configChangeListeners = sms - .getServicesByType(ConfigChangeListener.class); - for (ConfigChangeListener configChangeListener : configChangeListeners) { - // notify this service - try { - boolean notify = false; - String[] notifyNames = configChangeListener.notifyForConfigNames(); - if (notifyNames == null || notifyNames.length == 0) { - notify = true; - } else { - for (String notifyName : notifyNames) { - // check to see if the name matches one of those the listener cares about - for (String changedName : changedNames) { - if (notifyName != null && notifyName.equals(changedName)) { - notify = true; - break; - } + List configChangeListeners = serviceManagerSystem + .getServicesByType(ConfigChangeListener.class); + for (ConfigChangeListener configChangeListener : configChangeListeners) { + // notify this service + try { + boolean notify = false; + String[] notifyNames = configChangeListener.notifyForConfigNames(); + if (notifyNames == null || notifyNames.length == 0) { + notify = true; + } else { + for (String notifyName : notifyNames) { + // check to see if the name matches one of those the listener cares about + for (String changedName : changedNames) { + if (notifyName != null && notifyName.equals(changedName)) { + notify = true; + break; } } } - // do the notify if we should at this point - if (notify) { - configChangeListener.configurationChanged(changedSettingNames, changedSettings); - } - } catch (Exception e) { - log.error( - "Failure occurred while trying to notify service of config change: " + e.getMessage(), - e); } + // do the notify if we should at this point + if (notify) { + configChangeListener.configurationChanged(changedSettingNames, changedSettings); + } + } catch (Exception e) { + log.error( + "Failure occurred while trying to notify service of config change: " + e.getMessage(), + e); } } } diff --git a/dspace-services/src/main/java/org/dspace/servicemanager/spring/SpringServiceManager.java b/dspace-services/src/main/java/org/dspace/servicemanager/spring/SpringServiceManager.java index da4b115279..10b52495cc 100644 --- a/dspace-services/src/main/java/org/dspace/servicemanager/spring/SpringServiceManager.java +++ b/dspace-services/src/main/java/org/dspace/servicemanager/spring/SpringServiceManager.java @@ -7,6 +7,7 @@ */ package org.dspace.servicemanager.spring; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -36,7 +37,7 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; */ public final class SpringServiceManager implements ServiceManagerSystem { - private static Logger log = LoggerFactory.getLogger(SpringServiceManager.class); + private static final Logger log = LoggerFactory.getLogger(SpringServiceManager.class); private ClassPathXmlApplicationContext applicationContext; @@ -149,7 +150,7 @@ public final class SpringServiceManager implements ServiceManagerSystem { @SuppressWarnings("unchecked") @Override public List getServicesByType(Class type) { - ArrayList l = new ArrayList(); + ArrayList l = new ArrayList<>(); Map beans; try { beans = applicationContext.getBeansOfType(type, true, true); @@ -237,9 +238,11 @@ public final class SpringServiceManager implements ServiceManagerSystem { } } catch (ClassNotFoundException e) { //Ignore this exception, if we get one this just means that this module isn't loaded - } catch (Exception e) { - log.error("Error while retrieving spring resource paths for module: " + springLoaderClassName, - e); + } catch (IllegalAccessException | IllegalArgumentException + | InstantiationException | NoSuchMethodException + | SecurityException | InvocationTargetException e) { + log.error("Error while retrieving spring resource paths for module: {}", + springLoaderClassName, e); } } } @@ -323,7 +326,7 @@ public final class SpringServiceManager implements ServiceManagerSystem { @Override public List getServicesNames() { - ArrayList beanNames = new ArrayList(); + ArrayList beanNames = new ArrayList<>(); String[] singletons = applicationContext.getBeanFactory().getSingletonNames(); for (String singleton : singletons) { if (singleton.startsWith("org.springframework.context")) { @@ -342,7 +345,7 @@ public final class SpringServiceManager implements ServiceManagerSystem { @Override public Map getServices() { - Map services = new HashMap(); + Map services = new HashMap<>(); String[] singletons = applicationContext.getBeanFactory().getSingletonNames(); for (String singleton : singletons) { if (singleton.startsWith("org.springframework.context")) { From de3c46bd5f6f406154d46b7aac798783c543c1a6 Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Sun, 25 Aug 2019 14:51:00 -0400 Subject: [PATCH 002/125] [DS-2378] Pass 2: fold SpringServiceManager into DSpaceServiceManager and simplify. --- .../servicemanager/DSpaceServiceManager.java | 423 +++++++++++++----- .../dspace/servicemanager/package-info.java | 3 +- .../DSpaceBeanFactoryPostProcessor.java | 20 +- .../spring/SpringServiceManager.java | 369 --------------- .../servicemanager/spring/package-info.java | 2 +- .../DSpaceServiceManagerTest.java | 10 +- .../spring/TestSpringServiceManager.java | 229 ---------- 7 files changed, 329 insertions(+), 727 deletions(-) delete mode 100644 dspace-services/src/main/java/org/dspace/servicemanager/spring/SpringServiceManager.java delete mode 100644 dspace-services/src/test/java/org/dspace/servicemanager/spring/TestSpringServiceManager.java diff --git a/dspace-services/src/main/java/org/dspace/servicemanager/DSpaceServiceManager.java b/dspace-services/src/main/java/org/dspace/servicemanager/DSpaceServiceManager.java index 2c8dc01eb7..d3f2b03ff2 100644 --- a/dspace-services/src/main/java/org/dspace/servicemanager/DSpaceServiceManager.java +++ b/dspace-services/src/main/java/org/dspace/servicemanager/DSpaceServiceManager.java @@ -7,35 +7,41 @@ */ package org.dspace.servicemanager; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import org.apache.commons.lang3.ArrayUtils; import org.dspace.kernel.Activator; +import org.dspace.kernel.config.SpringLoader; import org.dspace.kernel.mixins.ConfigChangeListener; import org.dspace.kernel.mixins.InitializedService; import org.dspace.kernel.mixins.ServiceChangeListener; import org.dspace.kernel.mixins.ServiceManagerReadyAware; import org.dspace.kernel.mixins.ShutdownService; import org.dspace.servicemanager.config.DSpaceConfigurationService; -import org.dspace.servicemanager.spring.SpringServiceManager; +import org.dspace.servicemanager.spring.DSpaceBeanFactoryPostProcessor; import org.dspace.services.ConfigurationService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeansException; import org.springframework.beans.PropertyAccessorFactory; -import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; /** - * This is the core service manager which ties together the other - * service managers and generally handles any edge cases in the various - * systems. + * A service locator based on Spring. * * @author Aaron Zeckoski (azeckoski @ gmail.com) */ @@ -43,11 +49,56 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { private static Logger log = LoggerFactory.getLogger(DSpaceServiceManager.class); + public static final String CONFIG_PATH = "spring/spring-dspace-applicationContext.xml"; + public static final String CORE_RESOURCE_PATH = "classpath*:spring/spring-dspace-core-services.xml"; + public static final String ADDON_RESOURCE_PATH = "classpath*:spring/spring-dspace-addon-*-services.xml"; + private final DSpaceConfigurationService configurationService; + private ClassPathXmlApplicationContext applicationContext; + protected boolean running = false; - private ServiceManagerSystem serviceManagerSystem; + protected boolean developing = false; + + protected boolean testing = false; + + protected String[] springXmlConfigFiles = null; + + /** + * This holds the stack of activators. It is randomly ordered. + */ + private final List activators = Collections.synchronizedList(new ArrayList<>()); + + /** + * Standard constructor. + * + * @param configurationService current DSpace configuration service + */ + public DSpaceServiceManager(DSpaceConfigurationService configurationService) { + if (configurationService == null) { + throw new IllegalArgumentException("Failure creating service manager: configuration service is null"); + } + this.configurationService = configurationService; + this.developing = configurationService.getPropertyAsType("service.manager.developing", boolean.class); + } + + /** + * TESTING - This is for testing only. + * + * @param configurationService current DSpace configuration service. + * @param springXmlConfigFiles one or more Spring XML configuration files. + */ + protected DSpaceServiceManager(DSpaceConfigurationService configurationService, + String... springXmlConfigFiles) { + if (configurationService == null) { + throw new IllegalArgumentException("Configuration service cannot be null"); + } + this.configurationService = configurationService; + this.springXmlConfigFiles = springXmlConfigFiles; + this.testing = true; + this.developing = true; + } /** * @return true if the service manager is running @@ -57,7 +108,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { } /** - * Checks to see if the service manager is running, if not throws an exception + * Checks to see if the service manager is running. * * @throws IllegalStateException if not running */ @@ -68,39 +119,21 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { } /** - * This holds the stack of activators. It is randomly ordered. + * @return the current spring bean factory OR null if there is not one. */ - private final List activators = Collections.synchronizedList(new ArrayList<>()); - - protected boolean developing = false; - - /** - * Standard constructor. - * - * @param configurationService current DSpace configuration service - */ - public DSpaceServiceManager(DSpaceConfigurationService configurationService) { - if (configurationService == null) { - throw new IllegalArgumentException("Failure creating service manager, configuration service is null"); + public ListableBeanFactory getBeanFactory() { + if (applicationContext != null) { + return applicationContext.getBeanFactory(); } - this.configurationService = configurationService; - this.developing = configurationService.getPropertyAsType("service.manager.developing", boolean.class); + return null; } - protected boolean testing = false; - protected String[] springXmlConfigFiles = null; - /** - * TESTING - This is for testing only. - * - * @param configurationService current DSpace configuration service - * @param springXmlConfigFiles one or more Spring XML configs + * @return the parent core Spring {@link ApplicationContext} */ - protected DSpaceServiceManager(DSpaceConfigurationService configurationService, String... springXmlConfigFiles) { - this.configurationService = configurationService; - this.springXmlConfigFiles = springXmlConfigFiles; - this.testing = true; - this.developing = true; + @Override + public ClassPathXmlApplicationContext getApplicationContext() { + return applicationContext; } /** @@ -123,7 +156,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { } /** - * Unregisters all registered activators using this service manager. + * De-registers all registered activators using this service manager. */ private void unregisterActivators() { for (Activator activator : activators) { @@ -143,11 +176,11 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { } /** - * This will call all the services which want to be notified when the service manager is ready + * This will call all the services which want to be notified when the service manager is ready. */ public void notifyServiceManagerReady() { List services - = serviceManagerSystem.getServicesByType(ServiceManagerReadyAware.class); + = getServicesByType(ServiceManagerReadyAware.class); for (ServiceManagerReadyAware serviceManagerReadyAware : services) { try { serviceManagerReadyAware.serviceManagerReady(this); @@ -159,7 +192,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { } /** - * Checks to see if a listener should be notified + * Checks to see if a listener should be notified. * * @param implementedTypes the types implemented by the service changing * @param serviceChangeListener the listener @@ -185,21 +218,30 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { } /** - * Shut down all service managers, including this one. + * Shut down the Spring context and leave the "running" state. */ @Override public void shutdown() { unregisterActivators(); - try { - serviceManagerSystem.shutdown(); - } catch (Exception e) { - // shutdown failures are not great but should NOT cause an interruption of processing - log.error("Failure shutting down service manager ({}): {}", - serviceManagerSystem, e.getMessage(), e); + + if (applicationContext != null) { + try { + applicationContext.close(); + } catch (Exception e) { + // keep going anyway + log.warn("Exception closing ApplicationContext: {}", e.getMessage(), e); + } + try { + applicationContext.destroy(); + } catch (Exception e) { + // keep going anyway + log.warn("Exception destroying ApplicationContext: {}", e.getMessage(), e); + } + applicationContext = null; } + this.running = false; // wait til the end - this.serviceManagerSystem = null; - log.info("Shutdown DSpace core service manager"); + log.info("DSpace service manager is shut down."); } /* (non-Javadoc) @@ -219,20 +261,30 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { } } } + + long startTime = System.currentTimeMillis(); try { // have to put this at the top because otherwise initializing beans will die when they try to use the SMS this.running = true; - // create the SMS and start it - SpringServiceManager springSMS = new SpringServiceManager(this, configurationService, testing, developing, - springXmlConfigFiles); - try { - springSMS.startup(); - } catch (Exception e) { - // startup failures are deadly - throw new IllegalStateException("failure starting up spring service manager: " + e.getMessage(), e); + + // get all Spring config paths + String[] allPaths = getSpringPaths(testing, springXmlConfigFiles, configurationService); + applicationContext = new ClassPathXmlApplicationContext(allPaths, false); + // Make sure that the Spring files from the config directory can override the Spring files from our jars + applicationContext.setAllowBeanDefinitionOverriding(true); + applicationContext.setAllowCircularReferences(true); + //applicationContext.registerShutdownHook(); // this interferes with the kernel shutdown hook + // add the config interceptors (partially done in the xml) + applicationContext.addBeanFactoryPostProcessor( + new DSpaceBeanFactoryPostProcessor(this, configurationService, testing)); + applicationContext.refresh(); + if (developing) { + log.warn("Service Manager is running in developmentMode. Services will be loaded on demand only"); + // TODO find a way to set this sucker to super duper lazy mode? it is currently not actually doing it + } else { + applicationContext.getBeanFactory().preInstantiateSingletons(); + applicationContext.getBeanFactory().freezeConfiguration(); } - // add it to the list of service managers - this.serviceManagerSystem = springSMS; // now startup the activators registerActivators(); @@ -246,36 +298,66 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { log.error(message, e); throw new RuntimeException(message, e); } + + long totalTime = System.currentTimeMillis() - startTime; + log.info("Service Manager started up in {} ms with {} services...", + totalTime, applicationContext.getBeanDefinitionCount()); } @Override public void registerService(String name, Object service) { checkRunning(); - if (name == null || service == null) { - throw new IllegalArgumentException("name and service cannot be null"); + if (name == null) { + throw new IllegalArgumentException("name cannot be null"); + } + if (service == null) { + throw new IllegalArgumentException("service cannot be null"); } // register service/provider - serviceManagerSystem.registerService(name, service); + try { + applicationContext.getBeanFactory().autowireBean(service); + } catch (BeansException e) { + throw new IllegalArgumentException( + "Invalid service (" + service + ") with name (" + name + ") registration: " + e.getMessage(), e); + } + registerBean(name, service); } @Override public void registerServiceNoAutowire(String name, Object service) { checkRunning(); - if (name == null || service == null) { - throw new IllegalArgumentException("name and service cannot be null"); + if (name == null) { + throw new IllegalArgumentException("name cannot be null"); + } + if (service == null) { + throw new IllegalArgumentException("service cannot be null"); } // register service/provider - serviceManagerSystem.registerServiceNoAutowire(name, service); + registerBean(name, service); } + @SuppressWarnings("unchecked") @Override public T registerServiceClass(String name, Class type) { checkRunning(); - if (name == null || type == null) { - throw new IllegalArgumentException("name and type cannot be null"); + if (name == null) { + throw new IllegalArgumentException("name cannot be null"); + } + if (type == null) { + throw new IllegalArgumentException("type cannot be null"); } - return serviceManagerSystem.registerServiceClass(name, type); + T service; + try { + service = (T) applicationContext.getBeanFactory() + .autowire(type, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true); + registerBean(name, service); + } catch (BeansException e) { + throw new IllegalArgumentException("Invalid service class (" + type + + ") with name (" + name + + ") registration: " + e.getMessage(), e); + } + return service; } @Override @@ -285,43 +367,113 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { throw new IllegalArgumentException("name cannot be null"); } - serviceManagerSystem.unregisterService(name); + if (applicationContext.containsBean(name)) { + try { + Object beanInstance = applicationContext.getBean(name); + try { + applicationContext.getBeanFactory().destroyBean(name, beanInstance); + } catch (NoSuchBeanDefinitionException e) { + // this happens if the bean was registered manually (annoyingly) + DSpaceServiceManager.shutdownService(beanInstance); + } + } catch (BeansException e) { + // nothing to do here, could not find the bean + } + } } + /** + * This handles the common part of various types of service registrations. + * + * @param name name of bean + * @param service service object + */ + private void registerBean(String name, Object service) { + try { + applicationContext.getBeanFactory().initializeBean(service, name); + applicationContext.getBeanFactory().registerSingleton(name, service); + } catch (BeansException e) { + throw new IllegalArgumentException( + "Invalid service (" + service + ") with name (" + name + ") registration: " + e.getMessage(), e); + } + } + + @SuppressWarnings("unchecked") @Override public T getServiceByName(String name, Class type) { checkRunning(); if (type == null) { - throw new IllegalArgumentException("type cannot be null"); + throw new IllegalArgumentException("Type cannot be null"); } + T service = null; - try { - service = serviceManagerSystem.getServiceByName(name, type); - } catch (Exception e) { - // keep going + // handle special case to return the core AC + if (ApplicationContext.class.getName().equals(name) + && ApplicationContext.class.isAssignableFrom(type)) { + service = (T) getApplicationContext(); + } else { + if (name != null) { + // get by name and type + try { + service = (T) applicationContext.getBean(name, type); + } catch (BeansException e) { + // no luck, try the fall back option + log.info( + "Unable to locate bean by name or id={}." + + " Will try to look up bean by type next." + + " BeansException: {}", name, e.getMessage()); + service = null; + } + } else { + // try making up the name based on the type + try { + service = (T) applicationContext.getBean(type.getName(), type); + } catch (BeansException e) { + // no luck, try the fall back option + log.info("Unable to locate bean by name or id={}." + + " Will try to look up bean by type next." + + " BeansException: {}", type.getName(), e.getMessage()); + service = null; + } + } + // if still no luck then try by type only + if (name == null + && service == null) { + try { + Map map = applicationContext.getBeansOfType(type); + if (map.size() == 1) { + // only return the bean if there is exactly one + service = (T) map.values().iterator().next(); + } else { + log.error("Multiple beans of type {} found. Only one was expected!", type.getName()); + } + } catch (BeansException e) { + // I guess there are no beans of this type + log.error(e.getMessage(), e); + service = null; + } + } } return service; } - @Override - public ConfigurableApplicationContext getApplicationContext() { - return serviceManagerSystem.getApplicationContext(); - } - + @SuppressWarnings("unchecked") @Override public List getServicesByType(Class type) { checkRunning(); if (type == null) { throw new IllegalArgumentException("type cannot be null"); } - HashSet set = new HashSet<>(); + + List services = new ArrayList<>(); + Map beans; try { - set.addAll(serviceManagerSystem.getServicesByType(type)); - } catch (Exception e) { - // keep going + beans = applicationContext.getBeansOfType(type, true, true); + services.addAll((Collection) beans.values()); + } catch (BeansException e) { + throw new RuntimeException("Failed to get beans of type (" + type + "): " + e.getMessage(), e); } - // put the set into a list for easier access and sort it - List services = new ArrayList<>(set); + Collections.sort(services, new ServiceManagerUtils.ServiceComparator()); return services; } @@ -329,14 +481,16 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { @Override public List getServicesNames() { checkRunning(); - List names = new ArrayList<>(); - try { - names.addAll(serviceManagerSystem.getServicesNames()); - } catch (Exception e) { - // keep going + ArrayList beanNames = new ArrayList<>(); + String[] singletons = applicationContext.getBeanFactory().getSingletonNames(); + for (String singleton : singletons) { + if (singleton.startsWith("org.springframework.context")) { + continue; // skip the Spring standard ones + } + beanNames.add(singleton); } - Collections.sort(names); - return names; + Collections.sort(beanNames); + return beanNames; } @Override @@ -345,29 +499,24 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { if (name == null) { throw new IllegalArgumentException("name cannot be null"); } - boolean exists = false; - try { - exists = serviceManagerSystem.isServiceExists(name); - } catch (Exception e) { - // keep going - } - return exists; + return applicationContext.containsBean(name); } @Override public Map getServices() { checkRunning(); Map services = new HashMap<>(); - try { - for (Entry entry : serviceManagerSystem.getServices().entrySet()) { - if (!services.containsKey(entry.getKey())) { - services.put(entry.getKey(), entry.getValue()); - } + String[] singletons = applicationContext.getBeanFactory().getSingletonNames(); + for (String singleton : singletons) { + if (singleton.startsWith("org.springframework.context")) { + continue; // skip the spring standard ones } - } catch (Exception e) { - log.error( - "Failed to get list of services from service manager ({}): {}", - serviceManagerSystem.getClass(), e.getMessage(), e); + String beanName = singleton; + Object service = applicationContext.getBeanFactory().getSingleton(beanName); + if (service == null) { + continue; + } + services.put(beanName, service); } return services; } @@ -393,8 +542,8 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { changedSettings.put(configName, configurationService.getProperty(configName)); } // notify the services that implement the mixin - List configChangeListeners = serviceManagerSystem - .getServicesByType(ConfigChangeListener.class); + List configChangeListeners + = getServicesByType(ConfigChangeListener.class); for (ConfigChangeListener configChangeListener : configChangeListeners) { // notify this service try { @@ -497,9 +646,61 @@ public final class DSpaceServiceManager implements ServiceManagerSystem { try { ((ShutdownService) service).shutdown(); } catch (Exception e) { - log.error("Failure shutting down service: " + service, e); + log.error("Failure shutting down service: {}", service, e); } } } + /** + * Build the complete list of Spring configuration paths, including + * hard-wired paths. + * + * @param testMode are we testing the service manager? + * @param configPaths paths supplied at startup. + * @param configurationService DSpace configuration source. + * @return + */ + public static String[] getSpringPaths(boolean testMode, String[] configPaths, + DSpaceConfigurationService configurationService) { + List pathList = new LinkedList<>(); + pathList.add(CONFIG_PATH); + pathList.add(ADDON_RESOURCE_PATH); + if (testMode) { + log.warn("TEST Service Manager running in test mode: no core beans will be started"); + } else { + // only load the core beans when not testing the service manager + pathList.add(CORE_RESOURCE_PATH); + } + if (configPaths != null) { + pathList.addAll(Arrays.asList(configPaths)); + } + if (testMode) { + log.warn("TEST Spring Service Manager running in test mode, no DSpace home Spring files will be loaded"); + } else { + //Retrieve all our spring file locations depending on the deployed module + String[] springLoaderClassNames = configurationService.getArrayProperty("spring.springloader.modules"); + if (springLoaderClassNames != null) { + for (String springLoaderClassName : springLoaderClassNames) { + try { + Class springLoaderClass = (Class) Class + .forName(springLoaderClassName.trim()); + String[] resourcePaths = springLoaderClass.getConstructor().newInstance() + .getResourcePaths(configurationService); + if (resourcePaths != null) { + pathList.addAll(Arrays.asList(resourcePaths)); + } + } catch (ClassNotFoundException e) { + //Ignore this exception, if we get one this just means that this module isn't loaded + } catch (IllegalAccessException | IllegalArgumentException + | InstantiationException | NoSuchMethodException + | SecurityException | InvocationTargetException e) { + log.error("Error while retrieving Spring resource paths for module: {}", + springLoaderClassName, e); + } + } + } + } + return pathList.toArray(new String[pathList.size()]); + } + } diff --git a/dspace-services/src/main/java/org/dspace/servicemanager/package-info.java b/dspace-services/src/main/java/org/dspace/servicemanager/package-info.java index 8e8adbd1de..6c1f80f133 100644 --- a/dspace-services/src/main/java/org/dspace/servicemanager/package-info.java +++ b/dspace-services/src/main/java/org/dspace/servicemanager/package-info.java @@ -7,7 +7,8 @@ */ /** - * Register, configure, manipulate services. + * Register, configure, manipulate, locate services. + * See {@link DSpaceServiceManager} for a starting point. */ package org.dspace.servicemanager; diff --git a/dspace-services/src/main/java/org/dspace/servicemanager/spring/DSpaceBeanFactoryPostProcessor.java b/dspace-services/src/main/java/org/dspace/servicemanager/spring/DSpaceBeanFactoryPostProcessor.java index 245527e76d..7f7a9aea25 100644 --- a/dspace-services/src/main/java/org/dspace/servicemanager/spring/DSpaceBeanFactoryPostProcessor.java +++ b/dspace-services/src/main/java/org/dspace/servicemanager/spring/DSpaceBeanFactoryPostProcessor.java @@ -10,8 +10,6 @@ package org.dspace.servicemanager.spring; import org.dspace.servicemanager.ServiceManagerSystem; import org.dspace.servicemanager.config.DSpaceConfigurationService; import org.dspace.services.ConfigurationService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; @@ -25,19 +23,17 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; */ public final class DSpaceBeanFactoryPostProcessor implements BeanFactoryPostProcessor { - private static Logger log = LoggerFactory.getLogger(DSpaceBeanFactoryPostProcessor.class); - + private ServiceManagerSystem serviceManager; private DSpaceConfigurationService configurationService; - private ServiceManagerSystem parent; private boolean testMode = false; - public DSpaceBeanFactoryPostProcessor(ServiceManagerSystem parent, - DSpaceConfigurationService configurationService, boolean testMode) { - if (parent == null || configurationService == null) { - throw new IllegalArgumentException("parent and configuration service cannot be null"); + public DSpaceBeanFactoryPostProcessor(ServiceManagerSystem serviceManager, + DSpaceConfigurationService configurationService, boolean testMode) { + if (configurationService == null) { + throw new IllegalArgumentException("Configuration service cannot be null"); } + this.serviceManager = serviceManager; this.configurationService = configurationService; - this.parent = parent; this.testMode = testMode; } @@ -45,11 +41,11 @@ public final class DSpaceBeanFactoryPostProcessor implements BeanFactoryPostProc * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory(org * .springframework.beans.factory.config.ConfigurableListableBeanFactory) */ - + @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // force config service to be registered first beanFactory.registerSingleton(ConfigurationService.class.getName(), configurationService); - beanFactory.registerSingleton(ServiceManagerSystem.class.getName(), parent); + beanFactory.registerSingleton(ServiceManagerSystem.class.getName(), serviceManager); } } diff --git a/dspace-services/src/main/java/org/dspace/servicemanager/spring/SpringServiceManager.java b/dspace-services/src/main/java/org/dspace/servicemanager/spring/SpringServiceManager.java deleted file mode 100644 index 10b52495cc..0000000000 --- a/dspace-services/src/main/java/org/dspace/servicemanager/spring/SpringServiceManager.java +++ /dev/null @@ -1,369 +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.servicemanager.spring; - -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.dspace.kernel.config.SpringLoader; -import org.dspace.servicemanager.DSpaceServiceManager; -import org.dspace.servicemanager.ServiceManagerSystem; -import org.dspace.servicemanager.config.DSpaceConfigurationService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.beans.factory.config.AutowireCapableBeanFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * This is the Spring implementation of the service manager. - * - * @author Aaron Zeckoski (azeckoski @ gmail.com) - */ -public final class SpringServiceManager implements ServiceManagerSystem { - - private static final Logger log = LoggerFactory.getLogger(SpringServiceManager.class); - - private ClassPathXmlApplicationContext applicationContext; - - /** - * @return the parent core Spring {@link ApplicationContext} - */ - @Override - public ClassPathXmlApplicationContext getApplicationContext() { - return applicationContext; - } - - /** - * @return the current spring bean factory OR null if there is not one - */ - public ListableBeanFactory getBeanFactory() { - if (applicationContext != null) { - return applicationContext.getBeanFactory(); - } - return null; - } - - private final ServiceManagerSystem parent; - private final DSpaceConfigurationService configurationService; - private boolean testMode = false; - private boolean developmentMode = false; - private String[] configPaths = null; - - /** - * For TESTING: - * Allows adding extra spring config paths. - * - * @param parent parent ServiceManagerSystem - * @param configurationService current DSpace configuration service - * @param testMode if true then do not load the core beans - * @param developmentMode if true then services loaded on demand only - * @param configPaths additional spring config paths within this classloader - */ - public SpringServiceManager(ServiceManagerSystem parent, DSpaceConfigurationService configurationService, - boolean testMode, boolean developmentMode, String... configPaths) { - if (parent == null) { - throw new IllegalArgumentException("parent SMS cannot be null"); - } - this.parent = parent; - if (configurationService == null) { - throw new IllegalArgumentException("configuration service cannot be null"); - } - this.configurationService = configurationService; - this.testMode = testMode; - this.developmentMode = developmentMode; - this.configPaths = configPaths; - } - - public static final String configPath = "spring/spring-dspace-applicationContext.xml"; - public static final String coreResourcePath = "classpath*:spring/spring-dspace-core-services.xml"; - public static final String addonResourcePath = "classpath*:spring/spring-dspace-addon-*-services.xml"; - - @SuppressWarnings("unchecked") - @Override - public T getServiceByName(String name, Class type) { - T bean = null; - // handle special case to return the core AC - if (ApplicationContext.class.getName().equals(name) - && ApplicationContext.class.isAssignableFrom(type)) { - bean = (T) getApplicationContext(); - } else { - if (name != null) { - // get by name and type - try { - bean = (T) applicationContext.getBean(name, type); - } catch (BeansException e) { - // no luck, try the fall back option - log.info( - "Unable to locate bean by name or id=" + name + ". Will try to look up bean by type next. " + - "BeansException: " + e - .getMessage()); - bean = null; - } - } else { - // try making up the name based on the type - try { - bean = (T) applicationContext.getBean(type.getName(), type); - } catch (BeansException e) { - // no luck, try the fall back option - log.info("Unable to locate bean by name or id=" + type - .getName() + ". Will try to look up bean by type next. BeansException: " + e.getMessage()); - bean = null; - } - } - // if still no luck then try by type only - if (name == null - && bean == null) { - try { - Map map = applicationContext.getBeansOfType(type); - if (map.size() == 1) { - // only return the bean if there is exactly one - bean = (T) map.values().iterator().next(); - } else { - log.error("Multiple beans of type " + type.getName() + " found. Only one was expected!"); - } - } catch (BeansException e) { - // I guess there are no beans of this type - log.error(e.getMessage(), e); - bean = null; - } - } - } - return bean; - } - - @SuppressWarnings("unchecked") - @Override - public List getServicesByType(Class type) { - ArrayList l = new ArrayList<>(); - Map beans; - try { - beans = applicationContext.getBeansOfType(type, true, true); - l.addAll((Collection) beans.values()); - } catch (BeansException e) { - throw new RuntimeException("Failed to get beans of type (" + type + "): " + e.getMessage(), e); - } - return l; - } - - @Override - public void shutdown() { - if (applicationContext != null) { - try { - applicationContext.close(); - } catch (Exception e) { - // keep going anyway - e.printStackTrace(); - } - try { - applicationContext.destroy(); - } catch (Exception e) { - // keep going anyway - e.printStackTrace(); - } - applicationContext = null; - log.info("Spring Service Manager Shutdown..."); - } - } - - @Override - public void startup() { - long startTime = System.currentTimeMillis(); - // get all spring config paths - String[] allPaths = getSpringPaths(testMode, configPaths, configurationService); - applicationContext = new ClassPathXmlApplicationContext(allPaths, false); - // Make sure that the spring files from the config directoy can override the spring files from our jars - applicationContext.setAllowBeanDefinitionOverriding(true); - applicationContext.setAllowCircularReferences(true); - //applicationContext.registerShutdownHook(); // this interferes with the kernel shutdown hook - // add the config interceptors (partially done in the xml) - applicationContext - .addBeanFactoryPostProcessor(new DSpaceBeanFactoryPostProcessor(parent, configurationService, testMode)); - applicationContext.refresh(); - if (developmentMode) { - log.warn("Spring Service Manager is running in developmentMode, services will be loaded on demand only"); - // TODO find a way to set this sucker to super duper lazy mode? it is currently not actually doing it - } else { - applicationContext.getBeanFactory().preInstantiateSingletons(); - applicationContext.getBeanFactory().freezeConfiguration(); - } - long totalTime = System.currentTimeMillis() - startTime; - log.info("Spring Service Manager started up in " + totalTime + " ms with " + applicationContext - .getBeanDefinitionCount() + " services..."); - } - - public static String[] getSpringPaths(boolean testMode, String[] configPaths, - DSpaceConfigurationService configurationService) { - List pathList = new LinkedList<>(); - pathList.add(configPath); - pathList.add(addonResourcePath); - if (testMode) { - log.warn("TEST Spring Service Manager running in test mode, no core beans will be started"); - } else { - // only load the core beans when not testing the service manager - pathList.add(coreResourcePath); - } - if (configPaths != null) { - pathList.addAll(Arrays.asList(configPaths)); - } - if (testMode) { - log.warn("TEST Spring Service Manager running in test mode, no dspace home spring files will be loaded"); - } else { - //Retrieve all our spring file locations depending on the deployed module - String[] springLoaderClassNames = configurationService.getArrayProperty("spring.springloader.modules"); - if (springLoaderClassNames != null) { - for (String springLoaderClassName : springLoaderClassNames) { - try { - Class springLoaderClass = (Class) Class - .forName(springLoaderClassName.trim()); - String[] resourcePaths = springLoaderClass.getConstructor().newInstance() - .getResourcePaths(configurationService); - if (resourcePaths != null) { - pathList.addAll(Arrays.asList(resourcePaths)); - } - } catch (ClassNotFoundException e) { - //Ignore this exception, if we get one this just means that this module isn't loaded - } catch (IllegalAccessException | IllegalArgumentException - | InstantiationException | NoSuchMethodException - | SecurityException | InvocationTargetException e) { - log.error("Error while retrieving spring resource paths for module: {}", - springLoaderClassName, e); - } - } - } - } - return pathList.toArray(new String[pathList.size()]); - } - - @SuppressWarnings("unchecked") - @Override - public T registerServiceClass(String name, Class type) { - if (name == null || type == null) { - throw new IllegalArgumentException("name and type must not be null for service registration"); - } - T service; - try { - service = (T) applicationContext.getBeanFactory() - .autowire(type, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true); - registerBean(name, service); - } catch (BeansException e) { - throw new IllegalArgumentException( - "Invalid service class (" + type + ") with name (" + name + ") registration: " + e.getMessage(), e); - } - return service; - } - - @Override - public void registerService(String name, Object service) { - if (name == null || service == null) { - throw new IllegalArgumentException("name and service must not be null for service registration"); - } - try { - applicationContext.getBeanFactory().autowireBean(service); - } catch (BeansException e) { - throw new IllegalArgumentException( - "Invalid service (" + service + ") with name (" + name + ") registration: " + e.getMessage(), e); - } - registerBean(name, service); - } - - @Override - public void registerServiceNoAutowire(String name, Object service) { - if (name == null || service == null) { - throw new IllegalArgumentException("name and service must not be null for service registration"); - } - registerBean(name, service); - } - - /** - * This handles the common part of the 2 types of service - * registrations. - * - * @param name name of bean - * @param service service object - */ - private void registerBean(String name, Object service) { - try { - applicationContext.getBeanFactory().initializeBean(service, name); - applicationContext.getBeanFactory().registerSingleton(name, service); - } catch (BeansException e) { - throw new IllegalArgumentException( - "Invalid service (" + service + ") with name (" + name + ") registration: " + e.getMessage(), e); - } - } - - @Override - public void unregisterService(String name) { - if (applicationContext.containsBean(name)) { - try { - Object beanInstance = applicationContext.getBean(name); - try { - applicationContext.getBeanFactory().destroyBean(name, beanInstance); - } catch (NoSuchBeanDefinitionException e) { - // this happens if the bean was registered manually (annoyingly) - DSpaceServiceManager.shutdownService(beanInstance); - } - } catch (BeansException e) { - // nothing to do here, could not find the bean - } - } - } - - @Override - public List getServicesNames() { - ArrayList beanNames = new ArrayList<>(); - String[] singletons = applicationContext.getBeanFactory().getSingletonNames(); - for (String singleton : singletons) { - if (singleton.startsWith("org.springframework.context")) { - continue; // skip the spring standard ones - } - beanNames.add(singleton); - } - Collections.sort(beanNames); - return beanNames; - } - - @Override - public boolean isServiceExists(String name) { - return applicationContext.containsBean(name); - } - - @Override - public Map getServices() { - Map services = new HashMap<>(); - String[] singletons = applicationContext.getBeanFactory().getSingletonNames(); - for (String singleton : singletons) { - if (singleton.startsWith("org.springframework.context")) { - continue; // skip the spring standard ones - } - String beanName = singleton; - Object service = applicationContext.getBeanFactory().getSingleton(beanName); - if (service == null) { - continue; - } - services.put(beanName, service); - } - return services; - } - - @Override - public void pushConfig(Map settings) { - throw new UnsupportedOperationException("Not implemented for individual service manager systems"); - } - -} diff --git a/dspace-services/src/main/java/org/dspace/servicemanager/spring/package-info.java b/dspace-services/src/main/java/org/dspace/servicemanager/spring/package-info.java index 8f491c877a..e979f2aea5 100644 --- a/dspace-services/src/main/java/org/dspace/servicemanager/spring/package-info.java +++ b/dspace-services/src/main/java/org/dspace/servicemanager/spring/package-info.java @@ -9,7 +9,7 @@ /** * Spring extensions and adaptors for DSpace. * - * @see org.dspace.utils.DSpace for starting the kernel. + * See {@link org.dspace.utils.DSpace} for starting the kernel. */ package org.dspace.servicemanager.spring; diff --git a/dspace-services/src/test/java/org/dspace/servicemanager/DSpaceServiceManagerTest.java b/dspace-services/src/test/java/org/dspace/servicemanager/DSpaceServiceManagerTest.java index 83f5cdfec2..47029d94c4 100644 --- a/dspace-services/src/test/java/org/dspace/servicemanager/DSpaceServiceManagerTest.java +++ b/dspace-services/src/test/java/org/dspace/servicemanager/DSpaceServiceManagerTest.java @@ -23,7 +23,6 @@ import org.dspace.servicemanager.config.DSpaceConfigurationService; import org.dspace.servicemanager.example.ConcreteExample; import org.dspace.servicemanager.fakeservices.FakeService1; import org.dspace.servicemanager.spring.SpringAnnotationBean; -import org.dspace.servicemanager.spring.TestSpringServiceManager; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -34,6 +33,7 @@ import org.junit.Test; * @author Aaron Zeckoski (azeckoski @ gmail.com) */ public class DSpaceServiceManagerTest { + public static String SPRING_TEST_CONFIG_FILE = "spring/spring-test-services.xml"; DSpaceServiceManager dsm; DSpaceConfigurationService configurationService; @@ -46,7 +46,7 @@ public class DSpaceServiceManagerTest { configurationService.loadConfig(SampleAnnotationBean.class.getName() + ".sampleValue", "beckyz"); configurationService.loadConfig("fakeBean.fakeParam", "beckyz"); - dsm = new DSpaceServiceManager(configurationService, TestSpringServiceManager.SPRING_TEST_CONFIG_FILE); + dsm = new DSpaceServiceManager(configurationService, SPRING_TEST_CONFIG_FILE); } @After @@ -256,7 +256,7 @@ public class DSpaceServiceManagerTest { public void testPushConfig() { dsm.startup(); - Map properties = new HashMap(); + Map properties = new HashMap<>(); properties.put("some.test.thing", "A value"); dsm.pushConfig(properties); @@ -298,7 +298,7 @@ public class DSpaceServiceManagerTest { assertEquals(1, service.getTriggers()); // now we do a config change - Map properties = new HashMap(); + Map properties = new HashMap<>(); properties.put("azeckoski.FakeService1.something", "THING"); dsm.pushConfig(properties); assertEquals("config:THING", service.getSomething()); @@ -317,10 +317,12 @@ public class DSpaceServiceManagerTest { public int value = 0; + @Override public void init() { value++; } + @Override public void shutdown() { value++; } diff --git a/dspace-services/src/test/java/org/dspace/servicemanager/spring/TestSpringServiceManager.java b/dspace-services/src/test/java/org/dspace/servicemanager/spring/TestSpringServiceManager.java deleted file mode 100644 index 62353755f5..0000000000 --- a/dspace-services/src/test/java/org/dspace/servicemanager/spring/TestSpringServiceManager.java +++ /dev/null @@ -1,229 +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.servicemanager.spring; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.List; - -import org.dspace.servicemanager.MockServiceManagerSystem; -import org.dspace.servicemanager.SampleAnnotationBean; -import org.dspace.servicemanager.config.DSpaceConfigurationService; -import org.dspace.servicemanager.example.ConcreteExample; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - - -/** - * Testing the spring based service manager - * - * @author Aaron Zeckoski (azeckoski @ gmail.com) - */ -public class TestSpringServiceManager { - - public static String SPRING_TEST_CONFIG_FILE = "spring/spring-test-services.xml"; - - SpringServiceManager ssm; - DSpaceConfigurationService configurationService; - - @Before - public void init() { - configurationService = new DSpaceConfigurationService(); - configurationService.loadConfig(SampleAnnotationBean.class.getName() + ".sampleValue", "beckyz"); - configurationService.loadConfig("fakeBean.fakeParam", "beckyz"); - - ssm = new SpringServiceManager(new MockServiceManagerSystem(ssm), configurationService, true, true, - SPRING_TEST_CONFIG_FILE); - } - - @After - public void shutdown() { - if (ssm != null) { - ssm.shutdown(); - } - ssm = null; - configurationService = null; - } - - /** - * Test method for {@link org.dspace.servicemanager.spring.SpringServiceManager#startup()}. - */ - @Test - public void testStartup() { - // testing we can start this up with null config - configurationService.clear(); - ssm.startup(); - } - - @Test - public void testStartupWithConfig() { - // testing we can start this up a real config - ssm.startup(); - } - - /** - * Test method for {@link org.dspace.servicemanager.spring.SpringServiceManager#shutdown()}. - */ - @Test - public void testShutdown() { - ssm.startup(); - ssm.shutdown(); - } - - /** - * Test method for - * {@link org.dspace.servicemanager.spring.SpringServiceManager#getServiceByName(java.lang.String, java.lang.Class)}. - */ - @Test - public void testGetServiceByName() { - configurationService.clear(); // no config - ssm.startup(); - - ConcreteExample concrete = ssm.getServiceByName(ConcreteExample.class.getName(), ConcreteExample.class); - assertNotNull(concrete); - assertEquals("azeckoski", concrete.getName()); - concrete = null; - - SampleAnnotationBean sab = ssm - .getServiceByName(SampleAnnotationBean.class.getName(), SampleAnnotationBean.class); - assertNotNull(sab); - assertEquals(null, sab.getSampleValue()); - sab = null; - } - - @Test - public void testGetServiceByNameConfig() { - ssm.startup(); - - ConcreteExample concrete = ssm.getServiceByName(ConcreteExample.class.getName(), ConcreteExample.class); - assertNotNull(concrete); - assertEquals("azeckoski", concrete.getName()); - concrete = null; - - SampleAnnotationBean sab = ssm - .getServiceByName(SampleAnnotationBean.class.getName(), SampleAnnotationBean.class); - assertNotNull(sab); - assertEquals("beckyz", sab.getSampleValue()); - sab = null; - - SpringAnnotationBean spr = ssm - .getServiceByName(SpringAnnotationBean.class.getName(), SpringAnnotationBean.class); - assertNotNull(spr); - assertEquals("azeckoski", spr.getConcreteName()); - assertEquals("aaronz", spr.getExampleName()); - assertEquals(null, spr.getSampleValue()); - spr = null; - } - - /** - * Test method for {@link org.dspace.servicemanager.spring.SpringServiceManager#getServicesByType(java.lang.Class)}. - */ - @Test - public void testGetServicesByType() { - ssm.startup(); - - List l = ssm.getServicesByType(ConcreteExample.class); - assertNotNull(l); - assertEquals(1, l.size()); - assertEquals("azeckoski", l.get(0).getName()); - l = null; - - List l2 = ssm.getServicesByType(SampleAnnotationBean.class); - assertNotNull(l2); - assertEquals(1, l2.size()); - l2 = null; - } - - /** - * Test method for - * {@link org.dspace.servicemanager.spring.SpringServiceManager#registerServiceClass(java.lang.String, java.lang.Class)}. - */ - @Test - public void testRegisterServiceClass() { - ssm.startup(); - - SampleAnnotationBean sab = ssm.registerServiceClass("newAnnote", SampleAnnotationBean.class); - assertNotNull(sab); - sab = null; - - List l = ssm.getServicesByType(SampleAnnotationBean.class); - assertNotNull(l); - assertEquals(2, l.size()); - l = null; - - try { - ssm.registerService("fakey", (Class) null); - fail("should have thrown exception"); - } catch (IllegalArgumentException e) { - assertNotNull(e.getMessage()); - } - } - - /** - * Test method for - * {@link org.dspace.servicemanager.spring.SpringServiceManager#registerService(java.lang.String, java.lang.Object)}. - */ - @Test - public void testRegisterService() { - ssm.startup(); - - String name = "myNewService"; - ssm.registerService(name, "AZ"); - String service = ssm.getServiceByName(name, String.class); - assertNotNull(service); - assertEquals("AZ", service); - - try { - ssm.registerService("fakey", (Object) null); - fail("should have thrown exception"); - } catch (IllegalArgumentException e) { - assertNotNull(e.getMessage()); - } - } - - @Test - public void testUnregisterService() { - ssm.startup(); - - String name = "myNewService"; - ssm.registerService(name, "AZ"); - String service = ssm.getServiceByName(name, String.class); - assertNotNull(service); - assertEquals("AZ", service); - - ssm.unregisterService(name); - } - - @Test - public void testGetServicesNames() { - ssm.startup(); - - List names = ssm.getServicesNames(); - assertNotNull(names); - assertTrue(names.size() >= 3); - names = null; - } - - @Test - public void testIsServiceExists() { - ssm.startup(); - - String name = ConcreteExample.class.getName(); - boolean exists = ssm.isServiceExists(name); - assertTrue(exists); - - exists = ssm.isServiceExists("XXXXXXXXXXXXXXX"); - assertFalse(exists); - } - -} From 84803770c0850dcc16029a4fee3ebad73ef9dccd Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Mon, 26 Aug 2019 16:17:00 -0400 Subject: [PATCH 003/125] [DS-2378] Copy a blob of test code from deleted TestSpringServiceManager. --- .../dspace/servicemanager/DSpaceServiceManagerTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dspace-services/src/test/java/org/dspace/servicemanager/DSpaceServiceManagerTest.java b/dspace-services/src/test/java/org/dspace/servicemanager/DSpaceServiceManagerTest.java index 47029d94c4..a49d115410 100644 --- a/dspace-services/src/test/java/org/dspace/servicemanager/DSpaceServiceManagerTest.java +++ b/dspace-services/src/test/java/org/dspace/servicemanager/DSpaceServiceManagerTest.java @@ -185,6 +185,14 @@ public class DSpaceServiceManagerTest { // a value should be pre-set! assertEquals("beckyz", sab.getSampleValue()); sab = null; + + SpringAnnotationBean spr = dsm.getServiceByName( + SpringAnnotationBean.class.getName(), SpringAnnotationBean.class); + assertNotNull(spr); + assertEquals("azeckoski", spr.getConcreteName()); + assertEquals("aaronz", spr.getExampleName()); + assertEquals(null, spr.getSampleValue()); + spr = null; } /** From 4b92af8239d3e8b4481d3b9b4ca4c18cdde015f2 Mon Sep 17 00:00:00 2001 From: Kevin Van de Velde Date: Thu, 3 Oct 2019 09:41:51 +0200 Subject: [PATCH 004/125] [DS-4351] Upgrade spring (boot) & hibernate to newer versions --- dspace-server-webapp/pom.xml | 2 +- .../java/org/dspace/app/rest/Application.java | 2 +- .../app/rest/MappedItemRestController.java | 2 +- .../app/rest/RestResourceController.java | 15 +++++----- .../AuthorityEntryLinkRepository.java | 2 +- .../repository/BitstreamRestRepository.java | 2 +- .../repository/BrowseEntryLinkRepository.java | 2 +- .../repository/BrowseItemLinkRepository.java | 2 +- .../repository/CollectionRestRepository.java | 2 +- .../repository/CommunityRestRepository.java | 2 +- .../rest/repository/DSpaceRestRepository.java | 28 +++++++++++-------- .../repository/EPersonRestRepository.java | 4 +-- .../rest/repository/GroupRestRepository.java | 2 +- .../rest/repository/ItemRestRepository.java | 2 +- .../SubmissionDefinitionRestRepository.java | 2 +- .../SubmissionFormRestRepository.java | 2 +- .../SubmissionPanelRestRepository.java | 2 +- .../SubmissionUploadRestRepository.java | 2 +- .../WorkspaceItemRestRepository.java | 4 +-- .../app/rest/utils/DiscoverQueryBuilder.java | 4 +-- .../java/org/dspace/app/rest/utils/Utils.java | 4 +-- dspace-services/pom.xml | 2 +- pom.xml | 10 +++---- 23 files changed, 54 insertions(+), 47 deletions(-) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 0c872184ff..1b952caf21 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -211,7 +211,7 @@ org.springframework.data spring-data-rest-hal-browser - 2.5.7.RELEASE + 3.1.10.RELEASE 2.8.11 - 2.26 - 5.2.8.Final - 5.4.2.Final + 2.28 + 5.4.5.Final + 6.0.17.Final 7.3.1 - 4.3.24.RELEASE - 1.4.4.RELEASE + 5.1.9.RELEASE + 2.1.8.RELEASE ${basedir} From e2c353d75e9b339d13f7f2279929edd21f26b2fa Mon Sep 17 00:00:00 2001 From: Samuel Date: Fri, 25 Oct 2019 18:21:49 +0200 Subject: [PATCH 005/125] DS-4351 Upgrade spring (boot) & hibernate to newer versions --- dspace-api/pom.xml | 135 +----------------- .../dspace/app/bulkedit/BulkEditChange.java | 1 + .../util/GoogleBitstreamComparatorTest.java | 8 -- .../dspace/content/EntityServiceImplTest.java | 10 -- .../content/RelationshipServiceImplTest.java | 16 --- .../NameAscendingComparatorTest.java | 2 - .../dspace/content/virtual/RelatedTest.java | 4 - .../src/test/resources/log4j.properties | 10 +- dspace-oai/pom.xml | 3 +- dspace-server-webapp/pom.xml | 46 ++---- .../java/org/dspace/app/rest/Application.java | 9 +- .../app/rest/RestResourceController.java | 30 ++-- .../app/rest/StatisticsRestController.java | 5 +- .../rest/converter/BrowseEntryConverter.java | 7 +- .../app/rest/converter/DSpaceConverter.java | 10 +- .../AuthorityEntryLinkRepository.java | 3 +- .../DSpaceObjectRestRepository.java | 6 +- .../repository/EPersonRestRepository.java | 6 +- .../SubmissionDefinitionRestRepository.java | 3 +- .../SubmissionPanelRestRepository.java | 3 +- .../SubmissionUploadRestRepository.java | 5 +- .../WorkflowItemRestRepository.java | 4 +- .../WorkspaceItemRestRepository.java | 4 +- .../app/rest/utils/ApplicationConfig.java | 2 +- .../java/org/dspace/app/rest/utils/Utils.java | 3 +- .../src/main/resources/application.properties | 2 + .../rest/BitstreamFormatRestRepositoryIT.java | 2 +- .../jwt/EPersonClaimProviderTest.java | 1 - .../security/jwt/JWTTokenHandlerTest.java | 1 - .../jwt/SpecialGroupClaimProviderTest.java | 2 +- .../AbstractControllerIntegrationTest.java | 2 +- .../AbstractWebClientIntegrationTest.java | 2 +- .../rest/utils/DiscoverQueryBuilderTest.java | 113 ++++++++++----- .../src/test/resources/log4j.properties | 6 +- dspace-services/pom.xml | 34 +---- .../src/test/resources/log4j.properties | 4 +- dspace/config/log4j2-console.xml | 30 ++-- dspace/config/log4j2.xml | 85 +++++------ .../config/spring/api/access-conditions.xml | 10 +- dspace/config/spring/api/core-hibernate.xml | 4 +- dspace/pom.xml | 5 + pom.xml | 51 +++++-- 42 files changed, 281 insertions(+), 408 deletions(-) diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 13ea5a56c7..c14f7a4d58 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -296,16 +296,7 @@ - - org.hibernate - hibernate-core - - - org.jboss.logging - jboss-logging - - - + org.hibernate hibernate-ehcache @@ -315,10 +306,11 @@ hibernate-jpamodelgen - org.hibernate - hibernate-validator-cdi - ${hibernate-validator.version} + org.hibernate + hibernate-validator-cdi + ${hibernate-validator.version} + org.springframework spring-orm @@ -355,28 +347,6 @@ org.apache.jena apache-jena-libs pom - - - com.fasterxml.jackson.core - jackson-core - - - com.fasterxml.jackson.core - jackson-databind - - - org.slf4j - slf4j-log4j12 - - - log4j - log4j - - - - - commons-cli - commons-cli commons-codec @@ -434,18 +404,6 @@ org.jdom jdom - - org.apache.logging.log4j - log4j-api - - - org.apache.logging.log4j - log4j-1.2-api - - - org.apache.logging.log4j - log4j-core - oro oro @@ -458,10 +416,6 @@ org.apache.pdfbox fontbox - - org.apache.poi - poi - org.apache.poi poi-scratchpad @@ -481,12 +435,6 @@ xerces xercesImpl - - - xml-apis - xml-apis - - xml-apis @@ -539,66 +487,15 @@ rome-modules 1.0 - - gr.ekt.bte - bte-core - 0.9.3.5 - - - - org.mockito - mockito-core - - - log4j - log4j - - - gr.ekt.bte bte-io 0.9.3.5 - - - - org.apache.commons - commons-lang3 - - - - org.mockito - mockito-core - - - log4j - log4j - - - - - org.apache.httpcomponents - httpcore org.apache.httpcomponents httpclient - - org.apache.solr - solr-solrj - ${solr.client.version} - - - org.slf4j - jcl-over-slf4j - - - org.slf4j - slf4j-api - - - org.apache.solr @@ -606,10 +503,6 @@ ${solr.client.version} - - org.apache.commons - commons-configuration2 - com.maxmind.geoip2 geoip2 @@ -625,12 +518,6 @@ 2.1.7 - - org.apache.lucene - lucene-core - ${solr.client.version} - - com.coverity.security coverity-escapers @@ -655,11 +542,6 @@ postgresql - - org.slf4j - slf4j-api - - jdbm jdbm @@ -744,12 +626,6 @@ com.amazonaws aws-java-sdk-s3 1.10.50 - - - joda-time - joda-time - - @@ -791,6 +667,7 @@ hibernate-jpa-2.1-api 1.0.0.Final + diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkEditChange.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkEditChange.java index 0dbb8bd7bb..150a6ea20d 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkEditChange.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/BulkEditChange.java @@ -19,6 +19,7 @@ import org.dspace.content.Item; * @author Stuart Lewis */ public class BulkEditChange { + /** * The item these changes relate to */ diff --git a/dspace-api/src/test/java/org/dspace/app/util/GoogleBitstreamComparatorTest.java b/dspace-api/src/test/java/org/dspace/app/util/GoogleBitstreamComparatorTest.java index 68b50a4f10..039d634938 100644 --- a/dspace-api/src/test/java/org/dspace/app/util/GoogleBitstreamComparatorTest.java +++ b/dspace-api/src/test/java/org/dspace/app/util/GoogleBitstreamComparatorTest.java @@ -138,7 +138,6 @@ public class GoogleBitstreamComparatorTest extends AbstractUnitTest { when(bitstreamFormat3.getMIMEType()).thenReturn("application/postscript"); when(bitstream1.getSizeBytes()).thenReturn(Long.valueOf(100)); when(bitstream2.getSizeBytes()).thenReturn(Long.valueOf(200)); - when(bitstream3.getSizeBytes()).thenReturn(Long.valueOf(300)); List toSort = bundle.getBitstreams(); Collections.sort(toSort, new GoogleBitstreamComparator(context, settings)); @@ -181,7 +180,6 @@ public class GoogleBitstreamComparatorTest extends AbstractUnitTest { when(bitstreamFormat1.getMIMEType()).thenReturn("unknown"); when(bitstreamFormat2.getMIMEType()).thenReturn("text/richtext"); when(bitstreamFormat3.getMIMEType()).thenReturn("text/richtext"); - when(bitstream1.getSizeBytes()).thenReturn(Long.valueOf(400)); when(bitstream2.getSizeBytes()).thenReturn(Long.valueOf(200)); when(bitstream3.getSizeBytes()).thenReturn(Long.valueOf(300)); @@ -342,9 +340,6 @@ public class GoogleBitstreamComparatorTest extends AbstractUnitTest { when(bitstreamFormat1.getMIMEType()).thenReturn("text/richtext"); when(bitstreamFormat2.getMIMEType()).thenReturn("application/msword"); when(bitstreamFormat3.getMIMEType()).thenReturn("application/postscript"); - when(bitstream1.getSizeBytes()).thenReturn(Long.valueOf(100)); - when(bitstream2.getSizeBytes()).thenReturn(Long.valueOf(200)); - when(bitstream3.getSizeBytes()).thenReturn(Long.valueOf(300)); List toSort = bundle.getBitstreams(); Collections.sort(toSort, new GoogleBitstreamComparator(context, settings)); @@ -362,9 +357,6 @@ public class GoogleBitstreamComparatorTest extends AbstractUnitTest { when(bitstreamFormat1.getMIMEType()).thenReturn("text/richtext"); when(bitstreamFormat2.getMIMEType()).thenReturn("application/msword"); when(bitstreamFormat3.getMIMEType()).thenReturn("audio/x-wav"); - when(bitstream1.getSizeBytes()).thenReturn(Long.valueOf(300)); - when(bitstream2.getSizeBytes()).thenReturn(Long.valueOf(200)); - when(bitstream3.getSizeBytes()).thenReturn(Long.valueOf(100)); List toSort = bundle.getBitstreams(); Collections.sort(toSort, new GoogleBitstreamComparator(context, settings)); diff --git a/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java b/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java index fb8e1c6ab3..60ebbb2bec 100644 --- a/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java +++ b/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java @@ -86,10 +86,6 @@ public class EntityServiceImplTest { list.add(metadataValue); EntityType entityType = entityTypeService.findByEntityType(context, "testType"); - // Mock the state of objects utilized in getType() to meet the success criteria of an invocation - when(metadataValue.getValue()).thenReturn("testType"); - when(itemService.getMetadata(item, "relationship", "type", null, Item.ANY)).thenReturn(list); - // The returned EntityType should equal our defined entityType case assertEquals("TestGetType 0", entityType, entityService.getType(context, entity)); } @@ -149,7 +145,6 @@ public class EntityServiceImplTest { when(relationshipService.findAll(context)).thenReturn(relationshipList); when(relationship.getRelationshipType()).thenReturn(relationshipType); when(relationshipType.getLeftLabel()).thenReturn("leftLabel"); - when(relationshipType.getRightLabel()).thenReturn("rightLabel"); // The relation(s) reported from our defined label should match our relationshipList assertEquals("TestGetRelationsByLabel 0", relationshipList, @@ -178,13 +173,9 @@ public class EntityServiceImplTest { when(metadataValue.getValue()).thenReturn("testType"); when(entity.getItem()).thenReturn(item); when(itemService.getMetadata(item, "relationship", "type", null, Item.ANY)).thenReturn(list); - when(relationshipTypeDAO.findAll(context, RelationshipType.class)).thenReturn(relationshipTypeList); when(relationshipTypeService.findAll(context)).thenReturn(relationshipTypeList); when(relationshipType.getLeftType()).thenReturn(leftType); - when(relationshipType.getRightType()).thenReturn(rightType); - when(entityTypeService.findByEntityType(context, "value")).thenReturn(leftType); when(leftType.getID()).thenReturn(0); - when(rightType.getID()).thenReturn(1); when(entityService.getType(context, entity)).thenReturn(leftType); // Mock // The relation(s) reported from our mocked Entity should match our relationshipList @@ -264,7 +255,6 @@ public class EntityServiceImplTest { // to meet the success criteria of the invocation when(relationshipTypeService.findAll(context)).thenReturn(list); when(relationshipType.getLeftLabel()).thenReturn("leftLabel"); - when(relationshipType.getRightLabel()).thenReturn("rightLabel"); // The RelationshipType(s) reported from our mocked Entity should match our list assertEquals("TestGetRelationshipTypesByLabel 0", list, diff --git a/dspace-api/src/test/java/org/dspace/content/RelationshipServiceImplTest.java b/dspace-api/src/test/java/org/dspace/content/RelationshipServiceImplTest.java index 47a1a0b473..3b6ec201f7 100644 --- a/dspace-api/src/test/java/org/dspace/content/RelationshipServiceImplTest.java +++ b/dspace-api/src/test/java/org/dspace/content/RelationshipServiceImplTest.java @@ -206,8 +206,6 @@ public class RelationshipServiceImplTest { .isUseForPlaceTrueForRelationshipType(relationship.getRelationshipType(), true)).thenReturn(true); when(authorizeService .authorizeActionBoolean(context, relationship.getLeftItem(), Constants.WRITE)).thenReturn(true); - when(authorizeService - .authorizeActionBoolean(context, relationship.getRightItem(), Constants.WRITE)).thenReturn(true); when(relationshipService.findByItem(context,leftItem)).thenReturn(leftTypelist); when(relationshipService.findByItem(context,rightItem)).thenReturn(rightTypelist); when(leftEntityType.getLabel()).thenReturn("Entitylabel"); @@ -232,8 +230,6 @@ public class RelationshipServiceImplTest { @Test public void testDelete() throws Exception { - // Mock admin state - when(authorizeService.isAdmin(context)).thenReturn(true); // Declare objects utilized in unit test MetadataValue metVal = mock(MetadataValue.class); @@ -261,19 +257,10 @@ public class RelationshipServiceImplTest { .thenReturn(true); when(authorizeService.authorizeActionBoolean(context, relationship.getLeftItem(), Constants.WRITE)) .thenReturn(true); - when(authorizeService.authorizeActionBoolean(context, relationship.getRightItem(), Constants.WRITE)) - .thenReturn(true); when(relationshipService.findByItem(context,leftItem)).thenReturn(leftTypelist); when(relationshipService.findByItem(context,rightItem)).thenReturn(rightTypelist); - when(leftEntityType.getLabel()).thenReturn("Entitylabel"); - when(rightEntityType.getLabel()).thenReturn("Entitylabel"); - when(metVal.getValue()).thenReturn("Entitylabel"); - when(metsList.get(0).getValue()).thenReturn("Entitylabel"); when(relationshipService.findByItemAndRelationshipType(context, leftItem, testRel, true)) .thenReturn(leftTypelist); - when(itemService.getMetadata(leftItem, "relationship", "type", null, Item.ANY)).thenReturn(metsList); - when(itemService.getMetadata(rightItem, "relationship", "type", null, Item.ANY)).thenReturn(metsList); - when(relationshipDAO.create(any(), any())).thenReturn(relationship); when(relationshipService.find(context,0)).thenReturn(relationship); // Invoke delete() @@ -287,7 +274,6 @@ public class RelationshipServiceImplTest { public void testUpdate() throws Exception { // Mock admin state context.turnOffAuthorisationSystem(); - when(authorizeService.isAdmin(context)).thenReturn(true); // Declare objects utilized in unit test MetadataValue metVal = mock(MetadataValue.class); @@ -311,8 +297,6 @@ public class RelationshipServiceImplTest { when(itemService.getMetadata(rightItem, "relationship", "type", null, Item.ANY)).thenReturn(metsList); when(authorizeService.authorizeActionBoolean(context, relationship.getLeftItem(), Constants.WRITE)).thenReturn(true); - when(authorizeService.authorizeActionBoolean(context, relationship.getRightItem(), - Constants.WRITE)).thenReturn(true); // Invoke update() relationshipService.update(context, relationship); diff --git a/dspace-api/src/test/java/org/dspace/content/comparator/NameAscendingComparatorTest.java b/dspace-api/src/test/java/org/dspace/content/comparator/NameAscendingComparatorTest.java index d65360e8fb..e03ce73ada 100644 --- a/dspace-api/src/test/java/org/dspace/content/comparator/NameAscendingComparatorTest.java +++ b/dspace-api/src/test/java/org/dspace/content/comparator/NameAscendingComparatorTest.java @@ -54,14 +54,12 @@ public class NameAscendingComparatorTest { @Test public void testCompareFirstNull() throws Exception { - when(dso2.getName()).thenReturn("b"); assertTrue(comparator.compare(null, dso2) < 0); } @Test public void testCompareSecondNull() throws Exception { - when(dso1.getName()).thenReturn("a"); assertTrue(comparator.compare(dso1, null) > 0); } diff --git a/dspace-api/src/test/java/org/dspace/content/virtual/RelatedTest.java b/dspace-api/src/test/java/org/dspace/content/virtual/RelatedTest.java index 535a2db3ec..e1e78b6db2 100644 --- a/dspace-api/src/test/java/org/dspace/content/virtual/RelatedTest.java +++ b/dspace-api/src/test/java/org/dspace/content/virtual/RelatedTest.java @@ -132,9 +132,7 @@ public class RelatedTest { // Mock the state of objects utilized in getRelationsByLabel() to meet the success criteria of an invocation when(item.getID()).thenReturn(UUID.randomUUID()); when(relationshipType.getLeftLabel()).thenReturn("LeftLabel"); - when(relationshipType.getRightLabel()).thenReturn("RightLabel"); when(relationshipType.getLeftType()).thenReturn(entityType); - when(relationshipType.getRightType()).thenReturn(entityType); when(entityService.getAllRelationshipTypes(context, entity)).thenReturn(relationshipTypeList); when(entityService.findByItemId(context, item.getID())).thenReturn(entity); when(entityService.getType(context, entity)).thenReturn(entityType); @@ -142,9 +140,7 @@ public class RelatedTest { .thenReturn(relationshipList); when(relationship.getRelationshipType()).thenReturn(relationshipType); when(relationship.getLeftPlace()).thenReturn(0); - when(relationship.getRightPlace()).thenReturn(1); when(relationship.getRightItem()).thenReturn(item); - when(relationship.getLeftItem()).thenReturn(item); // The reported values should match out mocked collection of values assertEquals("TestGetValues 0", virtualMetadataConfiguration.getValues(context, item), diff --git a/dspace-api/src/test/resources/log4j.properties b/dspace-api/src/test/resources/log4j.properties index 4e7fbff3e3..2797b7c655 100644 --- a/dspace-api/src/test/resources/log4j.properties +++ b/dspace-api/src/test/resources/log4j.properties @@ -19,16 +19,12 @@ log4j.rootCategory=INFO, A1 # A1 is set to be a ConsoleAppender. -log4j.appender.A1=org.apache.logging.log4j.ConsoleAppender +log4j.appender.A1=org.apache.log4j.ConsoleAppender # A1 uses PatternLayout. log4j.appender.A1.layout=org.apache.logging.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=%d %-5p %c @ %m%n -# block passwords from being exposed in Axis logs. -# (DEBUG exposes passwords in Basic Auth) -log4j.logger.org.apache.axis.handlers.http.HTTPAuthHandler=INFO - ########################################################################### # Other settings ########################################################################### @@ -44,9 +40,9 @@ log4j.logger.org.dspace.servicemanager=ERROR log4j.logger.org.dspace.providers=ERROR log4j.logger.org.dspace.utils=ERROR -log4j.appender.stdout=org.apache.logging.log4j.ConsoleAppender +log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out -log4j.appender.stdout.layout=org.apache.logging.log4j.PatternLayout +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n # # Root logger option diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index 0e7f2bd0eb..fe8a940fc3 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -16,8 +16,7 @@ ${basedir}/.. 3.2.10 - - 5.86.1.RELEASE + 5.87.0.RELEASE diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 1b952caf21..5bc661ebf8 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -161,6 +161,7 @@ + @@ -179,22 +180,12 @@ provided --> - - org.springframework.boot - spring-boot-starter-web - ${spring-boot.version} - - - org.springframework.boot - spring-boot-starter-tomcat - provided - ${spring-boot.version} - org.springframework.boot spring-boot-starter-data-rest ${spring-boot.version} + org.springframework.boot spring-boot-starter-aop @@ -232,7 +223,7 @@ org.springframework.boot spring-boot-starter - ${spring-boot.version} + ${spring-boot.version} org.springframework.boot @@ -240,10 +231,11 @@ + org.springframework.boot spring-boot-starter-log4j2 - ${spring-boot.version} + ${spring-boot.version} @@ -252,11 +244,6 @@ dspace-api - - org.dspace - dspace-services - - @@ -277,13 +264,10 @@ - org.apache.commons - commons-collections4 - - - joda-time - joda-time + com.fasterxml.jackson.core + jackson-databind + com.nimbusds nimbus-jose-jwt @@ -301,20 +285,6 @@ spring-boot-starter-test ${spring-boot.version} test - - - - org.json - json - - - - com.jayway.jsonpath - json-path - - com.jayway.jsonpath diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/Application.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/Application.java index bb68b0ee38..900324fc72 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/Application.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/Application.java @@ -27,12 +27,12 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer import org.springframework.context.annotation.Bean; import org.springframework.core.annotation.Order; import org.springframework.hateoas.RelProvider; +import org.springframework.lang.NonNull; import org.springframework.web.context.request.RequestContextListener; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** * Define the Spring Boot Application settings itself. This class takes the place @@ -124,9 +124,10 @@ public class Application extends SpringBootServletInitializer { @Bean public WebMvcConfigurer webMvcConfigurer() { - return new WebMvcConfigurerAdapter() { + + return new WebMvcConfigurer() { @Override - public void addCorsMappings(CorsRegistry registry) { + public void addCorsMappings(@NonNull CorsRegistry registry) { String[] corsAllowedOrigins = configuration.getCorsAllowedOrigins(); if (corsAllowedOrigins != null) { registry.addMapping("/api/**").allowedMethods(CorsConfiguration.ALL) @@ -138,7 +139,7 @@ public class Application extends SpringBootServletInitializer { } @Override - public void addArgumentResolvers(List argumentResolvers) { + public void addArgumentResolvers(@NonNull List argumentResolvers) { argumentResolvers.add(new SearchFilterResolver()); } }; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/RestResourceController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/RestResourceController.java index 3839d343a7..04f6bb926b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/RestResourceController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/RestResourceController.java @@ -68,6 +68,7 @@ import org.springframework.hateoas.Resource; import org.springframework.hateoas.ResourceSupport; import org.springframework.hateoas.Resources; import org.springframework.hateoas.UriTemplate; +import org.springframework.hateoas.mvc.ControllerLinkBuilder; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -449,7 +450,7 @@ public class RestResourceController implements InitializingBean { DSpaceResource result = repository.wrapResource(modelObject); linkService.addLinks(result); //TODO manage HTTPHeader - return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result); + return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), result); } /** @@ -482,7 +483,7 @@ public class RestResourceController implements InitializingBean { DSpaceResource result = repository.wrapResource(modelObject); linkService.addLinks(result); //TODO manage HTTPHeader - return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result); + return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), result); } @@ -520,7 +521,7 @@ public class RestResourceController implements InitializingBean { if (modelObject != null) { DSpaceResource result = repository.wrapResource(modelObject); linkService.addLinks(result); - return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result); + return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), result); } else { return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT); } @@ -612,7 +613,7 @@ public class RestResourceController implements InitializingBean { } DSpaceResource result = repository.wrapResource(modelObject); linkService.addLinks(result); - return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result); + return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), result); } /** @@ -652,7 +653,7 @@ public class RestResourceController implements InitializingBean { linkService.addLinks(result); resources.add(result); } - return ControllerUtils.toResponseEntity(HttpStatus.OK, null, Resources.wrap(resources)); + return ControllerUtils.toResponseEntity(HttpStatus.OK, new HttpHeaders(), Resources.wrap(resources)); } /** @@ -731,7 +732,7 @@ public class RestResourceController implements InitializingBean { DSpaceResource result = repository.wrapResource(modelObject); linkService.addLinks(result); //TODO manage HTTPHeader - return ControllerUtils.toResponseEntity(HttpStatus.OK, null, result); + return ControllerUtils.toResponseEntity(HttpStatus.OK, new HttpHeaders(), result); } @@ -934,19 +935,24 @@ public class RestResourceController implements InitializingBean { @RequestParam(required = false) String projection, HttpServletResponse response) { + DSpaceRestRepository repository = utils.getResourceRepository(apiCategory, model); - Link link = linkTo(methodOn(this.getClass(), apiCategory, model).findAll(apiCategory, model, - page, assembler, projection, response)) - .withSelfRel(); + + RestResourceController restResourceController = methodOn(this.getClass(), apiCategory, model); + + PagedResources> all = restResourceController + .findAll(apiCategory, model, page, assembler, projection, response); + + ControllerLinkBuilder controllerLinkBuilder = linkTo(all); + + Link link = controllerLinkBuilder.withSelfRel(); Page> resources; try { resources = repository.findAll(page).map(repository::wrapResource); resources.forEach(linkService::addLinks); } catch (PaginationException pe) { - resources = new PageImpl>(new ArrayList>(), page, pe.getTotal()); - } catch (RepositoryMethodNotImplementedException mne) { - throw mne; + resources = new PageImpl<>(new ArrayList<>(), page, pe.getTotal()); } PagedResources> result = assembler.toResource(resources, link); if (repositoryUtils.haveSearchMethods(repository)) { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/StatisticsRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/StatisticsRestController.java index 6b55879158..b7b94280f1 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/StatisticsRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/StatisticsRestController.java @@ -27,6 +27,7 @@ import org.springframework.data.rest.webmvc.ControllerUtils; import org.springframework.hateoas.Link; import org.springframework.hateoas.PagedResources; import org.springframework.hateoas.ResourceSupport; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; @@ -94,13 +95,13 @@ public class StatisticsRestController implements InitializingBean { @RequestMapping(method = RequestMethod.POST, value = "/viewevents") public ResponseEntity postViewEvent() throws Exception { ViewEventResource result = new ViewEventResource(viewEventRestRepository.createViewEvent(), utils); - return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result); + return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), result); } @RequestMapping(method = RequestMethod.POST, value = "/searchevents") public ResponseEntity postSearchEvent() throws Exception { SearchEventResource result = new SearchEventResource(searchEventRestRepository.createSearchEvent(), utils); - return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result); + return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), result); } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/BrowseEntryConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/BrowseEntryConverter.java index 677ecc1549..9de892c2e8 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/BrowseEntryConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/BrowseEntryConverter.java @@ -7,9 +7,10 @@ */ package org.dspace.app.rest.converter; +import java.util.function.Function; + import org.apache.logging.log4j.Logger; import org.dspace.app.rest.model.BrowseEntryRest; -import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; /** @@ -19,11 +20,11 @@ import org.springframework.stereotype.Component; * @author Andrea Bollini (andrea.bollini at 4science.it) */ @Component -public class BrowseEntryConverter implements Converter { +public class BrowseEntryConverter implements Function { private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(BrowseEntryConverter.class); @Override - public BrowseEntryRest convert(String[] source) { + public BrowseEntryRest apply(String[] source) { BrowseEntryRest entry = new BrowseEntryRest(); entry.setValue(source[0]); entry.setAuthority(source[1]); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/DSpaceConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/DSpaceConverter.java index d195f1ab8d..749b385644 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/DSpaceConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/DSpaceConverter.java @@ -7,9 +7,17 @@ */ package org.dspace.app.rest.converter; +import java.util.function.Function; + import org.springframework.core.convert.converter.Converter; -public interface DSpaceConverter extends Converter { +public interface DSpaceConverter extends Converter, Function { + + @Override + default R apply(M source) { + return convert(source); + } + @Override public default R convert(M source) { return fromModel(source); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorityEntryLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorityEntryLinkRepository.java index 90ebd601f5..1250374566 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorityEntryLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/AuthorityEntryLinkRepository.java @@ -74,7 +74,8 @@ public class AuthorityEntryLinkRepository extends AbstractDSpaceRestRepository if (StringUtils.isNotBlank(metadata)) { String[] tokens = org.dspace.core.Utils.tokenize(metadata); String fieldKey = org.dspace.core.Utils.standardize(tokens[0], tokens[1], tokens[2], "_"); - Choices choices = cas.getMatches(fieldKey, query, collection, Math.toIntExact(pageable.getOffset()), pageable.getPageSize(), + Choices choices = cas.getMatches(fieldKey, query, collection, Math.toIntExact(pageable.getOffset()), + pageable.getPageSize(), context.getCurrentLocale().toString()); for (Choice value : choices.values) { results.add(authorityUtils.convertEntry(value, name)); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DSpaceObjectRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DSpaceObjectRestRepository.java index dc03cd54e3..99a9f0e31c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DSpaceObjectRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DSpaceObjectRestRepository.java @@ -19,6 +19,7 @@ import org.dspace.app.rest.repository.patch.DSpaceObjectPatch; import org.dspace.authorize.AuthorizeException; import org.dspace.content.DSpaceObject; import org.dspace.content.service.DSpaceObjectService; +import org.dspace.core.Context; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ResourceNotFoundException; @@ -60,11 +61,12 @@ public abstract class DSpaceObjectRestRepository findAll(Context context, Pageable pageable) { List subConfs = new ArrayList(); int total = submissionConfigReader.countSubmissionConfigs(); - subConfs = submissionConfigReader.getAllSubmissionConfigs(pageable.getPageSize(), Math.toIntExact(pageable.getOffset())); + subConfs = submissionConfigReader.getAllSubmissionConfigs(pageable.getPageSize(), + Math.toIntExact(pageable.getOffset())); Page page = new PageImpl(subConfs, pageable, total).map(converter); return page; } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SubmissionPanelRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SubmissionPanelRestRepository.java index 92e01b8d2f..8abee23bd5 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SubmissionPanelRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SubmissionPanelRestRepository.java @@ -59,7 +59,8 @@ public class SubmissionPanelRestRepository extends DSpaceRestRepository findAll(Context context, Pageable pageable) { List subConfs = new ArrayList(); - subConfs = submissionConfigReader.getAllSubmissionConfigs(pageable.getPageSize(), Math.toIntExact(pageable.getOffset())); + subConfs = submissionConfigReader.getAllSubmissionConfigs(pageable.getPageSize(), + Math.toIntExact(pageable.getOffset())); int total = 0; List stepConfs = new ArrayList<>(); for (SubmissionConfig config : subConfs) { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SubmissionUploadRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SubmissionUploadRestRepository.java index 6db7f85883..afc9b02ad9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SubmissionUploadRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SubmissionUploadRestRepository.java @@ -79,7 +79,8 @@ public class SubmissionUploadRestRepository extends DSpaceRestRepository findAll(Context context, Pageable pageable) { List subConfs = new ArrayList(); - subConfs = submissionConfigReader.getAllSubmissionConfigs(pageable.getPageSize(), Math.toIntExact(pageable.getOffset())); + subConfs = submissionConfigReader.getAllSubmissionConfigs(pageable.getPageSize(), + Math.toIntExact(pageable.getOffset())); List results = new ArrayList<>(); for (SubmissionConfig config : subConfs) { for (int i = 0; i < config.getNumberOfSteps(); i++) { @@ -136,7 +137,7 @@ public class SubmissionUploadRestRepository extends DSpaceRestRepository errors = new ArrayList(); SubmissionConfig submissionConfig = @@ -229,7 +229,7 @@ public class WorkflowItemRestRepository extends DSpaceRestRepository operations = patch.getOperations(); - WorkflowItemRest wsi = findOne(id); + WorkflowItemRest wsi = findOne(context, id); XmlWorkflowItem source = wis.find(context, id); for (Operation op : operations) { //the value in the position 0 is a null value diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java index 697ee18ae3..d0c3d7f5ca 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java @@ -222,7 +222,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository errors = new ArrayList(); SubmissionConfig submissionConfig = @@ -271,7 +271,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository operations = patch.getOperations(); - WorkspaceItemRest wsi = findOne(id); + WorkspaceItemRest wsi = findOne(context, id); WorkspaceItem source = wis.find(context, id); for (Operation op : operations) { //the value in the position 0 is a null value diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/ApplicationConfig.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/ApplicationConfig.java index fd9059faa6..e2a4caa008 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/ApplicationConfig.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/ApplicationConfig.java @@ -24,7 +24,7 @@ import org.springframework.data.web.config.EnableSpringDataWebSupport; @Configuration @EnableSpringDataWebSupport @ComponentScan( {"org.dspace.app.rest.converter", "org.dspace.app.rest.repository", "org.dspace.app.rest.utils", - "org.dspace.app.configuration"}) + "org.dspace.app.configuration"}) public class ApplicationConfig { // Allowed CORS origins. Defaults to * (everywhere) // Can be overridden in DSpace configuration diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/Utils.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/Utils.java index d03e5f2d0d..ea6b54c84e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/Utils.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/Utils.java @@ -77,7 +77,8 @@ public class Utils { if (pageable.getOffset() + pageable.getPageSize() > total) { pageContent = fullContents.subList(Math.toIntExact(pageable.getOffset()), total); } else { - pageContent = fullContents.subList(Math.toIntExact(pageable.getOffset()), Math.toIntExact(pageable.getOffset()) + pageable.getPageSize()); + pageContent = fullContents.subList(Math.toIntExact(pageable.getOffset()), + Math.toIntExact(pageable.getOffset()) + pageable.getPageSize()); } return new PageImpl(pageContent, pageable, total); } diff --git a/dspace-server-webapp/src/main/resources/application.properties b/dspace-server-webapp/src/main/resources/application.properties index 37883da3ed..b40551739d 100644 --- a/dspace-server-webapp/src/main/resources/application.properties +++ b/dspace-server-webapp/src/main/resources/application.properties @@ -94,6 +94,8 @@ spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSou org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration, \ org.springframework.boot.autoconfigure.velocity.VelocityAutoConfiguration +spring.main.allow-bean-definition-overriding = true + ######################### # Spring Boot Logging levels # diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamFormatRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamFormatRestRepositoryIT.java index fa6ecaedfe..924744b27a 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamFormatRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BitstreamFormatRestRepositoryIT.java @@ -63,7 +63,7 @@ public class BitstreamFormatRestRepositoryIT extends AbstractControllerIntegrati .andExpect(content().contentType(contentType)) .andExpect(jsonPath("$.page.size", is(20))) .andExpect(jsonPath("$._links.self.href", startsWith(REST_SERVER_URL))) - .andExpect(jsonPath("$._links.self.href", endsWith("/api/core/bitstreamformats"))) + .andExpect(jsonPath("$._links.self.href", endsWith("/api/core/bitstreamformats{?projection}"))) ; } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/EPersonClaimProviderTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/EPersonClaimProviderTest.java index 954126b4d7..895baec162 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/EPersonClaimProviderTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/EPersonClaimProviderTest.java @@ -56,7 +56,6 @@ public class EPersonClaimProviderTest { public void setUp() throws Exception { context = Mockito.mock(Context.class); Mockito.doCallRealMethod().when(context).setCurrentUser(any(EPerson.class)); - Mockito.doCallRealMethod().when(context).getCurrentUser(); when(ePerson.getID()).thenReturn(UUID.fromString("c3bae216-a481-496b-a524-7df5aabdb609")); jwtClaimsSet = new JWTClaimsSet.Builder() .claim(EPersonClaimProvider.EPERSON_ID, "c3bae216-a481-496b-a524-7df5aabdb609") diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/JWTTokenHandlerTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/JWTTokenHandlerTest.java index a67f747b62..5cba14b658 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/JWTTokenHandlerTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/JWTTokenHandlerTest.java @@ -71,7 +71,6 @@ public class JWTTokenHandlerTest { @Before public void setUp() throws Exception { - when(ePerson.getEmail()).thenReturn("test@dspace.org"); when(ePerson.getSessionSalt()).thenReturn("01234567890123456789012345678901"); when(ePerson.getLastActive()).thenReturn(new Date()); when(context.getCurrentUser()).thenReturn(ePerson); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/SpecialGroupClaimProviderTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/SpecialGroupClaimProviderTest.java index ff3382cb6e..9a41409cb2 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/SpecialGroupClaimProviderTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/jwt/SpecialGroupClaimProviderTest.java @@ -55,7 +55,7 @@ public class SpecialGroupClaimProviderTest { context = Mockito.mock(Context.class); //Stub the specialgroups list that is normally kept in the context class Mockito.doAnswer(invocation -> { - UUID uuid = invocation.getArgumentAt(0, UUID.class); + UUID uuid = invocation.getArgument(0); specialGroups.add(uuid); return "done"; }).when(context).setSpecialGroup(any(UUID.class)); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractControllerIntegrationTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractControllerIntegrationTest.java index 4f24cba097..ec6fd21366 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractControllerIntegrationTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractControllerIntegrationTest.java @@ -28,7 +28,7 @@ import org.junit.Assert; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.support.ErrorPageFilter; +import org.springframework.boot.web.servlet.support.ErrorPageFilter; import org.springframework.data.rest.webmvc.RestMediaTypes; import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java index 26fa7f0ef7..eef602f47c 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractWebClientIntegrationTest.java @@ -13,9 +13,9 @@ import org.dspace.app.rest.utils.DSpaceConfigurationInitializer; import org.dspace.app.rest.utils.DSpaceKernelInitializer; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.embedded.LocalServerPort; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; import org.springframework.context.ApplicationContext; import org.springframework.http.HttpEntity; import org.springframework.http.ResponseEntity; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/utils/DiscoverQueryBuilderTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/utils/DiscoverQueryBuilderTest.java index 0ece5c9016..c58c9b3af9 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/utils/DiscoverQueryBuilderTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/utils/DiscoverQueryBuilderTest.java @@ -7,21 +7,29 @@ */ package org.dspace.app.rest.utils; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.dspace.discovery.configuration.DiscoveryConfigurationParameters.SORT.COUNT; +import static org.dspace.discovery.configuration.DiscoveryConfigurationParameters.SORT.VALUE; +import static org.dspace.discovery.configuration.DiscoveryConfigurationParameters.TYPE_HIERARCHICAL; +import static org.dspace.discovery.configuration.DiscoveryConfigurationParameters.TYPE_TEXT; +import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isEmptyOrNullString; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.eq; +import static org.junit.Assert.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.when; import java.sql.SQLException; import java.util.Arrays; import java.util.LinkedList; import java.util.List; +import java.util.function.Function; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.parameter.SearchFilter; @@ -43,13 +51,14 @@ import org.dspace.discovery.configuration.DiscoverySortConfiguration; import org.dspace.discovery.configuration.DiscoverySortFieldConfiguration; import org.dspace.discovery.configuration.HierarchicalSidebarFacetConfiguration; import org.dspace.services.ConfigurationService; +import org.hamcrest.FeatureMatcher; +import org.hamcrest.Matcher; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.internal.matchers.apachecommons.ReflectionEquals; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; @@ -83,13 +92,11 @@ public class DiscoverQueryBuilderTest { public void setUp() throws Exception { when(configurationService.getIntProperty(eq("rest.search.max.results"), anyInt())).thenReturn(100); - when(searchService.escapeQueryChars(any(String.class))).then(invocation -> invocation.getArguments()[0]); - when(searchService.toSortFieldIndex(any(String.class), any(String.class))) .then(invocation -> invocation.getArguments()[0] + "_sort"); when(searchService - .getFacetYearRange(eq(context), any(IndexableObject.class), any(DiscoverySearchFilterFacet.class), + .getFacetYearRange(eq(context), nullable(IndexableObject.class), any(DiscoverySearchFilterFacet.class), any(), any(DiscoverQuery.class))) .then(invocation -> new FacetYearRange((DiscoverySearchFilterFacet) invocation.getArguments()[2])); @@ -144,9 +151,9 @@ public class DiscoverQueryBuilderTest { dateFacet.setFacetLimit(6); HierarchicalSidebarFacetConfiguration hierarchyFacet = new HierarchicalSidebarFacetConfiguration(); hierarchyFacet.setIndexFieldName("hierarchy"); - hierarchyFacet.setType(DiscoveryConfigurationParameters.TYPE_HIERARCHICAL); + hierarchyFacet.setType(TYPE_HIERARCHICAL); hierarchyFacet.setFacetLimit(7); - hierarchyFacet.setSortOrderSidebar(DiscoveryConfigurationParameters.SORT.VALUE); + hierarchyFacet.setSortOrderSidebar(VALUE); discoveryConfiguration.setSidebarFacets(Arrays.asList(subjectFacet, dateFacet, hierarchyFacet)); discoveryConfiguration.setSearchFilters(Arrays.asList(subjectFacet, dateFacet, hierarchyFacet)); @@ -173,15 +180,15 @@ public class DiscoverQueryBuilderTest { assertThat(discoverQuery.getFacetMinCount(), is(1)); assertThat(discoverQuery.getFacetOffset(), is(0)); assertThat(discoverQuery.getFacetFields(), hasSize(2)); - assertThat(discoverQuery.getFacetFields(), containsInAnyOrder(new ReflectionEquals( - new DiscoverFacetField("subject", DiscoveryConfigurationParameters.TYPE_TEXT, 6, - DiscoveryConfigurationParameters.SORT.COUNT)), new ReflectionEquals( - new DiscoverFacetField("hierarchy", DiscoveryConfigurationParameters.TYPE_HIERARCHICAL, 8, - DiscoveryConfigurationParameters.SORT.VALUE)))); + assertThat(discoverQuery.getFacetFields(), containsInAnyOrder( + discoverFacetFieldMatcher(new DiscoverFacetField("subject", TYPE_TEXT, 6, COUNT)), + discoverFacetFieldMatcher(new DiscoverFacetField("hierarchy", TYPE_HIERARCHICAL, 8, VALUE)) + )); assertThat(discoverQuery.getHitHighlightingFields(), hasSize(2)); - assertThat(discoverQuery.getHitHighlightingFields(), - containsInAnyOrder(new ReflectionEquals(new DiscoverHitHighlightingField("dc.title", 0, 3)), - new ReflectionEquals(new DiscoverHitHighlightingField("fulltext", 0, 3)))); + assertThat(discoverQuery.getHitHighlightingFields(), containsInAnyOrder( + discoverHitHighlightingFieldMatcher(new DiscoverHitHighlightingField("dc.title", 0, 3)), + discoverHitHighlightingFieldMatcher(new DiscoverHitHighlightingField("fulltext", 0, 3)) + )); } @Test @@ -201,15 +208,15 @@ public class DiscoverQueryBuilderTest { assertThat(discoverQuery.getFacetMinCount(), is(1)); assertThat(discoverQuery.getFacetOffset(), is(0)); assertThat(discoverQuery.getFacetFields(), hasSize(2)); - assertThat(discoverQuery.getFacetFields(), containsInAnyOrder(new ReflectionEquals( - new DiscoverFacetField("subject", DiscoveryConfigurationParameters.TYPE_TEXT, 6, - DiscoveryConfigurationParameters.SORT.COUNT)), new ReflectionEquals( - new DiscoverFacetField("hierarchy", DiscoveryConfigurationParameters.TYPE_HIERARCHICAL, 8, - DiscoveryConfigurationParameters.SORT.VALUE)))); + assertThat(discoverQuery.getFacetFields(), containsInAnyOrder( + discoverFacetFieldMatcher(new DiscoverFacetField("subject", TYPE_TEXT, 6, COUNT)), + discoverFacetFieldMatcher(new DiscoverFacetField("hierarchy", TYPE_HIERARCHICAL, 8, VALUE)) + )); assertThat(discoverQuery.getHitHighlightingFields(), hasSize(2)); - assertThat(discoverQuery.getHitHighlightingFields(), - containsInAnyOrder(new ReflectionEquals(new DiscoverHitHighlightingField("dc.title", 0, 3)), - new ReflectionEquals(new DiscoverHitHighlightingField("fulltext", 0, 3)))); + assertThat(discoverQuery.getHitHighlightingFields(), containsInAnyOrder( + discoverHitHighlightingFieldMatcher(new DiscoverHitHighlightingField("dc.title", 0, 3)), + discoverHitHighlightingFieldMatcher(new DiscoverHitHighlightingField("fulltext", 0, 3)) + )); } @Test @@ -231,15 +238,15 @@ public class DiscoverQueryBuilderTest { assertThat(discoverQuery.getFacetMinCount(), is(1)); assertThat(discoverQuery.getFacetOffset(), is(0)); assertThat(discoverQuery.getFacetFields(), hasSize(2)); - assertThat(discoverQuery.getFacetFields(), containsInAnyOrder(new ReflectionEquals( - new DiscoverFacetField("subject", DiscoveryConfigurationParameters.TYPE_TEXT, 6, - DiscoveryConfigurationParameters.SORT.COUNT)), new ReflectionEquals( - new DiscoverFacetField("hierarchy", DiscoveryConfigurationParameters.TYPE_HIERARCHICAL, 8, - DiscoveryConfigurationParameters.SORT.VALUE)))); + assertThat(discoverQuery.getFacetFields(), containsInAnyOrder( + discoverFacetFieldMatcher(new DiscoverFacetField("subject", TYPE_TEXT, 6, COUNT)), + discoverFacetFieldMatcher(new DiscoverFacetField("hierarchy", TYPE_HIERARCHICAL, 8, VALUE)) + )); assertThat(discoverQuery.getHitHighlightingFields(), hasSize(2)); - assertThat(discoverQuery.getHitHighlightingFields(), - containsInAnyOrder(new ReflectionEquals(new DiscoverHitHighlightingField("dc.title", 0, 3)), - new ReflectionEquals(new DiscoverHitHighlightingField("fulltext", 0, 3)))); + assertThat(discoverQuery.getHitHighlightingFields(), containsInAnyOrder( + discoverHitHighlightingFieldMatcher(new DiscoverHitHighlightingField("dc.title", 0, 3)), + discoverHitHighlightingFieldMatcher(new DiscoverHitHighlightingField("fulltext", 0, 3)) + )); } @Test(expected = DSpaceBadRequestException.class) @@ -250,7 +257,7 @@ public class DiscoverQueryBuilderTest { @Test(expected = DSpaceBadRequestException.class) public void testInvalidSortField() throws Exception { - page = new PageRequest(2, 10, Sort.Direction.ASC, "test"); + page = PageRequest.of(2, 10, Sort.Direction.ASC, "test"); queryBuilder .buildQuery(context, scope, discoveryConfiguration, query, Arrays.asList(searchFilter), "ITEM", page); } @@ -289,8 +296,7 @@ public class DiscoverQueryBuilderTest { assertThat(discoverQuery.getFacetOffset(), is(10)); assertThat(discoverQuery.getFacetFields(), hasSize(1)); assertThat(discoverQuery.getFacetFields(), contains( - new ReflectionEquals(new DiscoverFacetField("subject", DiscoveryConfigurationParameters.TYPE_TEXT, 11, - DiscoveryConfigurationParameters.SORT.COUNT, "prefix")) + discoverFacetFieldMatcher(new DiscoverFacetField("subject", TYPE_TEXT, 11, COUNT, "prefix")) )); } @@ -300,4 +306,35 @@ public class DiscoverQueryBuilderTest { Arrays.asList(searchFilter), "item", page, "test"); } + public Matcher discoverFacetFieldMatcher(DiscoverFacetField expected) { + + return allOf( + hasProperty(expected, DiscoverFacetField::getField, "field"), + hasProperty(expected, DiscoverFacetField::getType, "type"), + hasProperty(expected, DiscoverFacetField::getPrefix, "prefix"), + hasProperty(expected, DiscoverFacetField::getLimit, "limit"), + hasProperty(expected, DiscoverFacetField::getOffset, "offset") + ); + } + + public Matcher discoverHitHighlightingFieldMatcher + (DiscoverHitHighlightingField expected) { + + return allOf( + hasProperty(expected, DiscoverHitHighlightingField::getField, "field"), + hasProperty(expected, DiscoverHitHighlightingField::getMaxChars, "maxChars"), + hasProperty(expected, DiscoverHitHighlightingField::getMaxSnippets, "maxSnippets") + ); + } + + public FeatureMatcher hasProperty(T expected, Function property, String description) { + + return new FeatureMatcher + (equalTo(property.apply(expected)), description, description) { + + protected U featureValueOf(T actual) { + return property.apply(actual); + } + }; + } } \ No newline at end of file diff --git a/dspace-server-webapp/src/test/resources/log4j.properties b/dspace-server-webapp/src/test/resources/log4j.properties index b982e8bd74..2797b7c655 100644 --- a/dspace-server-webapp/src/test/resources/log4j.properties +++ b/dspace-server-webapp/src/test/resources/log4j.properties @@ -19,7 +19,7 @@ log4j.rootCategory=INFO, A1 # A1 is set to be a ConsoleAppender. -log4j.appender.A1=org.apache.logging.log4j.ConsoleAppender +log4j.appender.A1=org.apache.log4j.ConsoleAppender # A1 uses PatternLayout. log4j.appender.A1.layout=org.apache.logging.log4j.PatternLayout @@ -40,9 +40,9 @@ log4j.logger.org.dspace.servicemanager=ERROR log4j.logger.org.dspace.providers=ERROR log4j.logger.org.dspace.utils=ERROR -log4j.appender.stdout=org.apache.logging.log4j.ConsoleAppender +log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out -log4j.appender.stdout.layout=org.apache.logging.log4j.PatternLayout +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n # # Root logger option diff --git a/dspace-services/pom.xml b/dspace-services/pom.xml index c23050f4c5..45c74448d7 100644 --- a/dspace-services/pom.xml +++ b/dspace-services/pom.xml @@ -81,11 +81,6 @@ - - - org.slf4j - slf4j-api - org.springframework @@ -138,28 +133,6 @@ 6.1.26 test - - org.apache.logging.log4j - log4j-api - ${log4j.version} - - - org.apache.logging.log4j - log4j-core - ${log4j.version} - - - org.apache.logging.log4j - log4j-slf4j-impl - ${log4j.version} - - - - commons-logging - commons-logging - jar - provided - org.apache.commons commons-collections4 @@ -178,6 +151,13 @@ javax.annotation-api 1.3.2 + + + org.springframework.boot + spring-boot-starter-log4j2 + ${spring-boot.version} + + diff --git a/dspace-services/src/test/resources/log4j.properties b/dspace-services/src/test/resources/log4j.properties index 7dbc0a3bd0..2f1799c59c 100644 --- a/dspace-services/src/test/resources/log4j.properties +++ b/dspace-services/src/test/resources/log4j.properties @@ -1,7 +1,7 @@ log4j.rootCategory=info log4j.rootLogger=info, stdout -log4j.appender.stdout=org.apache.logging.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.logging.log4j.PatternLayout +log4j.appender.stdout=ConsoleAppender +log4j.appender.stdout.layout=PatternLayout log4j.appender.stdout.layout.ConversionPattern= %p %m [%d] (%F:%L) %n diff --git a/dspace/config/log4j2-console.xml b/dspace/config/log4j2-console.xml index db2998f6be..3d51b12336 100644 --- a/dspace/config/log4j2-console.xml +++ b/dspace/config/log4j2-console.xml @@ -6,27 +6,27 @@ Its goal is to simply output logs to the commandline / console. --> - - + - ${log4j:configParentLocation}/../log - + ${log4j:configParentLocation}/../log + - - + - - - + + - - - - - - + + + + + + diff --git a/dspace/config/log4j2.xml b/dspace/config/log4j2.xml index 98a0300125..b78505a93d 100644 --- a/dspace/config/log4j2.xml +++ b/dspace/config/log4j2.xml @@ -1,91 +1,82 @@ - - + + - ${log4j:configParentLocation}/../log + ${log4j:configParentLocation}/../log - INFO + INFO - INFO - + INFO + - + - - + - - yyyy-MM-dd - - - + - - + - - yyyy-MM-dd - - - + + - - - - - + - - - + + - - + # Block services logging except on exceptions - - - - - # Block passwords from being exposed in Axis logs. # (DEBUG exposes passwords in Basic Auth) - - - + + + + + + diff --git a/dspace/config/spring/api/access-conditions.xml b/dspace/config/spring/api/access-conditions.xml index 5050db1dab..be8477c55c 100644 --- a/dspace/config/spring/api/access-conditions.xml +++ b/dspace/config/spring/api/access-conditions.xml @@ -10,11 +10,11 @@ - - - - - + + + + + diff --git a/dspace/config/spring/api/core-hibernate.xml b/dspace/config/spring/api/core-hibernate.xml index 09094de971..784acdcd26 100644 --- a/dspace/config/spring/api/core-hibernate.xml +++ b/dspace/config/spring/api/core-hibernate.xml @@ -4,12 +4,12 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-lazy-init="true"> - + - + diff --git a/dspace/pom.xml b/dspace/pom.xml index c03dab19db..09cd6d43af 100644 --- a/dspace/pom.xml +++ b/dspace/pom.xml @@ -281,6 +281,11 @@ + + org.dspace.modules + additions + provided + diff --git a/pom.xml b/pom.xml index 21c8d2a74f..34e6ab252d 100644 --- a/pom.xml +++ b/pom.xml @@ -30,12 +30,12 @@ 2.13.0 - 2.6.2 - 1.7.22 + 2.11.2 + 1.7.25 - 2.8.11 + 2.9.9 2.28 - 5.4.5.Final + 5.3.11.Final 6.0.17.Final @@ -43,7 +43,7 @@ 5.1.9.RELEASE 2.1.8.RELEASE + as it is used to reference the LICENSE_HEADER and *.properties file(s) in that directory. --> ${basedir} @@ -1265,16 +1265,37 @@ log4j-core ${log4j.version} - + org.apache.logging.log4j log4j-web ${log4j.version} - + org.apache.logging.log4j log4j-slf4j-impl ${log4j.version} + + org.apache.logging.log4j + log4j-jul + ${log4j.version} + + + org.apache.logging.log4j + log4j-1.2-api + ${log4j.version} + + + org.slf4j + jul-to-slf4j + ${slf4j.version} + + + + commons-logging + commons-logging + 1.2 + oro @@ -1422,7 +1443,7 @@ org.slf4j - slf4j-log4j12 + log4j-over-slf4j ${slf4j.version} @@ -1515,7 +1536,7 @@ org.mockito mockito-core - 1.10.19 + 2.23.4 test @@ -1537,7 +1558,7 @@ com.fasterxml.jackson.core jackson-databind - 2.8.11.2 + ${jackson.version} com.google.guava @@ -1569,6 +1590,16 @@ xom 1.2.5 + + org.dspace + dspace + ${project.version} + + + net.bytebuddy + byte-buddy + 1.9.5 + From 930951445ffd365af8c728aec10bcc2065984294 Mon Sep 17 00:00:00 2001 From: Samuel Date: Fri, 25 Oct 2019 18:21:49 +0200 Subject: [PATCH 006/125] DS-4351 Upgrade spring (boot) & hibernate to newer versions - taskid 65955 internal questions - fix Q2 --- dspace/config/log4j2.xml | 42 ++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/dspace/config/log4j2.xml b/dspace/config/log4j2.xml index b78505a93d..67c2d39e52 100644 --- a/dspace/config/log4j2.xml +++ b/dspace/config/log4j2.xml @@ -23,22 +23,40 @@ + pattern='%d %-5p %c @ %m%n'/> + + yyyy-MM-dd + + + pattern='%m%n'/> + + yyyy-MM-dd + + @@ -60,20 +78,20 @@ # Block services logging except on exceptions + level='ERROR'/> + level='ERROR'/> + level='ERROR'/> + level='ERROR'/> + level='ERROR'/> # Block passwords from being exposed in Axis logs. # (DEBUG exposes passwords in Basic Auth) + level='INFO'/> From 52661fed8c361a548a67d3f4853a58f4effa522a Mon Sep 17 00:00:00 2001 From: Samuel Date: Wed, 30 Oct 2019 15:49:43 +0100 Subject: [PATCH 007/125] DS-4351 Upgrade spring (boot) & hibernate to newer versions - taskid 65955 internal questions - fix Q6 --- pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pom.xml b/pom.xml index 34e6ab252d..c03cf4bea5 100644 --- a/pom.xml +++ b/pom.xml @@ -1590,11 +1590,6 @@ xom 1.2.5 - - org.dspace - dspace - ${project.version} - net.bytebuddy byte-buddy From 840106ba63909ca33a6b901408435fa1a07ac0ff Mon Sep 17 00:00:00 2001 From: Marie Verdonck Date: Mon, 4 Nov 2019 15:47:51 +0100 Subject: [PATCH 008/125] =?UTF-8?q?[DS-4317]=20DELETE=20/api/core/bundles/?= =?UTF-8?q?<:uuid>=20endpoint=20functionality=20=E2=80=A8=20>=20deletes=20?= =?UTF-8?q?bundle=20with=20given=20uuid=20and=20all=20its=20bitstreams=20?= =?UTF-8?q?=E2=80=A8>=20with=20IT=20cases=20and=20javadoc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rest/repository/BundleRestRepository.java | 25 ++++ .../app/rest/BundleRestRepositoryIT.java | 123 ++++++++++++++++++ 2 files changed, 148 insertions(+) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java index 911f7304e5..729fda03cc 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java @@ -215,4 +215,29 @@ public class BundleRestRepository extends DSpaceObjectRestRepository wrapResource(BundleRest model, String... rels) { return new BundleResource(model, utils, rels); } + + /** + * Deletes a bundle whose uuid is given and deletes all the bitstreams it contains in BundleService.delete + * @param context + * the dspace context + * @param id + * the id of the bundle to delete + */ + @Override + protected void delete(Context context, UUID id) { + Bundle bundleToDelete = null; + try { + bundleToDelete = bundleService.find(context, id); + } catch (SQLException e) { + throw new RuntimeException("Can't find a bundle with id: " + id, e); + } + try { + bundleService.delete(context, bundleToDelete); + } catch (AuthorizeException e) { + throw new AccessDeniedException("You do not have the right access rights to delete this bundle " + + "with id: " + id, e); + } catch (IOException | SQLException e) { + throw new RuntimeException("Something went wrong trying to delete bundle with id: " + id, e); + } + } } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BundleRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BundleRestRepositoryIT.java index ca93948f0a..7b09fd3f2f 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BundleRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BundleRestRepositoryIT.java @@ -11,6 +11,7 @@ import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; @@ -423,4 +424,126 @@ public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest { ))); } + @Test + public void deleteBundle() throws Exception { + context.turnOffAuthorisationSystem(); + + String bitstreamContent = "Dummy content"; + try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) { + bitstream1 = BitstreamBuilder.createBitstream(context, item, is) + .withName("Bitstream") + .withDescription("Description") + .withMimeType("text/plain") + .build(); + bitstream2 = BitstreamBuilder.createBitstream(context, item, is) + .withName("Bitstream2") + .withDescription("Description2") + .withMimeType("text/plain") + .build(); + } + + bundle1 = BundleBuilder.createBundle(context, item) + .withName("testname") + .withBitstream(bitstream1) + .withBitstream(bitstream2) + .build(); + + context.restoreAuthSystemState(); + + String token = getAuthToken(admin.getEmail(), password); + + // Check if bundle is present + getClient().perform(get("/api/core/bundles/" + bundle1.getID() + "/bitstreams")) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$._embedded.bitstreams", Matchers.hasItems( + BitstreamMatcher.matchBitstreamEntry(bitstream1), + BitstreamMatcher.matchBitstreamEntry(bitstream2) + ))); + + // Delete bundle with admin auth token + getClient(token).perform(delete("/api/core/bundles/" + bundle1.getID())) + .andExpect(status().is(204)); + + // Verify 404 after delete for bundle AND its bitstreams + getClient(token).perform(get("/api/core/bundles/" + bundle1.getID())) + .andExpect(status().isNotFound()); + getClient(token).perform(get("/api/core/bitstreams/" + bitstream1.getID())) + .andExpect(status().isNotFound()); + getClient(token).perform(get("/api/core/bitstreams/" + bitstream2.getID())) + .andExpect(status().isNotFound()); + } + + @Test + public void deleteBundle_Forbidden() throws Exception { + context.turnOffAuthorisationSystem(); + + String bitstreamContent = "Dummy content"; + try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) { + bitstream1 = BitstreamBuilder.createBitstream(context, item, is) + .withName("Bitstream") + .withDescription("Description") + .withMimeType("text/plain") + .build(); + bitstream2 = BitstreamBuilder.createBitstream(context, item, is) + .withName("Bitstream2") + .withDescription("Description2") + .withMimeType("text/plain") + .build(); + } + + bundle1 = BundleBuilder.createBundle(context, item) + .withName("testname") + .withBitstream(bitstream1) + .withBitstream(bitstream2) + .build(); + + context.restoreAuthSystemState(); + + String token = getAuthToken(eperson.getEmail(), password); + + // Try to delete bundle with eperson auth token + getClient(token).perform(delete("/api/core/bundles/" + bundle1.getID())) + .andExpect(status().isForbidden()); + + // Verify the bundle is still here + getClient(token).perform(get("/api/core/bundles/" + bundle1.getID())) + .andExpect(status().isOk()); + } + + @Test + public void deleteBundle_NoAuthToken() throws Exception { + context.turnOffAuthorisationSystem(); + + String bitstreamContent = "Dummy content"; + try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) { + bitstream1 = BitstreamBuilder.createBitstream(context, item, is) + .withName("Bitstream") + .withDescription("Description") + .withMimeType("text/plain") + .build(); + bitstream2 = BitstreamBuilder.createBitstream(context, item, is) + .withName("Bitstream2") + .withDescription("Description2") + .withMimeType("text/plain") + .build(); + } + + bundle1 = BundleBuilder.createBundle(context, item) + .withName("testname") + .withBitstream(bitstream1) + .withBitstream(bitstream2) + .build(); + + context.restoreAuthSystemState(); + + // Try to delete bundle without auth token + getClient().perform(delete("/api/core/bundles/" + bundle1.getID())) + .andExpect(status().isUnauthorized()); + + // Verify the bundle is still here + getClient().perform(get("/api/core/bundles/" + bundle1.getID())) + .andExpect(status().isOk()); + } + } From c56216e46b82080b96178764c80bc12e04d7c617 Mon Sep 17 00:00:00 2001 From: Marie Verdonck Date: Thu, 7 Nov 2019 17:24:15 +0100 Subject: [PATCH 009/125] 65985: bundle delete improvements (from feedback) --- .../app/rest/repository/BundleRestRepository.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java index 729fda03cc..6debafef69 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java @@ -42,6 +42,7 @@ import org.dspace.core.Context; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Component; @@ -224,18 +225,19 @@ public class BundleRestRepository extends DSpaceObjectRestRepository Date: Wed, 13 Nov 2019 16:35:49 -0800 Subject: [PATCH 010/125] [DS-3906] REST endpoint for discovering withdrawn and private items. --- .../SolrServiceUnDiscoverableItemsPlugin.java | 32 ++++ .../DiscoveryConfigurationService.java | 13 +- .../repository/DiscoveryRestRepository.java | 8 +- dspace/config/spring/api/discovery.xml | 158 +++++++++++++++++- 4 files changed, 206 insertions(+), 5 deletions(-) create mode 100644 dspace-api/src/main/java/org/dspace/discovery/SolrServiceUnDiscoverableItemsPlugin.java diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceUnDiscoverableItemsPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceUnDiscoverableItemsPlugin.java new file mode 100644 index 0000000000..4ec292b093 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceUnDiscoverableItemsPlugin.java @@ -0,0 +1,32 @@ +package org.dspace.discovery; + +import static org.apache.logging.log4j.LogManager.getLogger; + +import java.sql.SQLException; + +import org.apache.logging.log4j.Logger; +import org.apache.solr.client.solrj.SolrQuery; +import org.dspace.authorize.service.AuthorizeService; +import org.dspace.core.Context; +import org.dspace.core.LogManager; +import org.springframework.beans.factory.annotation.Autowired; + +public class SolrServiceUnDiscoverableItemsPlugin implements SolrServiceSearchPlugin { + + private static final Logger log = getLogger(SolrServiceUnDiscoverableItemsPlugin.class.getSimpleName()); + + @Autowired(required = true) + protected AuthorizeService authorizeService; + + @Override + public void additionalSearchParameters(Context context, DiscoverQuery discoveryQuery, SolrQuery solrQuery) { + try { + if (!authorizeService.isAdmin(context)) { + solrQuery.addFilterQuery("NOT(withdrawn:true"); + solrQuery.addFilterQuery("NOT(discoverable:false)"); + } + } catch (SQLException e) { + log.error(LogManager.getHeader(context, "Error while adding non-administrator filter to query", ""), e); + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java index 53433f879f..dfdc86ecbb 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java +++ b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java @@ -13,7 +13,9 @@ import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; +import org.dspace.content.Community; import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; import org.dspace.discovery.IndexableObject; import org.dspace.services.factory.DSpaceServicesFactory; @@ -69,7 +71,16 @@ public class DiscoveryConfigurationService { public DiscoveryConfiguration getDiscoveryConfigurationByNameOrDso(final String configurationName, final IndexableObject dso) { - if (StringUtils.isNotBlank(configurationName) && getMap().containsKey(configurationName)) { + + if (dso instanceof Community && configurationName.contentEquals("unDiscoverableItems")) { + // Use community-level configuration if it is defined. If not, fall back to configuration name. + if (getMap().containsKey(configurationName + "." +((Community) dso).getHandle())) { + return getMap().get(configurationName + "." +((Community) dso).getHandle()); + } else { + return getMap().get(configurationName); + } + } + else if (StringUtils.isNotBlank(configurationName) && getMap().containsKey(configurationName)) { return getMap().get(configurationName); } else { return getDiscoveryConfiguration(dso); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DiscoveryRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DiscoveryRestRepository.java index 4d861c350b..f79576dfaf 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DiscoveryRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DiscoveryRestRepository.java @@ -102,7 +102,13 @@ public class DiscoveryRestRepository extends AbstractDSpaceRestRepository { try { discoverQuery = queryBuilder .buildQuery(context, scopeObject, discoveryConfiguration, query, searchFilters, dsoType, page); - searchResult = searchService.search(context, scopeObject, discoverQuery); + + if (configuration != null && configuration.contentEquals("unDiscoverableItems")) { + // Prevents the exclusion of withdrawn and private items for this configuration. + searchResult = searchService.search(context, scopeObject, discoverQuery, true); + } else { + searchResult = searchService.search(context, scopeObject, discoverQuery); + } } catch (SearchServiceException e) { log.error("Error while searching with Discovery", e); diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index ad985b0d9c..f00d78a7e1 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -51,9 +51,9 @@ - + - + @@ -156,7 +156,7 @@ - search.resourcetype:2 OR search.resourcetype:3 OR search.resourcetype:4 + search.resourcetype:2 OR search.resourcetype:3 OR search.resourcetype:4> @@ -244,6 +244,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:2 + withdrawn:true OR discoverable:false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dc.title + dc.contributor.author + dc.creator + dc.subject + + + + + + + + + + + + + @@ -298,6 +438,8 @@ search.resourcetype:2 OR search.resourcetype:3 OR search.resourcetype:4 + NOT(withdrawn:true) + NOT(discoverable:false) @@ -568,6 +710,8 @@ search.resourcetype:2 AND entityType_keyword:Publication + NOT(withdrawn:true) + NOT(discoverable:false) @@ -695,6 +839,8 @@ search.resourcetype:2 AND entityType_keyword:OrgUnit + NOT(withdrawn:true) + NOT(discoverable:false) @@ -756,6 +902,8 @@ search.resourcetype:2 AND entityType_keyword:JournalIssue + NOT(withdrawn:true) + NOT(discoverable:false) @@ -816,6 +964,8 @@ search.resourcetype:2 AND entityType_keyword:JournalVolume + NOT(withdrawn:true) + NOT(discoverable:false) @@ -876,6 +1026,8 @@ search.resourcetype:2 AND entityType_keyword:Journal + NOT(withdrawn:true) + NOT(discoverable:false) From b6849e51a653d6a4d8e6309a834363fbbb8a5f09 Mon Sep 17 00:00:00 2001 From: Michael W Spalti Date: Wed, 13 Nov 2019 17:33:25 -0800 Subject: [PATCH 011/125] Fixing tests for travis (currently unable to test on local machine) --- .../discovery/SolrServiceUnDiscoverableItemsPlugin.java | 7 +++++++ .../configuration/DiscoveryConfigurationService.java | 2 +- .../app/rest/repository/DiscoveryRestRepository.java | 2 +- dspace/config/spring/api/discovery.xml | 4 ++-- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceUnDiscoverableItemsPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceUnDiscoverableItemsPlugin.java index 4ec292b093..c0c2533fd2 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceUnDiscoverableItemsPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceUnDiscoverableItemsPlugin.java @@ -1,3 +1,10 @@ +/** + * 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.discovery; import static org.apache.logging.log4j.LogManager.getLogger; diff --git a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java index dfdc86ecbb..bf14a8b1fb 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java +++ b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java @@ -72,7 +72,7 @@ public class DiscoveryConfigurationService { public DiscoveryConfiguration getDiscoveryConfigurationByNameOrDso(final String configurationName, final IndexableObject dso) { - if (dso instanceof Community && configurationName.contentEquals("unDiscoverableItems")) { + if (dso instanceof Community && configurationName.contentEquals("showUnDiscoverableItems")) { // Use community-level configuration if it is defined. If not, fall back to configuration name. if (getMap().containsKey(configurationName + "." +((Community) dso).getHandle())) { return getMap().get(configurationName + "." +((Community) dso).getHandle()); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DiscoveryRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DiscoveryRestRepository.java index f79576dfaf..cce4c6c36a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DiscoveryRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/DiscoveryRestRepository.java @@ -103,7 +103,7 @@ public class DiscoveryRestRepository extends AbstractDSpaceRestRepository { discoverQuery = queryBuilder .buildQuery(context, scopeObject, discoveryConfiguration, query, searchFilters, dsoType, page); - if (configuration != null && configuration.contentEquals("unDiscoverableItems")) { + if (configuration != null && configuration.contentEquals("showUnDiscoverableItems")) { // Prevents the exclusion of withdrawn and private items for this configuration. searchResult = searchService.search(context, scopeObject, discoverQuery, true); } else { diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index f00d78a7e1..c9513e62f0 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -53,7 +53,7 @@ - + @@ -156,7 +156,7 @@ - search.resourcetype:2 OR search.resourcetype:3 OR search.resourcetype:4> + search.resourcetype:2 OR search.resourcetype:3 OR search.resourcetype:4 From 9d45a1d89f3d89d75f2d49ce0c95a1b6087b29eb Mon Sep 17 00:00:00 2001 From: Michael W Spalti Date: Wed, 13 Nov 2019 17:49:53 -0800 Subject: [PATCH 012/125] Formatting corrections. --- .../configuration/DiscoveryConfigurationService.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java index bf14a8b1fb..dd83a4c5bc 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java +++ b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java @@ -15,7 +15,6 @@ import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.dspace.content.Community; import org.dspace.content.DSpaceObject; -import org.dspace.content.Item; import org.dspace.discovery.IndexableObject; import org.dspace.services.factory.DSpaceServicesFactory; @@ -74,13 +73,12 @@ public class DiscoveryConfigurationService { if (dso instanceof Community && configurationName.contentEquals("showUnDiscoverableItems")) { // Use community-level configuration if it is defined. If not, fall back to configuration name. - if (getMap().containsKey(configurationName + "." +((Community) dso).getHandle())) { - return getMap().get(configurationName + "." +((Community) dso).getHandle()); + if (getMap().containsKey(configurationName + "." + ((Community) dso).getHandle())) { + return getMap().get(configurationName + "." + ((Community) dso).getHandle()); } else { return getMap().get(configurationName); } - } - else if (StringUtils.isNotBlank(configurationName) && getMap().containsKey(configurationName)) { + } else if (StringUtils.isNotBlank(configurationName) && getMap().containsKey(configurationName)) { return getMap().get(configurationName); } else { return getDiscoveryConfiguration(dso); From fcd6429ec034c663008aa738190e317d96083d7e Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Thu, 14 Nov 2019 11:18:47 +0100 Subject: [PATCH 013/125] [Task 66086] implemented a configuration on the RelationshipType object to determine whether metadata should be copied left or right or not at all when deleting a relationship --- .../dspace/app/util/InitializeEntities.java | 23 ++++- .../content/RelationshipServiceImpl.java | 4 +- .../org/dspace/content/RelationshipType.java | 43 +++++++++ .../content/RelationshipTypeServiceImpl.java | 20 ++++ .../service/RelationshipTypeService.java | 21 +++++ ....13__relationship_type_copy_left_right.sql | 14 +++ ....13__relationship_type_copy_left_right.sql | 14 +++ ....13__relationship_type_copy_left_right.sql | 14 +++ .../RelationshipMetadataServiceTest.java | 92 +++++++++++++++++++ .../converter/RelationshipTypeConverter.java | 2 + .../app/rest/model/RelationshipTypeRest.java | 34 +++++++ .../RelationshipDeleteRestRepositoryIT.java | 29 ++++++ .../rest/builder/RelationshipTypeBuilder.java | 9 ++ .../rest/matcher/RelationshipTypeMatcher.java | 13 ++- .../test/AbstractEntityIntegrationTest.java | 10 +- 15 files changed, 328 insertions(+), 14 deletions(-) create mode 100644 dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V7.0_2019.11.13__relationship_type_copy_left_right.sql create mode 100644 dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/oracle/V7.0_2019.11.13__relationship_type_copy_left_right.sql create mode 100644 dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V7.0_2019.11.13__relationship_type_copy_left_right.sql diff --git a/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java b/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java index fece5aeb69..6d54008fd0 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java +++ b/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java @@ -130,7 +130,21 @@ public class InitializeEntities { String rightType = eElement.getElementsByTagName("rightType").item(0).getTextContent(); String leftwardType = eElement.getElementsByTagName("leftwardType").item(0).getTextContent(); String rightwardType = eElement.getElementsByTagName("rightwardType").item(0).getTextContent(); + Node copyLeftNode = eElement.getElementsByTagName("copyLeft").item(0); + Boolean copyLeft; + if (copyLeftNode == null) { + copyLeft = false; + } else { + copyLeft = Boolean.valueOf(copyLeftNode.getTextContent()); + } + Node copyRightNode = eElement.getElementsByTagName("copyRight").item(0); + Boolean copyRight; + if (copyRightNode == null) { + copyRight = false; + } else { + copyRight = Boolean.valueOf(copyRightNode.getTextContent()); + } NodeList leftCardinalityList = eElement.getElementsByTagName("leftCardinality"); NodeList rightCardinalityList = eElement.getElementsByTagName("rightCardinality"); @@ -156,7 +170,7 @@ public class InitializeEntities { } populateRelationshipType(context, leftType, rightType, leftwardType, rightwardType, leftCardinalityMin, leftCardinalityMax, - rightCardinalityMin, rightCardinalityMax); + rightCardinalityMin, rightCardinalityMax, copyLeft, copyRight); } @@ -175,7 +189,8 @@ public class InitializeEntities { private void populateRelationshipType(Context context, String leftType, String rightType, String leftwardType, String rightwardType, String leftCardinalityMin, String leftCardinalityMax, - String rightCardinalityMin, String rightCardinalityMax) + String rightCardinalityMin, String rightCardinalityMax, + Boolean copyLeft, Boolean copyRight) throws SQLException, AuthorizeException { EntityType leftEntityType = entityTypeService.findByEntityType(context,leftType); @@ -215,8 +230,10 @@ public class InitializeEntities { if (relationshipType == null) { relationshipTypeService.create(context, leftEntityType, rightEntityType, leftwardType, rightwardType, leftCardinalityMinInteger, leftCardinalityMaxInteger, - rightCardinalityMinInteger, rightCardinalityMaxInteger); + rightCardinalityMinInteger, rightCardinalityMaxInteger, copyLeft, copyRight); } else { + relationshipType.setCopyLeft(copyLeft); + relationshipType.setCopyRight(copyRight); relationshipType.setLeftMinCardinality(leftCardinalityMinInteger); relationshipType.setLeftMaxCardinality(leftCardinalityMaxInteger); relationshipType.setRightMinCardinality(rightCardinalityMinInteger); diff --git a/dspace-api/src/main/java/org/dspace/content/RelationshipServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/RelationshipServiceImpl.java index abbfd5d64d..e55cc90206 100644 --- a/dspace-api/src/main/java/org/dspace/content/RelationshipServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/RelationshipServiceImpl.java @@ -330,8 +330,8 @@ public class RelationshipServiceImpl implements RelationshipService { @Override public void delete(Context context, Relationship relationship) throws SQLException, AuthorizeException { - //TODO: retrieve default settings from configuration - delete(context, relationship, false, false); + delete(context, relationship, relationship.getRelationshipType().isCopyLeft(), + relationship.getRelationshipType().isCopyRight()); } @Override diff --git a/dspace-api/src/main/java/org/dspace/content/RelationshipType.java b/dspace-api/src/main/java/org/dspace/content/RelationshipType.java index 0d33c98adf..4390825bb1 100644 --- a/dspace-api/src/main/java/org/dspace/content/RelationshipType.java +++ b/dspace-api/src/main/java/org/dspace/content/RelationshipType.java @@ -102,6 +102,17 @@ public class RelationshipType implements ReloadableEntity { @Column(name = "right_max_cardinality") private Integer rightMaxCardinality; + /** + * The boolean indicating whether the metadata should be copied on left item or not + */ + @Column(name = "copy_left", nullable = false) + private boolean copyLeft; + + /** + * The boolean indicating whether the metadata should be copied on right item or not + */ + @Column(name = "copy_right", nullable = false) + private boolean copyRight; /** * Protected constructor, create object using: * {@link org.dspace.content.service.RelationshipTypeService#create(Context)} } @@ -244,6 +255,38 @@ public class RelationshipType implements ReloadableEntity { this.rightMaxCardinality = rightMaxCardinality; } + /** + * Generic getter for the copyLeft + * @return the copyLeft value of this RelationshipType + */ + public boolean isCopyLeft() { + return copyLeft; + } + + /** + * Generic setter for the copyLeft + * @param copyLeft The copyLeft to be set on this RelationshipType + */ + public void setCopyLeft(boolean copyLeft) { + this.copyLeft = copyLeft; + } + + /** + * Generic getter for the copyRight + * @return the copyRight value of this RelationshipType + */ + public boolean isCopyRight() { + return copyRight; + } + + /** + * Generic setter for the copyRight + * @param copyRight The copyRight to be set on this RelationshipType + */ + public void setCopyRight(boolean copyRight) { + this.copyRight = copyRight; + } + /** * Standard getter for the ID of this RelationshipType * @return The ID of this RelationshipType diff --git a/dspace-api/src/main/java/org/dspace/content/RelationshipTypeServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/RelationshipTypeServiceImpl.java index 0864e8c185..992eb2a14d 100644 --- a/dspace-api/src/main/java/org/dspace/content/RelationshipTypeServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/RelationshipTypeServiceImpl.java @@ -117,6 +117,26 @@ public class RelationshipTypeServiceImpl implements RelationshipTypeService { return create(context, relationshipType); } + @Override + public RelationshipType create(Context context, EntityType leftEntityType, EntityType rightEntityType, + String leftwardType, String rightwardType, Integer leftCardinalityMinInteger, + Integer leftCardinalityMaxInteger, Integer rightCardinalityMinInteger, + Integer rightCardinalityMaxInteger, Boolean copyLeft, Boolean copyRight) + throws SQLException, AuthorizeException { + RelationshipType relationshipType = new RelationshipType(); + relationshipType.setLeftType(leftEntityType); + relationshipType.setRightType(rightEntityType); + relationshipType.setLeftwardType(leftwardType); + relationshipType.setRightwardType(rightwardType); + relationshipType.setCopyLeft(copyLeft); + relationshipType.setCopyRight(copyRight); + relationshipType.setLeftMinCardinality(leftCardinalityMinInteger); + relationshipType.setLeftMaxCardinality(leftCardinalityMaxInteger); + relationshipType.setRightMinCardinality(rightCardinalityMinInteger); + relationshipType.setRightMaxCardinality(rightCardinalityMaxInteger); + return create(context, relationshipType); + } + @Override public RelationshipType find(Context context,int id) throws SQLException { return relationshipTypeDAO.findByID(context, RelationshipType.class, id); diff --git a/dspace-api/src/main/java/org/dspace/content/service/RelationshipTypeService.java b/dspace-api/src/main/java/org/dspace/content/service/RelationshipTypeService.java index 7030ce94f0..a56104ec4e 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/RelationshipTypeService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/RelationshipTypeService.java @@ -135,6 +135,7 @@ public interface RelationshipTypeService extends DSpaceCRUDService findByEntityType(Context context, EntityType entityType, boolean isLeft, Integer limit, Integer offset) throws SQLException; + /** * This method will support the creation of a RelationshipType object with the given parameters * @param context The relevant DSpace context @@ -155,4 +156,24 @@ public interface RelationshipTypeService extends DSpaceCRUDService authorList = itemService.getMetadata(leftItem, "dc", "contributor", "author", Item.ANY); + assertThat(authorList.size(), equalTo(1)); + assertThat(authorList.get(0).getValue(), equalTo("familyName, firstName")); + assertThat(authorList.get(0).getMetadataField().getMetadataSchema().getName(), equalTo("dc")); + assertThat(authorList.get(0).getMetadataField().getElement(), equalTo("contributor")); + assertThat(authorList.get(0).getMetadataField().getQualifier(), equalTo("author")); + assertNull(authorList.get(0).getAuthority()); + + //verify there's no relation.isAuthorOfPublication actual metadata + List relationshipMetadataList = itemService + .getMetadata(leftItem, MetadataSchemaEnum.RELATION.getName(), "isAuthorOfPublication", null, Item.ANY); + assertThat(relationshipMetadataList.size(), equalTo(0)); + + //request the virtual metadata of the publication only + List list = relationshipMetadataService.getRelationshipMetadata(leftItem, true); + assertThat(list.size(), equalTo(0)); + } + + @Test + public void testAuthorDeleteRelationshipCopyToRightItemFromDefaultInDb() throws Exception { + initPublicationAuthorWithCopyParams(false, true); + context.turnOffAuthorisationSystem(); + //delete the relationship, copying the virtual metadata to actual metadata on the rightItem + //rightItem is the author + relationshipService.delete(context, relationship); + context.restoreAuthSystemState(); + + //verify there's no dc.contributor.author actual metadata on the publication + List authorList = itemService.getMetadata(leftItem, "dc", "contributor", "author", Item.ANY); + assertThat(authorList.size(), equalTo(0)); + + //verify there's no relation.isAuthorOfPublication actual metadata on the publication + List relationshipMetadataList = itemService + .getMetadata(leftItem, MetadataSchemaEnum.RELATION.getName(), "isAuthorOfPublication", null, Item.ANY); + assertThat(relationshipMetadataList.size(), equalTo(0)); + } + + @Test + public void testDeleteAuthorRelationshipCopyToBothItemsFromDefaultsInDb() throws Exception { + initPublicationAuthorWithCopyParams(true, true); + context.turnOffAuthorisationSystem(); + //delete the relationship, copying the virtual metadata to actual metadata on the both items + relationshipService.delete(context, relationship); + context.restoreAuthSystemState(); + + //verify the dc.contributor.author actual metadata + List authorList = itemService.getMetadata(leftItem, "dc", "contributor", "author", Item.ANY); + assertThat(authorList.size(), equalTo(1)); + assertThat(authorList.get(0).getValue(), equalTo("familyName, firstName")); + assertThat(authorList.get(0).getMetadataField().getMetadataSchema().getName(), equalTo("dc")); + assertThat(authorList.get(0).getMetadataField().getElement(), equalTo("contributor")); + assertThat(authorList.get(0).getMetadataField().getQualifier(), equalTo("author")); + assertNull(authorList.get(0).getAuthority()); + + //verify there's no relation.isAuthorOfPublication actual metadata + List relationshipMetadataList = itemService + .getMetadata(leftItem, MetadataSchemaEnum.RELATION.getName(), "isAuthorOfPublication", null, Item.ANY); + assertThat(relationshipMetadataList.size(), equalTo(0)); + } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RelationshipTypeConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RelationshipTypeConverter.java index 4ac98ee762..1826fd75c9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RelationshipTypeConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RelationshipTypeConverter.java @@ -34,6 +34,8 @@ public class RelationshipTypeConverter implements DSpaceConverter { private String leftwardType; private String rightwardType; + private boolean copyLeft; + private boolean copyRight; private Integer leftMinCardinality; private Integer leftMaxCardinality; private Integer rightMinCardinality; @@ -57,6 +59,38 @@ public class RelationshipTypeRest extends BaseObjectRest { this.rightwardType = rightwardType; } + /** + * Generic getter for the copyLeft + * @return the copyLeft value of this RelationshipTypeRest + */ + public boolean isCopyLeft() { + return copyLeft; + } + + /** + * Generic setter for the copyLeft + * @param copyLeft The copyLeft to be set on this RelationshipTypeRest + */ + public void setCopyLeft(boolean copyLeft) { + this.copyLeft = copyLeft; + } + + /** + * Generic getter for the copyRight + * @return the copyRight value of this RelationshipTypeRest + */ + public boolean isCopyRight() { + return copyRight; + } + + /** + * Generic setter for the copyRight + * @param copyRight The copyRight to be set on this RelationshipTypeRest + */ + public void setCopyRight(boolean copyRight) { + this.copyRight = copyRight; + } + public Integer getLeftMinCardinality() { return leftMinCardinality; } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipDeleteRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipDeleteRestRepositoryIT.java index ac9e4d9fa4..1483d70e7c 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipDeleteRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipDeleteRestRepositoryIT.java @@ -571,4 +571,33 @@ public class RelationshipDeleteRestRepositoryIT extends AbstractEntityIntegratio "relation", "isPersonOfProject", Item.ANY, Item.ANY); assertThat(projectRelationships.size(), equalTo(1)); } + + @Test + public void deleteItemCopyVirtualMetadataConfigured() throws Exception { + initPersonProjectPublication(); + + getClient(adminAuthToken).perform( + delete("/api/core/items/" + personItem.getID() + "?copyVirtualMetadata=configured")) + .andExpect(status().isNoContent()); + + publicationItem = itemService.find(context, publicationItem.getID()); + List publicationAuthorList = itemService.getMetadata(publicationItem, + "dc", "contributor", "author", Item.ANY); + assertThat(publicationAuthorList.size(), equalTo(0)); + + List publicationRelationships = itemService.getMetadata(publicationItem, + "relation", "isAuthorOfPublication", Item.ANY, Item.ANY); + assertThat(publicationRelationships.size(), equalTo(0)); + + projectItem = itemService.find(context, projectItem.getID()); + List projectAuthorList = itemService.getMetadata(projectItem, + "dc", "contributor", "author", Item.ANY); + assertThat(projectAuthorList.size(), equalTo(1)); + assertThat(projectAuthorList.get(0).getValue(), equalTo("Smith, Donald")); + assertNull(projectAuthorList.get(0).getAuthority()); + List projectRelationships = itemService.getMetadata(projectItem, + "relation", "isPersonOfProject", Item.ANY, Item.ANY); + assertThat(projectRelationships.size(), equalTo(0)); + } + } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/builder/RelationshipTypeBuilder.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/builder/RelationshipTypeBuilder.java index dd0eb0d976..b532d03d60 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/builder/RelationshipTypeBuilder.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/builder/RelationshipTypeBuilder.java @@ -106,4 +106,13 @@ public class RelationshipTypeBuilder extends AbstractBuilder matchExplicitRelationshipTypeValuesAndExplicitEntityType(int id, String leftwardType, String rightwardType, Integer leftMinCardinality, Integer leftMaxCardinality, Integer rightMinCardinality, Integer rightMaxCardinality, - EntityType leftEntityType, EntityType rightEntityType) { + EntityType leftEntityType, EntityType rightEntityType, boolean copyLeft, boolean copyRight) { return matchExplicitRelationshipTypeValuesAndExplicitEntityTypeValues(id, leftwardType, rightwardType, leftMinCardinality, leftMaxCardinality, rightMinCardinality, @@ -59,17 +61,20 @@ public class RelationshipTypeMatcher { leftEntityType.getID(), leftEntityType.getLabel(), rightEntityType.getID(), - rightEntityType.getLabel()); + rightEntityType.getLabel(), + copyLeft, copyRight); } private static Matcher matchExplicitRelationshipTypeValuesAndExplicitEntityTypeValues(int id, String leftwardType, String rightwardType, Integer leftMinCardinality, Integer leftMaxCardinality, Integer rightMinCardinality, Integer rightMaxCardinality, int leftEntityTypeId, String leftEntityTypeLabel, - int rightEntityTypeId, String rightEntityTypeLabel) { + int rightEntityTypeId, String rightEntityTypeLabel, boolean copyLeft, boolean copyRight) { return allOf( hasJsonPath("$.id", is(id)), hasJsonPath("$.leftwardType", is(leftwardType)), hasJsonPath("$.rightwardType", is(rightwardType)), + hasJsonPath("$.copyLeft", is(copyLeft)), + hasJsonPath("$.copyRight", is(copyRight)), hasJsonPath("$.leftMinCardinality", is(leftMinCardinality)), hasJsonPath("$.leftMaxCardinality", is(leftMaxCardinality)), hasJsonPath("$.rightMinCardinality", is(rightMinCardinality)), diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractEntityIntegrationTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractEntityIntegrationTest.java index a193c0a616..0b1d81a40e 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractEntityIntegrationTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractEntityIntegrationTest.java @@ -58,19 +58,19 @@ public class AbstractEntityIntegrationTest extends AbstractControllerIntegration RelationshipTypeBuilder.createRelationshipTypeBuilder(context, publication, person, "isAuthorOfPublication", "isPublicationOfAuthor", 0, null, 0, - null).build(); + null).withCopyLeft(false).withCopyRight(true).build(); RelationshipTypeBuilder.createRelationshipTypeBuilder(context, publication, project, "isProjectOfPublication", "isPublicationOfProject", 0, null, 0, - null).build(); + null).withCopyRight(true).build(); RelationshipTypeBuilder.createRelationshipTypeBuilder(context, publication, orgUnit, "isOrgUnitOfPublication", "isPublicationOfOrgUnit", 0, null, 0, - null).build(); + null).withCopyLeft(false).build(); RelationshipTypeBuilder.createRelationshipTypeBuilder(context, person, project, "isProjectOfPerson", "isPersonOfProject", 0, null, 0, - null).build(); + null).withCopyLeft(true).withCopyRight(true).build(); RelationshipTypeBuilder.createRelationshipTypeBuilder(context, person, orgUnit, "isOrgUnitOfPerson", "isPersonOfOrgUnit", 0, null, 0, @@ -82,7 +82,7 @@ public class AbstractEntityIntegrationTest extends AbstractControllerIntegration RelationshipTypeBuilder.createRelationshipTypeBuilder(context, journal, journalVolume, "isVolumeOfJournal", "isJournalOfVolume", 0, null, 1, - null).build(); + null).withCopyLeft(true).build(); RelationshipTypeBuilder.createRelationshipTypeBuilder(context, journalVolume, journalIssue, "isIssueOfJournalVolume", "isJournalVolumeOfIssue", 0, From d225489cab05e30c601cf6e5b2277b26e5af8419 Mon Sep 17 00:00:00 2001 From: Ben Bosman Date: Tue, 19 Nov 2019 13:01:58 +0100 Subject: [PATCH 014/125] Travis trigger --- .../src/main/java/org/dspace/app/util/InitializeEntities.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java b/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java index 6d54008fd0..23b99f3e8a 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java +++ b/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java @@ -230,7 +230,8 @@ public class InitializeEntities { if (relationshipType == null) { relationshipTypeService.create(context, leftEntityType, rightEntityType, leftwardType, rightwardType, leftCardinalityMinInteger, leftCardinalityMaxInteger, - rightCardinalityMinInteger, rightCardinalityMaxInteger, copyLeft, copyRight); + rightCardinalityMinInteger, rightCardinalityMaxInteger, + copyLeft, copyRight); } else { relationshipType.setCopyLeft(copyLeft); relationshipType.setCopyRight(copyRight); From 646651a6d9b77ec24fabe3e68e4e410eee08bf87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Wed, 20 Nov 2019 15:48:50 +0000 Subject: [PATCH 015/125] Filtering Entities on the default context --- dspace/config/crosswalks/oai/xoai.xml | 61 +++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/dspace/config/crosswalks/oai/xoai.xml b/dspace/config/crosswalks/oai/xoai.xml index 868382ccf0..8261ed9b20 100644 --- a/dspace/config/crosswalks/oai/xoai.xml +++ b/dspace/config/crosswalks/oai/xoai.xml @@ -290,18 +290,39 @@ By default, return an Item record: * If it is publicly accessible * OR it has been withdrawn (in order to display a tombstone record). + * AND doesn't have a relationship.type field + * OR the relationship.type is a Publication + * limiting the results only to Publications as expected This filter is used by the default context ([oai]/request). --> - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -398,6 +419,30 @@ info:eu-repo/grantAgreement/ + + + + org.dspace.xoai.filter.DSpaceMetadataExistsFilter + + relationship.type + + + + + + org.dspace.xoai.filter.DSpaceAtLeastOneMetadataFilter + + relationship.type + equal + + Publication + publication + + + + + From ccf047cd63bb7e275eaeb0df592e00dd3f11299c Mon Sep 17 00:00:00 2001 From: Chris Wilper Date: Sat, 23 Nov 2019 07:18:17 -0500 Subject: [PATCH 016/125] DS-4391 Get modified date from the right store This also tightens up the contract and improves javadocs a bit, so callers know what to expect. --- .../dspace/content/BitstreamServiceImpl.java | 6 +++++- .../content/service/BitstreamService.java | 12 +++++++++++- .../bitstore/BitstreamStorageServiceImpl.java | 19 +++++++++++-------- .../service/BitstreamStorageService.java | 11 +++++++---- .../app/rest/BitstreamRestController.java | 5 ++++- 5 files changed, 38 insertions(+), 15 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/content/BitstreamServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/BitstreamServiceImpl.java index 78d65800b1..83e91a2d7b 100644 --- a/dspace-api/src/main/java/org/dspace/content/BitstreamServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/BitstreamServiceImpl.java @@ -14,6 +14,8 @@ import java.util.Iterator; import java.util.List; import java.util.UUID; +import javax.annotation.Nullable; + import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; @@ -462,7 +464,9 @@ public class BitstreamServiceImpl extends DSpaceObjectServiceImpl imp return bitstreamDAO.getNotReferencedBitstreams(context); } - public Long getLastModified(Bitstream bitstream) { + @Nullable + @Override + public Long getLastModified(Bitstream bitstream) throws IOException { return bitstreamStorageService.getLastModified(bitstream); } } diff --git a/dspace-api/src/main/java/org/dspace/content/service/BitstreamService.java b/dspace-api/src/main/java/org/dspace/content/service/BitstreamService.java index 87f380cbca..4250041b5d 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/BitstreamService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/BitstreamService.java @@ -14,6 +14,8 @@ import java.util.Iterator; import java.util.List; import java.util.UUID; +import javax.annotation.Nullable; + import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; import org.dspace.content.BitstreamFormat; @@ -222,5 +224,13 @@ public interface BitstreamService extends DSpaceObjectService, DSpace List getNotReferencedBitstreams(Context context) throws SQLException; - public Long getLastModified(Bitstream bitstream); + /** + * Gets the last modified timestamp of the the given bitstream's content, if known. + * + * @param bitstream the bitstream. + * @return the timestamp in milliseconds, or {@code null} if unknown. + * @throws IOException if an unexpected io error occurs. + */ + @Nullable + Long getLastModified(Bitstream bitstream) throws IOException; } diff --git a/dspace-api/src/main/java/org/dspace/storage/bitstore/BitstreamStorageServiceImpl.java b/dspace-api/src/main/java/org/dspace/storage/bitstore/BitstreamStorageServiceImpl.java index c63b4ebe7e..a0d9101fb8 100644 --- a/dspace-api/src/main/java/org/dspace/storage/bitstore/BitstreamStorageServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/storage/bitstore/BitstreamStorageServiceImpl.java @@ -16,6 +16,8 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import javax.annotation.Nullable; + import org.apache.commons.collections4.MapUtils; import org.apache.logging.log4j.Logger; import org.dspace.authorize.AuthorizeException; @@ -326,15 +328,16 @@ public class BitstreamStorageServiceImpl implements BitstreamStorageService, Ini } } - public Long getLastModified(Bitstream bitstream) { - Map wantedMetadata = new HashMap(); - wantedMetadata.put("modified", null); - try { - wantedMetadata = stores.get(incoming).about(bitstream, wantedMetadata); - } catch (IOException e) { - log.error(e); + @Nullable + @Override + public Long getLastModified(Bitstream bitstream) throws IOException { + Map attrs = new HashMap(); + attrs.put("modified", null); + attrs = stores.get(bitstream.getStoreNumber()).about(bitstream, attrs); + if (attrs == null || !attrs.containsKey("modified")) { + return null; } - return Long.valueOf(wantedMetadata.get("modified").toString()); + return Long.valueOf(attrs.get("modified").toString()); } /** diff --git a/dspace-api/src/main/java/org/dspace/storage/bitstore/service/BitstreamStorageService.java b/dspace-api/src/main/java/org/dspace/storage/bitstore/service/BitstreamStorageService.java index 95963b14ca..209ef5d16b 100644 --- a/dspace-api/src/main/java/org/dspace/storage/bitstore/service/BitstreamStorageService.java +++ b/dspace-api/src/main/java/org/dspace/storage/bitstore/service/BitstreamStorageService.java @@ -12,6 +12,7 @@ import java.io.InputStream; import java.sql.SQLException; import java.util.Map; import java.util.UUID; +import javax.annotation.Nullable; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; @@ -181,11 +182,13 @@ public interface BitstreamStorageService { /** - * Get the last modified timestamp of the file linked to the given bitstream + * Gets the last modified timestamp of the the given bitstream's content, if known. * - * @param bitstream The bitstream for which to get the last modified timestamp - * @return The last modified timestamp in milliseconds + * @param bitstream the bitstream. + * @return the timestamp in milliseconds, or {@code null} if unknown. + * @throws IOException if an unexpected io error occurs. */ - public Long getLastModified(Bitstream bitstream); + @Nullable + Long getLastModified(Bitstream bitstream) throws IOException; } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamRestController.java index 773c33d8a6..dbfa707476 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamRestController.java @@ -140,10 +140,13 @@ public class BitstreamRestController { .withLength(bitstreamTuple.getRight()) .withChecksum(bit.getChecksum()) .withMimetype(mimetype) - .withLastModified(lastModified) .with(request) .with(response); + if (lastModified != null) { + sender.withLastModified(lastModified); + } + //Determine if we need to send the file as a download or if the browser can open it inline long dispositionThreshold = configurationService.getLongProperty("webui.content_disposition_threshold"); if (dispositionThreshold >= 0 && bitstreamTuple.getRight() > dispositionThreshold) { From 46d4f5e30ac75243557fc0db9fc48c024a687f21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Mon, 25 Nov 2019 12:01:40 +0000 Subject: [PATCH 017/125] Initial oai_openaire metadata format support with entities --- .../main/java/org/dspace/xoai/app/XOAI.java | 6 + .../java/org/dspace/xoai/util/ItemUtils.java | 447 +++-- .../oai/metadataFormats/oai_openaire.xsl | 1672 +++++++++++++++++ dspace/config/crosswalks/oai/xoai.xml | 11 + 4 files changed, 1945 insertions(+), 191 deletions(-) create mode 100644 dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl diff --git a/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java b/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java index 8704324a88..9b7e0be6f5 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java @@ -447,6 +447,12 @@ public class XOAI { for (String f : getFileFormats(item)) { doc.addField("metadata.dc.format.mimetype", f); } + + // Message output before processing - for debugging purposes + if (verbose) { + println(String.format("Item %s with handle %s is about to be indexed", + item.getID().toString(), handle)); + } ByteArrayOutputStream out = new ByteArrayOutputStream(); XmlOutputContext xmlContext = XmlOutputContext.emptyContext(out, Second); diff --git a/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java b/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java index 10bbc61e70..482dbab1f7 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java @@ -26,10 +26,12 @@ import org.dspace.content.Bundle; import org.dspace.content.Item; import org.dspace.content.MetadataField; import org.dspace.content.MetadataValue; +import org.dspace.content.Relationship; import org.dspace.content.authority.Choices; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.BitstreamService; import org.dspace.content.service.ItemService; +import org.dspace.content.service.RelationshipService; import org.dspace.core.ConfigurationManager; import org.dspace.core.Constants; import org.dspace.core.Context; @@ -43,19 +45,22 @@ import org.dspace.xoai.data.DSpaceItem; public class ItemUtils { private static final Logger log = LogManager.getLogger(ItemUtils.class); - private static final MetadataExposureService metadataExposureService - = UtilServiceFactory.getInstance().getMetadataExposureService(); + private static final MetadataExposureService metadataExposureService = UtilServiceFactory.getInstance() + .getMetadataExposureService(); - private static final ItemService itemService - = ContentServiceFactory.getInstance().getItemService(); + private static final ItemService itemService = ContentServiceFactory.getInstance().getItemService(); - private static final BitstreamService bitstreamService - = ContentServiceFactory.getInstance().getBitstreamService(); + private static final RelationshipService relationshipService = ContentServiceFactory.getInstance() + .getRelationshipService(); + + private static final BitstreamService bitstreamService = ContentServiceFactory.getInstance() + .getBitstreamService(); /** * Default constructor */ - private ItemUtils() { } + private ItemUtils() { + } private static Element getElement(List list, String name) { for (Element e : list) { @@ -73,228 +78,288 @@ public class ItemUtils { return e; } - private static Element.Field createValue( - String name, String value) { + private static Element.Field createValue(String name, String value) { Element.Field e = new Element.Field(); e.setValue(value); e.setName(name); return e; } + private static Element createBundlesElement(Context context, Item item) throws SQLException { + Element bundles = create("bundles"); + + List bs; + + bs = item.getBundles(); + for (Bundle b : bs) { + Element bundle = create("bundle"); + bundles.getElement().add(bundle); + bundle.getField().add(createValue("name", b.getName())); + + Element bitstreams = create("bitstreams"); + bundle.getElement().add(bitstreams); + List bits = b.getBitstreams(); + for (Bitstream bit : bits) { + Element bitstream = create("bitstream"); + bitstreams.getElement().add(bitstream); + String url = ""; + String bsName = bit.getName(); + String sid = String.valueOf(bit.getSequenceID()); + String baseUrl = ConfigurationManager.getProperty("oai", "bitstream.baseUrl"); + String handle = null; + // get handle of parent Item of this bitstream, if there + // is one: + List bn = bit.getBundles(); + if (!bn.isEmpty()) { + List bi = bn.get(0).getItems(); + if (!bi.isEmpty()) { + handle = bi.get(0).getHandle(); + } + } + if (bsName == null) { + List ext = bit.getFormat(context).getExtensions(); + bsName = "bitstream_" + sid + (ext.isEmpty() ? "" : ext.get(0)); + } + if (handle != null && baseUrl != null) { + url = baseUrl + "/bitstream/" + handle + "/" + sid + "/" + URLUtils.encode(bsName); + } else { + url = URLUtils.encode(bsName); + } + + String cks = bit.getChecksum(); + String cka = bit.getChecksumAlgorithm(); + String oname = bit.getSource(); + String name = bit.getName(); + String description = bit.getDescription(); + + if (name != null) { + bitstream.getField().add(createValue("name", name)); + } + if (oname != null) { + bitstream.getField().add(createValue("originalName", name)); + } + if (description != null) { + bitstream.getField().add(createValue("description", description)); + } + bitstream.getField().add(createValue("format", bit.getFormat(context).getMIMEType())); + bitstream.getField().add(createValue("size", "" + bit.getSizeBytes())); + bitstream.getField().add(createValue("url", url)); + bitstream.getField().add(createValue("checksum", cks)); + bitstream.getField().add(createValue("checksumAlgorithm", cka)); + bitstream.getField().add(createValue("sid", bit.getSequenceID() + "")); + } + } + + return bundles; + } + + private static Element createLicenseElement(Context context, Item item) + throws SQLException, AuthorizeException, IOException { + Element license = create("license"); + List licBundles; + licBundles = itemService.getBundles(item, Constants.LICENSE_BUNDLE_NAME); + if (!licBundles.isEmpty()) { + Bundle licBundle = licBundles.get(0); + List licBits = licBundle.getBitstreams(); + if (!licBits.isEmpty()) { + Bitstream licBit = licBits.get(0); + InputStream in; + + in = bitstreamService.retrieve(context, licBit); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Utils.bufferedCopy(in, out); + license.getField().add(createValue("bin", Base64Utils.encode(out.toString()))); + + } + } + return license; + } + + /** + * This method will create a top Element <relationships> and all subsequent + * <relationship> related for an item + * @param context + * @param item + * @return + * @throws SQLException + */ + private static Element createRelationshipsElement(Context context, Item item) throws SQLException { + Element relationships = create("relationships"); + + List rels = relationshipService.findByItem(context, item); + + // To build a list of all related Items + for (Relationship rel : rels) { + Item leftItem = rel.getLeftItem(); + Item rightItem = rel.getRightItem(); + boolean isLeftItem = false; + + Element relationship = create("relationship"); + + Item relItem; + //get the related item of the current item + if (leftItem.getID() != item.getID()) { + relItem = leftItem; + isLeftItem = true; + } else { + relItem = rightItem; + } + + relationship.getField().add(createValue("virtualRelationId", + org.dspace.core.Constants.VIRTUAL_AUTHORITY_PREFIX + rel.getID())); + relationship.getField().add(createValue("uuid", relItem.getID().toString())); + relationship.getField().add(createValue("name", isLeftItem ? + rel.getRightwardValue() : rel.getLeftwardValue() )); + + //just process each related item + List vals = itemService.getMetadata(relItem, Item.ANY, Item.ANY, Item.ANY, Item.ANY); + for (MetadataValue val : vals) { + MetadataField field = val.getMetadataField(); + try { + // Don't expose fields that are hidden by configuration + if (metadataExposureService.isHidden(context, field.getMetadataSchema().getName(), + field.getElement(), field.getQualifier())) { + continue; + } + + Element schema = getElement(relationship.getElement(), field.getMetadataSchema().getName()); + if (schema == null) { + schema = create(field.getMetadataSchema().getName()); + relationship.getElement().add(schema); + } + + fillSchemaElement(schema, val); + } catch (SQLException se) { + throw new RuntimeException(se); + } + } + relationships.getElement().add(relationship); + + } + return relationships; + } + + /** + * This method will add all sub-elements to the top element schema like: dc, or dcterms, ... + * @param schema Element argument passed by reference that will be changed + * @param val Metadatavalue that will be processed + * @throws SQLException + */ + private static void fillSchemaElement(Element schema, MetadataValue val) throws SQLException { + MetadataField field = val.getMetadataField(); + Element valueElem = schema; + + // Has element.. with XOAI one could have only schema and value + if (field.getElement() != null && !field.getElement().equals("")) { + Element element = getElement(schema.getElement(), field.getElement()); + if (element == null) { + element = create(field.getElement()); + schema.getElement().add(element); + } + valueElem = element; + + // Qualified element? + if (field.getQualifier() != null && !field.getQualifier().equals("")) { + Element qualifier = getElement(element.getElement(), field.getQualifier()); + if (qualifier == null) { + qualifier = create(field.getQualifier()); + element.getElement().add(qualifier); + } + valueElem = qualifier; + } + } + + // Language? + if (val.getLanguage() != null && !val.getLanguage().equals("")) { + Element language = getElement(valueElem.getElement(), val.getLanguage()); + if (language == null) { + language = create(val.getLanguage()); + valueElem.getElement().add(language); + } + valueElem = language; + } else { + Element language = getElement(valueElem.getElement(), "none"); + if (language == null) { + language = create("none"); + valueElem.getElement().add(language); + } + valueElem = language; + } + + valueElem.getField().add(createValue("value", val.getValue())); + if (val.getAuthority() != null) { + valueElem.getField().add(createValue("authority", val.getAuthority())); + if (val.getConfidence() != Choices.CF_NOVALUE) { + valueElem.getField().add(createValue("confidence", val.getConfidence() + "")); + } + } + } + public static Metadata retrieveMetadata(Context context, Item item) { Metadata metadata; // read all metadata into Metadata Object metadata = new Metadata(); + List vals = itemService.getMetadata(item, Item.ANY, Item.ANY, Item.ANY, Item.ANY); for (MetadataValue val : vals) { MetadataField field = val.getMetadataField(); - - // Don't expose fields that are hidden by configuration try { - if (metadataExposureService.isHidden(context, - field.getMetadataSchema().getName(), - field.getElement(), - field.getQualifier())) { + // Don't expose fields that are hidden by configuration + if (metadataExposureService.isHidden(context, field.getMetadataSchema().getName(), field.getElement(), + field.getQualifier())) { continue; } + + Element schema = getElement(metadata.getElement(), field.getMetadataSchema().getName()); + if (schema == null) { + schema = create(field.getMetadataSchema().getName()); + metadata.getElement().add(schema); + } + + fillSchemaElement(schema, val); } catch (SQLException se) { throw new RuntimeException(se); } - - Element valueElem = null; - Element schema = getElement(metadata.getElement(), field.getMetadataSchema().getName()); - if (schema == null) { - schema = create(field.getMetadataSchema().getName()); - metadata.getElement().add(schema); - } - valueElem = schema; - - // Has element.. with XOAI one could have only schema and value - if (field.getElement() != null && !field.getElement().equals("")) { - Element element = getElement(schema.getElement(), - field.getElement()); - if (element == null) { - element = create(field.getElement()); - schema.getElement().add(element); - } - valueElem = element; - - // Qualified element? - if (field.getQualifier() != null && !field.getQualifier().equals("")) { - Element qualifier = getElement(element.getElement(), - field.getQualifier()); - if (qualifier == null) { - qualifier = create(field.getQualifier()); - element.getElement().add(qualifier); - } - valueElem = qualifier; - } - } - - // Language? - if (val.getLanguage() != null && !val.getLanguage().equals("")) { - Element language = getElement(valueElem.getElement(), - val.getLanguage()); - if (language == null) { - language = create(val.getLanguage()); - valueElem.getElement().add(language); - } - valueElem = language; - } else { - Element language = getElement(valueElem.getElement(), - "none"); - if (language == null) { - language = create("none"); - valueElem.getElement().add(language); - } - valueElem = language; - } - - valueElem.getField().add(createValue("value", val.getValue())); - if (val.getAuthority() != null) { - valueElem.getField().add(createValue("authority", val.getAuthority())); - if (val.getConfidence() != Choices.CF_NOVALUE) { - valueElem.getField().add(createValue("confidence", val.getConfidence() + "")); - } - } } + // Done! Metadata has been read! // Now adding bitstream info - Element bundles = create("bundles"); - metadata.getElement().add(bundles); - - List bs; try { - bs = item.getBundles(); - for (Bundle b : bs) { - Element bundle = create("bundle"); - bundles.getElement().add(bundle); - bundle.getField() - .add(createValue("name", b.getName())); - - Element bitstreams = create("bitstreams"); - bundle.getElement().add(bitstreams); - List bits = b.getBitstreams(); - for (Bitstream bit : bits) { - Element bitstream = create("bitstream"); - bitstreams.getElement().add(bitstream); - String url = ""; - String bsName = bit.getName(); - String sid = String.valueOf(bit.getSequenceID()); - String baseUrl = ConfigurationManager.getProperty("oai", - "bitstream.baseUrl"); - String handle = null; - // get handle of parent Item of this bitstream, if there - // is one: - List bn = bit.getBundles(); - if (!bn.isEmpty()) { - List bi = bn.get(0).getItems(); - if (!bi.isEmpty()) { - handle = bi.get(0).getHandle(); - } - } - if (bsName == null) { - List ext = bit.getFormat(context).getExtensions(); - bsName = "bitstream_" + sid - + (ext.isEmpty() ? "" : ext.get(0)); - } - if (handle != null && baseUrl != null) { - url = baseUrl + "/bitstream/" - + handle + "/" - + sid + "/" - + URLUtils.encode(bsName); - } else { - url = URLUtils.encode(bsName); - } - - String cks = bit.getChecksum(); - String cka = bit.getChecksumAlgorithm(); - String oname = bit.getSource(); - String name = bit.getName(); - String description = bit.getDescription(); - - if (name != null) { - bitstream.getField().add( - createValue("name", name)); - } - if (oname != null) { - bitstream.getField().add( - createValue("originalName", name)); - } - if (description != null) { - bitstream.getField().add( - createValue("description", description)); - } - bitstream.getField().add( - createValue("format", bit.getFormat(context) - .getMIMEType())); - bitstream.getField().add( - createValue("size", "" + bit.getSizeBytes())); - bitstream.getField().add(createValue("url", url)); - bitstream.getField().add( - createValue("checksum", cks)); - bitstream.getField().add( - createValue("checksumAlgorithm", cka)); - bitstream.getField().add( - createValue("sid", bit.getSequenceID() - + "")); - } - } - } catch (SQLException e1) { - e1.printStackTrace(); + Element bundles = createBundlesElement(context, item); + metadata.getElement().add(bundles); + } catch (SQLException e) { + log.warn(e.getMessage(), e); } - // Other info Element other = create("others"); - other.getField().add( - createValue("handle", item.getHandle())); - other.getField().add( - createValue("identifier", DSpaceItem.buildIdentifier(item.getHandle()))); - other.getField().add( - createValue("lastModifyDate", item - .getLastModified().toString())); + other.getField().add(createValue("handle", item.getHandle())); + other.getField().add(createValue("identifier", DSpaceItem.buildIdentifier(item.getHandle()))); + other.getField().add(createValue("lastModifyDate", item.getLastModified().toString())); metadata.getElement().add(other); // Repository Info Element repository = create("repository"); - repository.getField().add( - createValue("name", - ConfigurationManager.getProperty("dspace.name"))); - repository.getField().add( - createValue("mail", - ConfigurationManager.getProperty("mail.admin"))); + repository.getField().add(createValue("name", ConfigurationManager.getProperty("dspace.name"))); + repository.getField().add(createValue("mail", ConfigurationManager.getProperty("mail.admin"))); metadata.getElement().add(repository); // Licensing info - Element license = create("license"); - List licBundles; try { - licBundles = itemService.getBundles(item, Constants.LICENSE_BUNDLE_NAME); - if (!licBundles.isEmpty()) { - Bundle licBundle = licBundles.get(0); - List licBits = licBundle.getBitstreams(); - if (!licBits.isEmpty()) { - Bitstream licBit = licBits.get(0); - InputStream in; - try { - in = bitstreamService.retrieve(context, licBit); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - Utils.bufferedCopy(in, out); - license.getField().add( - createValue("bin", - Base64Utils.encode(out.toString()))); - metadata.getElement().add(license); - } catch (AuthorizeException | IOException | SQLException e) { - log.warn(e.getMessage(), e); - } + Element license = createLicenseElement(context, item); + metadata.getElement().add(license); + } catch (AuthorizeException | IOException | SQLException e) { + log.warn(e.getMessage(), e); + } - } - } - } catch (SQLException e1) { - log.warn(e1.getMessage(), e1); + // Relationships + try { + Element relationships = createRelationshipsElement(context, item); + metadata.getElement().add(relationships); + } catch (SQLException e) { + log.warn(e.getMessage(), e); } return metadata; diff --git a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl new file mode 100644 index 0000000000..2361ea996f --- /dev/null +++ b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl @@ -0,0 +1,1672 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + e-mail + + + mailto: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AlternativeTitle + + + Subtitle + + + TranslatedTitle + + + Other + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Supervisor + + + Editor + + + Other + + + + + + + + + + + + + + + + + + + + + + + + Supervisor + + + Editor + + + Other + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + http://doi.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + European Commission + Fundação para a Ciência e Tecnologia + Welcome Trust + + + + + + + + + 10.13039/501100008530 + 10.13039/501100001871 + 10.13039/100010269 + + + + + + + + + + + + + + + + + + + Available + + + + + Collected + + + + + Copyrighted + + + + + Created + + + + + + Submitted + + + + + Updated + + + + + Valid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + http://purl.org/coar/resource_type/c_1162 + + annotation + + + + http://purl.org/coar/resource_type/c_0640 + + journal + + + + http://purl.org/coar/resource_type/c_6501 + + + literature + + journal article + + + + http://purl.org/coar/resource_type/c_b239 + + editorial + + + + http://purl.org/coar/resource_type/c_7a1f + + bachelor thesis + + + + http://purl.org/coar/resource_type/c_86bc + + bibliography + + + + http://purl.org/coar/resource_type/c_2f33 + + + literature + + book + + + + http://purl.org/coar/resource_type/c_3248 + + book part + + + + http://purl.org/coar/resource_type/c_ba08 + + book review + + + + http://purl.org/coar/resource_type/c_7ad9 + + website + + + + http://purl.org/coar/resource_type/c_e9a0 + + interactive resource + + + + http://purl.org/coar/resource_type/c_f744 + + conference proceedings + + + + http://purl.org/coar/resource_type/c_c94f + + conference object + + + + http://purl.org/coar/resource_type/c_5794 + + conference paper + + + + http://purl.org/coar/resource_type/c_6670 + + conference poster + + + + http://purl.org/coar/resource_type/c_3e5a + + contribution to journal + + + + http://purl.org/coar/resource_type/c_beb9 + + data paper + + + + http://purl.org/coar/resource_type/c_ddb1 + + + dataset + + dataset + + + + http://purl.org/coar/resource_type/c_db06 + + doctoral thesis + + + + http://purl.org/coar/resource_type/c_c513 + + image + + + + http://purl.org/coar/resource_type/c_8544 + + lecture + + + + http://purl.org/coar/resource_type/c_0857 + + letter + + + + http://purl.org/coar/resource_type/c_bdcc + + master thesis + + + + http://purl.org/coar/resource_type/c_8a7e + + moving image + + + + http://purl.org/coar/resource_type/c_2659 + + periodical + + + + http://purl.org/coar/resource_type/c_545b + + letter to the editor + + + + http://purl.org/coar/resource_type/c_15cd + + patent + + + + http://purl.org/coar/resource_type/c_816b + + preprint + + + + http://purl.org/coar/resource_type/c_93fc + + report + + + + http://purl.org/coar/resource_type/c_ba1f + + report part + + + + http://purl.org/coar/resource_type/c_baaf + + research proposal + + + + http://purl.org/coar/resource_type/c_efa0 + + review + + + + http://purl.org/coar/resource_type/c_5ce6 + + + software + + software + + + + http://purl.org/coar/resource_type/c_ecc8 + + still image + + + + http://purl.org/coar/resource_type/c_71bd + + technical documentation + + + + http://purl.org/coar/resource_type/c_393c + + workflow + + + + http://purl.org/coar/resource_type/c_8042 + + working paper + + + + http://purl.org/coar/resource_type/c_46ec + + thesis + + + + http://purl.org/coar/resource_type/c_12cc + + cartographic material + + + + http://purl.org/coar/resource_type/c_12cd + + map + + + + http://purl.org/coar/resource_type/c_12ce + + video + + + + http://purl.org/coar/resource_type/c_18cc + + sound + + + + http://purl.org/coar/resource_type/c_18cd + + musical composition + + + + http://purl.org/coar/resource_type/c_18cf + + text + + + + http://purl.org/coar/resource_type/c_18cp + + conference paper not in proceedings + + + + http://purl.org/coar/resource_type/c_18co + + conference poster not in proceedings + + + + http://purl.org/coar/resource_type/c_18cw + + musical notation + + + + http://purl.org/coar/resource_type/c_18ww + + internal report + + + + http://purl.org/coar/resource_type/c_18wz + + memorandum + + + + http://purl.org/coar/resource_type/c_18wq + + other type of report + + + + http://purl.org/coar/resource_type/c_186u + + policy report + + + + http://purl.org/coar/resource_type/c_18op + + project deliverable + + + + http://purl.org/coar/resource_type/c_18hj + + report to funding agency + + + + http://purl.org/coar/resource_type/c_18ws + + research report + + + + http://purl.org/coar/resource_type/c_18gh + + technical report + + + + http://purl.org/coar/resource_type/c_dcae04bc + + review article + + + + http://purl.org/coar/resource_type/c_2df8fbb1 + + research article + + + + http://purl.org/coar/resource_type/c_1843 + + + other research product + + other + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + http://purl.org/coar/access_right/c_abf2 + + + http://purl.org/coar/access_right/c_f1cf + + + http://purl.org/coar/access_right/c_16ec + + + http://purl.org/coar/access_right/c_14cb + + + + + + + + + + + + + + + open access + + + embargoed access + + + restricted access + + + metadata only access + + + + + + + + + + + + + + + + Handle + + + + + + DOI + + + + + + URL + + + + + + + + + + + + + + + + + + + + + + + + + + Creative Commons Attribution-NonCommercial-ShareAlike + + + Creative Commons Attribution-NonCommercial-NoDerivs + + + Creative Commons Attribution-NonCommercial + + + Creative Commons Attribution-ShareAlike + + + Creative Commons Attribution-NoDerivs + + + Creative Commons Attribution + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FOS + + + FOS + + + FOS + + + + + + + + + + + + + + + + + + + + + + + + + fulltext + + + + other + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARK + + + arXiv + + + bibcode + + + DOI + + + EAN13 + + + EISSN + + + Handle + + + IGSN + + + ISBN + + + ISSN + + + ISTC + + + LISSN + + + LSID + + + PMID + + + PURL + + + UPC + + + URL + + + URN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DOI + + + URL + + + + + IsVersionOf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + http://purl.org/coar/version/c_ab4af688f83e57aa + + + http://purl.org/coar/version/c_970fb48d4fbd8a85 + + + http://purl.org/coar/version/c_b1a7d7d4d402bcce + + + http://purl.org/coar/version/c_71e4c1898caa6e32 + + + http://purl.org/coar/version/c_e19f295774971610 + + + http://purl.org/coar/version/c_be7fb7dd8ff6fe43 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dspace/config/crosswalks/oai/xoai.xml b/dspace/config/crosswalks/oai/xoai.xml index 8261ed9b20..702aa9080e 100644 --- a/dspace/config/crosswalks/oai/xoai.xml +++ b/dspace/config/crosswalks/oai/xoai.xml @@ -20,6 +20,7 @@ + This is the default context of the DSpace OAI-PMH data provider. @@ -70,6 +71,7 @@ This contexts complies with OpenAIRE Guidelines for Literature Repositories v3.0. + @@ -155,6 +157,15 @@ http://irdb.nii.ac.jp/oai http://irdb.nii.ac.jp/oai/junii2-3-1.xsd + + + oai_openaire + metadataFormats/oai_openaire.xsl + http://namespace.openaire.eu/schema/oaire/ + https://www.openaire.eu/schema/repo-lit/4.0/openaire.xsd + From 532d8434c8dd6b270eea789ab00cfec660f2c658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Mon, 25 Nov 2019 13:31:04 +0000 Subject: [PATCH 018/125] Initial oai_openaire metadata format support with entities --- .../oai/metadataFormats/oai_openaire.xsl | 85 ++++++++++--------- 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl index 2361ea996f..34f7f0865d 100644 --- a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl +++ b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl @@ -576,7 +576,7 @@ - + @@ -594,7 +594,7 @@ - + - + @@ -1232,7 +1232,7 @@ - + @@ -1269,7 +1269,7 @@ - + @@ -1298,7 +1298,7 @@ - + @@ -1307,39 +1307,39 @@ - + - + - + - + - + - + - + - + - + - + - + - + @@ -1347,51 +1347,51 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1574,6 +1574,7 @@ + @@ -1591,7 +1592,7 @@ - + @@ -1616,7 +1617,7 @@ - + @@ -1634,9 +1635,9 @@ - + - + From e6e4ccb942986fe4b27c9b4930bd8533ae6b3aef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Mon, 25 Nov 2019 14:13:52 +0000 Subject: [PATCH 019/125] Changing Relationships to Entities node element --- .../src/main/java/org/dspace/xoai/util/ItemUtils.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java b/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java index 482dbab1f7..88dedf08f3 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java @@ -184,7 +184,7 @@ public class ItemUtils { * @throws SQLException */ private static Element createRelationshipsElement(Context context, Item item) throws SQLException { - Element relationships = create("relationships"); + Element relationships = create("entities"); List rels = relationshipService.findByItem(context, item); @@ -194,7 +194,7 @@ public class ItemUtils { Item rightItem = rel.getRightItem(); boolean isLeftItem = false; - Element relationship = create("relationship"); + Element relationship = create("entity"); Item relItem; //get the related item of the current item @@ -208,7 +208,7 @@ public class ItemUtils { relationship.getField().add(createValue("virtualRelationId", org.dspace.core.Constants.VIRTUAL_AUTHORITY_PREFIX + rel.getID())); relationship.getField().add(createValue("uuid", relItem.getID().toString())); - relationship.getField().add(createValue("name", isLeftItem ? + relationship.getField().add(createValue("relationName", isLeftItem ? rel.getRightwardValue() : rel.getLeftwardValue() )); //just process each related item From a4006cd17ee8683c147f26c7fda6b20b3073fdf8 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Wed, 27 Nov 2019 11:43:19 +0100 Subject: [PATCH 020/125] 67450: Discovery clean index fix --- .../org/dspace/discovery/SolrServiceImpl.java | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java index 00865f919c..e9fd85ff93 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java @@ -561,29 +561,40 @@ public class SolrServiceImpl implements SearchService, IndexingService { // Query for all indexed Items, Collections and Communities, // returning just their handle query.setFields(HANDLE_FIELD, RESOURCE_UNIQUE_ID, RESOURCE_ID_FIELD, RESOURCE_TYPE_FIELD); + query.addSort(RESOURCE_UNIQUE_ID, SolrQuery.ORDER.asc); query.setQuery(RESOURCE_TYPE_FIELD + ":" + type); - QueryResponse rsp = getSolr().query(query, SolrRequest.METHOD.POST); - SolrDocumentList docs = rsp.getResults(); - Iterator iter = docs.iterator(); - while (iter.hasNext()) { + // Get the total amount of results + QueryResponse totalResponse = getSolr().query(query); + long total = totalResponse.getResults().getNumFound(); - SolrDocument doc = (SolrDocument) iter.next(); + int start = 0; + int batch = 100; - String uniqueID = (String) doc.getFieldValue(RESOURCE_UNIQUE_ID); + query.setRows(batch); + while (start < total) { + query.setStart(start); + QueryResponse rsp = getSolr().query(query, SolrRequest.METHOD.POST); + SolrDocumentList docs = rsp.getResults(); - IndexableObject o = findIndexableObject(context, doc); + for (SolrDocument doc : docs) { + String uniqueID = (String) doc.getFieldValue(RESOURCE_UNIQUE_ID); - if (o == null) { - log.info("Deleting: " + uniqueID); - /* - * Use IndexWriter to delete, its easier to manage - * write.lock - */ - unIndexContent(context, uniqueID); - } else { - log.debug("Keeping: " + o.getUniqueIndexID()); + IndexableObject o = findIndexableObject(context, doc); + + if (o == null) { + log.info("Deleting: " + uniqueID); + /* + * Use IndexWriter to delete, its easier to manage + * write.lock + */ + unIndexContent(context, uniqueID); + } else { + log.debug("Keeping: " + o.getUniqueIndexID()); + } } + + start += batch; } } } catch (Exception e) { From dacc74c0a339ce41a9b18cf4b99dad37fe5f00bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Wed, 27 Nov 2019 11:58:51 +0000 Subject: [PATCH 021/125] comments --- .../java/org/dspace/xoai/util/ItemUtils.java | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java b/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java index 88dedf08f3..68b7dffd75 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java @@ -45,16 +45,17 @@ import org.dspace.xoai.data.DSpaceItem; public class ItemUtils { private static final Logger log = LogManager.getLogger(ItemUtils.class); - private static final MetadataExposureService metadataExposureService = UtilServiceFactory.getInstance() - .getMetadataExposureService(); + private static final MetadataExposureService metadataExposureService + = UtilServiceFactory.getInstance().getMetadataExposureService(); - private static final ItemService itemService = ContentServiceFactory.getInstance().getItemService(); + private static final ItemService itemService + = ContentServiceFactory.getInstance().getItemService(); - private static final RelationshipService relationshipService = ContentServiceFactory.getInstance() - .getRelationshipService(); + private static final RelationshipService relationshipService + = ContentServiceFactory.getInstance().getRelationshipService(); - private static final BitstreamService bitstreamService = ContentServiceFactory.getInstance() - .getBitstreamService(); + private static final BitstreamService bitstreamService + = ContentServiceFactory.getInstance().getBitstreamService(); /** * Default constructor @@ -240,7 +241,7 @@ public class ItemUtils { } /** - * This method will add all sub-elements to the top element schema like: dc, or dcterms, ... + * This method will add all sub-elements to a top element, like: dc, or dcterms, ... * @param schema Element argument passed by reference that will be changed * @param val Metadatavalue that will be processed * @throws SQLException @@ -295,6 +296,12 @@ public class ItemUtils { } } + /** + * Utility method to retrieve a structured XML in XOAI format + * @param context + * @param item + * @return Structured XML Metadata in XOAI format + */ public static Metadata retrieveMetadata(Context context, Item item) { Metadata metadata; @@ -354,7 +361,7 @@ public class ItemUtils { log.warn(e.getMessage(), e); } - // Relationships + // Relationships info try { Element relationships = createRelationshipsElement(context, item); metadata.getElement().add(relationships); From a5d999dbd8ad05eec34a366751b592a84dd7e0cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Wed, 27 Nov 2019 12:03:30 +0000 Subject: [PATCH 022/125] remove trailing whitespaces --- dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java b/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java index 9b7e0be6f5..0bf2fef557 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java @@ -447,12 +447,12 @@ public class XOAI { for (String f : getFileFormats(item)) { doc.addField("metadata.dc.format.mimetype", f); } - + // Message output before processing - for debugging purposes if (verbose) { println(String.format("Item %s with handle %s is about to be indexed", item.getID().toString(), handle)); - } + } ByteArrayOutputStream out = new ByteArrayOutputStream(); XmlOutputContext xmlContext = XmlOutputContext.emptyContext(out, Second); From b0016fc2457cc5004ed38d82dcb6e604538b9365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Wed, 27 Nov 2019 14:37:13 +0000 Subject: [PATCH 023/125] remove trailing whitespaces --- dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java b/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java index 68b7dffd75..525a685712 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java @@ -297,7 +297,7 @@ public class ItemUtils { } /** - * Utility method to retrieve a structured XML in XOAI format + * Utility method to retrieve a structured XML in XOAI format * @param context * @param item * @return Structured XML Metadata in XOAI format From e24fa61c8e74579d1ef91d9abd6590546c55f9c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Thu, 28 Nov 2019 10:39:30 +0000 Subject: [PATCH 024/125] indentation fix --- dspace/config/crosswalks/oai/xoai.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dspace/config/crosswalks/oai/xoai.xml b/dspace/config/crosswalks/oai/xoai.xml index 702aa9080e..9f83be4615 100644 --- a/dspace/config/crosswalks/oai/xoai.xml +++ b/dspace/config/crosswalks/oai/xoai.xml @@ -322,11 +322,11 @@ - - - - - + + + + + From 4fda5c1354f1be081095c2ef5aaa592ddbf02682 Mon Sep 17 00:00:00 2001 From: Ben Bosman Date: Thu, 28 Nov 2019 14:16:04 +0100 Subject: [PATCH 025/125] improving performance of the getType function, it's not a virtual field --- .../src/main/java/org/dspace/content/EntityServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/content/EntityServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/EntityServiceImpl.java index eb25605cff..00d522f926 100644 --- a/dspace-api/src/main/java/org/dspace/content/EntityServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/EntityServiceImpl.java @@ -51,7 +51,7 @@ public class EntityServiceImpl implements EntityService { @Override public EntityType getType(Context context, Entity entity) throws SQLException { Item item = entity.getItem(); - List list = itemService.getMetadata(item, "relationship", "type", null, Item.ANY); + List list = itemService.getMetadata(item, "relationship", "type", null, Item.ANY, false); if (!list.isEmpty()) { return entityTypeService.findByEntityType(context, list.get(0).getValue()); } else { From 9c533340885211b6d5348809571e4ad62ab74bd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Thu, 28 Nov 2019 15:45:29 +0000 Subject: [PATCH 026/125] Initial openaire submission forms --- dspace/config/submission-forms.xml | 1006 +++++++++++++++++++++++++++- 1 file changed, 1004 insertions(+), 2 deletions(-) diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index 52d4cf4ce9..b29a9c6c86 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -308,7 +308,6 @@ -
@@ -585,6 +584,523 @@ + + +
+ + + dc + title + + false + + onebox + Enter the main title of the item. + You must enter a main title for this item. + + + + + dc + title + alternative + true + + onebox + If the item has any alternative titles, please enter them here. + + + + + + isAuthorOfPublication + personConfiguration + true + + Add an author + + dc + contributor + author + name + + At least one author (plain text or relationship) is required + + + + + + + + dc + date + issued + false + + + date + Please give the date of previous publication or public distribution. + You can leave out the day + and/or month if they aren't applicable. + + You must enter at least the year. + + + + + dc + publisher + + false + + + onebox + Enter the name of the publisher of the previously issued instance of this item. + + + + + + dc + relation + HasVersion + false + + onebox + Enter the URL/DOI of the editor version of this item. + + + + + + dc + relation + References + false + + onebox + Enter the URL/DOI of the related Dataset. + + + + + + dc + identifier + + + true + + qualdrop_value + If the item has any identification numbers or codes associated with + it, please enter the types + and the actual numbers or codes. + + + + + + + oaire + citation + title + false + + onebox + Include the name of related item like the journal name, book title or event name. + + + + + + oaire + citation + conferencePlace + false + + onebox + Enter the event location. + + + + + + oaire + citation + conferenceDate + false + + date + Enter the date of the event. + + + + + + oaire + citation + volume + false + + onebox + Enter the volume of the item. + + + + + + oaire + citation + issue + false + + onebox + Enter the issue number of the item. + + + + + + oaire + citation + edition + false + + onebox + Enter the edition of the item. + + + + + + oaire + citation + startPage + false + + onebox + Enter the start page number. + + + + + + oaire + citation + endPage + false + + onebox + Enter the last page number. + + + + + + dc + type + + true + + dropdown + Select the type(s) of content of the item. To select more than one value in the list, you may + have to hold down the "CTRL" or "Shift" key. + + + + + + + oaire + version + false + + dropdown + Select the version of the resource. If the resource does not have that information, please + select "Not Applicable (or Unknown)". + + + + + + dc + language + iso + false + + dropdown + Select the language of the main content of the item. If the language does not appear in the + list, please select 'Other'. If the content does not really have a language (for example, if it + is a dataset or an image) please select 'N/A'. + + + + +
+ +
+ + + dc + subject + + + true + + tag + Enter appropriate subject keywords or phrases. + + srsc + + + + + + + + + + + dc + description + abstract + false + + textarea + Enter the abstract of the item. + + + + + + isProjectOfPublication + projectConfiguration + true + + Add a related Funding + + dc + relation + onebox + + + + + + + dc + rights + false + + dropdown + Select the access type of the resource. + + + + + + oaire + license + condition + false + + dropdown + Select the license of the resource. + + + + + + dc + coverage + + false + + textarea + Enter the coverage of the item, like a period, jurisdiction, etc. + + + + + + dc + description + + false + + textarea + Enter any other description or comments in this box. + + + +
+ +
+ + + person + familyName + + onebox + Enter the last name of the person + + + + + person + givenName + + onebox + Enter the first name of the person + + + + + dc + Title + + onebox + Enter the name of the person + + + + + person + affiliation + name + + onebox + Enter the first name of the person + + + + + person + email + + onebox + Enter the email of the person + + + + + person + identifier + + + true + + qualdrop_value + If the author has any identifiers or codes associated with + it, please enter the types and the actual numbers or codes. + + + + +
+ +
+ + + dc + title + + onebox + Enter the name of the project + + + + + dc + identifier + uri + + onebox + Enter the URL of the project webpage + + + + + dc + identifier + + onebox + Enter the identifier of the project + + + oaire + fundingStream + + textarea + Enter the name of the funding stream of the project + + + + + isFundingAgencyOfProject + fundingAgencyConfiguration + false + + Add a Funding Agency + + oaire + funder + name + onebox + + One funding agency is required + + +
+ +
+ + + organization + legalName + + onebox + Enter the name of the orgunit or organization + + + + + organization + identifier + + + true + + qualdrop_value + If the organization has any identifiers or codes associated with + it, please enter the types and the actual numbers or codes. + + + + + + + dc + description + + textarea + Enter the description of the orgunit + + +
+ @@ -770,6 +1286,492 @@ + + + + + + Without License + + + + Attribution (CC-BY) + http://creativecommons.org/licenses/by/4.0/ + + + Attribution, No Derivative Works (CC-BY-ND) + http://creativecommons.org/licenses/by-nd/4.0/ + + + Attribution, Share-alike (CC-BY-SA) + http://creativecommons.org/licenses/by-sa/4.0/ + + + Attribution, Non-commercial (CC-BY-NC) + http://creativecommons.org/licenses/by-nc/4.0/ + + + Attribution, Non-commercial, No Derivative Works (CC-BY-NC-ND) + http://creativecommons.org/licenses/by-nc-nd/4.0/ + + + Attribution, Non-commercial, Share-alike (CC-BY-NC-SA) + http://creativecommons.org/licenses/by-nc-sa/4.0/ + + + + Other + other + + + + + + + + Interactive Resource + interactive resource + + + - Website + website + + + Dataset + dataset + + + - Interview + interview + + + Image + image + + + - Moving Image + moving image + + + -- Video + video + + + - Still Image + still image + + + Other + other + + + Software + software + + + - Research Software + research software + + + Workflow + workflow + + + Cartographic Material + cartographic material + + + - Map + map + + + Sound + sound + + + - Musical Composition + musical composition + + + Text + text + + + - Annotation + annotation + + + - Bibliography + bibliography + + + - Book + book + + + -- Book Part + book part + + + - Conference Object + conference object + + + -- Conference Proceedings + conference proceedings + + + --- Conference Paper + conference paper + + + --- Conference Poster + conference poster + + + -- Conference Paper Not In Proceedings + conference paper not in proceedings + + + -- Conference Poster Not In Proceedings + conference poster not in proceedings + + + - Lecture + lecture + + + - Letter + letter + + + - Periodical + periodical + + + -- Journal + journal + + + --- Contribution to Journal + contribution to journal + + + ---- Journal Article + journal article + + + ----- Data Paper + data paper + + + ----- Review Article + review article + + + ----- Research Article + research article + + + ----- Corrigendum + corrigendum + + + ----- Software Paper + software paper + + + ---- Editorial + editorial + + + ---- Letter to the Editor + letter to the editor + + + -- Newspaper + newspaper + + + --- Newspaper Article + newspaper article + + + -- Magazine + magazine + + + - Patent + patent + + + - Preprint + preprint + + + - Report + report + + + -- Report Part + report part + + + -- Internal Report + internal report + + + -- Memorandum + memorandum + + + -- Other Type of Report + other type of report + + + -- Policy Report + policy report + + + -- Project Deliverable + project deliverable + + + --- Data Management Plan + data management plan + + + -- Report to Funding Agency + report to funding agency + + + -- Research Report + research report + + + -- Technical Report + technical report + + + - Research Proposal + research proposal + + + - Review + review + + + -- Book Review + book review + + + - Technical Documentation + technical documentation + + + - Working Paper + working paper + + + - Thesis + thesis + + + -- Bachelor Thesis + bachelor thesis + + + -- Doctoral Thesis + doctoral thesis + + + -- Master Thesis + master thesis + + + - Musical Notation + musical notation + + + - Blog Post + blog post + + + - Manuscript + website + + + Learning Object + learning object + + + Clinical Trial + clinical trial + + + Clinical Study + clinical study + + + + + + Author’s Original + http://purl.org/coar/version/c_b1a7d7d4d402bcce + + + Submitted Manuscript Under Review + http://purl.org/coar/version/c_71e4c1898caa6e32 + + + Accepted Manuscript + http://purl.org/coar/version/c_ab4af688f83e57aa + + + Proof + http://purl.org/coar/version/c_fa2ee174bc00049f + + + Version of Record + http://purl.org/coar/version/c_970fb48d4fbd8a85 + + + Corrected Version of Record + http://purl.org/coar/version/c_e19f295774971610 + + + Enhanced Version of Record + http://purl.org/coar/version/c_dc82b40f9837b551 + + + Not Applicable (or Unknown) + http://purl.org/coar/version/c_be7fb7dd8ff6fe43 + + + + + + + N/A + + + + English (United States) + eng + + + English + eng + + + Spanish + spa + + + German + deu + + + French + fra + + + Italian + ita + + + Japanese + jpn + + + Chinese + zho + + + Portuguese + por + + + Turkish + tur + + + (Other) + other + + + + + + open access + http://purl.org/coar/access_right/c_abf2 + + + embargoed access + http://purl.org/coar/access_right/c_f1cf + + + restricted access + http://purl.org/coar/access_right/c_16ec + + + metadata only access + http://purl.org/coar/access_right/c_14cb + + + + + + Scopus Author ID + scopus-author-id + + + Ciencia ID + ciencia-id + + + Google Scholar ID + gsid + + + Open Researcher and Contributor ID (ORCID) + orcid + + + Web of Science ResearcherID + rid + + + ISNI - International Standard Name Identifier + isni + + + + + + ISNI - International Standard Name Identifier + isni + + + Ringgold identifier + rin + + + Research Organization Registry + ror + + + Other + + + + - + \ No newline at end of file From a8bf0f7efa04b50ce109eb1e9e6aa0da76175ad0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Thu, 28 Nov 2019 16:04:51 +0000 Subject: [PATCH 027/125] comments --- dspace/config/submission-forms.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index b29a9c6c86..d41f3b2498 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -1286,6 +1286,8 @@ + + @@ -1653,9 +1655,6 @@ - N/A From 90b0862453ef5f4b89804971fcf24369b673bbb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Thu, 28 Nov 2019 17:31:09 +0000 Subject: [PATCH 028/125] initial openaire on default item submission forms --- dspace/config/item-submission.xml | 315 ++++++++++++++++------------- dspace/config/submission-forms.xml | 4 +- 2 files changed, 173 insertions(+), 146 deletions(-) diff --git a/dspace/config/item-submission.xml b/dspace/config/item-submission.xml index add6ef75f2..83d773966a 100644 --- a/dspace/config/item-submission.xml +++ b/dspace/config/item-submission.xml @@ -7,104 +7,104 @@ - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - org.dspace.app.rest.submit.step.CollectionStep - collection - submission - - - submit.progressbar.describe.stepone - org.dspace.app.rest.submit.step.DescribeStep - submission-form - - - submit.progressbar.describe.steptwo - org.dspace.app.rest.submit.step.DescribeStep - submission-form - + + + + + + + + + + + + + + + + + + + + + + + + + + + org.dspace.app.rest.submit.step.CollectionStep + collection + submission + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.steptwo + org.dspace.app.rest.submit.step.DescribeStep + submission-form + - - submit.progressbar.describe.stepone - org.dspace.app.rest.submit.step.DescribeStep - submission-form - - - submit.progressbar.describe.stepone - org.dspace.app.rest.submit.step.DescribeStep - submission-form - - - submit.progressbar.describe.stepone - org.dspace.app.rest.submit.step.DescribeStep - submission-form - - - submit.progressbar.describe.stepone - org.dspace.app.rest.submit.step.DescribeStep - submission-form - - - submit.progressbar.describe.stepone - org.dspace.app.rest.submit.step.DescribeStep - submission-form - - - submit.progressbar.describe.stepone - org.dspace.app.rest.submit.step.DescribeStep - submission-form - + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + - - submit.progressbar.upload - org.dspace.app.rest.submit.step.UploadStep - upload - - - submit.progressbar.license - org.dspace.app.rest.submit.step.LicenseStep - license - submission - + + submit.progressbar.upload + org.dspace.app.rest.submit.step.UploadStep + upload + + + submit.progressbar.license + org.dspace.app.rest.submit.step.LicenseStep + license + submission + - - Sample - org.dspace.submit.step.SampleStep - sample - - + + Sample + org.dspace.submit.step.SampleStep + sample + + @@ -157,69 +157,96 @@ - + - + - + - - + + - + - + - + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index d41f3b2498..46d40bf9bd 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -916,7 +916,7 @@ condition false - dropdown + dropdown Select the license of the resource.
@@ -947,7 +947,7 @@
-
+ person From 3afd0d8d0266afad0f4b4358b3f503b7c678a995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Fri, 29 Nov 2019 10:40:54 +0000 Subject: [PATCH 029/125] changing form names and adding references into item-submission and indentation --- dspace/config/item-submission.xml | 148 +++++++++++++++++------------ dspace/config/submission-forms.xml | 10 +- 2 files changed, 93 insertions(+), 65 deletions(-) diff --git a/dspace/config/item-submission.xml b/dspace/config/item-submission.xml index 83d773966a..6c4a5aba6d 100644 --- a/dspace/config/item-submission.xml +++ b/dspace/config/item-submission.xml @@ -106,36 +106,63 @@ submission - + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + - - - + + + - - + + - - + + - - + + - + Sample org.dspace.submit.step.SampleStep @@ -143,43 +170,43 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + - - + + - - + + - + - - + + - + - - + + @@ -222,30 +249,31 @@ - + - + - - + + - + + - + - + - + - + - + - + diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index 46d40bf9bd..deecd43972 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -586,7 +586,7 @@ - + dc @@ -838,7 +838,7 @@ -
+ dc @@ -947,7 +947,7 @@
-
+ person @@ -1011,7 +1011,7 @@
-
+ dc @@ -1065,7 +1065,7 @@
-
+ organization From dbfbc853bfe7538655b5645653624017864f198a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Fri, 29 Nov 2019 10:55:44 +0000 Subject: [PATCH 030/125] changing case for identifiers --- dspace/config/item-submission.xml | 31 +++++++++++++++--------------- dspace/config/submission-forms.xml | 12 ++++++------ 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/dspace/config/item-submission.xml b/dspace/config/item-submission.xml index 6c4a5aba6d..9e33987789 100644 --- a/dspace/config/item-submission.xml +++ b/dspace/config/item-submission.xml @@ -106,28 +106,29 @@ submission - + + submit.progressbar.describe.stepone org.dspace.app.rest.submit.step.DescribeStep submission-form - + submit.progressbar.describe.stepone org.dspace.app.rest.submit.step.DescribeStep submission-form - + submit.progressbar.describe.stepone org.dspace.app.rest.submit.step.DescribeStep submission-form - + submit.progressbar.describe.stepone org.dspace.app.rest.submit.step.DescribeStep submission-form - + submit.progressbar.describe.stepone org.dspace.app.rest.submit.step.DescribeStep submission-form @@ -248,13 +249,13 @@ - - + + - - + + @@ -263,17 +264,17 @@ - + - + - + - + - + - + diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index deecd43972..293d6af62c 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -586,7 +586,7 @@ - + dc @@ -614,7 +614,7 @@ isAuthorOfPublication - personConfiguration + openAIRECreatorConfiguration true Add an author @@ -838,7 +838,7 @@ -
+ dc @@ -947,7 +947,7 @@
-
+ person @@ -1011,7 +1011,7 @@
-
+ dc @@ -1065,7 +1065,7 @@
-
+ organization From 4c9a30bb14e2a6926ecef89efcb8f08721fafce2 Mon Sep 17 00:00:00 2001 From: Kevin Van de Velde Date: Fri, 29 Nov 2019 14:26:50 +0100 Subject: [PATCH 031/125] [DS 4287] Refactoring the IndexableObject & SolrServiceImpl to become more expandable --- .../org/dspace/app/util/SyndicationFeed.java | 16 +- .../java/org/dspace/browse/BrowserScope.java | 10 +- .../org/dspace/browse/ItemCountDAOSolr.java | 3 +- .../java/org/dspace/browse/SolrBrowseDAO.java | 12 +- .../java/org/dspace/content/Collection.java | 9 +- .../dspace/content/CollectionServiceImpl.java | 18 - .../java/org/dspace/content/Community.java | 9 +- .../dspace/content/CommunityServiceImpl.java | 18 - .../dspace/content/InProgressSubmission.java | 9 +- .../main/java/org/dspace/content/Item.java | 10 +- .../org/dspace/content/ItemServiceImpl.java | 18 - .../org/dspace/content/WorkspaceItem.java | 14 +- .../content/WorkspaceItemServiceImpl.java | 13 - .../factory/ContentServiceFactory.java | 22 - .../factory/ContentServiceFactoryImpl.java | 7 - .../content/service/CollectionService.java | 4 +- .../content/service/CommunityService.java | 4 +- .../service/InProgressSubmissionService.java | 4 +- .../service/IndexableObjectService.java | 44 - .../dspace/content/service/ItemService.java | 2 +- .../content/service/WorkspaceItemService.java | 2 +- .../main/java/org/dspace/core/Constants.java | 22 +- .../org/dspace/discovery/DiscoverQuery.java | 6 +- .../org/dspace/discovery/DiscoverResult.java | 2 +- .../org/dspace/discovery/IndexClient.java | 56 +- .../dspace/discovery/IndexEventConsumer.java | 21 +- .../org/dspace/discovery/IndexableObject.java | 34 +- .../org/dspace/discovery/IndexingService.java | 5 - .../org/dspace/discovery/SearchUtils.java | 10 +- .../org/dspace/discovery/SolrSearchCore.java | 87 + ...ceContentInOriginalBundleFilterPlugin.java | 7 +- .../discovery/SolrServiceFileInfoPlugin.java | 7 +- .../org/dspace/discovery/SolrServiceImpl.java | 1487 ++--------------- ...lrServiceMetadataBrowseIndexingPlugin.java | 17 +- .../SolrServiceResourceRestrictionPlugin.java | 5 +- .../SolrServiceSpellIndexingPlugin.java | 7 +- .../DiscoveryConfigurationService.java | 6 +- .../ClaimedTaskIndexFactoryImpl.java | 85 + .../CollectionIndexFactoryImpl.java | 146 ++ .../CommunityIndexFactoryImpl.java | 118 ++ .../DSpaceObjectIndexFactoryImpl.java | 79 + .../indexobject/IndexFactoryImpl.java | 193 +++ .../indexobject/IndexableClaimedTask.java | 51 + .../indexobject/IndexableCollection.java | 35 + .../indexobject/IndexableCommunity.java | 34 + .../indexobject/IndexableDSpaceObject.java | 43 + .../IndexableInProgressSubmission.java | 35 + .../discovery/indexobject/IndexableItem.java | 41 + .../indexobject/IndexablePoolTask.java | 51 + .../indexobject/IndexableWorkflowItem.java | 38 + .../indexobject/IndexableWorkspaceItem.java | 38 + .../InprogressSubmissionIndexFactoryImpl.java | 63 + .../indexobject/ItemIndexFactoryImpl.java | 684 ++++++++ .../indexobject/PoolTaskIndexFactoryImpl.java | 90 + .../WorkflowItemIndexFactoryImpl.java | 85 + .../WorkspaceItemIndexFactoryImpl.java | 84 + .../factory/ClaimedTaskIndexFactory.java | 18 + .../factory/CollectionIndexFactory.java | 32 + .../factory/CommunityIndexFactory.java | 18 + .../factory/DSpaceObjectIndexFactory.java | 40 + .../indexobject/factory/IndexFactory.java | 91 + .../factory/IndexObjectFactoryFactory.java | 159 ++ .../IndexObjectFactoryFactoryImpl.java | 27 + .../InprogressSubmissionIndexFactory.java | 34 + .../indexobject/factory/ItemIndexFactory.java | 41 + .../factory/PoolTaskIndexFactory.java | 18 + .../factory/WorkflowItemIndexFactory.java | 18 + .../factory/WorkspaceItemIndexFactory.java | 18 + .../main/java/org/dspace/search/Harvest.java | 14 +- .../org/dspace/workflow/WorkflowItem.java | 3 +- .../dspace/workflow/WorkflowItemService.java | 2 +- .../workflowbasic/BasicWorkflowItem.java | 11 +- .../BasicWorkflowItemServiceImpl.java | 14 - .../storedcomponents/ClaimedTask.java | 10 +- .../ClaimedTaskServiceImpl.java | 13 +- .../storedcomponents/PoolTask.java | 10 +- .../storedcomponents/PoolTaskServiceImpl.java | 13 +- .../storedcomponents/XmlWorkflowItem.java | 15 +- .../XmlWorkflowItemServiceImpl.java | 14 - .../service/ClaimedTaskService.java | 6 +- .../service/PoolTaskService.java | 6 +- .../config/spring/api/solr-services.xml | 4 +- ...rviceImpl.java => MockSolrSearchCore.java} | 2 +- .../dspace/app/rest/OpenSearchController.java | 3 +- .../converter/AInprogressItemConverter.java | 14 +- .../rest/converter/ClaimedTaskConverter.java | 5 +- .../rest/converter/CollectionConverter.java | 2 +- .../rest/converter/CommunityConverter.java | 2 +- .../converter/DiscoverResultConverter.java | 9 +- .../converter/IndexableObjectConverter.java | 4 +- .../app/rest/converter/ItemConverter.java | 2 +- .../app/rest/converter/PoolTaskConverter.java | 5 +- .../rest/converter/WorkflowItemConverter.java | 4 +- .../converter/WorkspaceItemConverter.java | 4 +- .../rest/model/AInprogressSubmissionRest.java | 4 +- .../app/rest/model/WorkflowItemRest.java | 2 +- .../app/rest/model/WorkspaceItemRest.java | 2 +- .../repository/BrowseItemLinkRepository.java | 4 +- ...imedTaskRestPermissionEvaluatorPlugin.java | 4 +- ...PoolTaskRestPermissionEvaluatorPlugin.java | 4 +- ...WorkflowRestPermissionEvaluatorPlugin.java | 4 +- .../app/rest/utils/DiscoverQueryBuilder.java | 23 +- .../dspace/app/rest/utils/ScopeResolver.java | 12 +- .../config/spring/api/solr-services.xml | 33 + .../app/rest/DiscoveryRestControllerIT.java | 14 +- .../AbstractIntegrationTestWithDatabase.java | 11 +- .../rest/utils/DiscoverQueryBuilderTest.java | 19 +- ...rviceImpl.java => MockSolrSearchCore.java} | 2 +- .../spring/api/core-factory-services.xml | 2 + dspace/config/spring/api/core-services.xml | 8 + dspace/config/spring/api/discovery.xml | 24 +- dspace/config/spring/api/solr-services.xml | 1 + dspace/solr/search/conf/schema.xml | 2 +- 113 files changed, 3043 insertions(+), 1857 deletions(-) delete mode 100644 dspace-api/src/main/java/org/dspace/content/service/IndexableObjectService.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/SolrSearchCore.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/ClaimedTaskIndexFactoryImpl.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/CollectionIndexFactoryImpl.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/CommunityIndexFactoryImpl.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/DSpaceObjectIndexFactoryImpl.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexFactoryImpl.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableClaimedTask.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableCollection.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableCommunity.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableDSpaceObject.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableInProgressSubmission.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableItem.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexablePoolTask.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableWorkflowItem.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableWorkspaceItem.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/InprogressSubmissionIndexFactoryImpl.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/PoolTaskIndexFactoryImpl.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/WorkflowItemIndexFactoryImpl.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/WorkspaceItemIndexFactoryImpl.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/ClaimedTaskIndexFactory.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/CollectionIndexFactory.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/CommunityIndexFactory.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/DSpaceObjectIndexFactory.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexFactory.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexObjectFactoryFactory.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexObjectFactoryFactoryImpl.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/InprogressSubmissionIndexFactory.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/ItemIndexFactory.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/PoolTaskIndexFactory.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/WorkflowItemIndexFactory.java create mode 100644 dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/WorkspaceItemIndexFactory.java rename dspace-api/src/test/java/org/dspace/discovery/{MockSolrServiceImpl.java => MockSolrSearchCore.java} (86%) create mode 100644 dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/solr-services.xml rename dspace-server-webapp/src/test/java/org/dspace/discovery/{MockSolrServiceImpl.java => MockSolrSearchCore.java} (92%) diff --git a/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java b/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java index 4bb89a1739..f72035b4e1 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java +++ b/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java @@ -50,9 +50,11 @@ import org.dspace.content.service.CollectionService; import org.dspace.content.service.CommunityService; import org.dspace.content.service.ItemService; import org.dspace.core.ConfigurationManager; -import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.discovery.IndexableObject; +import org.dspace.discovery.indexobject.IndexableCollection; +import org.dspace.discovery.indexobject.IndexableCommunity; +import org.dspace.discovery.indexobject.IndexableItem; import org.dspace.handle.factory.HandleServiceFactory; import org.dspace.services.ConfigurationService; import org.dspace.services.factory.DSpaceServicesFactory; @@ -200,8 +202,8 @@ public class SyndicationFeed { logoURL = ConfigurationManager.getProperty("webui.feed.logo.url"); } else { Bitstream logo = null; - if (dso.getType() == Constants.COLLECTION) { - Collection col = (Collection) dso; + if (dso instanceof IndexableCollection) { + Collection col = ((IndexableCollection) dso).getIndexedObject(); defaultTitle = col.getName(); feed.setDescription(collectionService.getMetadata(col, "short_description")); logo = col.getLogo(); @@ -210,8 +212,8 @@ public class SyndicationFeed { podcastFeed = true; } objectURL = resolveURL(request, col); - } else if (dso.getType() == Constants.COMMUNITY) { - Community comm = (Community) dso; + } else if (dso instanceof IndexableCommunity) { + Community comm = ((IndexableCommunity) dso).getIndexedObject(); defaultTitle = comm.getName(); feed.setDescription(communityService.getMetadata(comm, "short_description")); logo = comm.getLogo(); @@ -251,10 +253,10 @@ public class SyndicationFeed { if (items != null) { List entries = new ArrayList(); for (IndexableObject idxObj : items) { - if (idxObj.getType() != Constants.ITEM) { + if (!(idxObj instanceof IndexableItem)) { continue; } - Item item = (Item) idxObj; + Item item = ((IndexableItem) idxObj).getIndexedObject(); boolean hasDate = false; SyndEntry entry = new SyndEntryImpl(); entries.add(entry); diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowserScope.java b/dspace-api/src/main/java/org/dspace/browse/BrowserScope.java index 10cb23f8e9..ec61d37abc 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowserScope.java +++ b/dspace-api/src/main/java/org/dspace/browse/BrowserScope.java @@ -12,6 +12,8 @@ import org.dspace.content.Community; import org.dspace.content.DSpaceObject; import org.dspace.core.Context; import org.dspace.discovery.IndexableObject; +import org.dspace.discovery.indexobject.IndexableCollection; +import org.dspace.discovery.indexobject.IndexableCommunity; import org.dspace.sort.SortException; import org.dspace.sort.SortOption; @@ -136,10 +138,10 @@ public class BrowserScope { */ public void setBrowseContainer(IndexableObject dso) throws BrowseException { - if (dso instanceof Collection) { - this.collection = (Collection) dso; - } else if (dso instanceof Community) { - this.community = (Community) dso; + if (dso instanceof IndexableCollection) { + this.collection = ((IndexableCollection) dso).getIndexedObject(); + } else if (dso instanceof IndexableCommunity) { + this.community = ((IndexableCommunity) dso).getIndexedObject(); } else { throw new BrowseException("The container must be a community or a collection"); } diff --git a/dspace-api/src/main/java/org/dspace/browse/ItemCountDAOSolr.java b/dspace-api/src/main/java/org/dspace/browse/ItemCountDAOSolr.java index 4b741847a8..7bc6ac3aec 100644 --- a/dspace-api/src/main/java/org/dspace/browse/ItemCountDAOSolr.java +++ b/dspace-api/src/main/java/org/dspace/browse/ItemCountDAOSolr.java @@ -23,6 +23,7 @@ import org.dspace.discovery.DiscoverResult.FacetResult; import org.dspace.discovery.SearchService; import org.dspace.discovery.SearchServiceException; import org.dspace.discovery.configuration.DiscoveryConfigurationParameters; +import org.dspace.discovery.indexobject.IndexableItem; import org.dspace.services.factory.DSpaceServicesFactory; /** @@ -122,7 +123,7 @@ public class ItemCountDAOSolr implements ItemCountDAO { query.addFacetField(new DiscoverFacetField("location.coll", DiscoveryConfigurationParameters.TYPE_STANDARD, -1, DiscoveryConfigurationParameters.SORT.COUNT)); - query.addFilterQueries("search.resourcetype:2"); // count only items + query.addFilterQueries("search.resourcetype:" + IndexableItem.TYPE); // count only items query.addFilterQueries("NOT(discoverable:false)"); // only discoverable query.setMaxResults(0); diff --git a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java index ae491ad935..0de895adc2 100644 --- a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java +++ b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java @@ -20,7 +20,6 @@ import org.apache.logging.log4j.Logger; import org.dspace.authorize.factory.AuthorizeServiceFactory; import org.dspace.authorize.service.AuthorizeService; import org.dspace.content.Item; -import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.discovery.DiscoverFacetField; import org.dspace.discovery.DiscoverQuery; @@ -32,6 +31,7 @@ import org.dspace.discovery.IndexableObject; import org.dspace.discovery.SearchService; import org.dspace.discovery.SearchServiceException; import org.dspace.discovery.configuration.DiscoveryConfigurationParameters; +import org.dspace.discovery.indexobject.IndexableItem; import org.dspace.services.factory.DSpaceServicesFactory; /** @@ -210,7 +210,7 @@ public class SolrBrowseDAO implements BrowseDAO { } // filter on item to be sure to don't include any other object // indexed in the Discovery Search core - query.addFilterQueries("search.resourcetype:" + Constants.ITEM); + query.addFilterQueries("search.resourcetype:" + IndexableItem.TYPE); if (orderField != null) { query.setSortField("bi_" + orderField + "_sort", ascending ? SORT_ORDER.asc : SORT_ORDER.desc); @@ -308,10 +308,10 @@ public class SolrBrowseDAO implements BrowseDAO { DiscoverResult resp = getSolrResponse(); List bitems = new ArrayList<>(); - for (IndexableObject solrDoc : resp.getIndexableObjects()) { + for (IndexableObject solrDoc : resp.getIndexableObjects()) { // FIXME introduce project, don't retrieve Item immediately when // processing the query... - Item item = (Item) solrDoc; + Item item = ((IndexableItem) solrDoc).getIndexedObject(); bitems.add(item); } return bitems; @@ -322,7 +322,7 @@ public class SolrBrowseDAO implements BrowseDAO { throws BrowseException { DiscoverQuery query = new DiscoverQuery(); query.setQuery("search.resourceid:" + itemID - + " AND search.resourcetype:" + Constants.ITEM); + + " AND search.resourcetype:" + IndexableItem.TYPE); query.setMaxResults(1); DiscoverResult resp = null; try { @@ -345,7 +345,7 @@ public class SolrBrowseDAO implements BrowseDAO { addLocationScopeFilter(query); addStatusFilter(query); query.setMaxResults(0); - query.addFilterQueries("search.resourcetype:" + Constants.ITEM); + query.addFilterQueries("search.resourcetype:" + IndexableItem.TYPE); // We need to take into account the fact that we may be in a subset of the items if (authority != null) { diff --git a/dspace-api/src/main/java/org/dspace/content/Collection.java b/dspace-api/src/main/java/org/dspace/content/Collection.java index 0d6a662b29..32d70aacaf 100644 --- a/dspace-api/src/main/java/org/dspace/content/Collection.java +++ b/dspace-api/src/main/java/org/dspace/content/Collection.java @@ -12,7 +12,6 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.UUID; import javax.persistence.Cacheable; import javax.persistence.CascadeType; @@ -32,7 +31,6 @@ import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.CollectionService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.discovery.IndexableObject; import org.dspace.eperson.Group; import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.proxy.HibernateProxyHelper; @@ -55,7 +53,7 @@ import org.hibernate.proxy.HibernateProxyHelper; @Table(name = "collection") @Cacheable @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, include = "non-lazy") -public class Collection extends DSpaceObject implements DSpaceObjectLegacySupport, IndexableObject { +public class Collection extends DSpaceObject implements DSpaceObjectLegacySupport { @Column(name = "collection_id", insertable = false, updatable = false) private Integer legacyId; @@ -331,9 +329,4 @@ public class Collection extends DSpaceObject implements DSpaceObjectLegacySuppor return collectionService; } - @Override - public String getTypeText() { - return Constants.typeText[Constants.COLLECTION]; - } - } diff --git a/dspace-api/src/main/java/org/dspace/content/CollectionServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/CollectionServiceImpl.java index 828d154840..93c6e5053a 100644 --- a/dspace-api/src/main/java/org/dspace/content/CollectionServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/CollectionServiceImpl.java @@ -277,15 +277,6 @@ public class CollectionServiceImpl extends DSpaceObjectServiceImpl i return collectionDAO.findByID(context, Collection.class, id); } - @Override - /** - * This method is an alias of the find method needed to avoid ambiguity between the IndexableObjectService interface - * and the DSpaceObjectService interface - */ - public Collection findIndexableObject(Context context, UUID id) throws SQLException { - return collectionDAO.findByID(context, Collection.class, id); - } - @Override public void setMetadata(Context context, Collection collection, String field, String value) throws MissingResourceException, SQLException { @@ -794,15 +785,6 @@ public class CollectionServiceImpl extends DSpaceObjectServiceImpl i return Constants.COLLECTION; } - @Override - /** - * This method is an alias of the getSupportsTypeConstant method needed to avoid ambiguity between the - * IndexableObjectService interface and the DSpaceObjectService interface - */ - public int getSupportsIndexableObjectTypeConstant() { - return getSupportsTypeConstant(); - } - @Override public List findAuthorized(Context context, Community community, int actionID) throws SQLException { List myResults = new ArrayList<>(); diff --git a/dspace-api/src/main/java/org/dspace/content/Community.java b/dspace-api/src/main/java/org/dspace/content/Community.java index aecd03fcd6..f8319b4cd1 100644 --- a/dspace-api/src/main/java/org/dspace/content/Community.java +++ b/dspace-api/src/main/java/org/dspace/content/Community.java @@ -11,7 +11,6 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.UUID; import javax.persistence.Cacheable; import javax.persistence.CascadeType; @@ -32,7 +31,6 @@ import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.CommunityService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.discovery.IndexableObject; import org.dspace.eperson.Group; import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.proxy.HibernateProxyHelper; @@ -51,7 +49,7 @@ import org.hibernate.proxy.HibernateProxyHelper; @Table(name = "community") @Cacheable @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, include = "non-lazy") -public class Community extends DSpaceObject implements DSpaceObjectLegacySupport, IndexableObject { +public class Community extends DSpaceObject implements DSpaceObjectLegacySupport { /** * log4j category */ @@ -254,11 +252,6 @@ public class Community extends DSpaceObject implements DSpaceObjectLegacySupport return Constants.COMMUNITY; } - @Override - public String getTypeText() { - return Constants.typeText[Constants.COMMUNITY]; - } - @Override public String getName() { String value = getCommunityService() diff --git a/dspace-api/src/main/java/org/dspace/content/CommunityServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/CommunityServiceImpl.java index 242a5ff389..c49442267a 100644 --- a/dspace-api/src/main/java/org/dspace/content/CommunityServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/CommunityServiceImpl.java @@ -137,15 +137,6 @@ public class CommunityServiceImpl extends DSpaceObjectServiceImpl imp return communityDAO.findByID(context, Community.class, id); } - @Override - /** - * This method is an alias of the find method needed to avoid ambiguity between the IndexableObjectService interface - * and the DSpaceObjectService interface - */ - public Community findIndexableObject(Context context, UUID id) throws SQLException { - return find(context, id); - } - @Override public List findAll(Context context) throws SQLException { MetadataField sortField = metadataFieldService.findByElement(context, MetadataSchemaEnum.DC.getName(), @@ -520,15 +511,6 @@ public class CommunityServiceImpl extends DSpaceObjectServiceImpl imp return Constants.COMMUNITY; } - @Override - /** - * This method is an alias of the getSupportsTypeConstant method needed to avoid ambiguity between the - * IndexableObjectService interface and the DSpaceObjectService interface - */ - public int getSupportsIndexableObjectTypeConstant() { - return getSupportsTypeConstant(); - } - /** * Internal method to remove the community and all its children from the * database, and perform any pre/post-cleanup diff --git a/dspace-api/src/main/java/org/dspace/content/InProgressSubmission.java b/dspace-api/src/main/java/org/dspace/content/InProgressSubmission.java index df1d9c1623..5e7a04c4c9 100644 --- a/dspace-api/src/main/java/org/dspace/content/InProgressSubmission.java +++ b/dspace-api/src/main/java/org/dspace/content/InProgressSubmission.java @@ -7,10 +7,9 @@ */ package org.dspace.content; -import java.io.Serializable; import java.sql.SQLException; -import org.dspace.discovery.IndexableObject; +import org.dspace.core.ReloadableEntity; import org.dspace.eperson.EPerson; /** @@ -20,13 +19,13 @@ import org.dspace.eperson.EPerson; * @author Robert Tansley * @version $Revision$ */ -public interface InProgressSubmission extends IndexableObject { +public interface InProgressSubmission extends ReloadableEntity { /** * Get the internal ID of this submission * * @return the internal identifier */ - ID getID(); + Integer getID(); /** * Get the incomplete item object @@ -48,7 +47,7 @@ public interface InProgressSubmission extends Indexable * @return the submitting e-person * @throws SQLException if database error */ - EPerson getSubmitter() throws SQLException; + EPerson getSubmitter(); /** * Find out if the submission has (or is intended to have) more than one diff --git a/dspace-api/src/main/java/org/dspace/content/Item.java b/dspace-api/src/main/java/org/dspace/content/Item.java index adb2eaaacd..20975c8ccf 100644 --- a/dspace-api/src/main/java/org/dspace/content/Item.java +++ b/dspace-api/src/main/java/org/dspace/content/Item.java @@ -13,7 +13,6 @@ import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.UUID; import javax.persistence.CascadeType; import javax.persistence.Column; @@ -35,7 +34,6 @@ import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.ItemService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.discovery.IndexableObject; import org.dspace.eperson.EPerson; import org.hibernate.proxy.HibernateProxyHelper; @@ -55,7 +53,7 @@ import org.hibernate.proxy.HibernateProxyHelper; */ @Entity @Table(name = "item") -public class Item extends DSpaceObject implements DSpaceObjectLegacySupport, IndexableObject { +public class Item extends DSpaceObject implements DSpaceObjectLegacySupport { /** * log4j logger @@ -376,10 +374,4 @@ public class Item extends DSpaceObject implements DSpaceObjectLegacySupport, Ind } return itemService; } - - @Override - public String getTypeText() { - return getItemService().getTypeText(this); - } - } diff --git a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java index 2edd72b0f7..9502a2ca32 100644 --- a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java @@ -172,15 +172,6 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl implements It return item; } - @Override - /** - * This method is an alias of the find method needed to avoid ambiguity between the IndexableObjectService interface - * and the DSpaceObjectService interface - */ - public Item findIndexableObject(Context context, UUID id) throws SQLException { - return find(context, id); - } - @Override public Item create(Context context, WorkspaceItem workspaceItem) throws SQLException, AuthorizeException { if (workspaceItem.getItem() != null) { @@ -677,15 +668,6 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl implements It return Constants.ITEM; } - @Override - /** - * This method is an alias of the getSupportsTypeConstant method needed to avoid ambiguity between the - * IndexableObjectService interface and the DSpaceObjectService interface - */ - public int getSupportsIndexableObjectTypeConstant() { - return getSupportsTypeConstant(); - } - protected void rawDelete(Context context, Item item) throws AuthorizeException, SQLException, IOException { authorizeService.authorizeAction(context, item, Constants.REMOVE); diff --git a/dspace-api/src/main/java/org/dspace/content/WorkspaceItem.java b/dspace-api/src/main/java/org/dspace/content/WorkspaceItem.java index 0a61f4d93a..e2ded4815d 100644 --- a/dspace-api/src/main/java/org/dspace/content/WorkspaceItem.java +++ b/dspace-api/src/main/java/org/dspace/content/WorkspaceItem.java @@ -8,7 +8,6 @@ package org.dspace.content; import java.io.Serializable; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @@ -27,10 +26,7 @@ import javax.persistence.SequenceGenerator; import javax.persistence.Table; import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.core.ReloadableEntity; -import org.dspace.discovery.IndexableObject; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; import org.dspace.workflow.WorkflowItem; @@ -45,7 +41,7 @@ import org.hibernate.proxy.HibernateProxyHelper; @Entity @Table(name = "workspaceitem") public class WorkspaceItem - implements InProgressSubmission, Serializable, ReloadableEntity, IndexableObject { + implements InProgressSubmission, Serializable { @Id @Column(name = "workspace_item_id", unique = true, nullable = false) @@ -197,7 +193,7 @@ public class WorkspaceItem } @Override - public EPerson getSubmitter() throws SQLException { + public EPerson getSubmitter() { return item.getSubmitter(); } @@ -242,10 +238,4 @@ public class WorkspaceItem void addSupervisorGroup(Group group) { supervisorGroups.add(group); } - - @Override - public int getType() { - return Constants.WORKSPACEITEM; - } - } diff --git a/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java index 42ff757446..c45f6c737c 100644 --- a/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/WorkspaceItemServiceImpl.java @@ -60,11 +60,6 @@ public class WorkspaceItemServiceImpl implements WorkspaceItemService { } - @Override - public int getSupportsIndexableObjectTypeConstant() { - return Constants.WORKSPACEITEM; - } - @Override public WorkspaceItem find(Context context, int id) throws SQLException { WorkspaceItem workspaceItem = workspaceItemDAO.findByID(context, WorkspaceItem.class, id); @@ -83,14 +78,6 @@ public class WorkspaceItemServiceImpl implements WorkspaceItemService { return workspaceItem; } - @Override - public WorkspaceItem findIndexableObject(Context context, Integer id) throws SQLException { - if (id != null) { - return find(context, id); - } - return null; - } - @Override public WorkspaceItem create(Context context, Collection collection, boolean template) throws AuthorizeException, SQLException { diff --git a/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactory.java b/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactory.java index f7c5274883..4010e14861 100644 --- a/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactory.java +++ b/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactory.java @@ -7,7 +7,6 @@ */ package org.dspace.content.factory; -import java.io.Serializable; import java.util.List; import org.dspace.content.DSpaceObject; @@ -24,7 +23,6 @@ import org.dspace.content.service.DSpaceObjectService; import org.dspace.content.service.EntityService; import org.dspace.content.service.EntityTypeService; import org.dspace.content.service.InProgressSubmissionService; -import org.dspace.content.service.IndexableObjectService; import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; import org.dspace.content.service.MetadataFieldService; @@ -35,7 +33,6 @@ import org.dspace.content.service.RelationshipTypeService; import org.dspace.content.service.SiteService; import org.dspace.content.service.SupervisedItemService; import org.dspace.content.service.WorkspaceItemService; -import org.dspace.discovery.IndexableObject; import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.workflow.factory.WorkflowServiceFactory; @@ -47,13 +44,6 @@ import org.dspace.workflow.factory.WorkflowServiceFactory; */ public abstract class ContentServiceFactory { - /** - * Return the list of all the available implementations of the IndexableObjectService interface - * - * @return the list of IndexableObjectService - */ - public abstract List getIndexableObjectServices(); - public abstract List> getDSpaceObjectServices(); public abstract List> @@ -142,18 +132,6 @@ public abstract class ContentServiceFactory { throw new UnsupportedOperationException("Unknown DSpace type: " + type); } - @SuppressWarnings("unchecked") - public , PK extends Serializable> IndexableObjectService - getIndexableObjectService(int type) { - for (int i = 0; i < getIndexableObjectServices().size(); i++) { - IndexableObjectService objectService = getIndexableObjectServices().get(i); - if (objectService.getSupportsIndexableObjectTypeConstant() == type) { - return (IndexableObjectService) objectService; - } - } - throw new UnsupportedOperationException("Unknown Findable Object type: " + type); - } - public DSpaceObjectLegacySupportService getDSpaceLegacyObjectService(int type) { for (int i = 0; i < getDSpaceObjectLegacySupportServices().size(); i++) { DSpaceObjectLegacySupportService objectLegacySupportService = diff --git a/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactoryImpl.java b/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactoryImpl.java index db2a192bda..6f123ae1ba 100644 --- a/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/factory/ContentServiceFactoryImpl.java @@ -20,7 +20,6 @@ import org.dspace.content.service.DSpaceObjectLegacySupportService; import org.dspace.content.service.DSpaceObjectService; import org.dspace.content.service.EntityService; import org.dspace.content.service.EntityTypeService; -import org.dspace.content.service.IndexableObjectService; import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; import org.dspace.content.service.MetadataFieldService; @@ -31,7 +30,6 @@ import org.dspace.content.service.RelationshipTypeService; import org.dspace.content.service.SiteService; import org.dspace.content.service.SupervisedItemService; import org.dspace.content.service.WorkspaceItemService; -import org.dspace.utils.DSpace; import org.springframework.beans.factory.annotation.Autowired; /** @@ -85,11 +83,6 @@ public class ContentServiceFactoryImpl extends ContentServiceFactory { @Autowired(required = true) private EntityService entityService; - @Override - public List getIndexableObjectServices() { - return new DSpace().getServiceManager().getServicesByType(IndexableObjectService.class); - } - @Override public List> getDSpaceObjectServices() { return dSpaceObjectServices; diff --git a/dspace-api/src/main/java/org/dspace/content/service/CollectionService.java b/dspace-api/src/main/java/org/dspace/content/service/CollectionService.java index 063f217d79..aa8bc94d25 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/CollectionService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/CollectionService.java @@ -13,7 +13,6 @@ import java.sql.SQLException; import java.util.List; import java.util.Map; import java.util.MissingResourceException; -import java.util.UUID; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; @@ -31,8 +30,7 @@ import org.dspace.eperson.Group; * @author kevinvandevelde at atmire.com */ public interface CollectionService - extends DSpaceObjectService, DSpaceObjectLegacySupportService, - IndexableObjectService { + extends DSpaceObjectService, DSpaceObjectLegacySupportService { /** * Create a new collection with a new ID. diff --git a/dspace-api/src/main/java/org/dspace/content/service/CommunityService.java b/dspace-api/src/main/java/org/dspace/content/service/CommunityService.java index 3e9b372930..6284b27e25 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/CommunityService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/CommunityService.java @@ -12,7 +12,6 @@ import java.io.InputStream; import java.sql.SQLException; import java.util.List; import java.util.MissingResourceException; -import java.util.UUID; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; @@ -28,8 +27,7 @@ import org.dspace.eperson.Group; * * @author kevinvandevelde at atmire.com */ -public interface CommunityService extends DSpaceObjectService, DSpaceObjectLegacySupportService, - IndexableObjectService { +public interface CommunityService extends DSpaceObjectService, DSpaceObjectLegacySupportService { /** diff --git a/dspace-api/src/main/java/org/dspace/content/service/InProgressSubmissionService.java b/dspace-api/src/main/java/org/dspace/content/service/InProgressSubmissionService.java index 627e27bad6..aa81b16fba 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/InProgressSubmissionService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/InProgressSubmissionService.java @@ -7,7 +7,6 @@ */ package org.dspace.content.service; -import java.io.Serializable; import java.sql.SQLException; import org.dspace.app.util.DCInputsReaderException; @@ -25,8 +24,7 @@ import org.dspace.core.Context; * @param class type * @author kevinvandevelde at atmire.com */ -public interface InProgressSubmissionService, ID extends Serializable> - extends IndexableObjectService { +public interface InProgressSubmissionService { /** * Deletes submission wrapper, doesn't delete item contents diff --git a/dspace-api/src/main/java/org/dspace/content/service/IndexableObjectService.java b/dspace-api/src/main/java/org/dspace/content/service/IndexableObjectService.java deleted file mode 100644 index 929f244206..0000000000 --- a/dspace-api/src/main/java/org/dspace/content/service/IndexableObjectService.java +++ /dev/null @@ -1,44 +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.content.service; - -import java.io.Serializable; -import java.sql.SQLException; - -import org.dspace.core.Context; -import org.dspace.discovery.IndexableObject; - -/** - * Base Service interface class for any IndexableObject. The name of the methods contains IndexableObject to avoid - * ambiguity reference as some implementation supports both this interface than the DSpaceObectService interface - * - * @param - * class type of the indexable object - * @param - * class type of the primary key - * @author Andrea Bollini (andrea.bollini at 4science.it) - */ -public interface IndexableObjectService, PK extends Serializable> { - - /** - * Generic find for when the precise type of an IndexableObject is not known - * - * @param context - the context - * @param id - id within table of type'd indexable objects - * @return the indexable object found, or null if it does not exist. - * @throws SQLException only upon failure accessing the database. - */ - public T findIndexableObject(Context context, PK id) throws SQLException; - - /** - * Returns the Constants which this service supports - * - * @return a org.dspace.core.Constants that represents a IndexableObject type - */ - public int getSupportsIndexableObjectTypeConstant(); -} diff --git a/dspace-api/src/main/java/org/dspace/content/service/ItemService.java b/dspace-api/src/main/java/org/dspace/content/service/ItemService.java index 8f651b0e59..71b736f1bd 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/ItemService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/ItemService.java @@ -38,7 +38,7 @@ import org.dspace.eperson.Group; * @author kevinvandevelde at atmire.com */ public interface ItemService - extends DSpaceObjectService, DSpaceObjectLegacySupportService, IndexableObjectService { + extends DSpaceObjectService, DSpaceObjectLegacySupportService { public Thumbnail getThumbnail(Context context, Item item, boolean requireOriginal) throws SQLException; diff --git a/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java b/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java index 6394f0eb17..3ee381706c 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/WorkspaceItemService.java @@ -27,7 +27,7 @@ import org.dspace.workflow.WorkflowItem; * * @author kevinvandevelde at atmire.com */ -public interface WorkspaceItemService extends InProgressSubmissionService { +public interface WorkspaceItemService extends InProgressSubmissionService { /** * Get a workspace item from the database. The item, collection and diff --git a/dspace-api/src/main/java/org/dspace/core/Constants.java b/dspace-api/src/main/java/org/dspace/core/Constants.java index 9e4a8db840..8feb2434f8 100644 --- a/dspace-api/src/main/java/org/dspace/core/Constants.java +++ b/dspace-api/src/main/java/org/dspace/core/Constants.java @@ -55,31 +55,11 @@ public class Constants { */ public static final int EPERSON = 7; - /** - * Type of workspace item objects - */ - public static final int WORKSPACEITEM = 8; - - /** - * Type of workflow item objects - */ - public static final int WORKFLOWITEM = 9; - - /** - * Type of pool task objects - */ - public static final int POOLTASK = 10; - - /** - * Type of claimed task objects - */ - public static final int CLAIMEDTASK = 11; - /** * lets you look up type names from the type IDs */ public static final String[] typeText = { "BITSTREAM", "BUNDLE", "ITEM", "COLLECTION", "COMMUNITY", "SITE", "GROUP", - "EPERSON", "WORKSPACEITEM", "WORKFLOWITEM", "POOLTASK", "CLAIMEDTASK" }; + "EPERSON"}; /** * Special Bundle and Bitstream Names: diff --git a/dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java b/dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java index a21c33cdd1..d3efb3c626 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java +++ b/dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java @@ -31,7 +31,7 @@ public class DiscoverQuery { **/ private String query; private List filterQueries; - private int DSpaceObjectFilter = -1; + private String DSpaceObjectFilter = null; private List fieldPresentQueries; private boolean spellCheck; @@ -120,7 +120,7 @@ public class DiscoverQuery { * * @param DSpaceObjectFilter the DSpace object filer */ - public void setDSpaceObjectFilter(int DSpaceObjectFilter) { + public void setDSpaceObjectFilter(String DSpaceObjectFilter) { this.DSpaceObjectFilter = DSpaceObjectFilter; } @@ -130,7 +130,7 @@ public class DiscoverQuery { * * @return the DSpace object filer */ - public int getDSpaceObjectFilter() { + public String getDSpaceObjectFilter() { return DSpaceObjectFilter; } diff --git a/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java b/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java index a6bfa0b2b5..b2bd0fc5ff 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java +++ b/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java @@ -243,7 +243,7 @@ public class DiscoverResult { String dsoString = SearchDocument.getIndexableObjectStringRepresentation(idxObj); List result = searchDocuments.get(dsoString); if (result == null) { - return new ArrayList(); + return new ArrayList<>(); } else { return result; } diff --git a/dspace-api/src/main/java/org/dspace/discovery/IndexClient.java b/dspace-api/src/main/java/org/dspace/discovery/IndexClient.java index c4f88e8edd..2e7b00a617 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/IndexClient.java +++ b/dspace-api/src/main/java/org/dspace/discovery/IndexClient.java @@ -10,6 +10,7 @@ package org.dspace.discovery; import java.io.IOException; import java.sql.SQLException; import java.util.Iterator; +import java.util.Optional; import java.util.UUID; import org.apache.commons.cli.CommandLine; @@ -17,11 +18,16 @@ import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.dspace.content.Collection; import org.dspace.content.Community; +import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.ItemService; -import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.discovery.indexobject.IndexableCollection; +import org.dspace.discovery.indexobject.IndexableCommunity; +import org.dspace.discovery.indexobject.IndexableItem; +import org.dspace.discovery.indexobject.factory.IndexFactory; +import org.dspace.discovery.indexobject.factory.IndexObjectFactoryFactory; import org.dspace.handle.factory.HandleServiceFactory; import org.dspace.scripts.DSpaceRunnable; import org.springframework.beans.factory.annotation.Autowired; @@ -79,28 +85,42 @@ public class IndexClient extends DSpaceRunnable { } catch (Exception e) { // nothing to do, it should be an handle } - IndexableObject dso = null; + Optional indexableObject = Optional.empty(); if (uuid != null) { - dso = ContentServiceFactory.getInstance().getItemService().find(context, uuid); - if (dso == null) { + final Item item = ContentServiceFactory.getInstance().getItemService().find(context, uuid); + if (item != null) { + indexableObject = Optional.of(new IndexableItem(item)); + } else { // it could be a community - dso = ContentServiceFactory.getInstance().getCommunityService().find(context, uuid); - if (dso == null) { + final Community community = ContentServiceFactory.getInstance(). + getCommunityService().find(context, uuid); + if (community != null) { + indexableObject = Optional.of(new IndexableCommunity(community)); + } else { // it could be a collection - dso = ContentServiceFactory.getInstance().getCollectionService().find(context, uuid); + final Collection collection = ContentServiceFactory.getInstance(). + getCollectionService().find(context, uuid); + if (collection != null) { + indexableObject = Optional.of(new IndexableCollection(collection)); + } } } } else { - dso = (IndexableObject) HandleServiceFactory.getInstance() - .getHandleService().resolveToObject(context, param); + final DSpaceObject dso = HandleServiceFactory.getInstance() + .getHandleService().resolveToObject(context, param); + if (dso != null) { + final IndexFactory indexableObjectService = IndexObjectFactoryFactory.getInstance(). + getIndexFactoryByType(String.valueOf(dso.getType())); + indexableObject = indexableObjectService.findIndexableObject(context, dso.getID().toString()); + } } - if (dso == null) { + if (!indexableObject.isPresent()) { throw new IllegalArgumentException("Cannot resolve " + param + " to a DSpace object"); } handler.logInfo("Indexing " + param + " force " + commandLine.hasOption("f")); final long startTimeMillis = System.currentTimeMillis(); - final long count = indexAll(indexer, ContentServiceFactory.getInstance().getItemService(), context, - dso); + final long count = indexAll(indexer, ContentServiceFactory.getInstance(). + getItemService(), context, indexableObject.get()); final long seconds = (System.currentTimeMillis() - startTimeMillis) / 1000; handler.logInfo("Indexed " + count + " object" + (count > 1 ? "s" : "") + " in " + seconds + " seconds"); } else if (indexClientOptions == IndexClientOptions.UPDATE || @@ -163,11 +183,11 @@ public class IndexClient extends DSpaceRunnable { indexingService.indexContent(context, dso, true, true); count++; - if (dso.getType() == Constants.COMMUNITY) { + if (dso.getIndexedObject() instanceof Community) { final Community community = (Community) dso; final String communityHandle = community.getHandle(); for (final Community subcommunity : community.getSubcommunities()) { - count += indexAll(indexingService, itemService, context, subcommunity); + count += indexAll(indexingService, itemService, context, new IndexableCommunity(subcommunity)); //To prevent memory issues, discard an object from the cache after processing context.uncacheEntity(subcommunity); } @@ -176,13 +196,13 @@ public class IndexClient extends DSpaceRunnable { communityHandle); for (final Collection collection : reloadedCommunity.getCollections()) { count++; - indexingService.indexContent(context, collection, true, true); + indexingService.indexContent(context, new IndexableCollection(collection), true, true); count += indexItems(indexingService, itemService, context, collection); //To prevent memory issues, discard an object from the cache after processing context.uncacheEntity(collection); } - } else if (dso.getType() == Constants.COLLECTION) { - count += indexItems(indexingService, itemService, context, (Collection) dso); + } else if (dso instanceof IndexableCollection) { + count += indexItems(indexingService, itemService, context, (Collection) dso.getIndexedObject()); } return count; @@ -209,7 +229,7 @@ public class IndexClient extends DSpaceRunnable { final Iterator itemIterator = itemService.findByCollection(context, collection); while (itemIterator.hasNext()) { Item item = itemIterator.next(); - indexingService.indexContent(context, item, true, false); + indexingService.indexContent(context, new IndexableItem(item), true, false); count++; //To prevent memory issues, discard an object from the cache after processing context.uncacheEntity(item); diff --git a/dspace-api/src/main/java/org/dspace/discovery/IndexEventConsumer.java b/dspace-api/src/main/java/org/dspace/discovery/IndexEventConsumer.java index 29c857fa9b..cab51a2c5a 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/IndexEventConsumer.java +++ b/dspace-api/src/main/java/org/dspace/discovery/IndexEventConsumer.java @@ -15,6 +15,7 @@ import org.dspace.content.Bundle; import org.dspace.content.DSpaceObject; import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.discovery.indexobject.factory.IndexObjectFactoryFactory; import org.dspace.event.Consumer; import org.dspace.event.Event; import org.dspace.services.factory.DSpaceServicesFactory; @@ -42,6 +43,8 @@ public class IndexEventConsumer implements Consumer { .getServiceByName(IndexingService.class.getName(), IndexingService.class); + IndexObjectFactoryFactory indexObjectServiceFactory = IndexObjectFactoryFactory.getInstance(); + @Override public void initialize() throws Exception { @@ -58,8 +61,8 @@ public class IndexEventConsumer implements Consumer { public void consume(Context ctx, Event event) throws Exception { if (objectsToUpdate == null) { - objectsToUpdate = new HashSet(); - uniqueIdsToDelete = new HashSet(); + objectsToUpdate = new HashSet<>(); + uniqueIdsToDelete = new HashSet<>(); } int st = event.getSubjectType(); @@ -103,11 +106,11 @@ public class IndexEventConsumer implements Consumer { if (subject == null) { log.warn(event.getEventTypeAsString() + " event, could not get object for " + event.getSubjectTypeAsString() + " id=" - + String.valueOf(event.getSubjectID()) + + event.getSubjectID() + ", perhaps it has been deleted."); } else { log.debug("consume() adding event to update queue: " + event.toString()); - objectsToUpdate.add((IndexableObject)subject); + objectsToUpdate.addAll(indexObjectServiceFactory.getIndexableObjects(ctx, subject)); } break; @@ -116,11 +119,11 @@ public class IndexEventConsumer implements Consumer { if (object == null) { log.warn(event.getEventTypeAsString() + " event, could not get object for " + event.getObjectTypeAsString() + " id=" - + String.valueOf(event.getObjectID()) + + event.getObjectID() + ", perhaps it has been deleted."); } else { log.debug("consume() adding event to update queue: " + event.toString()); - objectsToUpdate.add((IndexableObject)object); + objectsToUpdate.addAll(indexObjectServiceFactory.getIndexableObjects(ctx, subject)); } break; @@ -159,14 +162,14 @@ public class IndexEventConsumer implements Consumer { * allow the search indexer to make * decisions on indexing and/or removal */ - iu = ctx.reloadEntity(iu); + iu.setIndexedObject(ctx.reloadEntity(iu.getIndexedObject())); ; String uniqueIndexID = iu.getUniqueIndexID(); if (uniqueIndexID != null && !uniqueIdsToDelete.contains(uniqueIndexID)) { try { indexer.indexContent(ctx, iu, true, true); log.debug("Indexed " - + Constants.typeText[iu.getType()] - + ", id=" + String.valueOf(iu.getID()) + + iu.getTypeText() + + ", id=" + iu.getID() + ", unique_id=" + uniqueIndexID); } catch (Exception e) { log.error("Failed while indexing object: ", e); diff --git a/dspace-api/src/main/java/org/dspace/discovery/IndexableObject.java b/dspace-api/src/main/java/org/dspace/discovery/IndexableObject.java index fe67d9787b..6b5ab76faa 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/IndexableObject.java +++ b/dspace-api/src/main/java/org/dspace/discovery/IndexableObject.java @@ -8,6 +8,7 @@ package org.dspace.discovery; import java.io.Serializable; +import java.util.Date; import org.dspace.core.Constants; import org.dspace.core.ReloadableEntity; @@ -20,13 +21,27 @@ import org.dspace.core.ReloadableEntity; * @param * the Class of the primary key */ -public interface IndexableObject extends ReloadableEntity { +public interface IndexableObject { /** * - * @return the integer constant representing the Entity Type, @see {@link Constants} + * @return the string constant representing the Entity Type, @see {@link Constants} */ - public int getType(); + String getType(); + + PK getID(); + + /** + * Get the entity that is linked to this indexable object + * @return a database entity + */ + T getIndexedObject(); + + /** + * Set the entity that is linked to this indexable object + * @param object the database entity + */ + void setIndexedObject(T object); /** * @@ -37,11 +52,16 @@ public interface IndexableObject extends ReloadableEnti } /** - * + * * @return a textual alias of the Entity Type @see {@link #getType()} */ - default public String getTypeText() { - return Constants.typeText[getType()]; - }; + String getTypeText(); + /** + * Return the last modified date of an of an object, or if no modification dates are stored, return NUll + * @return the last modified date + */ + default Date getLastModified() { + return null; + } } diff --git a/dspace-api/src/main/java/org/dspace/discovery/IndexingService.java b/dspace-api/src/main/java/org/dspace/discovery/IndexingService.java index 253008105b..a7270be2a5 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/IndexingService.java +++ b/dspace-api/src/main/java/org/dspace/discovery/IndexingService.java @@ -51,14 +51,9 @@ public interface IndexingService { void updateIndex(Context context, boolean force); - void updateIndex(Context context, boolean force, int type); - void cleanIndex(boolean force) throws IOException, SQLException, SearchServiceException; - void cleanIndex(boolean force, int type) throws IOException, - SQLException, SearchServiceException; - void commit() throws SearchServiceException; void optimize() throws SearchServiceException; diff --git a/dspace-api/src/main/java/org/dspace/discovery/SearchUtils.java b/dspace-api/src/main/java/org/dspace/discovery/SearchUtils.java index ce3567e916..90afb09eca 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SearchUtils.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SearchUtils.java @@ -32,6 +32,15 @@ import org.dspace.workflow.WorkflowItem; * @author Ben Bosman (ben at atmire dot com) */ public class SearchUtils { + + public static final String AUTHORITY_SEPARATOR = "###"; + public static final String LAST_INDEXED_FIELD = "SolrIndexer.lastIndexed"; + public static final String RESOURCE_UNIQUE_ID = "search.uniqueid"; + public static final String RESOURCE_TYPE_FIELD = "search.resourcetype"; + public static final String RESOURCE_ID_FIELD = "search.resourceid"; + public static final String NAMED_RESOURCE_TYPE = "namedresourcetype"; + public static final String FILTER_SEPARATOR = "\n|||\n"; + /** * Cached search service **/ @@ -161,5 +170,4 @@ public class SearchUtils { DiscoveryConfiguration configurationExtra = getDiscoveryConfigurationByName(confName); result.add(configurationExtra); } - } diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrSearchCore.java b/dspace-api/src/main/java/org/dspace/discovery/SolrSearchCore.java new file mode 100644 index 0000000000..f61287ac87 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrSearchCore.java @@ -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.discovery; + +import java.io.IOException; + +import org.apache.commons.validator.routines.UrlValidator; +import org.apache.log4j.Logger; +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.SolrRequest; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.impl.HttpSolrClient; +import org.dspace.discovery.indexobject.IndexableItem; +import org.dspace.services.ConfigurationService; +import org.dspace.services.factory.DSpaceServicesFactory; +import org.dspace.storage.rdbms.DatabaseUtils; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Bean containing the SolrClient for the search core + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class SolrSearchCore { + + private final Logger log = Logger.getLogger(SolrSearchCore.class); + @Autowired + protected IndexingService indexingService; + @Autowired + protected ConfigurationService configurationService; + + /** + * SolrServer for processing indexing events. + */ + protected SolrClient solr = null; + + public SolrClient getSolr() { + if (solr == null) { + initSolr(); + } + return solr; + } + + /** + * Initialize the solr search core + */ + protected void initSolr() { + if (solr == null) { + String solrService = DSpaceServicesFactory.getInstance().getConfigurationService() + .getProperty("discovery.search.server"); + + UrlValidator urlValidator = new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS); + if (urlValidator.isValid(solrService) || configurationService + .getBooleanProperty("discovery.solr.url.validation.enabled", true)) { + try { + log.debug("Solr URL: " + solrService); + HttpSolrClient solrServer = new HttpSolrClient.Builder(solrService).build(); + + solrServer.setBaseURL(solrService); + solrServer.setUseMultiPartPost(true); + // Dummy/test query to search for Item (type=2) of ID=1 + SolrQuery solrQuery = new SolrQuery() + .setQuery(SearchUtils.RESOURCE_TYPE_FIELD + ":" + IndexableItem.TYPE + + " AND " + SearchUtils.RESOURCE_ID_FIELD + ":1"); + // Only return obj identifier fields in result doc + solrQuery.setFields(SearchUtils.RESOURCE_TYPE_FIELD, SearchUtils.RESOURCE_ID_FIELD); + solrServer.query(solrQuery, SolrRequest.METHOD.POST); + + // As long as Solr initialized, check with DatabaseUtils to see + // if a reindex is in order. If so, reindex everything + DatabaseUtils.checkReindexDiscovery(indexingService); + + solr = solrServer; + } catch (SolrServerException | IOException e) { + log.error("Error while initializing solr server", e); + } + } else { + log.error("Error while initializing solr, invalid url: " + solrService); + } + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceContentInOriginalBundleFilterPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceContentInOriginalBundleFilterPlugin.java index d389b53538..3d94350f1c 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceContentInOriginalBundleFilterPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceContentInOriginalBundleFilterPlugin.java @@ -14,6 +14,7 @@ import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.Item; import org.dspace.core.Context; +import org.dspace.discovery.indexobject.IndexableItem; /** * This plugin adds three fields to the solr index to make a facet with/without @@ -29,9 +30,9 @@ import org.dspace.core.Context; public class SolrServiceContentInOriginalBundleFilterPlugin implements SolrServiceIndexPlugin { @Override - public void additionalIndex(Context context, IndexableObject dso, SolrInputDocument document) { - if (dso instanceof Item) { - Item item = (Item) dso; + public void additionalIndex(Context context, IndexableObject indexableObject, SolrInputDocument document) { + if (indexableObject instanceof IndexableItem) { + Item item = ((IndexableItem) indexableObject).getIndexedObject(); boolean hasOriginalBundleWithContent = hasOriginalBundleWithContent(item); // _keyword and _filter because diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceFileInfoPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceFileInfoPlugin.java index e14aa1dbc3..3f5e765b0e 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceFileInfoPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceFileInfoPlugin.java @@ -14,6 +14,7 @@ import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.Item; import org.dspace.core.Context; +import org.dspace.discovery.indexobject.IndexableItem; /** *

@@ -40,9 +41,9 @@ public class SolrServiceFileInfoPlugin implements SolrServiceIndexPlugin { private static final String SOLR_FIELD_NAME_FOR_DESCRIPTIONS = "original_bundle_descriptions"; @Override - public void additionalIndex(Context context, IndexableObject dso, SolrInputDocument document) { - if (dso instanceof Item) { - Item item = (Item) dso; + public void additionalIndex(Context context, IndexableObject indexableObject, SolrInputDocument document) { + if (indexableObject instanceof IndexableItem) { + Item item = ((IndexableItem) indexableObject).getIndexedObject(); List bundles = item.getBundles(); if (bundles != null) { for (Bundle bundle : bundles) { diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java index 00865f919c..b75d1c131a 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java @@ -7,11 +7,8 @@ */ package org.dspace.discovery; -import static org.dspace.discovery.configuration.DiscoverySortConfiguration.SCORE; - import java.io.IOException; import java.io.PrintWriter; -import java.io.Serializable; import java.io.StringWriter; import java.sql.SQLException; import java.text.ParseException; @@ -19,36 +16,26 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; -import java.util.Comparator; import java.util.Date; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.TimeZone; import java.util.UUID; -import java.util.Vector; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.collections4.Transformer; -import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.time.DateFormatUtils; -import org.apache.commons.validator.routines.UrlValidator; import org.apache.logging.log4j.Logger; -import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.impl.HttpSolrClient; -import org.apache.solr.client.solrj.request.AbstractUpdateRequest; -import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest; import org.apache.solr.client.solrj.response.FacetField; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.client.solrj.util.ClientUtils; @@ -57,64 +44,36 @@ import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.params.FacetParams; import org.apache.solr.common.params.HighlightParams; -import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.MoreLikeThisParams; import org.apache.solr.common.params.SpellingParams; import org.apache.solr.common.util.NamedList; -import org.apache.solr.handler.extraction.ExtractingParams; import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.factory.AuthorizeServiceFactory; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; -import org.dspace.content.MetadataField; -import org.dspace.content.MetadataSchema; -import org.dspace.content.MetadataValue; -import org.dspace.content.WorkspaceItem; -import org.dspace.content.authority.Choices; -import org.dspace.content.authority.service.ChoiceAuthorityService; -import org.dspace.content.authority.service.MetadataAuthorityService; import org.dspace.content.factory.ContentServiceFactory; -import org.dspace.content.service.CollectionService; -import org.dspace.content.service.CommunityService; -import org.dspace.content.service.ItemService; -import org.dspace.content.service.WorkspaceItemService; import org.dspace.core.ConfigurationManager; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.Email; import org.dspace.core.I18nUtil; import org.dspace.core.LogManager; -import org.dspace.discovery.configuration.DiscoveryConfiguration; import org.dspace.discovery.configuration.DiscoveryConfigurationParameters; -import org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration; -import org.dspace.discovery.configuration.DiscoveryHitHighlightingConfiguration; import org.dspace.discovery.configuration.DiscoveryMoreLikeThisConfiguration; -import org.dspace.discovery.configuration.DiscoveryRecentSubmissionsConfiguration; -import org.dspace.discovery.configuration.DiscoverySearchFilter; import org.dspace.discovery.configuration.DiscoverySearchFilterFacet; import org.dspace.discovery.configuration.DiscoverySortConfiguration; -import org.dspace.discovery.configuration.DiscoverySortFieldConfiguration; -import org.dspace.discovery.configuration.HierarchicalSidebarFacetConfiguration; +import org.dspace.discovery.indexobject.IndexableCollection; +import org.dspace.discovery.indexobject.IndexableCommunity; +import org.dspace.discovery.indexobject.IndexableItem; +import org.dspace.discovery.indexobject.factory.IndexFactory; +import org.dspace.discovery.indexobject.factory.IndexObjectFactoryFactory; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; import org.dspace.eperson.factory.EPersonServiceFactory; import org.dspace.eperson.service.GroupService; -import org.dspace.handle.service.HandleService; import org.dspace.services.factory.DSpaceServicesFactory; -import org.dspace.storage.rdbms.DatabaseUtils; -import org.dspace.util.MultiFormatDateParser; -import org.dspace.util.SolrUtils; -import org.dspace.workflow.WorkflowItem; -import org.dspace.xmlworkflow.WorkflowConfigurationException; -import org.dspace.xmlworkflow.factory.XmlWorkflowFactory; -import org.dspace.xmlworkflow.storedcomponents.ClaimedTask; -import org.dspace.xmlworkflow.storedcomponents.PoolTask; -import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; -import org.dspace.xmlworkflow.storedcomponents.service.ClaimedTaskService; -import org.dspace.xmlworkflow.storedcomponents.service.PoolTaskService; -import org.dspace.xmlworkflow.storedcomponents.service.XmlWorkflowItemService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -153,94 +112,20 @@ public class SolrServiceImpl implements SearchService, IndexingService { private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(SolrServiceImpl.class); - protected static final String LAST_INDEXED_FIELD = "SolrIndexer.lastIndexed"; - protected static final String HANDLE_FIELD = "handle"; - protected static final String RESOURCE_UNIQUE_ID = "search.uniqueid"; - protected static final String RESOURCE_TYPE_FIELD = "search.resourcetype"; - protected static final String RESOURCE_ID_FIELD = "search.resourceid"; - protected static final String NAMED_RESOURCE_TYPE = "namedresourcetype"; - - public static final String FILTER_SEPARATOR = "\n|||\n"; - - public static final String AUTHORITY_SEPARATOR = "###"; - - public static final String STORE_SEPARATOR = "\n|||\n"; - - public static final String VARIANTS_STORE_SEPARATOR = "###"; - - @Autowired(required = true) + @Autowired protected ContentServiceFactory contentServiceFactory; - @Autowired(required = true) - protected ChoiceAuthorityService choiceAuthorityService; - @Autowired(required = true) - protected CommunityService communityService; - @Autowired(required = true) - protected CollectionService collectionService; - @Autowired(required = true) - protected ItemService itemService; - @Autowired(required = true) - protected HandleService handleService; - @Autowired(required = true) - protected MetadataAuthorityService metadataAuthorityService; - @Autowired(required = true) - protected WorkspaceItemService workspaceItemService; - @Autowired(required = true) - protected XmlWorkflowItemService workflowItemService; - @Autowired(required = true) - protected ClaimedTaskService claimedTaskService; - @Autowired(required = true) - protected PoolTaskService poolTaskService; - @Autowired(required = true) - protected XmlWorkflowFactory workflowFactory; - @Autowired(required = true) + @Autowired protected GroupService groupService; - - /** - * Non-Static SolrServer for processing indexing events. - */ - protected SolrClient solr = null; - + @Autowired + protected IndexObjectFactoryFactory indexObjectServiceFactory; + @Autowired + protected SolrSearchCore solrSearchCore; protected SolrServiceImpl() { } - protected SolrClient getSolr() { - if (solr == null) { - String solrService = DSpaceServicesFactory.getInstance().getConfigurationService() - .getProperty("discovery.search.server"); - UrlValidator urlValidator = new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS); - if (urlValidator.isValid(solrService) || ConfigurationManager - .getBooleanProperty("discovery", "solr.url.validation.enabled", true)) { - try { - log.debug("Solr URL: " + solrService); - HttpSolrClient solrServer = new HttpSolrClient.Builder(solrService).build(); - - solrServer.setBaseURL(solrService); - solrServer.setUseMultiPartPost(true); - // Dummy/test query to search for Item (type=2) of ID=1 - SolrQuery solrQuery = new SolrQuery() - .setQuery(RESOURCE_TYPE_FIELD + ":2 AND " + RESOURCE_ID_FIELD + ":1"); - // Only return obj identifier fields in result doc - solrQuery.setFields(RESOURCE_TYPE_FIELD, RESOURCE_ID_FIELD); - solrServer.query(solrQuery, SolrRequest.METHOD.POST); - - // As long as Solr initialized, check with DatabaseUtils to see - // if a reindex is in order. If so, reindex everything - DatabaseUtils.checkReindexDiscovery(this); - - solr = solrServer; - } catch (SolrServerException | IOException e) { - log.error("Error while initializing solr server", e); - } - } else { - log.error("Error while initializing solr, invalid url: " + solrService); - } - } - - return solr; - } /** * If the handle for the "dso" already exists in the index, and the "dso" @@ -263,62 +148,32 @@ public class SolrServiceImpl implements SearchService, IndexingService { * then it is updated, otherwise a new document is added. * * @param context Users Context - * @param dso DSpace Object (Item, Collection or Community + * @param indexableObject The object we want to index * @param force Force update even if not stale. * @throws SQLException if error */ @Override - public void indexContent(Context context, IndexableObject dso, - boolean force) throws SQLException { + public void indexContent(Context context, IndexableObject indexableObject, + boolean force) { try { - String uuid = dso.getID().toString(); - switch (dso.getType()) { - case Constants.ITEM: - Item item = (Item) dso; - if (item.isArchived() || item.isWithdrawn()) { - /** - * If the item is in the repository now, add it to the index - */ - if (force || requiresIndexing(dso.getUniqueIndexID(), ((Item) dso).getLastModified())) { - unIndexContent(context, dso); - buildDocument(context, (Item) dso); - } - } else { - /** - * Make sure the item is not in the index if it is not in - * archive or withdrawn. - */ - unIndexContent(context, dso); - log.info("Removed Item: " + uuid + " from Index"); - - /** - * reindex any in progress submission tasks associated with the item - */ - indexInProgressSubmissionItem(context, (Item) dso); - } - break; - - case Constants.COLLECTION: - buildDocument(context, (Collection) dso); - log.info("Wrote Collection: " + uuid + " to Index"); - break; - - case Constants.COMMUNITY: - buildDocument(context, (Community) dso); - log.info("Wrote Community: " + uuid + " to Index"); - break; - - default: - log - .error("Only Items, Collections and Communities can be Indexed"); + final IndexFactory indexableObjectFactory = indexObjectServiceFactory. + getIndexableObjectFactory(indexableObject); + if (force || requiresIndexing(indexableObject.getUniqueIndexID(), indexableObject.getLastModified())) { + update(context, indexableObjectFactory, indexableObject); + log.info(LogManager.getHeader(context, "indexed_object", indexableObject.getUniqueIndexID())); } - } catch (Exception e) { log.error(e.getMessage(), e); } } + protected void update(Context context, IndexFactory indexableObjectService, + IndexableObject indexableObject) throws IOException, SQLException, SolrServerException { + final SolrInputDocument solrInputDocument = indexableObjectService.buildDocument(context, indexableObject); + indexableObjectService.writeDocument(context, indexableObject, solrInputDocument); + } + /** * unIndex removes an Item, Collection, or Community * @@ -337,26 +192,23 @@ public class SolrServiceImpl implements SearchService, IndexingService { * unIndex removes an Item, Collection, or Community * * @param context The relevant DSpace Context. - * @param dso extension of DSpace Object, can be Community, Item, Collection or InProgressSubmission + * @param indexableObject The object to be indexed * @param commit if true force an immediate commit on SOLR * @throws SQLException if database error * @throws IOException if IO error */ @Override - public void unIndexContent(Context context, IndexableObject dso, boolean commit) + public void unIndexContent(Context context, IndexableObject indexableObject, boolean commit) throws SQLException, IOException { try { - if (dso == null) { + if (indexableObject == null) { return; } - String uniqueID = dso.getUniqueIndexID(); - log.debug("Try to delete uniqueID:" + uniqueID); - getSolr().deleteById(uniqueID); - if (Constants.ITEM == dso.getType()) { - deleteInProgressSubmissionByItemID(uniqueID); - } + String uniqueID = indexableObject.getUniqueIndexID(); + log.info("Try to delete uniqueID:" + uniqueID); + indexObjectServiceFactory.getIndexableObjectFactory(indexableObject).delete(indexableObject); if (commit) { - getSolr().commit(); + solrSearchCore.getSolr().commit(); } } catch (Exception exception) { log.error(exception.getMessage(), exception); @@ -388,13 +240,10 @@ public class SolrServiceImpl implements SearchService, IndexingService { throws IOException { try { - if (getSolr() != null) { - getSolr().deleteById(searchUniqueID); - if (searchUniqueID.startsWith(Constants.ITEM + "-")) { - deleteInProgressSubmissionByItemID(searchUniqueID); - } + if (solrSearchCore.getSolr() != null) { + indexObjectServiceFactory.getIndexableObjectFactory(searchUniqueID).delete(searchUniqueID); if (commit) { - getSolr().commit(); + solrSearchCore.getSolr().commit(); } } } catch (SolrServerException e) { @@ -460,53 +309,19 @@ public class SolrServiceImpl implements SearchService, IndexingService { */ @Override public void updateIndex(Context context, boolean force) { - updateIndex(context, force, Constants.ITEM); - updateIndex(context, force, Constants.COLLECTION); - updateIndex(context, force, Constants.COMMUNITY); - } - - - @Override - public void updateIndex(Context context, boolean force, int type) { try { - switch (type) { - case Constants.ITEM: - Iterator items = itemService.findAllUnfiltered(context); - while (items.hasNext()) { - Item item = items.next(); - indexContent(context, item, force); - //To prevent memory issues, discard an object from the cache after processing - context.uncacheEntity(item); - } - for (WorkspaceItem wsi : workspaceItemService.findAll(context)) { - indexContent(context, wsi.getItem(), force); - //To prevent memory issues, discard an object from the cache after processing - context.uncacheEntity(wsi); - } - for (WorkflowItem wfi : workflowItemService.findAll(context)) { - indexContent(context, wfi.getItem(), force); - //To prevent memory issues, discard an object from the cache after processing - context.uncacheEntity(wfi); - } - break; - case Constants.COLLECTION: - List collections = collectionService.findAll(context); - for (Collection collection : collections) { - indexContent(context, collection, force); - } - break; - case Constants.COMMUNITY: - List communities = communityService.findAll(context); - for (Community community : communities) { - indexContent(context, community, force); - } - break; - default: - throw new IllegalArgumentException("No type known: " + type); + final List indexableObjectServices = indexObjectServiceFactory. + getIndexFactories(); + for (IndexFactory indexableObjectService : indexableObjectServices) { + final Iterator indexableObjects = indexableObjectService.findAll(context); + while (indexableObjects.hasNext()) { + final IndexableObject indexableObject = indexableObjects.next(); + indexContent(context, indexableObject, force); + context.uncacheEntity(indexableObject.getIndexedObject()); + } } - - if (getSolr() != null) { - getSolr().commit(); + if (solrSearchCore.getSolr() != null) { + solrSearchCore.getSolr().commit(); } } catch (Exception e) { @@ -525,52 +340,31 @@ public class SolrServiceImpl implements SearchService, IndexingService { */ @Override public void cleanIndex(boolean force) throws IOException, SQLException, SearchServiceException { - if (force) { - try { - getSolr().deleteByQuery( - "search.resourcetype:[" + Constants.ITEM + " TO " + Constants.COMMUNITY + "]" + - " OR " + - "search.resourcetype:[" + Constants.WORKSPACEITEM + " TO " + Constants.CLAIMEDTASK + "]"); - } catch (Exception e) { - throw new SearchServiceException(e.getMessage(), e); - } - } else { - cleanIndex(false, Constants.ITEM); - cleanIndex(false, Constants.COLLECTION); - cleanIndex(false, Constants.COMMUNITY); - cleanIndex(false, Constants.WORKSPACEITEM); - cleanIndex(false, Constants.POOLTASK); - cleanIndex(false, Constants.CLAIMEDTASK); - cleanIndex(false, Constants.WORKFLOWITEM); - } - } - - @Override - public void cleanIndex(boolean force, int type) throws IOException, SQLException, SearchServiceException { Context context = new Context(); context.turnOffAuthorisationSystem(); try { - if (getSolr() == null) { + if (solrSearchCore.getSolr() == null) { return; } if (force) { - getSolr().deleteByQuery(RESOURCE_TYPE_FIELD + ":" + type); + final List indexableObjectServices = indexObjectServiceFactory. + getIndexFactories(); + for (IndexFactory indexableObjectService : indexableObjectServices) { + indexableObjectService.deleteAll(); + } } else { SolrQuery query = new SolrQuery(); // Query for all indexed Items, Collections and Communities, - // returning just their handle - query.setFields(HANDLE_FIELD, RESOURCE_UNIQUE_ID, RESOURCE_ID_FIELD, RESOURCE_TYPE_FIELD); - query.setQuery(RESOURCE_TYPE_FIELD + ":" + type); - QueryResponse rsp = getSolr().query(query, SolrRequest.METHOD.POST); + // returning just their unique identifier + query.setFields(SearchUtils.RESOURCE_UNIQUE_ID); + query.setQuery("*:*"); + QueryResponse rsp = solrSearchCore.getSolr().query(query, SolrRequest.METHOD.POST); SolrDocumentList docs = rsp.getResults(); - Iterator iter = docs.iterator(); - while (iter.hasNext()) { + for (SolrDocument doc : docs) { - SolrDocument doc = (SolrDocument) iter.next(); - - String uniqueID = (String) doc.getFieldValue(RESOURCE_UNIQUE_ID); + String uniqueID = (String) doc.getFieldValue(SearchUtils.RESOURCE_UNIQUE_ID); IndexableObject o = findIndexableObject(context, doc); @@ -600,12 +394,12 @@ public class SolrServiceImpl implements SearchService, IndexingService { @Override public void optimize() { try { - if (getSolr() == null) { + if (solrSearchCore.getSolr() == null) { return; } long start = System.currentTimeMillis(); System.out.println("SOLR Search Optimize -- Process Started:" + start); - getSolr().optimize(); + solrSearchCore.getSolr().optimize(); long finish = System.currentTimeMillis(); System.out.println("SOLR Search Optimize -- Process Finished:" + finish); System.out.println("SOLR Search Optimize -- Total time taken:" + (finish - start) + " (ms)."); @@ -620,13 +414,13 @@ public class SolrServiceImpl implements SearchService, IndexingService { public void buildSpellCheck() throws SearchServiceException, IOException { try { - if (getSolr() == null) { + if (solrSearchCore.getSolr() == null) { return; } SolrQuery solrQuery = new SolrQuery(); solrQuery.set("spellcheck", true); solrQuery.set(SpellingParams.SPELLCHECK_BUILD, true); - getSolr().query(solrQuery, SolrRequest.METHOD.POST); + solrSearchCore.getSolr().query(solrQuery, SolrRequest.METHOD.POST); } catch (SolrServerException e) { //Make sure to also log the exception since this command is usually run from a crontab. log.error(e, e); @@ -680,30 +474,35 @@ public class SolrServiceImpl implements SearchService, IndexingService { * Is stale checks the lastModified time stamp in the database and the index * to determine if the index is stale. * - * @param handle the handle of the dso + * @param uniqueId the unique identifier of the object that we want to index * @param lastModified the last modified date of the DSpace object * @return a boolean indicating if the dso should be re indexed again * @throws SQLException sql exception * @throws IOException io exception * @throws SearchServiceException if something went wrong with querying the solr server */ - protected boolean requiresIndexing(String handle, Date lastModified) + protected boolean requiresIndexing(String uniqueId, Date lastModified) throws SQLException, IOException, SearchServiceException { + // Check if we even have a last modified date + if (lastModified == null) { + return true; + } + boolean reindexItem = false; boolean inIndex = false; SolrQuery query = new SolrQuery(); - query.setQuery(RESOURCE_UNIQUE_ID + ":" + handle); + query.setQuery(SearchUtils.RESOURCE_UNIQUE_ID + ":" + uniqueId); // Specify that we ONLY want the LAST_INDEXED_FIELD returned in the field list (fl) - query.setFields(LAST_INDEXED_FIELD); + query.setFields(SearchUtils.LAST_INDEXED_FIELD); QueryResponse rsp; try { - if (getSolr() == null) { + if (solrSearchCore.getSolr() == null) { return false; } - rsp = getSolr().query(query, SolrRequest.METHOD.POST); + rsp = solrSearchCore.getSolr().query(query, SolrRequest.METHOD.POST); } catch (SolrServerException e) { throw new SearchServiceException(e.getMessage(), e); } @@ -712,7 +511,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { inIndex = true; - Object value = doc.getFieldValue(LAST_INDEXED_FIELD); + Object value = doc.getFieldValue(SearchUtils.LAST_INDEXED_FIELD); if (value instanceof Date) { Date lastIndexed = (Date) value; @@ -727,63 +526,6 @@ public class SolrServiceImpl implements SearchService, IndexingService { return reindexItem || !inIndex; } - - /** - * @param context DSpace context - * @param myitem the item for which our locations are to be retrieved - * @return a list containing the identifiers of the communities and collections - * @throws SQLException sql exception - */ - protected List getItemLocations(Context context, Item myitem) - throws SQLException { - List locations = new Vector(); - - // build list of community ids - List communities = itemService.getCommunities(context, myitem); - - // build list of collection ids - List collections = myitem.getCollections(); - - // now put those into strings - int i = 0; - - for (i = 0; i < communities.size(); i++) { - locations.add("m" + communities.get(i).getID()); - } - - for (i = 0; i < collections.size(); i++) { - locations.add("l" + collections.get(i).getID()); - } - - return locations; - } - - protected List getCollectionLocations(Context context, Collection target) throws SQLException { - List locations = new Vector(); - // build list of community ids - List communities = communityService.getAllParents(context, target); - - // now put those into strings - for (Community community : communities) { - locations.add("m" + community.getID()); - } - - return locations; - } - - protected List getCommunityLocations(Community target) throws SQLException { - List locations = new Vector(); - // build list of community ids - List communities = target.getParentCommunities(); - - // now put those into strings - for (Community community : communities) { - locations.add("m" + community.getID()); - } - - return locations; - } - @Override public String createLocationQueryForAdministrableItems(Context context) throws SQLException { @@ -850,928 +592,6 @@ public class SolrServiceImpl implements SearchService, IndexingService { return locationQuery.toString(); } - /** - * Write the document to the index under the appropriate handle. - * - * @param doc the solr document to be written to the server - * @param streams list of bitstream content streams - * @throws IOException A general class of exceptions produced by failed or interrupted I/O operations. - */ - protected void writeDocument(SolrInputDocument doc, FullTextContentStreams streams) throws IOException { - - try { - if (getSolr() != null) { - if (streams != null && !streams.isEmpty()) { - ContentStreamUpdateRequest req = new ContentStreamUpdateRequest("/update/extract"); - req.addContentStream(streams); - - ModifiableSolrParams params = new ModifiableSolrParams(); - - //req.setParam(ExtractingParams.EXTRACT_ONLY, "true"); - for (String name : doc.getFieldNames()) { - for (Object val : doc.getFieldValues(name)) { - params.add(ExtractingParams.LITERALS_PREFIX + name, val.toString()); - } - } - - req.setParams(params); - req.setParam(ExtractingParams.UNKNOWN_FIELD_PREFIX, "attr_"); - req.setParam(ExtractingParams.MAP_PREFIX + "content", "fulltext"); - req.setParam(ExtractingParams.EXTRACT_FORMAT, "text"); - req.setAction(AbstractUpdateRequest.ACTION.COMMIT, true, true); - req.process(getSolr()); - } else { - getSolr().add(doc); - } - } - } catch (SolrServerException e) { - log.error(e.getMessage(), e); - } - } - - /** - * Build a solr document for a DSpace Community. - * - * @param context The relevant DSpace Context. - * @param community Community to be indexed - * @throws SQLException if database error - * @throws IOException if IO error - */ - protected void buildDocument(Context context, Community community) - throws SQLException, IOException { - - List locations = getCommunityLocations(community); - - // Create Document - SolrInputDocument doc = buildDocument(Constants.COMMUNITY, community.getID(), - community.getHandle(), locations); - - DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration(community); - DiscoveryHitHighlightingConfiguration highlightingConfiguration = discoveryConfiguration - .getHitHighlightingConfiguration(); - List highlightedMetadataFields = new ArrayList(); - if (highlightingConfiguration != null) { - for (DiscoveryHitHighlightFieldConfiguration configuration : highlightingConfiguration - .getMetadataFields()) { - highlightedMetadataFields.add(configuration.getField()); - } - } - - // and populate it - String description = communityService.getMetadata(community, "introductory_text"); - String description_abstract = communityService.getMetadata(community, "short_description"); - String description_table = communityService.getMetadata(community, "side_bar_text"); - String rights = communityService.getMetadata(community, "copyright_text"); - String title = communityService.getMetadata(community, "name"); - - List toIgnoreMetadataFields = SearchUtils.getIgnoredMetadataFields(community.getType()); - addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.description", - description); - addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.description.abstract", - description_abstract); - addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, - "dc.description.tableofcontents", description_table); - addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.rights", rights); - addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.title", title); - - //Do any additional indexing, depends on the plugins - List solrServiceIndexPlugins = DSpaceServicesFactory.getInstance().getServiceManager() - .getServicesByType( - SolrServiceIndexPlugin.class); - for (SolrServiceIndexPlugin solrServiceIndexPlugin : solrServiceIndexPlugins) { - solrServiceIndexPlugin.additionalIndex(context, community, doc); - } - - writeDocument(doc, null); - } - - /** - * Build a solr document for a DSpace Collection. - * - * @param context The relevant DSpace Context. - * @param collection Collection to be indexed - * @throws SQLException sql exception - * @throws IOException IO exception - */ - protected void buildDocument(Context context, Collection collection) - throws SQLException, IOException { - List locations = getCollectionLocations(context, collection); - - // Create Lucene Document - SolrInputDocument doc = buildDocument(Constants.COLLECTION, collection.getID(), - collection.getHandle(), locations); - - DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration(collection); - DiscoveryHitHighlightingConfiguration highlightingConfiguration = discoveryConfiguration - .getHitHighlightingConfiguration(); - List highlightedMetadataFields = new ArrayList(); - if (highlightingConfiguration != null) { - for (DiscoveryHitHighlightFieldConfiguration configuration : highlightingConfiguration - .getMetadataFields()) { - highlightedMetadataFields.add(configuration.getField()); - } - } - - - // and populate it - String description = collectionService.getMetadata(collection, "introductory_text"); - String description_abstract = collectionService.getMetadata(collection, "short_description"); - String description_table = collectionService.getMetadata(collection, "side_bar_text"); - String provenance = collectionService.getMetadata(collection, "provenance_description"); - String rights = collectionService.getMetadata(collection, "copyright_text"); - String rights_license = collectionService.getMetadata(collection, "license"); - String title = collectionService.getMetadata(collection, "name"); - - List toIgnoreMetadataFields = SearchUtils.getIgnoredMetadataFields(collection.getType()); - addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.description", - description); - addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.description.abstract", - description_abstract); - addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, - "dc.description.tableofcontents", description_table); - addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.provenance", provenance); - addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.rights", rights); - addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.rights.license", - rights_license); - addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.title", title); - - - //Do any additional indexing, depends on the plugins - List solrServiceIndexPlugins = DSpaceServicesFactory.getInstance().getServiceManager() - .getServicesByType( - SolrServiceIndexPlugin.class); - for (SolrServiceIndexPlugin solrServiceIndexPlugin : solrServiceIndexPlugins) { - solrServiceIndexPlugin.additionalIndex(context, collection, doc); - } - - writeDocument(doc, null); - } - - /** - * Add the metadata value of the community/collection to the solr document - * IF needed highlighting is added ! - * - * @param doc the solr document - * @param highlightedMetadataFields the list of metadata fields that CAN be highlighted - * @param toIgnoreMetadataFields the list of metadata fields to skip adding to Solr - * @param metadataField the metadata field added - * @param value the value (can be NULL !) - */ - protected void addContainerMetadataField(SolrInputDocument doc, List highlightedMetadataFields, - List toIgnoreMetadataFields, String metadataField, String value) { - if (toIgnoreMetadataFields == null || !toIgnoreMetadataFields.contains(metadataField)) { - if (StringUtils.isNotBlank(value)) { - doc.addField(metadataField, value); - if (highlightedMetadataFields.contains(metadataField)) { - doc.addField(metadataField + "_hl", value); - } - } - } - } - - /** - * Build a Lucene document for a DSpace Item and write the index - * - * @param context Users Context - * @param item The DSpace Item to be indexed - * @throws SQLException if database error - * @throws IOException if IO error - */ - protected void buildDocument(Context context, Item item) - throws SQLException, IOException { - String handle = item.getHandle(); - - if (handle == null) { - handle = handleService.findHandle(context, item); - } - - // get the location string (for searching by collection & community) - List locations = getItemLocations(context, item); - - SolrInputDocument doc = buildDocument(Constants.ITEM, item.getID(), handle, - locations); - - log.debug("Building Item: " + handle); - - doc.addField("archived", item.isArchived()); - doc.addField("withdrawn", item.isWithdrawn()); - doc.addField("discoverable", item.isDiscoverable()); - doc.addField("lastModified", SolrUtils.getDateFormatter().format(item.getLastModified())); - - EPerson submitter = item.getSubmitter(); - if (submitter != null) { - addFacetIndex(doc, "submitter", submitter.getID().toString(), - submitter.getFullName()); - } - - List discoveryConfigurations = SearchUtils.getAllDiscoveryConfigurations(item); - addDiscoveryFields(doc, context, item, discoveryConfigurations); - - //mandatory facet to show status on mydspace - final String typeText = StringUtils.deleteWhitespace(item.getTypeText().toLowerCase()); - String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService().getProperty( - "discovery.facet.namedtype." + typeText, - typeText + SolrServiceImpl.AUTHORITY_SEPARATOR + typeText); - if (StringUtils.isNotBlank(acvalue)) { - addNamedResourceTypeIndex(doc, acvalue); - } - - // write the index and close the inputstreamreaders - try { - writeDocument(doc, new FullTextContentStreams(context, item)); - log.info("Wrote Item: " + item.getUniqueIndexID() + " to Index"); - } catch (RuntimeException e) { - log.error("Error while writing item to discovery index: " + item.getUniqueIndexID() + " message:" - + e.getMessage(), e); - } - } - - protected void addDiscoveryFields(SolrInputDocument doc, Context context, Item item, - List discoveryConfigurations) - throws SQLException, IOException { - //Keep a list of our sort values which we added, sort values can only be added once - List sortFieldsAdded = new ArrayList(); - Map> searchFilters = null; - Set hitHighlightingFields = new HashSet(); - try { - //A map used to save each sidebarFacet config by the metadata fields - searchFilters = new HashMap>(); - Map sortFields = new HashMap(); - Map recentSubmissionsConfigurationMap = new - HashMap(); - Set moreLikeThisFields = new HashSet(); - // some configuration are returned multiple times, skip them to save CPU cycles - Set appliedConf = new HashSet(); - // it is common to have search filter shared between multiple configurations - Set appliedDiscoverySearchFilter = new HashSet(); - - for (DiscoveryConfiguration discoveryConfiguration : discoveryConfigurations) { - if (appliedConf.contains(discoveryConfiguration.getId())) { - continue; - } else { - appliedConf.add(discoveryConfiguration.getId()); - } - for (int i = 0; i < discoveryConfiguration.getSearchFilters().size(); i++) { - if (appliedDiscoverySearchFilter - .contains(discoveryConfiguration.getSearchFilters().get(i).getIndexFieldName())) { - continue; - } else { - appliedDiscoverySearchFilter - .add(discoveryConfiguration.getSearchFilters().get(i).getIndexFieldName()); - } - List metadataValueList = new LinkedList<>(); - boolean shouldExposeMinMax = false; - DiscoverySearchFilter discoverySearchFilter = discoveryConfiguration.getSearchFilters().get(i); - if (StringUtils.equalsIgnoreCase(discoverySearchFilter.getFilterType(), "facet")) { - if (((DiscoverySearchFilterFacet) discoverySearchFilter).exposeMinAndMaxValue()) { - shouldExposeMinMax = true; - } - } - for (int j = 0; j < discoverySearchFilter.getMetadataFields().size(); j++) { - String metadataField = discoverySearchFilter.getMetadataFields().get(j); - List resultingList; - if (searchFilters.get(metadataField) != null) { - resultingList = searchFilters.get(metadataField); - } else { - //New metadata field, create a new list for it - resultingList = new ArrayList(); - } - - - if (shouldExposeMinMax) { - String[] splittedMetadataField = metadataField.split("\\."); - String schema = splittedMetadataField[0]; - String element = splittedMetadataField.length > 1 ? splittedMetadataField[1] : null; - String qualifier = splittedMetadataField.length > 2 ? splittedMetadataField[2] : null; - - metadataValueList.addAll(itemService.getMetadata(item, schema, - element, qualifier, Item.ANY)); - - } - - resultingList.add(discoverySearchFilter); - - searchFilters.put(metadataField, resultingList); - } - - if (!metadataValueList.isEmpty() && shouldExposeMinMax) { - metadataValueList.sort(new Comparator() { - public int compare(MetadataValue mdv1,MetadataValue mdv2) { - return mdv1.getValue().compareTo(mdv2.getValue()) ; - } - }); - MetadataValue firstMetadataValue = metadataValueList.get(0); - MetadataValue lastMetadataValue = metadataValueList.get(metadataValueList.size() - 1); - - doc.addField(discoverySearchFilter.getIndexFieldName() + "_min", firstMetadataValue.getValue()); - doc.addField(discoverySearchFilter.getIndexFieldName() - + "_min_sort", firstMetadataValue.getValue()); - doc.addField(discoverySearchFilter.getIndexFieldName() + "_max", lastMetadataValue.getValue()); - doc.addField(discoverySearchFilter.getIndexFieldName() - + "_max_sort", lastMetadataValue.getValue()); - - } - } - - DiscoverySortConfiguration sortConfiguration = discoveryConfiguration.getSearchSortConfiguration(); - if (sortConfiguration != null) { - for (DiscoverySortFieldConfiguration discoverySortConfiguration : sortConfiguration - .getSortFields()) { - sortFields.put(discoverySortConfiguration.getMetadataField(), discoverySortConfiguration); - } - } - - DiscoveryRecentSubmissionsConfiguration recentSubmissionConfiguration = discoveryConfiguration - .getRecentSubmissionConfiguration(); - if (recentSubmissionConfiguration != null) { - recentSubmissionsConfigurationMap - .put(recentSubmissionConfiguration.getMetadataSortField(), recentSubmissionConfiguration); - } - - DiscoveryHitHighlightingConfiguration hitHighlightingConfiguration = discoveryConfiguration - .getHitHighlightingConfiguration(); - if (hitHighlightingConfiguration != null) { - List fieldConfigurations = hitHighlightingConfiguration - .getMetadataFields(); - for (DiscoveryHitHighlightFieldConfiguration fieldConfiguration : fieldConfigurations) { - hitHighlightingFields.add(fieldConfiguration.getField()); - } - } - DiscoveryMoreLikeThisConfiguration moreLikeThisConfiguration = discoveryConfiguration - .getMoreLikeThisConfiguration(); - if (moreLikeThisConfiguration != null) { - for (String metadataField : moreLikeThisConfiguration.getSimilarityMetadataFields()) { - moreLikeThisFields.add(metadataField); - } - } - } - - - List toProjectionFields = new ArrayList(); - String[] projectionFields = DSpaceServicesFactory.getInstance().getConfigurationService() - .getArrayProperty("discovery.index.projection"); - if (projectionFields != null) { - for (String field : projectionFields) { - toProjectionFields.add(field.trim()); - } - } - - List toIgnoreMetadataFields = SearchUtils.getIgnoredMetadataFields(item.getType()); - List mydc = itemService.getMetadata(item, Item.ANY, Item.ANY, Item.ANY, Item.ANY); - for (MetadataValue meta : mydc) { - MetadataField metadataField = meta.getMetadataField(); - MetadataSchema metadataSchema = metadataField.getMetadataSchema(); - String field = metadataSchema.getName() + "." + metadataField.getElement(); - String unqualifiedField = field; - - String value = meta.getValue(); - - if (value == null) { - continue; - } - - if (metadataField.getQualifier() != null && !metadataField.getQualifier().trim().equals("")) { - field += "." + metadataField.getQualifier(); - } - - //We are not indexing provenance, this is useless - if (toIgnoreMetadataFields != null && (toIgnoreMetadataFields.contains(field) || toIgnoreMetadataFields - .contains(unqualifiedField + "." + Item.ANY))) { - continue; - } - - String authority = null; - String preferedLabel = null; - List variants = null; - boolean isAuthorityControlled = metadataAuthorityService - .isAuthorityControlled(metadataField); - - int minConfidence = isAuthorityControlled ? metadataAuthorityService - .getMinConfidence(metadataField) : Choices.CF_ACCEPTED; - - if (isAuthorityControlled && meta.getAuthority() != null - && meta.getConfidence() >= minConfidence) { - boolean ignoreAuthority = - DSpaceServicesFactory - .getInstance() - .getConfigurationService() - .getPropertyAsType("discovery.index.authority.ignore." + field, - DSpaceServicesFactory - .getInstance() - .getConfigurationService() - .getPropertyAsType("discovery.index.authority.ignore", - new Boolean(false)), - true); - if (!ignoreAuthority) { - authority = meta.getAuthority(); - - boolean ignorePrefered = - DSpaceServicesFactory - .getInstance() - .getConfigurationService() - .getPropertyAsType("discovery.index.authority.ignore-prefered." + field, - DSpaceServicesFactory - .getInstance() - .getConfigurationService() - .getPropertyAsType("discovery.index.authority.ignore-prefered", - new Boolean(false)), - true); - if (!ignorePrefered) { - - preferedLabel = choiceAuthorityService - .getLabel(meta, meta.getLanguage()); - } - - boolean ignoreVariants = - DSpaceServicesFactory - .getInstance() - .getConfigurationService() - .getPropertyAsType("discovery.index.authority.ignore-variants." + field, - DSpaceServicesFactory - .getInstance() - .getConfigurationService() - .getPropertyAsType("discovery.index.authority.ignore-variants", - new Boolean(false)), - true); - if (!ignoreVariants) { - variants = choiceAuthorityService - .getVariants(meta); - } - - } - } - - if ((searchFilters.get(field) != null || searchFilters - .get(unqualifiedField + "." + Item.ANY) != null)) { - List searchFilterConfigs = searchFilters.get(field); - if (searchFilterConfigs == null) { - searchFilterConfigs = searchFilters.get(unqualifiedField + "." + Item.ANY); - } - - for (DiscoverySearchFilter searchFilter : searchFilterConfigs) { - Date date = null; - String separator = DSpaceServicesFactory.getInstance().getConfigurationService() - .getProperty("discovery.solr.facets.split.char"); - if (separator == null) { - separator = FILTER_SEPARATOR; - } - if (searchFilter.getType().equals(DiscoveryConfigurationParameters.TYPE_DATE)) { - //For our search filters that are dates we format them properly - date = MultiFormatDateParser.parse(value); - if (date != null) { - //TODO: make this date format configurable ! - value = DateFormatUtils.formatUTC(date, "yyyy-MM-dd"); - } - } - doc.addField(searchFilter.getIndexFieldName(), value); - doc.addField(searchFilter.getIndexFieldName() + "_keyword", value); - - if (authority != null && preferedLabel == null) { - doc.addField(searchFilter.getIndexFieldName() - + "_keyword", value + AUTHORITY_SEPARATOR - + authority); - doc.addField(searchFilter.getIndexFieldName() - + "_authority", authority); - doc.addField(searchFilter.getIndexFieldName() - + "_acid", value.toLowerCase() - + separator + value - + AUTHORITY_SEPARATOR + authority); - } - - if (preferedLabel != null) { - doc.addField(searchFilter.getIndexFieldName(), - preferedLabel); - doc.addField(searchFilter.getIndexFieldName() - + "_keyword", preferedLabel); - doc.addField(searchFilter.getIndexFieldName() - + "_keyword", preferedLabel - + AUTHORITY_SEPARATOR + authority); - doc.addField(searchFilter.getIndexFieldName() - + "_authority", authority); - doc.addField(searchFilter.getIndexFieldName() - + "_acid", preferedLabel.toLowerCase() - + separator + preferedLabel - + AUTHORITY_SEPARATOR + authority); - } - if (variants != null) { - for (String var : variants) { - doc.addField(searchFilter.getIndexFieldName() + "_keyword", var); - doc.addField(searchFilter.getIndexFieldName() - + "_acid", var.toLowerCase() - + separator + var - + AUTHORITY_SEPARATOR + authority); - } - } - - //Add a dynamic fields for auto complete in search - doc.addField(searchFilter.getIndexFieldName() + "_ac", - value.toLowerCase() + separator + value); - if (preferedLabel != null) { - doc.addField(searchFilter.getIndexFieldName() - + "_ac", preferedLabel.toLowerCase() - + separator + preferedLabel); - } - if (variants != null) { - for (String var : variants) { - doc.addField(searchFilter.getIndexFieldName() - + "_ac", var.toLowerCase() + separator - + var); - } - } - - if (searchFilter.getFilterType().equals(DiscoverySearchFilterFacet.FILTER_TYPE_FACET)) { - if (searchFilter.getType().equals(DiscoveryConfigurationParameters.TYPE_TEXT)) { - //Add a special filter - //We use a separator to split up the lowercase and regular case, this is needed to - // get our filters in regular case - //Solr has issues with facet prefix and cases - if (authority != null) { - String facetValue = preferedLabel != null ? preferedLabel : value; - doc.addField(searchFilter.getIndexFieldName() + "_filter", facetValue - .toLowerCase() + separator + facetValue + AUTHORITY_SEPARATOR + authority); - } else { - doc.addField(searchFilter.getIndexFieldName() + "_filter", - value.toLowerCase() + separator + value); - } - } else if (searchFilter.getType().equals(DiscoveryConfigurationParameters.TYPE_DATE)) { - if (date != null) { - String indexField = searchFilter.getIndexFieldName() + ".year"; - String yearUTC = DateFormatUtils.formatUTC(date, "yyyy"); - doc.addField(searchFilter.getIndexFieldName() + "_keyword", yearUTC); - // add the year to the autocomplete index - doc.addField(searchFilter.getIndexFieldName() + "_ac", yearUTC); - doc.addField(indexField, yearUTC); - - if (yearUTC.startsWith("0")) { - doc.addField( - searchFilter.getIndexFieldName() - + "_keyword", - yearUTC.replaceFirst("0*", "")); - // add date without starting zeros for autocomplete e filtering - doc.addField( - searchFilter.getIndexFieldName() - + "_ac", - yearUTC.replaceFirst("0*", "")); - doc.addField( - searchFilter.getIndexFieldName() - + "_ac", - value.replaceFirst("0*", "")); - doc.addField( - searchFilter.getIndexFieldName() - + "_keyword", - value.replaceFirst("0*", "")); - } - - //Also save a sort value of this year, this is required for determining the upper - // & lower bound year of our facet - if (doc.getField(indexField + "_sort") == null) { - //We can only add one year so take the first one - doc.addField(indexField + "_sort", yearUTC); - } - } - } else if (searchFilter.getType() - .equals(DiscoveryConfigurationParameters.TYPE_HIERARCHICAL)) { - HierarchicalSidebarFacetConfiguration hierarchicalSidebarFacetConfiguration = - (HierarchicalSidebarFacetConfiguration) searchFilter; - String[] subValues = value.split(hierarchicalSidebarFacetConfiguration.getSplitter()); - if (hierarchicalSidebarFacetConfiguration - .isSkipFirstNodeLevel() && 1 < subValues.length) { - //Remove the first element of our array - subValues = (String[]) ArrayUtils.subarray(subValues, 1, subValues.length); - } - for (int i = 0; i < subValues.length; i++) { - StringBuilder valueBuilder = new StringBuilder(); - for (int j = 0; j <= i; j++) { - valueBuilder.append(subValues[j]); - if (j < i) { - valueBuilder.append(hierarchicalSidebarFacetConfiguration.getSplitter()); - } - } - - String indexValue = valueBuilder.toString().trim(); - doc.addField(searchFilter.getIndexFieldName() + "_tax_" + i + "_filter", - indexValue.toLowerCase() + separator + indexValue); - //We add the field x times that it has occurred - for (int j = i; j < subValues.length; j++) { - doc.addField(searchFilter.getIndexFieldName() + "_filter", - indexValue.toLowerCase() + separator + indexValue); - doc.addField(searchFilter.getIndexFieldName() + "_keyword", indexValue); - } - } - } - } - } - } - - if ((sortFields.get(field) != null || recentSubmissionsConfigurationMap - .get(field) != null) && !sortFieldsAdded.contains(field)) { - //Only add sort value once - String type; - if (sortFields.get(field) != null) { - type = sortFields.get(field).getType(); - } else { - type = recentSubmissionsConfigurationMap.get(field).getType(); - } - - if (type.equals(DiscoveryConfigurationParameters.TYPE_DATE)) { - Date date = MultiFormatDateParser.parse(value); - if (date != null) { - String stringDate = SolrUtils.getDateFormatter().format(date); - doc.addField(field + "_dt", stringDate); - } else { - log.warn("Error while indexing sort date field, item: " + item - .getHandle() + " metadata field: " + field + " date value: " + date); - } - } else { - doc.addField(field + "_sort", value); - } - sortFieldsAdded.add(field); - } - - if (hitHighlightingFields.contains(field) || hitHighlightingFields - .contains("*") || hitHighlightingFields.contains(unqualifiedField + "." + Item.ANY)) { - if (authority != null) { - doc.addField(field + "_hl", value + AUTHORITY_SEPARATOR + authority); - } else { - doc.addField(field + "_hl", value); - } - } - - if (moreLikeThisFields.contains(field) || moreLikeThisFields - .contains(unqualifiedField + "." + Item.ANY)) { - doc.addField(field + "_mlt", value); - } - - doc.addField(field, value); - if (authority != null) { - doc.addField(field + "_authority", authority); - } - if (toProjectionFields.contains(field) || toProjectionFields - .contains(unqualifiedField + "." + Item.ANY)) { - StringBuffer variantsToStore = new StringBuffer(); - if (variants != null) { - for (String var : variants) { - variantsToStore.append(VARIANTS_STORE_SEPARATOR); - variantsToStore.append(var); - } - } - doc.addField( - field + "_stored", - value + STORE_SEPARATOR + preferedLabel - + STORE_SEPARATOR - + (variantsToStore.length() > VARIANTS_STORE_SEPARATOR - .length() ? variantsToStore - .substring(VARIANTS_STORE_SEPARATOR - .length()) : "null") - + STORE_SEPARATOR + authority - + STORE_SEPARATOR + meta.getLanguage()); - } - - if (meta.getLanguage() != null && !meta.getLanguage().trim().equals("")) { - String langField = field + "." + meta.getLanguage(); - doc.addField(langField, value); - } - } - - } catch (Exception e) { - log.error(e.getMessage(), e); - } - - - log.debug(" Added Metadata"); - - try { - - List values = itemService.getMetadataByMetadataString(item, "dc.relation.ispartof"); - - if (values != null && values.size() > 0 && values.get(0) != null && values.get(0).getValue() != null) { - // group on parent - String handlePrefix = handleService.getCanonicalPrefix(); - - doc.addField("publication_grp", values.get(0).getValue().replaceFirst(handlePrefix, "")); - - } else { - // group on self - doc.addField("publication_grp", item.getHandle()); - } - - } catch (Exception e) { - log.error(e.getMessage(), e); - } - - - log.debug(" Added Grouping"); - - //Do any additional indexing, depends on the plugins - List solrServiceIndexPlugins = DSpaceServicesFactory.getInstance().getServiceManager() - .getServicesByType( - SolrServiceIndexPlugin.class); - for (SolrServiceIndexPlugin solrServiceIndexPlugin : solrServiceIndexPlugins) { - solrServiceIndexPlugin.additionalIndex(context, item, doc); - } - } - - private void deleteInProgressSubmissionByItemID(String uniqueID) throws SolrServerException, IOException { - String query = "inprogress.item:\"" + uniqueID + "\""; - log.debug("Try to delete all in progress submission [DELETEBYQUERY]:" + query); - getSolr().deleteByQuery(query); - } - - private void addFacetIndex(SolrInputDocument document, String field, String authority, String fvalue) { - addFacetIndex(document, field, fvalue, authority, fvalue); - } - - private void addFacetIndex(SolrInputDocument document, String field, String sortValue, String authority, - String fvalue) { - // the separator for the filter can be eventually configured - String separator = DSpaceServicesFactory.getInstance().getConfigurationService() - .getProperty("discovery.solr.facets.split.char"); - if (separator == null) { - separator = FILTER_SEPARATOR; - } - String acvalue = sortValue + separator + fvalue + SolrServiceImpl.AUTHORITY_SEPARATOR + authority; - document.addField(field + "_filter", acvalue); - // build the solr field used for the keyword search - document.addField(field + "_keyword", fvalue); - // build the solr fields used for the autocomplete - document.addField(field + "_ac", fvalue.toLowerCase() + separator + fvalue); - if (StringUtils.isNotBlank(authority)) { - document.addField(field + "_acid", fvalue.toLowerCase() + separator + fvalue - + SolrServiceImpl.AUTHORITY_SEPARATOR + authority); - document.addField(field + "_authority", authority); - } - } - - private void indexInProgressSubmissionItem(Context context, Item item) - throws SQLException, IOException, SolrServerException, WorkflowConfigurationException { - XmlWorkflowItem workflowItem = workflowItemService.findByItem(context, item); - if (workflowItem == null) { - WorkspaceItem workspaceItem = workspaceItemService.findByItem(context, item); - if (workspaceItem == null) { - // mmm... it could be a template item, skip it - return; - } - // workspaceitem - List locations = getCollectionLocations(context, workspaceItem.getCollection()); - SolrInputDocument doc = new SolrInputDocument(); - - doc.addField("lastModified", item.getLastModified()); - EPerson submitter = workspaceItem.getSubmitter(); - if (submitter != null) { - addFacetIndex(doc, "submitter", submitter.getID().toString(), - submitter.getFullName()); - } - - List discoveryConfigurations = SearchUtils - .getAllDiscoveryConfigurations(workspaceItem); - addDiscoveryFields(doc, context, item, discoveryConfigurations); - addBasicInfoToDocument(doc, Constants.WORKSPACEITEM, workspaceItem.getID(), null, locations); - - String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService() - .getProperty("discovery.facet.namedtype.workspace"); - if (StringUtils.isBlank(acvalue)) { - acvalue = workspaceItem.getTypeText(); - } - addNamedResourceTypeIndex(doc, acvalue); - doc.addField("inprogress.item", item.getUniqueIndexID()); - - getSolr().add(doc); - } else { - // so it is an item in the workflow - // get the location string (for searching by collection & community) - List locations = getCollectionLocations(context, workflowItem.getCollection()); - SolrInputDocument doc = new SolrInputDocument(); - - doc.addField("inprogress.item", item.getUniqueIndexID()); - doc.addField("lastModified", item.getLastModified()); - EPerson submitter = workflowItem.getSubmitter(); - if (submitter != null) { - addFacetIndex(doc, "submitter", submitter.getID().toString(), - submitter.getFullName()); - } - - List discoveryConfigurations = SearchUtils - .getAllDiscoveryConfigurations(workflowItem); - addDiscoveryFields(doc, context, item, discoveryConfigurations); - - List claimedTasks = claimedTaskService.find(context, workflowItem); - List pools = poolTaskService.find(context, workflowItem); - - List docs = new ArrayList(); - - if (claimedTasks != null) { - for (ClaimedTask claimedTask : claimedTasks) { - SolrInputDocument claimDoc = doc.deepCopy(); - addBasicInfoToDocument(claimDoc, Constants.CLAIMEDTASK, claimedTask.getID(), null, locations); - addFacetIndex(claimDoc, "action", claimedTask.getActionID(), claimedTask.getActionID()); - addFacetIndex(claimDoc, "step", claimedTask.getStepID(), claimedTask.getStepID()); - - claimDoc.addField("taskfor", "e" + claimedTask.getOwner().getID().toString()); - - String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService() - .getProperty("discovery.facet.namedtype.workflow.claimed"); - if (StringUtils.isBlank(acvalue)) { - acvalue = claimedTask.getTypeText(); - } - addNamedResourceTypeIndex(claimDoc, acvalue); - - docs.add(claimDoc); - } - } - - if (pools != null) { - for (PoolTask poolTask : pools) { - SolrInputDocument claimDoc = doc.deepCopy(); - addBasicInfoToDocument(claimDoc, Constants.POOLTASK, poolTask.getID(), null, locations); - addFacetIndex(claimDoc, "action", poolTask.getActionID(), poolTask.getActionID()); - addFacetIndex(claimDoc, "step", poolTask.getStepID(), poolTask.getStepID()); - - if (poolTask.getEperson() != null) { - claimDoc.addField("taskfor", "e" + poolTask.getEperson().getID().toString()); - } - if (poolTask.getGroup() != null) { - claimDoc.addField("taskfor", "g" + poolTask.getGroup().getID().toString()); - } - - String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService() - .getProperty("discovery.facet.namedtype.workflow.pooled"); - if (StringUtils.isBlank(acvalue)) { - acvalue = poolTask.getTypeText(); - } - addNamedResourceTypeIndex(claimDoc, acvalue); - docs.add(claimDoc); - } - } - - String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService() - .getProperty("discovery.facet.namedtype.workflow.item"); - if (StringUtils.isBlank(acvalue)) { - acvalue = workflowItem.getTypeText(); - } - addNamedResourceTypeIndex(doc, acvalue); - - addBasicInfoToDocument(doc, Constants.WORKFLOWITEM, workflowItem.getID(), null, locations); - docs.add(doc); - - if (docs.size() > 0) { - getSolr().add(docs); - } else { - // no tasks found?!? - log.error("No tasks found for workflowitem " + workflowItem.getID()); - } - } - } - - /** - * Create Lucene document with all the shared fields initialized. - * - * @param type Type of DSpace Object - * @param id internal identifier - * @param handle handle string - * @param locations list of collection/community internal identifiers - * @return initialized Lucene document - */ - protected SolrInputDocument buildDocument(int type, UUID id, String handle, - List locations) { - SolrInputDocument doc = new SolrInputDocument(); - addBasicInfoToDocument(doc, type, id, handle, locations); - return doc; - } - - private void addBasicInfoToDocument(SolrInputDocument doc, int type, Serializable id, String handle, - List locations) { - // want to be able to check when last updated - // (not tokenized, but it is indexed) - doc.addField(LAST_INDEXED_FIELD, - SolrUtils.getDateFormatter().format(new Date())); - - // New fields to weaken the dependence on handles, and allow for faster - // list display - doc.addField(RESOURCE_UNIQUE_ID, type + "-" + id); - doc.addField(RESOURCE_TYPE_FIELD, Integer.toString(type)); - doc.addField(RESOURCE_ID_FIELD, id.toString()); - - // want to be able to search for handle, so use keyword - // (not tokenized, but it is indexed) - if (handle != null) { - // want to be able to search for handle, so use keyword - // (not tokenized, but it is indexed) - doc.addField(HANDLE_FIELD, handle); - } - - if (locations != null) { - for (String location : locations) { - doc.addField("location", location); - if (location.startsWith("m")) { - doc.addField("location.comm", location.substring(1)); - } else { - doc.addField("location.coll", location.substring(1)); - } - } - } - } - /** * Helper function to retrieve a date using a best guess of the potential * date encodings on a field @@ -1871,12 +691,13 @@ public class SolrServiceImpl implements SearchService, IndexingService { public DiscoverResult search(Context context, IndexableObject dso, DiscoverQuery discoveryQuery, boolean includeUnDiscoverable) throws SearchServiceException { if (dso != null) { - if (dso instanceof Community) { + if (dso instanceof IndexableCommunity) { discoveryQuery.addFilterQueries("location:m" + dso.getID()); - } else if (dso instanceof Collection) { + } else if (dso instanceof IndexableCollection) { discoveryQuery.addFilterQueries("location:l" + dso.getID()); - } else if (dso instanceof Item) { - discoveryQuery.addFilterQueries(HANDLE_FIELD + ":" + ((Item) dso).getHandle()); + } else if (dso instanceof IndexableItem) { + discoveryQuery.addFilterQueries(SearchUtils.RESOURCE_UNIQUE_ID + ":" + dso. + getUniqueIndexID()); } } return search(context, discoveryQuery, includeUnDiscoverable); @@ -1888,13 +709,13 @@ public class SolrServiceImpl implements SearchService, IndexingService { public DiscoverResult search(Context context, DiscoverQuery discoveryQuery, boolean includeUnDiscoverable) throws SearchServiceException { try { - if (getSolr() == null) { + if (solrSearchCore.getSolr() == null) { return new DiscoverResult(); } SolrQuery solrQuery = resolveToSolrQuery(context, discoveryQuery, includeUnDiscoverable); - QueryResponse queryResponse = getSolr().query(solrQuery, SolrRequest.METHOD.POST); + QueryResponse queryResponse = solrSearchCore.getSolr().query(solrQuery, SolrRequest.METHOD.POST); return retrieveResult(context, discoveryQuery, queryResponse); } catch (Exception e) { @@ -1919,9 +740,8 @@ public class SolrServiceImpl implements SearchService, IndexingService { solrQuery.addField(fieldName); } // Also ensure a few key obj identifier fields are returned with every query - solrQuery.addField(HANDLE_FIELD); - solrQuery.addField(RESOURCE_TYPE_FIELD); - solrQuery.addField(RESOURCE_ID_FIELD); + solrQuery.addField(SearchUtils.RESOURCE_TYPE_FIELD); + solrQuery.addField(SearchUtils.RESOURCE_ID_FIELD); if (discoveryQuery.isSpellCheck()) { solrQuery.setParam(SpellingParams.SPELLCHECK_Q, query); @@ -1938,8 +758,8 @@ public class SolrServiceImpl implements SearchService, IndexingService { String filterQuery = discoveryQuery.getFilterQueries().get(i); solrQuery.addFilterQuery(filterQuery); } - if (discoveryQuery.getDSpaceObjectFilter() != -1) { - solrQuery.addFilterQuery(RESOURCE_TYPE_FIELD + ":" + discoveryQuery.getDSpaceObjectFilter()); + if (discoveryQuery.getDSpaceObjectFilter() != null) { + solrQuery.addFilterQuery(SearchUtils.RESOURCE_TYPE_FIELD + ":" + discoveryQuery.getDSpaceObjectFilter()); } for (int i = 0; i < discoveryQuery.getFieldPresentQueries().size(); i++) { @@ -2082,13 +902,14 @@ public class SolrServiceImpl implements SearchService, IndexingService { List searchFields = query.getSearchFields(); for (SolrDocument doc : solrQueryResponse.getResults()) { - IndexableObject dso = findIndexableObject(context, doc); + IndexableObject indexableObject = findIndexableObject(context, doc); - if (dso != null) { - result.addIndexableObject(dso); + if (indexableObject != null) { + result.addIndexableObject(indexableObject); } else { - log.error(LogManager.getHeader(context, "Error while retrieving DSpace object from discovery index", - "Handle: " + doc.getFirstValue(HANDLE_FIELD))); + log.error(LogManager.getHeader(context, + "Error while retrieving DSpace object from discovery index", + "Unique identifier: " + doc.getFirstValue(SearchUtils.RESOURCE_UNIQUE_ID))); continue; } @@ -2101,11 +922,11 @@ public class SolrServiceImpl implements SearchService, IndexingService { } resultDoc.addSearchField(field, valuesAsString.toArray(new String[valuesAsString.size()])); } - result.addSearchDocument(dso, resultDoc); + result.addSearchDocument(indexableObject, resultDoc); if (solrQueryResponse.getHighlighting() != null) { Map> highlightedFields = solrQueryResponse.getHighlighting().get( - dso.getType() + "-" + dso.getID()); + indexableObject.getUniqueIndexID()); if (MapUtils.isNotEmpty(highlightedFields)) { //We need to remove all the "_hl" appendix strings from our keys Map> resultMap = new HashMap>(); @@ -2120,8 +941,8 @@ public class SolrServiceImpl implements SearchService, IndexingService { resultMap.put(key.substring(0, key.lastIndexOf("_hl")), highlightedFields.get(key)); } - result.addHighlightedResult(dso, - new DiscoverResult.IndexableObjectHighlightResult(dso, resultMap)); + result.addHighlightedResult(indexableObject, + new DiscoverResult.IndexableObjectHighlightResult(indexableObject, resultMap)); } } } @@ -2220,35 +1041,16 @@ public class SolrServiceImpl implements SearchService, IndexingService { * An exception that provides information on a database access error or other errors. */ protected IndexableObject findIndexableObject(Context context, SolrDocument doc) throws SQLException { - Integer type = (Integer) doc.getFirstValue(RESOURCE_TYPE_FIELD); - Object id = doc.getFirstValue(RESOURCE_ID_FIELD); - String handle = (String) doc.getFirstValue(HANDLE_FIELD); - IndexableObject o = null; - Serializable uid = null; - if (type != null && id != null) { - switch (type) { - case Constants.WORKSPACEITEM: - case Constants.WORKFLOWITEM: - case Constants.POOLTASK: - case Constants.CLAIMEDTASK: - uid = Integer.parseInt((String) id); - break; - default: - uid = UUID.fromString((String) id); - break; - } - } + String type = (String) doc.getFirstValue(SearchUtils.RESOURCE_TYPE_FIELD); + String id = (String) doc.getFirstValue(SearchUtils.RESOURCE_ID_FIELD); + final IndexFactory indexableObjectService = indexObjectServiceFactory. + getIndexFactoryByType(type); + Optional indexableObject = indexableObjectService.findIndexableObject(context, id); - if (uid != null) { - o = (IndexableObject) contentServiceFactory.getIndexableObjectService(type).findIndexableObject(context, - uid); + if (!indexableObject.isPresent()) { + log.warn("Not able to retrieve object RESOURCE_ID:" + id + " - RESOURCE_TYPE_ID:" + type); } - - if (o == null) { - log.warn("Not able to retrieve object RESOURCE_ID:" + id + " - RESOURCE_TYPE_ID:" + type + " - HANDLE:" + - handle); - } - return o; + return indexableObject.orElse(null); } public List search(Context context, String query, int offset, int max, @@ -2261,14 +1063,14 @@ public class SolrServiceImpl implements SearchService, IndexingService { int offset, int max, String... filterquery) { try { - if (getSolr() == null) { + if (solrSearchCore.getSolr() == null) { return Collections.emptyList(); } SolrQuery solrQuery = new SolrQuery(); solrQuery.setQuery(query); //Only return obj identifier fields in result doc - solrQuery.setFields(RESOURCE_ID_FIELD, RESOURCE_TYPE_FIELD); + solrQuery.setFields(SearchUtils.RESOURCE_ID_FIELD, SearchUtils.RESOURCE_TYPE_FIELD); solrQuery.setStart(offset); solrQuery.setRows(max); if (orderfield != null) { @@ -2277,18 +1079,14 @@ public class SolrServiceImpl implements SearchService, IndexingService { if (filterquery != null) { solrQuery.addFilterQuery(filterquery); } - QueryResponse rsp = getSolr().query(solrQuery, SolrRequest.METHOD.POST); + QueryResponse rsp = solrSearchCore.getSolr().query(solrQuery, SolrRequest.METHOD.POST); SolrDocumentList docs = rsp.getResults(); Iterator iter = docs.iterator(); List result = new ArrayList(); while (iter.hasNext()) { SolrDocument doc = (SolrDocument) iter.next(); - - IndexableObject o = (IndexableObject)contentServiceFactory - .getIndexableObjectService((Integer) doc.getFirstValue(RESOURCE_TYPE_FIELD)) - .findIndexableObject(context, UUID.fromString((String) doc.getFirstValue(RESOURCE_ID_FIELD))); - + IndexableObject o = findIndexableObject(context, doc); if (o != null) { result.add(o); } @@ -2298,7 +1096,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { // Any acception that we get ignore it. // We do NOT want any crashed to shown by the user log.error(LogManager.getHeader(context, "Error while quering solr", "Query: " + query), e); - return new ArrayList(0); + return new ArrayList<>(0); } } @@ -2357,13 +1155,13 @@ public class SolrServiceImpl implements SearchService, IndexingService { @Override public List getRelatedItems(Context context, Item item, DiscoveryMoreLikeThisConfiguration mltConfig) { - List results = new ArrayList(); + List results = new ArrayList<>(); try { SolrQuery solrQuery = new SolrQuery(); //Set the query to handle since this is unique - solrQuery.setQuery(HANDLE_FIELD + ": " + item.getHandle()); + solrQuery.setQuery(SearchUtils.RESOURCE_UNIQUE_ID + ": " + new IndexableItem(item).getUniqueIndexID()); //Only return obj identifier fields in result doc - solrQuery.setFields(HANDLE_FIELD, RESOURCE_TYPE_FIELD, RESOURCE_ID_FIELD); + solrQuery.setFields(SearchUtils.RESOURCE_TYPE_FIELD, SearchUtils.RESOURCE_ID_FIELD); //Add the more like this parameters ! solrQuery.setParam(MoreLikeThisParams.MLT, true); //Add a comma separated list of the similar fields @@ -2382,23 +1180,21 @@ public class SolrServiceImpl implements SearchService, IndexingService { solrQuery.setParam(MoreLikeThisParams.DOC_COUNT, String.valueOf(mltConfig.getMax())); solrQuery.setParam(MoreLikeThisParams.MIN_WORD_LEN, String.valueOf(mltConfig.getMinWordLength())); - if (getSolr() == null) { + if (solrSearchCore.getSolr() == null) { return Collections.emptyList(); } - QueryResponse rsp = getSolr().query(solrQuery, SolrRequest.METHOD.POST); + QueryResponse rsp = solrSearchCore.getSolr().query(solrQuery, SolrRequest.METHOD.POST); NamedList mltResults = (NamedList) rsp.getResponse().get("moreLikeThis"); if (mltResults != null && mltResults.get(item.getType() + "-" + item.getID()) != null) { SolrDocumentList relatedDocs = (SolrDocumentList) mltResults.get(item.getType() + "-" + item.getID()); for (Object relatedDoc : relatedDocs) { SolrDocument relatedDocument = (SolrDocument) relatedDoc; IndexableObject relatedItem = findIndexableObject(context, relatedDocument); - if (relatedItem.getType() == Constants.ITEM) { - results.add((Item) relatedItem); + if (relatedItem instanceof IndexableItem) { + results.add(((IndexableItem) relatedItem).getIndexedObject()); } } } - - } catch (Exception e) { log.error( LogManager.getHeader(context, "Error while retrieving related items", "Handle: " + item.getHandle()), @@ -2409,8 +1205,8 @@ public class SolrServiceImpl implements SearchService, IndexingService { @Override public String toSortFieldIndex(String metadataField, String type) { - if (StringUtils.equalsIgnoreCase(SCORE, metadataField)) { - return SCORE; + if (StringUtils.equalsIgnoreCase(DiscoverySortConfiguration.SCORE, metadataField)) { + return DiscoverySortConfiguration.SCORE; } else if (StringUtils.equals(type, DiscoveryConfigurationParameters.TYPE_DATE)) { return metadataField + "_dt"; } else { @@ -2469,7 +1265,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { String separator = DSpaceServicesFactory.getInstance().getConfigurationService() .getProperty("discovery.solr.facets.split.char"); if (separator == null) { - separator = FILTER_SEPARATOR; + separator = SearchUtils.FILTER_SEPARATOR; } //Escape any regex chars separator = java.util.regex.Pattern.quote(separator); @@ -2477,7 +1273,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { StringBuffer valueBuffer = new StringBuffer(); int start = fqParts.length / 2; for (int i = start; i < fqParts.length; i++) { - String[] split = fqParts[i].split(AUTHORITY_SEPARATOR, 2); + String[] split = fqParts[i].split(SearchUtils.AUTHORITY_SEPARATOR, 2); valueBuffer.append(split[0]); } value = valueBuffer.toString(); @@ -2501,7 +1297,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { String separator = DSpaceServicesFactory.getInstance().getConfigurationService() .getProperty("discovery.solr.facets.split.char"); if (separator == null) { - separator = FILTER_SEPARATOR; + separator = SearchUtils.FILTER_SEPARATOR; } //Escape any regex chars separator = java.util.regex.Pattern.quote(separator); @@ -2509,7 +1305,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { StringBuffer authorityBuffer = new StringBuffer(); int start = fqParts.length / 2; for (int i = start; i < fqParts.length; i++) { - String[] split = fqParts[i].split(AUTHORITY_SEPARATOR, 2); + String[] split = fqParts[i].split(SearchUtils.AUTHORITY_SEPARATOR, 2); if (split.length == 2) { authorityBuffer.append(split[1]); } @@ -2533,7 +1329,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { String separator = DSpaceServicesFactory.getInstance().getConfigurationService() .getProperty("discovery.solr.facets.split.char"); if (separator == null) { - separator = FILTER_SEPARATOR; + separator = SearchUtils.FILTER_SEPARATOR; } //Escape any regex chars separator = java.util.regex.Pattern.quote(separator); @@ -2563,8 +1359,8 @@ public class SolrServiceImpl implements SearchService, IndexingService { @Override public void commit() throws SearchServiceException { try { - if (getSolr() != null) { - getSolr().commit(); + if (solrSearchCore.getSolr() != null) { + solrSearchCore.getSolr().commit(); } } catch (Exception e) { throw new SearchServiceException(e.getMessage(), e); @@ -2613,37 +1409,4 @@ public class SolrServiceImpl implements SearchService, IndexingService { } return null; } - - /** - * Add the necessary fields to the SOLR document to support a Discover Facet on resourcetypename (archived item, - * workspace item, workflow item, etc) - * - * @param document - * the solr document - * @param filterValue - * the filter value (i.e. \n|||\n### - */ - private void addNamedResourceTypeIndex(SolrInputDocument document, String filterValue) { - - // the separator for the filter can be eventually configured - String separator = DSpaceServicesFactory.getInstance().getConfigurationService() - .getProperty("discovery.solr.facets.split.char"); - if (separator == null) { - separator = FILTER_SEPARATOR; - } - - // split the authority part from the sort/display - String[] avalues = filterValue.split(SolrServiceImpl.AUTHORITY_SEPARATOR); - - String sortValue = avalues[0]; - String authorityValue = avalues.length == 2 ? avalues[1] : filterValue; - - // get the display value - int idxSeparator = sortValue.indexOf(separator); - String displayValue = idxSeparator != -1 ? sortValue.substring(idxSeparator + separator.length()) - : sortValue; - - addFacetIndex(document, NAMED_RESOURCE_TYPE, sortValue, authorityValue, displayValue); - } - } diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceMetadataBrowseIndexingPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceMetadataBrowseIndexingPlugin.java index 6d1035c4a0..187c6b0600 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceMetadataBrowseIndexingPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceMetadataBrowseIndexingPlugin.java @@ -23,6 +23,7 @@ import org.dspace.content.authority.service.ChoiceAuthorityService; import org.dspace.content.authority.service.MetadataAuthorityService; import org.dspace.content.service.ItemService; import org.dspace.core.Context; +import org.dspace.discovery.indexobject.IndexableItem; import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.sort.OrderFormat; import org.dspace.sort.SortException; @@ -56,12 +57,12 @@ public class SolrServiceMetadataBrowseIndexingPlugin implements SolrServiceIndex protected ChoiceAuthorityService choiceAuthorityService; @Override - public void additionalIndex(Context context, IndexableObject dso, SolrInputDocument document) { + public void additionalIndex(Context context, IndexableObject indexableObject, SolrInputDocument document) { // Only works for Items - if (!(dso instanceof Item)) { + if (!(indexableObject instanceof IndexableItem)) { return; } - Item item = (Item) dso; + Item item = ((IndexableItem) indexableObject).getIndexedObject(); // Get the currently configured browse indexes BrowseIndex[] bis; @@ -206,9 +207,9 @@ public class SolrServiceMetadataBrowseIndexingPlugin implements SolrServiceIndex bi.getDataType()); distFValues .add(nLabel - + SolrServiceImpl.FILTER_SEPARATOR + + SearchUtils.FILTER_SEPARATOR + preferedLabel - + SolrServiceImpl.AUTHORITY_SEPARATOR + + SearchUtils.AUTHORITY_SEPARATOR + values.get(x).getAuthority()); distValuesForAC.add(preferedLabel); } @@ -222,9 +223,9 @@ public class SolrServiceMetadataBrowseIndexingPlugin implements SolrServiceIndex bi.getDataType()); distFValues .add(nVal - + SolrServiceImpl.FILTER_SEPARATOR + + SearchUtils.FILTER_SEPARATOR + var - + SolrServiceImpl.AUTHORITY_SEPARATOR + + SearchUtils.AUTHORITY_SEPARATOR + values.get(x).getAuthority()); distValuesForAC.add(var); } @@ -241,7 +242,7 @@ public class SolrServiceMetadataBrowseIndexingPlugin implements SolrServiceIndex bi.getDataType()); distFValues .add(nVal - + SolrServiceImpl.FILTER_SEPARATOR + + SearchUtils.FILTER_SEPARATOR + values.get(x).getValue()); distFVal.add(values.get(x).getValue()); distValuesForAC.add(values.get(x).getValue()); diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceResourceRestrictionPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceResourceRestrictionPlugin.java index 853076fdc2..38e85dbf93 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceResourceRestrictionPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceResourceRestrictionPlugin.java @@ -24,6 +24,7 @@ import org.dspace.content.service.CommunityService; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.LogManager; +import org.dspace.discovery.indexobject.IndexableDSpaceObject; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; import org.dspace.eperson.service.GroupService; @@ -56,8 +57,8 @@ public class SolrServiceResourceRestrictionPlugin implements SolrServiceIndexPlu @Override public void additionalIndex(Context context, IndexableObject idxObj, SolrInputDocument document) { - if (idxObj instanceof DSpaceObject) { - DSpaceObject dso = (DSpaceObject) idxObj; + if (idxObj instanceof IndexableDSpaceObject) { + DSpaceObject dso = ((IndexableDSpaceObject) idxObj).getIndexedObject(); try { List policies = authorizeService.getPoliciesActionFilter(context, dso, Constants.READ); for (ResourcePolicy resourcePolicy : policies) { diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceSpellIndexingPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceSpellIndexingPlugin.java index 99c3fcf6ef..47a96d0352 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceSpellIndexingPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceSpellIndexingPlugin.java @@ -14,6 +14,7 @@ import org.dspace.content.Item; import org.dspace.content.MetadataValue; import org.dspace.content.service.ItemService; import org.dspace.core.Context; +import org.dspace.discovery.indexobject.IndexableItem; import org.springframework.beans.factory.annotation.Autowired; /** @@ -29,9 +30,9 @@ public class SolrServiceSpellIndexingPlugin implements SolrServiceIndexPlugin { protected ItemService itemService; @Override - public void additionalIndex(Context context, IndexableObject dso, SolrInputDocument document) { - if (dso instanceof Item) { - Item item = (Item) dso; + public void additionalIndex(Context context, IndexableObject indexableObject, SolrInputDocument document) { + if (indexableObject instanceof IndexableItem) { + Item item = ((IndexableItem) indexableObject).getIndexedObject(); List dcValues = itemService.getMetadata(item, Item.ANY, Item.ANY, Item.ANY, Item.ANY); List toIgnoreMetadataFields = SearchUtils.getIgnoredMetadataFields(item.getType()); for (MetadataValue dcValue : dcValues) { diff --git a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java index 53433f879f..2c12f923ae 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java +++ b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java @@ -13,8 +13,8 @@ import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; -import org.dspace.content.DSpaceObject; import org.dspace.discovery.IndexableObject; +import org.dspace.discovery.indexobject.IndexableDSpaceObject; import org.dspace.services.factory.DSpaceServicesFactory; /** @@ -45,8 +45,8 @@ public class DiscoveryConfigurationService { String name; if (dso == null) { name = "site"; - } else if (dso instanceof DSpaceObject) { - name = ((DSpaceObject) dso).getHandle(); + } else if (dso instanceof IndexableDSpaceObject) { + name = ((IndexableDSpaceObject) dso).getIndexedObject().getHandle(); } else { name = dso.getUniqueIndexID(); } diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/ClaimedTaskIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/ClaimedTaskIndexFactoryImpl.java new file mode 100644 index 0000000000..4ab11d5d6b --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/ClaimedTaskIndexFactoryImpl.java @@ -0,0 +1,85 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.discovery.indexobject; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.Iterator; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +import org.apache.solr.common.SolrInputDocument; +import org.dspace.core.Context; +import org.dspace.discovery.indexobject.factory.ClaimedTaskIndexFactory; +import org.dspace.discovery.indexobject.factory.WorkflowItemIndexFactory; +import org.dspace.services.factory.DSpaceServicesFactory; +import org.dspace.xmlworkflow.storedcomponents.ClaimedTask; +import org.dspace.xmlworkflow.storedcomponents.service.ClaimedTaskService; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Factory implementation for indexing/retrieving claimed tasks in the search core + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class ClaimedTaskIndexFactoryImpl extends IndexFactoryImpl + implements ClaimedTaskIndexFactory { + + @Autowired + protected ClaimedTaskService claimedTaskService; + @Autowired + WorkflowItemIndexFactory indexableWorkflowItemService; + + @Override + public Iterator findAll(Context context) throws SQLException { + final Iterator claimedTasks = claimedTaskService.findAll(context).iterator(); + return new Iterator() { + @Override + public boolean hasNext() { + return claimedTasks.hasNext(); + } + + @Override + public IndexableClaimedTask next() { + return new IndexableClaimedTask(claimedTasks.next()); + } + }; + } + + @Override + public String getType() { + return IndexableClaimedTask.TYPE; + } + + @Override + public SolrInputDocument buildDocument(Context context, IndexableClaimedTask indexableObject) + throws SQLException, IOException { + final SolrInputDocument doc = super.buildDocument(context, indexableObject); + final ClaimedTask claimedTask = indexableObject.getIndexedObject(); + indexableWorkflowItemService.storeInprogressItemFields(context, doc, claimedTask.getWorkflowItem()); + + addFacetIndex(doc, "action", claimedTask.getActionID(), claimedTask.getActionID()); + addFacetIndex(doc, "step", claimedTask.getStepID(), claimedTask.getStepID()); + + doc.addField("taskfor", "e" + claimedTask.getOwner().getID().toString()); + + String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService() + .getProperty("discovery.facet.namedtype.workflow.claimed"); + if (StringUtils.isBlank(acvalue)) { + acvalue = indexableObject.getTypeText(); + } + addNamedResourceTypeIndex(doc, acvalue); + + return doc; + } + + @Override + public Optional findIndexableObject(Context context, String id) throws SQLException { + final ClaimedTask claimedTask = claimedTaskService.find(context, Integer.parseInt(id)); + return claimedTask == null ? Optional.empty() : Optional.of(new IndexableClaimedTask(claimedTask)); + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/CollectionIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/CollectionIndexFactoryImpl.java new file mode 100644 index 0000000000..3cfccc40de --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/CollectionIndexFactoryImpl.java @@ -0,0 +1,146 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.discovery.indexobject; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import org.apache.solr.common.SolrInputDocument; +import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.CollectionService; +import org.dspace.content.service.CommunityService; +import org.dspace.core.Context; +import org.dspace.discovery.SearchUtils; +import org.dspace.discovery.configuration.DiscoveryConfiguration; +import org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration; +import org.dspace.discovery.configuration.DiscoveryHitHighlightingConfiguration; +import org.dspace.discovery.indexobject.factory.CollectionIndexFactory; +import org.springframework.beans.factory.annotation.Autowired; + + +/** + * Factory implementation for indexing/retrieving collections in the search core + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class CollectionIndexFactoryImpl extends DSpaceObjectIndexFactoryImpl + implements CollectionIndexFactory { + + @Autowired + protected CollectionService collectionService; + + @Autowired + protected CommunityService communityService; + + @Override + public Iterator findAll(Context context) throws SQLException { + Iterator collections = collectionService.findAll(context).iterator(); + + return new Iterator() { + @Override + public boolean hasNext() { + return collections.hasNext(); + } + + @Override + public IndexableCollection next() { + return new IndexableCollection(collections.next()); + } + }; + } + + @Override + public String getType() { + return IndexableCollection.TYPE; + } + + /** + * Build a solr document for a DSpace Collection. + * + * @param context The relevant DSpace Context. + * @param indexableCollection indexableCollection to be indexed + * @throws SQLException sql exception + * @throws IOException IO exception + */ + @Override + public SolrInputDocument buildDocument(Context context, IndexableCollection indexableCollection) + throws IOException, SQLException { + // Create Lucene Document + SolrInputDocument doc = super.buildDocument(context, indexableCollection); + + final Collection collection = indexableCollection.getIndexedObject(); + + DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration(collection); + DiscoveryHitHighlightingConfiguration highlightingConfiguration = discoveryConfiguration + .getHitHighlightingConfiguration(); + List highlightedMetadataFields = new ArrayList<>(); + if (highlightingConfiguration != null) { + for (DiscoveryHitHighlightFieldConfiguration configuration : highlightingConfiguration + .getMetadataFields()) { + highlightedMetadataFields.add(configuration.getField()); + } + } + + + // and populate it + String description = collectionService.getMetadata(collection, "introductory_text"); + String description_abstract = collectionService.getMetadata(collection, "short_description"); + String description_table = collectionService.getMetadata(collection, "side_bar_text"); + String provenance = collectionService.getMetadata(collection, "provenance_description"); + String rights = collectionService.getMetadata(collection, "copyright_text"); + String rights_license = collectionService.getMetadata(collection, "license"); + String title = collectionService.getMetadata(collection, "name"); + + List toIgnoreMetadataFields = SearchUtils.getIgnoredMetadataFields(collection.getType()); + addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.description", + description); + addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.description.abstract", + description_abstract); + addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, + "dc.description.tableofcontents", description_table); + addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.provenance", provenance); + addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.rights", rights); + addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.rights.license", + rights_license); + addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.title", title); + + return doc; + } + + @Override + public Optional findIndexableObject(Context context, String id) throws SQLException { + final Collection collection = (collectionService.find(context, UUID.fromString(id))); + return collection == null ? Optional.empty() : Optional.of(new IndexableCollection(collection)); + } + + @Override + public List getLocations(Context context, IndexableCollection indexableCollection) throws SQLException { + return getCollectionLocations(context, indexableCollection.getIndexedObject()); + } + + @Override + public List getCollectionLocations(Context context, Collection collection) throws SQLException { + List locations = new ArrayList<>(); + // build list of community ids + List communities = ContentServiceFactory.getInstance().getCommunityService(). + getAllParents(context, collection); + + // now put those into strings + for (Community community : communities) { + locations.add("m" + community.getID()); + } + + return locations; + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/CommunityIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/CommunityIndexFactoryImpl.java new file mode 100644 index 0000000000..f4c00eeadf --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/CommunityIndexFactoryImpl.java @@ -0,0 +1,118 @@ +/** + * 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.discovery.indexobject; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import org.apache.solr.common.SolrInputDocument; +import org.dspace.content.Community; +import org.dspace.content.service.CommunityService; +import org.dspace.core.Context; +import org.dspace.discovery.SearchUtils; +import org.dspace.discovery.configuration.DiscoveryConfiguration; +import org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration; +import org.dspace.discovery.configuration.DiscoveryHitHighlightingConfiguration; +import org.dspace.discovery.indexobject.factory.CommunityIndexFactory; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Factory implementation for indexing/retrieving communities in the search core + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class CommunityIndexFactoryImpl extends DSpaceObjectIndexFactoryImpl + implements CommunityIndexFactory { + + @Autowired(required = true) + protected CommunityService communityService; + + @Override + public Iterator findAll(Context context) throws SQLException { + Iterator communities = communityService.findAll(context).iterator(); + + return new Iterator() { + @Override + public boolean hasNext() { + return communities.hasNext(); + } + + @Override + public IndexableCommunity next() { + return new IndexableCommunity(communities.next()); + } + }; + } + + @Override + public String getType() { + return IndexableCommunity.TYPE; + } + + + @Override + public SolrInputDocument buildDocument(Context context, IndexableCommunity indexableObject) + throws SQLException, IOException { + SolrInputDocument doc = super.buildDocument(context, indexableObject); + final Community community = indexableObject.getIndexedObject(); + + DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration(community); + DiscoveryHitHighlightingConfiguration highlightingConfiguration = discoveryConfiguration + .getHitHighlightingConfiguration(); + List highlightedMetadataFields = new ArrayList(); + if (highlightingConfiguration != null) { + for (DiscoveryHitHighlightFieldConfiguration configuration : highlightingConfiguration + .getMetadataFields()) { + highlightedMetadataFields.add(configuration.getField()); + } + } + + // and populate it + String description = communityService.getMetadata(community, "introductory_text"); + String description_abstract = communityService.getMetadata(community, "short_description"); + String description_table = communityService.getMetadata(community, "side_bar_text"); + String rights = communityService.getMetadata(community, "copyright_text"); + String title = communityService.getMetadata(community, "name"); + + List toIgnoreMetadataFields = SearchUtils.getIgnoredMetadataFields(community.getType()); + addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.description", + description); + addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.description.abstract", + description_abstract); + addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, + "dc.description.tableofcontents", description_table); + addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.rights", rights); + addContainerMetadataField(doc, highlightedMetadataFields, toIgnoreMetadataFields, "dc.title", title); + return doc; + } + + @Override + public Optional findIndexableObject(Context context, String id) throws SQLException { + final Community community = communityService.find(context, UUID.fromString(id)); + return community == null ? Optional.empty() : Optional.of(new IndexableCommunity(community)); + } + + @Override + public List getLocations(Context context, IndexableCommunity indexableDSpaceObject) throws SQLException { + final Community target = indexableDSpaceObject.getIndexedObject(); + List locations = new ArrayList<>(); + // build list of community ids + List communities = target.getParentCommunities(); + + // now put those into strings + for (Community community : communities) { + locations.add("m" + community.getID()); + } + + return locations; + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/DSpaceObjectIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/DSpaceObjectIndexFactoryImpl.java new file mode 100644 index 0000000000..d5c65a3423 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/DSpaceObjectIndexFactoryImpl.java @@ -0,0 +1,79 @@ +/** + * 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.discovery.indexobject; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.apache.solr.common.SolrInputDocument; +import org.dspace.content.DSpaceObject; +import org.dspace.core.Context; +import org.dspace.discovery.indexobject.factory.DSpaceObjectIndexFactory; + +/** + * Factory implementation for indexing/retrieving DSpaceObjects in the search core + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public abstract class DSpaceObjectIndexFactoryImpl + extends IndexFactoryImpl implements DSpaceObjectIndexFactory { + + @Override + public SolrInputDocument buildDocument(Context context, T indexableObject) throws SQLException, IOException { + SolrInputDocument doc = super.buildDocument(context, indexableObject); + final DSpaceObject dso = indexableObject.getIndexedObject(); + + // want to be able to search for handle, so use keyword + // (not tokenized, but it is indexed) + if (dso.getHandle() != null) { + // want to be able to search for handle, so use keyword + // (not tokenized, but it is indexed) + doc.addField("handle", dso.getHandle()); + } + + final List locations = getLocations(context, indexableObject); + storeCommunityCollectionLocations(doc, locations); + return doc; + } + + /** + * Add the metadata value of the community/collection to the solr document + * IF needed highlighting is added ! + * + * @param doc the solr document + * @param highlightedMetadataFields the list of metadata fields that CAN be highlighted + * @param toIgnoreMetadataFields the list of metadata fields to skip adding to Solr + * @param metadataField the metadata field added + * @param value the value (can be NULL !) + */ + protected void addContainerMetadataField(SolrInputDocument doc, List highlightedMetadataFields, + List toIgnoreMetadataFields, String metadataField, String value) { + if ((toIgnoreMetadataFields == null || !toIgnoreMetadataFields.contains(metadataField)) + && StringUtils.isNotBlank(value)) { + doc.addField(metadataField, value); + if (highlightedMetadataFields.contains(metadataField)) { + doc.addField(metadataField + "_hl", value); + } + } + } + + @Override + public void storeCommunityCollectionLocations(SolrInputDocument doc, List locations) { + if (locations != null) { + for (String location : locations) { + doc.addField("location", location); + if (location.startsWith("m")) { + doc.addField("location.comm", location.substring(1)); + } else { + doc.addField("location.coll", location.substring(1)); + } + } + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexFactoryImpl.java new file mode 100644 index 0000000000..a32b687026 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexFactoryImpl.java @@ -0,0 +1,193 @@ +/** + * 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.discovery.indexobject; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.Date; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.request.AbstractUpdateRequest; +import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest; +import org.apache.solr.common.SolrInputDocument; +import org.apache.solr.common.params.ModifiableSolrParams; +import org.apache.solr.handler.extraction.ExtractingParams; +import org.dspace.core.Context; +import org.dspace.discovery.FullTextContentStreams; +import org.dspace.discovery.IndexableObject; +import org.dspace.discovery.SearchUtils; +import org.dspace.discovery.SolrSearchCore; +import org.dspace.discovery.SolrServiceIndexPlugin; +import org.dspace.discovery.indexobject.factory.IndexFactory; +import org.dspace.services.factory.DSpaceServicesFactory; +import org.dspace.util.SolrUtils; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Basis factory interface implementation for indexing/retrieving any IndexableObject in the search core + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public abstract class IndexFactoryImpl implements IndexFactory { + + @Autowired + protected List solrServiceIndexPlugins; + @Autowired + protected SolrSearchCore solrSearchCore; + + @Override + public SolrInputDocument buildDocument(Context context, T indexableObject) throws SQLException, IOException { + SolrInputDocument doc = new SolrInputDocument(); + // want to be able to check when last updated + // (not tokenized, but it is indexed) + doc.addField(SearchUtils.LAST_INDEXED_FIELD, SolrUtils.getDateFormatter().format(new Date())); + + // New fields to weaken the dependence on handles, and allow for faster + // list display + doc.addField(SearchUtils.RESOURCE_UNIQUE_ID, indexableObject.getType() + "-" + indexableObject.getID()); + doc.addField(SearchUtils.RESOURCE_TYPE_FIELD, indexableObject.getType()); + doc.addField(SearchUtils.RESOURCE_ID_FIELD, indexableObject.getID().toString()); + + //Do any additional indexing, depends on the plugins + for (SolrServiceIndexPlugin solrServiceIndexPlugin : solrServiceIndexPlugins) { + solrServiceIndexPlugin.additionalIndex(context, indexableObject, doc); + } + + return doc; + } + + @Override + public void writeDocument(Context context, T indexableObject, SolrInputDocument solrInputDocument) + throws SQLException, IOException, SolrServerException { + writeDocument(solrInputDocument, null); + } + + /** + * Write the document to the index under the appropriate unique identifier. + * + * @param doc the solr document to be written to the server + * @param streams list of bitstream content streams DiscoverQueryBuilderTest.java:285 + * @throws IOException A general class of exceptions produced by failed or interrupted I/O operations. + */ + protected void writeDocument(SolrInputDocument doc, FullTextContentStreams streams) + throws IOException, SolrServerException { + final SolrClient solr = solrSearchCore.getSolr(); + if (solr != null) { + if (streams != null && !streams.isEmpty()) { + ContentStreamUpdateRequest req = new ContentStreamUpdateRequest("/update/extract"); + req.addContentStream(streams); + + ModifiableSolrParams params = new ModifiableSolrParams(); + + //req.setParam(ExtractingParams.EXTRACT_ONLY, "true"); + for (String name : doc.getFieldNames()) { + for (Object val : doc.getFieldValues(name)) { + params.add(ExtractingParams.LITERALS_PREFIX + name, val.toString()); + } + } + + req.setParams(params); + req.setParam(ExtractingParams.UNKNOWN_FIELD_PREFIX, "attr_"); + req.setParam(ExtractingParams.MAP_PREFIX + "content", "fulltext"); + req.setParam(ExtractingParams.EXTRACT_FORMAT, "text"); + req.setAction(AbstractUpdateRequest.ACTION.COMMIT, true, true); + req.process(solr); + } else { + solr.add(doc); + } + } + } + + + /** + * Index the provided value as use for a sidebar facet + * @param document The solr document + * @param field The facet field name + * @param authority The authority linked to the field + * @param fvalue The display value for the facet + */ + protected void addFacetIndex(SolrInputDocument document, String field, String authority, String fvalue) { + addFacetIndex(document, field, fvalue, authority, fvalue); + } + + /** + * Index the provided value as use for a sidebar facet + * @param document The solr document + * @param field The facet field name + * @param sortValue The value on which we should sort our facet fields when retrieving + * @param authority The authority linked to the field + * @param fvalue The display value for the facet + */ + protected void addFacetIndex(SolrInputDocument document, String field, String sortValue, String authority, + String fvalue) { + // the separator for the filter can be eventually configured + String separator = DSpaceServicesFactory.getInstance().getConfigurationService() + .getProperty("discovery.solr.facets.split.char"); + if (separator == null) { + separator = SearchUtils.FILTER_SEPARATOR; + } + String acvalue = sortValue + separator + fvalue + SearchUtils.AUTHORITY_SEPARATOR + authority; + document.addField(field + "_filter", acvalue); + // build the solr field used for the keyword search + document.addField(field + "_keyword", fvalue); + // build the solr fields used for the autocomplete + document.addField(field + "_ac", fvalue.toLowerCase() + separator + fvalue); + if (StringUtils.isNotBlank(authority)) { + document.addField(field + "_acid", fvalue.toLowerCase() + separator + fvalue + + SearchUtils.AUTHORITY_SEPARATOR + authority); + document.addField(field + "_authority", authority); + } + } + + /** + * Add the necessary fields to the SOLR document to support a Discover Facet on resourcetypename (archived item, + * workspace item, workflow item, etc) + * + * @param document the solr document + * @param filterValue the filter value (i.e. \n|||\n### + */ + protected void addNamedResourceTypeIndex(SolrInputDocument document, String filterValue) { + + // the separator for the filter can be eventually configured + String separator = DSpaceServicesFactory.getInstance().getConfigurationService() + .getProperty("discovery.solr.facets.split.char"); + if (separator == null) { + separator = SearchUtils.FILTER_SEPARATOR; + } + + // split the authority part from the sort/display + String[] avalues = filterValue.split(SearchUtils.AUTHORITY_SEPARATOR); + + String sortValue = avalues[0]; + String authorityValue = avalues.length == 2 ? avalues[1] : filterValue; + + // get the display value + int idxSeparator = sortValue.indexOf(separator); + String displayValue = idxSeparator != -1 ? sortValue.substring(idxSeparator + separator.length()) + : sortValue; + + addFacetIndex(document, SearchUtils.NAMED_RESOURCE_TYPE, sortValue, authorityValue, displayValue); + } + + @Override + public void delete(T indexableObject) throws IOException, SolrServerException { + solrSearchCore.getSolr().deleteById(indexableObject.getUniqueIndexID()); + } + + @Override + public void delete(String indexableObjectIdentifier) throws IOException, SolrServerException { + solrSearchCore.getSolr().deleteById(indexableObjectIdentifier); + } + + @Override + public void deleteAll() throws IOException, SolrServerException { + solrSearchCore.getSolr().deleteByQuery(SearchUtils.RESOURCE_TYPE_FIELD + ":" + getType()); + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableClaimedTask.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableClaimedTask.java new file mode 100644 index 0000000000..3810b6803f --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableClaimedTask.java @@ -0,0 +1,51 @@ +/** + * 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.discovery.indexobject; + +import org.dspace.discovery.IndexableObject; +import org.dspace.xmlworkflow.storedcomponents.ClaimedTask; + +/** + * ClaimedTask implementation for the IndexableObject + * + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class IndexableClaimedTask implements IndexableObject { + + private ClaimedTask claimedTask; + public static final String TYPE = ClaimedTask.class.getSimpleName(); + + public IndexableClaimedTask(ClaimedTask claimedTask) { + this.claimedTask = claimedTask; + } + + @Override + public ClaimedTask getIndexedObject() { + return claimedTask; + } + + @Override + public void setIndexedObject(ClaimedTask claimedTask) { + this.claimedTask = claimedTask; + } + + @Override + public String getType() { + return TYPE; + } + + @Override + public Integer getID() { + return claimedTask.getID(); + } + + @Override + public String getTypeText() { + return "CLAIMEDTASK"; + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableCollection.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableCollection.java new file mode 100644 index 0000000000..d7a618c3f5 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableCollection.java @@ -0,0 +1,35 @@ +/** + * 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.discovery.indexobject; + +import org.dspace.content.Collection; +import org.dspace.core.Constants; + +/** + * Collection implementation for the IndexableObject + * + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class IndexableCollection extends IndexableDSpaceObject { + + public static final String TYPE = Collection.class.getSimpleName(); + + public IndexableCollection(Collection dso) { + super(dso); + } + + @Override + public String getType() { + return TYPE; + } + + @Override + public String getTypeText() { + return Constants.typeText[Constants.COLLECTION]; + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableCommunity.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableCommunity.java new file mode 100644 index 0000000000..46b927f00f --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableCommunity.java @@ -0,0 +1,34 @@ +/** + * 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.discovery.indexobject; + +import org.dspace.content.Community; +import org.dspace.core.Constants; + +/** + * Community implementation for the IndexableObject + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class IndexableCommunity extends IndexableDSpaceObject { + + public static final String TYPE = Community.class.getSimpleName(); + + public IndexableCommunity(Community dso) { + super(dso); + } + + @Override + public String getType() { + return TYPE; + } + + @Override + public String getTypeText() { + return Constants.typeText[Constants.COMMUNITY]; + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableDSpaceObject.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableDSpaceObject.java new file mode 100644 index 0000000000..7ad82b1a95 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableDSpaceObject.java @@ -0,0 +1,43 @@ +/** + * 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.discovery.indexobject; + +import java.util.UUID; + +import org.dspace.content.DSpaceObject; +import org.dspace.discovery.IndexableObject; + +/** + * DSpaceObject implementation for the IndexableObject, contains methods used by all DSpaceObject methods + * All DSpaceObjects that will be indexed in discovery should inherit from this class & have their own implementation + * + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public abstract class IndexableDSpaceObject implements IndexableObject { + + private T dso; + + public IndexableDSpaceObject(T dso) { + this.dso = dso; + } + + @Override + public T getIndexedObject() { + return dso; + } + + @Override + public void setIndexedObject(T dso) { + this.dso = dso; + } + + @Override + public UUID getID() { + return dso.getID(); + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableInProgressSubmission.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableInProgressSubmission.java new file mode 100644 index 0000000000..cfa27ff814 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableInProgressSubmission.java @@ -0,0 +1,35 @@ +/** + * 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.discovery.indexobject; + +import org.dspace.content.InProgressSubmission; +import org.dspace.discovery.IndexableObject; + +/** + * InProgressSubmission implementation for the IndexableObject + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public abstract class IndexableInProgressSubmission + implements IndexableObject { + + protected T inProgressSubmission; + + public IndexableInProgressSubmission(T inProgressSubmission) { + this.inProgressSubmission = inProgressSubmission; + } + + @Override + public T getIndexedObject() { + return inProgressSubmission; + } + + @Override + public void setIndexedObject(T inProgressSubmission) { + this.inProgressSubmission = inProgressSubmission; + } +} diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableItem.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableItem.java new file mode 100644 index 0000000000..ec67406e8f --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableItem.java @@ -0,0 +1,41 @@ +/** + * 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.discovery.indexobject; + +import java.util.Date; + +import org.dspace.content.Item; +import org.dspace.core.Constants; + +/** + * Item implementation for the IndexableObject + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class IndexableItem extends IndexableDSpaceObject { + + public static final String TYPE = Item.class.getSimpleName(); + + public IndexableItem(Item dso) { + super(dso); + } + + @Override + public Date getLastModified() { + return getIndexedObject().getLastModified(); + } + + @Override + public String getType() { + return TYPE; + } + + @Override + public String getTypeText() { + return Constants.typeText[Constants.ITEM]; + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexablePoolTask.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexablePoolTask.java new file mode 100644 index 0000000000..6eea1f0ebb --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexablePoolTask.java @@ -0,0 +1,51 @@ +/** + * 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.discovery.indexobject; + +import org.dspace.discovery.IndexableObject; +import org.dspace.xmlworkflow.storedcomponents.PoolTask; + +/** + * PoolTask implementation for the IndexableObject + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class IndexablePoolTask implements IndexableObject { + + public static final String TYPE = PoolTask.class.getSimpleName(); + + private PoolTask poolTask; + + public IndexablePoolTask(PoolTask poolTask) { + this.poolTask = poolTask; + } + + @Override + public PoolTask getIndexedObject() { + return poolTask; + } + + @Override + public void setIndexedObject(PoolTask poolTask) { + this.poolTask = poolTask; + } + + @Override + public String getType() { + return TYPE; + } + + @Override + public String getTypeText() { + return "POOLTASK"; + } + + @Override + public Integer getID() { + return poolTask.getID(); + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableWorkflowItem.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableWorkflowItem.java new file mode 100644 index 0000000000..016fec1bbb --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableWorkflowItem.java @@ -0,0 +1,38 @@ +/** + * 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.discovery.indexobject; + +import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; + +/** + * Workflow item implementation for the IndexableObject + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class IndexableWorkflowItem extends IndexableInProgressSubmission { + + public static final String TYPE = XmlWorkflowItem.class.getSimpleName(); + + public IndexableWorkflowItem(XmlWorkflowItem inProgressSubmission) { + super(inProgressSubmission); + } + + @Override + public String getType() { + return TYPE; + } + + @Override + public String getTypeText() { + return "WORKFLOWITEM"; + } + + @Override + public Integer getID() { + return getIndexedObject().getID(); + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableWorkspaceItem.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableWorkspaceItem.java new file mode 100644 index 0000000000..65b05b0d49 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexableWorkspaceItem.java @@ -0,0 +1,38 @@ +/** + * 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.discovery.indexobject; + +import org.dspace.content.WorkspaceItem; + +/** + * Workspace item implementation for the IndexableObject + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class IndexableWorkspaceItem extends IndexableInProgressSubmission { + + public static final String TYPE = WorkspaceItem.class.getSimpleName(); + + public IndexableWorkspaceItem(WorkspaceItem inProgressSubmission) { + super(inProgressSubmission); + } + + @Override + public String getType() { + return TYPE; + } + + @Override + public Integer getID() { + return getIndexedObject().getID(); + } + + @Override + public String getTypeText() { + return "WORKSPACEITEM"; + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/InprogressSubmissionIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/InprogressSubmissionIndexFactoryImpl.java new file mode 100644 index 0000000000..7d8a1f3a48 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/InprogressSubmissionIndexFactoryImpl.java @@ -0,0 +1,63 @@ +/** + * 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.discovery.indexobject; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.List; + +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.indexobject.factory.CollectionIndexFactory; +import org.dspace.discovery.indexobject.factory.InprogressSubmissionIndexFactory; +import org.dspace.discovery.indexobject.factory.ItemIndexFactory; +import org.dspace.eperson.EPerson; +import org.dspace.util.SolrUtils; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Factory implementation for indexing/retrieving InProgressSubmissions in the search core + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public abstract class InprogressSubmissionIndexFactoryImpl + extends IndexFactoryImpl implements InprogressSubmissionIndexFactory { + + @Autowired + protected CollectionIndexFactory indexableCollectionService; + @Autowired + protected ItemIndexFactory indexableItemService; + + + @Override + public SolrInputDocument buildDocument(Context context, T indexableObject) throws SQLException, IOException { + SolrInputDocument doc = super.buildDocument(context, indexableObject); + storeInprogressItemFields(context, doc, indexableObject.getIndexedObject()); + return doc; + } + + @Override + public void storeInprogressItemFields(Context context, SolrInputDocument doc, + InProgressSubmission inProgressSubmission) throws SQLException { + final Item item = inProgressSubmission.getItem(); + doc.addField("lastModified", SolrUtils.getDateFormatter().format(item.getLastModified())); + EPerson submitter = inProgressSubmission.getSubmitter(); + if (submitter != null) { + addFacetIndex(doc, "submitter", submitter.getID().toString(), + submitter.getFullName()); + } + + doc.addField("inprogress.item", new IndexableItem(inProgressSubmission.getItem()).getUniqueIndexID()); + + // get the location string (for searching by collection & community) + List locations = indexableCollectionService. + getCollectionLocations(context, inProgressSubmission.getCollection()); + indexableCollectionService.storeCommunityCollectionLocations(doc, locations); + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java new file mode 100644 index 0000000000..2b96856e72 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java @@ -0,0 +1,684 @@ +/** + * 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.discovery.indexobject; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.time.DateFormatUtils; +import org.apache.logging.log4j.Logger; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.common.SolrInputDocument; +import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.Item; +import org.dspace.content.MetadataField; +import org.dspace.content.MetadataSchema; +import org.dspace.content.MetadataValue; +import org.dspace.content.authority.Choices; +import org.dspace.content.authority.service.ChoiceAuthorityService; +import org.dspace.content.authority.service.MetadataAuthorityService; +import org.dspace.content.service.ItemService; +import org.dspace.core.Context; +import org.dspace.discovery.FullTextContentStreams; +import org.dspace.discovery.SearchUtils; +import org.dspace.discovery.configuration.DiscoveryConfiguration; +import org.dspace.discovery.configuration.DiscoveryConfigurationParameters; +import org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration; +import org.dspace.discovery.configuration.DiscoveryHitHighlightingConfiguration; +import org.dspace.discovery.configuration.DiscoveryMoreLikeThisConfiguration; +import org.dspace.discovery.configuration.DiscoveryRecentSubmissionsConfiguration; +import org.dspace.discovery.configuration.DiscoverySearchFilter; +import org.dspace.discovery.configuration.DiscoverySearchFilterFacet; +import org.dspace.discovery.configuration.DiscoverySortConfiguration; +import org.dspace.discovery.configuration.DiscoverySortFieldConfiguration; +import org.dspace.discovery.configuration.HierarchicalSidebarFacetConfiguration; +import org.dspace.discovery.indexobject.factory.ItemIndexFactory; +import org.dspace.eperson.EPerson; +import org.dspace.handle.service.HandleService; +import org.dspace.services.factory.DSpaceServicesFactory; +import org.dspace.util.MultiFormatDateParser; +import org.dspace.util.SolrUtils; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Factory implementation for indexing/retrieving items in the search core + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class ItemIndexFactoryImpl extends DSpaceObjectIndexFactoryImpl + implements ItemIndexFactory { + + private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(ItemIndexFactoryImpl.class); + public static final String VARIANTS_STORE_SEPARATOR = "###"; + public static final String STORE_SEPARATOR = "\n|||\n"; + + + @Autowired + protected HandleService handleService; + @Autowired + protected ItemService itemService; + @Autowired(required = true) + protected ChoiceAuthorityService choiceAuthorityService; + @Autowired + protected MetadataAuthorityService metadataAuthorityService; + + + @Override + public Iterator findAll(Context context) throws SQLException { + Iterator items = itemService.findAllUnfiltered(context); + return new Iterator() { + @Override + public boolean hasNext() { + return items.hasNext(); + } + + @Override + public IndexableItem next() { + return new IndexableItem(items.next()); + } + }; + } + + @Override + public String getType() { + return IndexableItem.TYPE; + } + + /** + * Build a Solr document for a DSpace Item and write the index + * + * @param context Users Context + * @param indexableItem The IndexableItem Item to be indexed + * @throws SQLException if database error + * @throws IOException if IO error + */ + @Override + public SolrInputDocument buildDocument(Context context, IndexableItem indexableItem) + throws SQLException, IOException { + SolrInputDocument doc = super.buildDocument(context, indexableItem); + + final Item item = indexableItem.getIndexedObject(); + + doc.addField("archived", item.isArchived()); + doc.addField("withdrawn", item.isWithdrawn()); + doc.addField("discoverable", item.isDiscoverable()); + doc.addField("lastModified", SolrUtils.getDateFormatter().format(item.getLastModified())); + + EPerson submitter = item.getSubmitter(); + if (submitter != null) { + addFacetIndex(doc, "submitter", submitter.getID().toString(), + submitter.getFullName()); + } + + List discoveryConfigurations = SearchUtils.getAllDiscoveryConfigurations(item); + addDiscoveryFields(doc, context, indexableItem.getIndexedObject(), discoveryConfigurations); + + //mandatory facet to show status on mydspace + final String typeText = StringUtils.deleteWhitespace(indexableItem.getTypeText().toLowerCase()); + String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService().getProperty( + "discovery.facet.namedtype." + typeText, + typeText + SearchUtils.AUTHORITY_SEPARATOR + typeText); + if (StringUtils.isNotBlank(acvalue)) { + addNamedResourceTypeIndex(doc, acvalue); + } + + // write the index and close the inputstreamreaders + try { + log.info("Wrote Item: " + item.getID() + " to Index"); + } catch (RuntimeException e) { + log.error("Error while writing item to discovery index: " + item.getID() + " message:" + + e.getMessage(), e); + } + return doc; + } + + @Override + public void addDiscoveryFields(SolrInputDocument doc, Context context, Item item, + List discoveryConfigurations) + throws SQLException, IOException { + //Keep a list of our sort values which we added, sort values can only be added once + List sortFieldsAdded = new ArrayList<>(); + Map> searchFilters = null; + Set hitHighlightingFields = new HashSet<>(); + try { + //A map used to save each sidebarFacet config by the metadata fields + searchFilters = new HashMap<>(); + Map sortFields = new HashMap<>(); + Map recentSubmissionsConfigurationMap = new + HashMap<>(); + Set moreLikeThisFields = new HashSet<>(); + // some configuration are returned multiple times, skip them to save CPU cycles + Set appliedConf = new HashSet<>(); + // it is common to have search filter shared between multiple configurations + Set appliedDiscoverySearchFilter = new HashSet<>(); + + for (DiscoveryConfiguration discoveryConfiguration : discoveryConfigurations) { + if (appliedConf.contains(discoveryConfiguration.getId())) { + continue; + } else { + appliedConf.add(discoveryConfiguration.getId()); + } + for (int i = 0; i < discoveryConfiguration.getSearchFilters().size(); i++) { + if (appliedDiscoverySearchFilter + .contains(discoveryConfiguration.getSearchFilters().get(i).getIndexFieldName())) { + continue; + } else { + appliedDiscoverySearchFilter + .add(discoveryConfiguration.getSearchFilters().get(i).getIndexFieldName()); + } + List metadataValueList = new LinkedList<>(); + boolean shouldExposeMinMax = false; + DiscoverySearchFilter discoverySearchFilter = discoveryConfiguration.getSearchFilters().get(i); + if (StringUtils.equalsIgnoreCase(discoverySearchFilter.getFilterType(), "facet")) { + if (((DiscoverySearchFilterFacet) discoverySearchFilter).exposeMinAndMaxValue()) { + shouldExposeMinMax = true; + } + } + for (int j = 0; j < discoverySearchFilter.getMetadataFields().size(); j++) { + String metadataField = discoverySearchFilter.getMetadataFields().get(j); + List resultingList; + if (searchFilters.get(metadataField) != null) { + resultingList = searchFilters.get(metadataField); + } else { + //New metadata field, create a new list for it + resultingList = new ArrayList<>(); + } + + + if (shouldExposeMinMax) { + String[] splittedMetadataField = metadataField.split("\\."); + String schema = splittedMetadataField[0]; + String element = splittedMetadataField.length > 1 ? splittedMetadataField[1] : null; + String qualifier = splittedMetadataField.length > 2 ? splittedMetadataField[2] : null; + + metadataValueList.addAll(itemService.getMetadata(item, schema, + element, qualifier, Item.ANY)); + + } + + resultingList.add(discoverySearchFilter); + + searchFilters.put(metadataField, resultingList); + } + + if (!metadataValueList.isEmpty() && shouldExposeMinMax) { + metadataValueList.sort((mdv1, mdv2) -> mdv1.getValue().compareTo(mdv2.getValue())); + MetadataValue firstMetadataValue = metadataValueList.get(0); + MetadataValue lastMetadataValue = metadataValueList.get(metadataValueList.size() - 1); + + doc.addField(discoverySearchFilter.getIndexFieldName() + "_min", firstMetadataValue.getValue()); + doc.addField(discoverySearchFilter.getIndexFieldName() + + "_min_sort", firstMetadataValue.getValue()); + doc.addField(discoverySearchFilter.getIndexFieldName() + "_max", lastMetadataValue.getValue()); + doc.addField(discoverySearchFilter.getIndexFieldName() + + "_max_sort", lastMetadataValue.getValue()); + + } + } + + DiscoverySortConfiguration sortConfiguration = discoveryConfiguration.getSearchSortConfiguration(); + if (sortConfiguration != null) { + for (DiscoverySortFieldConfiguration discoverySortConfiguration : sortConfiguration + .getSortFields()) { + sortFields.put(discoverySortConfiguration.getMetadataField(), discoverySortConfiguration); + } + } + + DiscoveryRecentSubmissionsConfiguration recentSubmissionConfiguration = discoveryConfiguration + .getRecentSubmissionConfiguration(); + if (recentSubmissionConfiguration != null) { + recentSubmissionsConfigurationMap + .put(recentSubmissionConfiguration.getMetadataSortField(), recentSubmissionConfiguration); + } + + DiscoveryHitHighlightingConfiguration hitHighlightingConfiguration = discoveryConfiguration + .getHitHighlightingConfiguration(); + if (hitHighlightingConfiguration != null) { + List fieldConfigurations = hitHighlightingConfiguration + .getMetadataFields(); + for (DiscoveryHitHighlightFieldConfiguration fieldConfiguration : fieldConfigurations) { + hitHighlightingFields.add(fieldConfiguration.getField()); + } + } + DiscoveryMoreLikeThisConfiguration moreLikeThisConfiguration = discoveryConfiguration + .getMoreLikeThisConfiguration(); + if (moreLikeThisConfiguration != null) { + for (String metadataField : moreLikeThisConfiguration.getSimilarityMetadataFields()) { + moreLikeThisFields.add(metadataField); + } + } + } + + + List toProjectionFields = new ArrayList<>(); + String[] projectionFields = DSpaceServicesFactory.getInstance().getConfigurationService() + .getArrayProperty("discovery.index.projection"); + if (projectionFields != null) { + for (String field : projectionFields) { + toProjectionFields.add(field.trim()); + } + } + + List toIgnoreMetadataFields = SearchUtils.getIgnoredMetadataFields(item.getType()); + List mydc = itemService.getMetadata(item, Item.ANY, Item.ANY, Item.ANY, Item.ANY); + for (MetadataValue meta : mydc) { + MetadataField metadataField = meta.getMetadataField(); + MetadataSchema metadataSchema = metadataField.getMetadataSchema(); + String field = metadataSchema.getName() + "." + metadataField.getElement(); + String unqualifiedField = field; + + String value = meta.getValue(); + + if (value == null) { + continue; + } + + if (metadataField.getQualifier() != null && !metadataField.getQualifier().trim().equals("")) { + field += "." + metadataField.getQualifier(); + } + + //We are not indexing provenance, this is useless + if (toIgnoreMetadataFields != null && (toIgnoreMetadataFields.contains(field) || toIgnoreMetadataFields + .contains(unqualifiedField + "." + Item.ANY))) { + continue; + } + + String authority = null; + String preferedLabel = null; + List variants = null; + boolean isAuthorityControlled = metadataAuthorityService + .isAuthorityControlled(metadataField); + + int minConfidence = isAuthorityControlled ? metadataAuthorityService + .getMinConfidence(metadataField) : Choices.CF_ACCEPTED; + + if (isAuthorityControlled && meta.getAuthority() != null + && meta.getConfidence() >= minConfidence) { + boolean ignoreAuthority = + DSpaceServicesFactory + .getInstance() + .getConfigurationService() + .getPropertyAsType("discovery.index.authority.ignore." + field, + DSpaceServicesFactory + .getInstance() + .getConfigurationService() + .getPropertyAsType("discovery.index.authority.ignore", + new Boolean(false)), + true); + if (!ignoreAuthority) { + authority = meta.getAuthority(); + + boolean ignorePrefered = + DSpaceServicesFactory + .getInstance() + .getConfigurationService() + .getPropertyAsType("discovery.index.authority.ignore-prefered." + field, + DSpaceServicesFactory + .getInstance() + .getConfigurationService() + .getPropertyAsType("discovery.index.authority.ignore-prefered", + new Boolean(false)), + true); + if (!ignorePrefered) { + + preferedLabel = choiceAuthorityService + .getLabel(meta, meta.getLanguage()); + } + + boolean ignoreVariants = + DSpaceServicesFactory + .getInstance() + .getConfigurationService() + .getPropertyAsType("discovery.index.authority.ignore-variants." + field, + DSpaceServicesFactory + .getInstance() + .getConfigurationService() + .getPropertyAsType("discovery.index.authority.ignore-variants", + new Boolean(false)), + true); + if (!ignoreVariants) { + variants = choiceAuthorityService + .getVariants(meta); + } + + } + } + + if ((searchFilters.get(field) != null || searchFilters + .get(unqualifiedField + "." + Item.ANY) != null)) { + List searchFilterConfigs = searchFilters.get(field); + if (searchFilterConfigs == null) { + searchFilterConfigs = searchFilters.get(unqualifiedField + "." + Item.ANY); + } + + for (DiscoverySearchFilter searchFilter : searchFilterConfigs) { + Date date = null; + String separator = DSpaceServicesFactory.getInstance().getConfigurationService() + .getProperty("discovery.solr.facets.split.char"); + if (separator == null) { + separator = SearchUtils.FILTER_SEPARATOR; + } + if (searchFilter.getType().equals(DiscoveryConfigurationParameters.TYPE_DATE)) { + //For our search filters that are dates we format them properly + date = MultiFormatDateParser.parse(value); + if (date != null) { + //TODO: make this date format configurable ! + value = DateFormatUtils.formatUTC(date, "yyyy-MM-dd"); + } + } + doc.addField(searchFilter.getIndexFieldName(), value); + doc.addField(searchFilter.getIndexFieldName() + "_keyword", value); + + if (authority != null && preferedLabel == null) { + doc.addField(searchFilter.getIndexFieldName() + + "_keyword", value + SearchUtils.AUTHORITY_SEPARATOR + + authority); + doc.addField(searchFilter.getIndexFieldName() + + "_authority", authority); + doc.addField(searchFilter.getIndexFieldName() + + "_acid", value.toLowerCase() + + separator + value + + SearchUtils.AUTHORITY_SEPARATOR + authority); + } + + if (preferedLabel != null) { + doc.addField(searchFilter.getIndexFieldName(), + preferedLabel); + doc.addField(searchFilter.getIndexFieldName() + + "_keyword", preferedLabel); + doc.addField(searchFilter.getIndexFieldName() + + "_keyword", preferedLabel + + SearchUtils.AUTHORITY_SEPARATOR + authority); + doc.addField(searchFilter.getIndexFieldName() + + "_authority", authority); + doc.addField(searchFilter.getIndexFieldName() + + "_acid", preferedLabel.toLowerCase() + + separator + preferedLabel + + SearchUtils.AUTHORITY_SEPARATOR + authority); + } + if (variants != null) { + for (String var : variants) { + doc.addField(searchFilter.getIndexFieldName() + "_keyword", var); + doc.addField(searchFilter.getIndexFieldName() + + "_acid", var.toLowerCase() + + separator + var + + SearchUtils.AUTHORITY_SEPARATOR + authority); + } + } + + //Add a dynamic fields for auto complete in search + doc.addField(searchFilter.getIndexFieldName() + "_ac", + value.toLowerCase() + separator + value); + if (preferedLabel != null) { + doc.addField(searchFilter.getIndexFieldName() + + "_ac", preferedLabel.toLowerCase() + + separator + preferedLabel); + } + if (variants != null) { + for (String var : variants) { + doc.addField(searchFilter.getIndexFieldName() + + "_ac", var.toLowerCase() + separator + + var); + } + } + + if (searchFilter.getFilterType().equals(DiscoverySearchFilterFacet.FILTER_TYPE_FACET)) { + if (searchFilter.getType().equals(DiscoveryConfigurationParameters.TYPE_TEXT)) { + //Add a special filter + //We use a separator to split up the lowercase and regular case, this is needed to + // get our filters in regular case + //Solr has issues with facet prefix and cases + if (authority != null) { + String facetValue = preferedLabel != null ? preferedLabel : value; + doc.addField(searchFilter.getIndexFieldName() + "_filter", facetValue + .toLowerCase() + separator + facetValue + SearchUtils.AUTHORITY_SEPARATOR + + authority); + } else { + doc.addField(searchFilter.getIndexFieldName() + "_filter", + value.toLowerCase() + separator + value); + } + } else if (searchFilter.getType().equals(DiscoveryConfigurationParameters.TYPE_DATE)) { + if (date != null) { + String indexField = searchFilter.getIndexFieldName() + ".year"; + String yearUTC = DateFormatUtils.formatUTC(date, "yyyy"); + doc.addField(searchFilter.getIndexFieldName() + "_keyword", yearUTC); + // add the year to the autocomplete index + doc.addField(searchFilter.getIndexFieldName() + "_ac", yearUTC); + doc.addField(indexField, yearUTC); + + if (yearUTC.startsWith("0")) { + doc.addField( + searchFilter.getIndexFieldName() + + "_keyword", + yearUTC.replaceFirst("0*", "")); + // add date without starting zeros for autocomplete e filtering + doc.addField( + searchFilter.getIndexFieldName() + + "_ac", + yearUTC.replaceFirst("0*", "")); + doc.addField( + searchFilter.getIndexFieldName() + + "_ac", + value.replaceFirst("0*", "")); + doc.addField( + searchFilter.getIndexFieldName() + + "_keyword", + value.replaceFirst("0*", "")); + } + + //Also save a sort value of this year, this is required for determining the upper + // & lower bound year of our facet + if (doc.getField(indexField + "_sort") == null) { + //We can only add one year so take the first one + doc.addField(indexField + "_sort", yearUTC); + } + } + } else if (searchFilter.getType() + .equals(DiscoveryConfigurationParameters.TYPE_HIERARCHICAL)) { + HierarchicalSidebarFacetConfiguration hierarchicalSidebarFacetConfiguration = + (HierarchicalSidebarFacetConfiguration) searchFilter; + String[] subValues = value.split(hierarchicalSidebarFacetConfiguration.getSplitter()); + if (hierarchicalSidebarFacetConfiguration + .isSkipFirstNodeLevel() && 1 < subValues.length) { + //Remove the first element of our array + subValues = (String[]) ArrayUtils.subarray(subValues, 1, subValues.length); + } + for (int i = 0; i < subValues.length; i++) { + StringBuilder valueBuilder = new StringBuilder(); + for (int j = 0; j <= i; j++) { + valueBuilder.append(subValues[j]); + if (j < i) { + valueBuilder.append(hierarchicalSidebarFacetConfiguration.getSplitter()); + } + } + + String indexValue = valueBuilder.toString().trim(); + doc.addField(searchFilter.getIndexFieldName() + "_tax_" + i + "_filter", + indexValue.toLowerCase() + separator + indexValue); + //We add the field x times that it has occurred + for (int j = i; j < subValues.length; j++) { + doc.addField(searchFilter.getIndexFieldName() + "_filter", + indexValue.toLowerCase() + separator + indexValue); + doc.addField(searchFilter.getIndexFieldName() + "_keyword", indexValue); + } + } + } + } + } + } + + if ((sortFields.get(field) != null || recentSubmissionsConfigurationMap + .get(field) != null) && !sortFieldsAdded.contains(field)) { + //Only add sort value once + String type; + if (sortFields.get(field) != null) { + type = sortFields.get(field).getType(); + } else { + type = recentSubmissionsConfigurationMap.get(field).getType(); + } + + if (type.equals(DiscoveryConfigurationParameters.TYPE_DATE)) { + Date date = MultiFormatDateParser.parse(value); + if (date != null) { + String stringDate = SolrUtils.getDateFormatter().format(date); + doc.addField(field + "_dt", stringDate); + } else { + log.warn("Error while indexing sort date field, item: " + item + .getHandle() + " metadata field: " + field + " date value: " + date); + } + } else { + doc.addField(field + "_sort", value); + } + sortFieldsAdded.add(field); + } + + if (hitHighlightingFields.contains(field) || hitHighlightingFields + .contains("*") || hitHighlightingFields.contains(unqualifiedField + "." + Item.ANY)) { + if (authority != null) { + doc.addField(field + "_hl", value + SearchUtils.AUTHORITY_SEPARATOR + authority); + } else { + doc.addField(field + "_hl", value); + } + } + + if (moreLikeThisFields.contains(field) || moreLikeThisFields + .contains(unqualifiedField + "." + Item.ANY)) { + doc.addField(field + "_mlt", value); + } + + doc.addField(field, value); + if (authority != null) { + doc.addField(field + "_authority", authority); + } + if (toProjectionFields.contains(field) || toProjectionFields + .contains(unqualifiedField + "." + Item.ANY)) { + StringBuffer variantsToStore = new StringBuffer(); + if (variants != null) { + for (String var : variants) { + variantsToStore.append(VARIANTS_STORE_SEPARATOR); + variantsToStore.append(var); + } + } + doc.addField( + field + "_stored", + value + STORE_SEPARATOR + preferedLabel + + STORE_SEPARATOR + + (variantsToStore.length() > VARIANTS_STORE_SEPARATOR + .length() ? variantsToStore + .substring(VARIANTS_STORE_SEPARATOR + .length()) : "null") + + STORE_SEPARATOR + authority + + STORE_SEPARATOR + meta.getLanguage()); + } + + if (meta.getLanguage() != null && !meta.getLanguage().trim().equals("")) { + String langField = field + "." + meta.getLanguage(); + doc.addField(langField, value); + } + } + + } catch (Exception e) { + log.error(e.getMessage(), e); + } + + + log.debug(" Added Metadata"); + + try { + + List values = itemService.getMetadataByMetadataString(item, "dc.relation.ispartof"); + + if (values != null && values.size() > 0 && values.get(0) != null && values.get(0).getValue() != null) { + // group on parent + String handlePrefix = handleService.getCanonicalPrefix(); + + doc.addField("publication_grp", values.get(0).getValue().replaceFirst(handlePrefix, "")); + + } else { + // group on self + doc.addField("publication_grp", item.getHandle()); + } + + } catch (Exception e) { + log.error(e.getMessage(), e); + } + + + log.debug(" Added Grouping"); + } + + @Override + public void writeDocument(Context context, IndexableItem indexableObject, SolrInputDocument solrInputDocument) + throws SQLException, IOException, SolrServerException { + writeDocument(solrInputDocument, new FullTextContentStreams(context, indexableObject.getIndexedObject())); + } + + @Override + public List getLocations(Context context, IndexableItem indexableDSpaceObject) + throws SQLException { + final Item item = indexableDSpaceObject.getIndexedObject(); + List locations = new ArrayList<>(); + + // build list of community ids + List communities = itemService.getCommunities(context, item); + + // build list of collection ids + List collections = item.getCollections(); + + // now put those into strings + int i = 0; + + for (i = 0; i < communities.size(); i++) { + locations.add("m" + communities.get(i).getID()); + } + + for (i = 0; i < collections.size(); i++) { + locations.add("l" + collections.get(i).getID()); + } + + return locations; + } + + @Override + public void delete(IndexableItem indexableObject) throws IOException, SolrServerException { + super.delete(indexableObject); + deleteInProgressData(indexableObject.getUniqueIndexID()); + } + + private void deleteInProgressData(String indexableObjectIdentifier) throws SolrServerException, IOException { + // Also delete any possible workflowItem / workspaceItem / tasks related to this item + String query = "inprogress.item:\"" + indexableObjectIdentifier + "\""; + log.debug("Try to delete all in progress submission [DELETEBYQUERY]:" + query); + solrSearchCore.getSolr().deleteByQuery(query); + } + + @Override + public void delete(String indexableObjectIdentifier) throws IOException, SolrServerException { + super.delete(indexableObjectIdentifier); + deleteInProgressData(indexableObjectIdentifier); + } + + @Override + public Optional findIndexableObject(Context context, String id) throws SQLException { + final Item item = itemService.find(context, UUID.fromString(id)); + return item == null ? Optional.empty() : Optional.of(new IndexableItem(item)); + } +} diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/PoolTaskIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/PoolTaskIndexFactoryImpl.java new file mode 100644 index 0000000000..5c9f8baf9c --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/PoolTaskIndexFactoryImpl.java @@ -0,0 +1,90 @@ +/** + * 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.discovery.indexobject; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.Iterator; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +import org.apache.solr.common.SolrInputDocument; +import org.dspace.core.Context; +import org.dspace.discovery.indexobject.factory.PoolTaskIndexFactory; +import org.dspace.discovery.indexobject.factory.WorkflowItemIndexFactory; +import org.dspace.services.factory.DSpaceServicesFactory; +import org.dspace.xmlworkflow.storedcomponents.PoolTask; +import org.dspace.xmlworkflow.storedcomponents.service.PoolTaskService; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Factory implementation for indexing/retrieving pooled tasks in the search core + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class PoolTaskIndexFactoryImpl extends IndexFactoryImpl + implements PoolTaskIndexFactory { + + @Autowired + protected PoolTaskService poolTaskService; + + @Autowired + WorkflowItemIndexFactory indexableWorkflowItemService; + + @Override + public Iterator findAll(Context context) throws SQLException { + final Iterator pooledTasks = poolTaskService.findAll(context).iterator(); + return new Iterator() { + @Override + public boolean hasNext() { + return pooledTasks.hasNext(); + } + + @Override + public IndexablePoolTask next() { + return new IndexablePoolTask(pooledTasks.next()); + } + }; + } + + @Override + public String getType() { + return IndexablePoolTask.TYPE; + } + + @Override + public SolrInputDocument buildDocument(Context context, IndexablePoolTask indexableObject) + throws SQLException, IOException { + final SolrInputDocument doc = super.buildDocument(context, indexableObject); + final PoolTask poolTask = indexableObject.getIndexedObject(); + indexableWorkflowItemService.storeInprogressItemFields(context, doc, poolTask.getWorkflowItem()); + + addFacetIndex(doc, "action", poolTask.getActionID(), poolTask.getActionID()); + addFacetIndex(doc, "step", poolTask.getStepID(), poolTask.getStepID()); + if (poolTask.getEperson() != null) { + doc.addField("taskfor", "e" + poolTask.getEperson().getID().toString()); + } + if (poolTask.getGroup() != null) { + doc.addField("taskfor", "g" + poolTask.getGroup().getID().toString()); + } + + String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService() + .getProperty("discovery.facet.namedtype.workflow.pooled"); + if (StringUtils.isBlank(acvalue)) { + acvalue = indexableObject.getTypeText(); + } + addNamedResourceTypeIndex(doc, acvalue); + + return doc; + } + + @Override + public Optional findIndexableObject(Context context, String id) throws SQLException { + final PoolTask poolTask = poolTaskService.find(context, Integer.parseInt(id)); + return poolTask == null ? Optional.empty() : Optional.of(new IndexablePoolTask(poolTask)); + } +} diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/WorkflowItemIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/WorkflowItemIndexFactoryImpl.java new file mode 100644 index 0000000000..b0800ecee8 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/WorkflowItemIndexFactoryImpl.java @@ -0,0 +1,85 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.discovery.indexobject; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +import org.apache.solr.common.SolrInputDocument; +import org.dspace.content.Item; +import org.dspace.core.Context; +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.XmlWorkflowItem; +import org.dspace.xmlworkflow.storedcomponents.service.XmlWorkflowItemService; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Factory implementation for indexing/retrieving workflow items in the search core + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class WorkflowItemIndexFactoryImpl extends InprogressSubmissionIndexFactoryImpl + implements WorkflowItemIndexFactory { + + @Autowired + protected XmlWorkflowItemService workflowItemService; + + @Override + public Iterator findAll(Context context) throws SQLException { + final Iterator workflowItems = workflowItemService.findAll(context).iterator(); + + return new Iterator() { + @Override + public boolean hasNext() { + return workflowItems.hasNext(); + } + + @Override + public IndexableWorkflowItem next() { + return new IndexableWorkflowItem(workflowItems.next()); + } + }; + } + + @Override + public String getType() { + return IndexableWorkflowItem.TYPE; + } + + @Override + public SolrInputDocument buildDocument(Context context, IndexableWorkflowItem indexableObject) + throws SQLException, IOException { + final SolrInputDocument doc = super.buildDocument(context, indexableObject); + final XmlWorkflowItem workflowItem = indexableObject.getIndexedObject(); + final Item item = workflowItem.getItem(); + List discoveryConfigurations = SearchUtils + .getAllDiscoveryConfigurations(workflowItem); + indexableItemService.addDiscoveryFields(doc, context, item, discoveryConfigurations); + + String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService() + .getProperty("discovery.facet.namedtype.workflow.item"); + if (StringUtils.isBlank(acvalue)) { + acvalue = indexableObject.getTypeText(); + } + addNamedResourceTypeIndex(doc, acvalue); + + return doc; + } + + @Override + public Optional findIndexableObject(Context context, String id) throws SQLException { + final XmlWorkflowItem xmlWorkflowItem = workflowItemService.find(context, Integer.parseInt(id)); + return xmlWorkflowItem == null ? Optional.empty() : Optional.of(new IndexableWorkflowItem(xmlWorkflowItem)); + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/WorkspaceItemIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/WorkspaceItemIndexFactoryImpl.java new file mode 100644 index 0000000000..5ecc5f3528 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/WorkspaceItemIndexFactoryImpl.java @@ -0,0 +1,84 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.discovery.indexobject; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +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; + +/** + * Factory implementation for indexing/retrieving workspace items in the search core + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class WorkspaceItemIndexFactoryImpl extends InprogressSubmissionIndexFactoryImpl + implements WorkspaceItemIndexFactory { + + @Autowired + protected WorkspaceItemService workspaceItemService; + + @Override + public Iterator findAll(Context context) throws SQLException { + final Iterator workspaceItems = workspaceItemService.findAll(context).iterator(); + + return new Iterator() { + @Override + public boolean hasNext() { + return workspaceItems.hasNext(); + } + + @Override + public IndexableWorkspaceItem next() { + return new IndexableWorkspaceItem(workspaceItems.next()); + } + }; + } + + @Override + public String getType() { + return IndexableWorkspaceItem.TYPE; + } + + @Override + public SolrInputDocument buildDocument(Context context, IndexableWorkspaceItem indexableObject) + throws SQLException, IOException { + final SolrInputDocument doc = super.buildDocument(context, indexableObject); + + String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService() + .getProperty("discovery.facet.namedtype.workspace"); + if (StringUtils.isBlank(acvalue)) { + acvalue = indexableObject.getTypeText(); + } + addNamedResourceTypeIndex(doc, acvalue); + final WorkspaceItem inProgressSubmission = indexableObject.getIndexedObject(); + + List discoveryConfigurations = SearchUtils + .getAllDiscoveryConfigurations(inProgressSubmission); + indexableItemService.addDiscoveryFields(doc, context, inProgressSubmission.getItem(), discoveryConfigurations); + + return doc; + } + + @Override + public Optional findIndexableObject(Context context, String id) throws SQLException { + final WorkspaceItem workspaceItem = workspaceItemService.find(context, Integer.parseInt(id)); + return workspaceItem == null ? Optional.empty() : Optional.of(new IndexableWorkspaceItem(workspaceItem)); + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/ClaimedTaskIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/ClaimedTaskIndexFactory.java new file mode 100644 index 0000000000..e5d8b1ba0d --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/ClaimedTaskIndexFactory.java @@ -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.discovery.indexobject.factory; + +import org.dspace.discovery.indexobject.IndexableClaimedTask; + +/** + * Factory interface for indexing/retrieving claimed tasks in the search core + * + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public interface ClaimedTaskIndexFactory extends IndexFactory { +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/CollectionIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/CollectionIndexFactory.java new file mode 100644 index 0000000000..52c21017f5 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/CollectionIndexFactory.java @@ -0,0 +1,32 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.discovery.indexobject.factory; + +import java.sql.SQLException; +import java.util.List; + +import org.dspace.content.Collection; +import org.dspace.core.Context; +import org.dspace.discovery.indexobject.IndexableCollection; + +/** + * Factory interface for indexing/retrieving collections in the search core + * + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public interface CollectionIndexFactory extends DSpaceObjectIndexFactory { + + /** + * Return a list of the identifiers of the owning communities from the provided collection prepended by "m" + * @param context DSpace context object + * @param collection DSpace collection + * @return A list of community identifiers with "m" prepended to every one + * @throws SQLException If database error + */ + public List getCollectionLocations(Context context, Collection collection) throws SQLException; +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/CommunityIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/CommunityIndexFactory.java new file mode 100644 index 0000000000..a7c72dc1d8 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/CommunityIndexFactory.java @@ -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.discovery.indexobject.factory; + +import org.dspace.discovery.indexobject.IndexableCommunity; + +/** + * Factory interface for indexing/retrieving communities in the search core + * + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public interface CommunityIndexFactory extends DSpaceObjectIndexFactory { +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/DSpaceObjectIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/DSpaceObjectIndexFactory.java new file mode 100644 index 0000000000..0321a5b69e --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/DSpaceObjectIndexFactory.java @@ -0,0 +1,40 @@ +/** + * 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.discovery.indexobject.factory; + +import java.sql.SQLException; +import java.util.List; + +import org.apache.solr.common.SolrInputDocument; +import org.dspace.core.Context; +import org.dspace.discovery.indexobject.IndexableDSpaceObject; + +/** + * Factory interface for indexing/retrieving DSpaceObjects in the search core + * + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public interface DSpaceObjectIndexFactory extends IndexFactory { + + + /** + * Return a list of the identifiers from the parents for the provided IndexableObject, + * communities will be prepended by "m", collections b "c" + * @param context DSpace context object + * @return A list of community identifiers with "m" prepended to every one + * @throws SQLException If database error + */ + List getLocations(Context context, T indexableDSpaceObject) throws SQLException; + + /** + * Store the provided locations in the solr document + * @param doc The solr input document + * @param locations The locations to be stored + */ + void storeCommunityCollectionLocations(SolrInputDocument doc, List locations); +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexFactory.java new file mode 100644 index 0000000000..87147b5383 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexFactory.java @@ -0,0 +1,91 @@ +/** + * 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.discovery.indexobject.factory; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.Iterator; +import java.util.Optional; + +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.common.SolrInputDocument; +import org.dspace.core.Context; +import org.dspace.discovery.IndexableObject; + +/** + * Basis factory interface for indexing/retrieving any IndexableObject in the search core + * + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public interface IndexFactory { + + /** + * Retrieve all instances of a certain indexable object type + * @param context DSpace context object + * @return An iterator containing all the objects to be indexed for the indexable object + * @throws SQLException If database error + */ + Iterator findAll(Context context) throws SQLException; + + /** + * Return the type of the indexable object + * @return a string containing the type + */ + String getType(); + + /** + * Create solr document with all the shared fields initialized. + * @param indexableObject the indexableObject that we want to index + * @return initialized solr document + */ + SolrInputDocument buildDocument(Context context, T indexableObject) throws SQLException, IOException; + + /** + * Write the provided document to the solr core + * @param context DSpace context object + * @param indexableObject The indexable object that we want to store in the search core + * @param solrInputDocument Solr input document which will be written to our discovery search core + * @throws SQLException If database error + * @throws IOException If IO error + * @throws SolrServerException If the solr document could not be written to the search core + */ + void writeDocument(Context context, T indexableObject, SolrInputDocument solrInputDocument) + throws SQLException, IOException, SolrServerException; + + /** + * Remove the provided indexable object from the solr core + * @param indexableObject The indexable object that we want to remove from the search core + * @throws IOException If IO error + * @throws SolrServerException If the solr document could not be removed to the search core + */ + void delete(T indexableObject) throws IOException, SolrServerException; + + /** + * Remove the provided indexable object from the solr core + * @param indexableObjectIdentifier The identifier that we want to remove from the search core + * @throws IOException If IO error + * @throws SolrServerException If the solr document could not be removed to the search core + */ + void delete(String indexableObjectIdentifier) throws IOException, SolrServerException; + + /** + * Remove all indexable objects of the implementing type from the search core + * @throws IOException If IO error + * @throws SolrServerException If the solr document could not be removed to the search core + */ + void deleteAll() throws IOException, SolrServerException; + + /** + * Retrieve a single indexable object using the provided identifier + * @param context DSpace context object + * @param id The identifier for which we want to retrieve our indexable object + * @return An indexable object + * @throws SQLException If database error + */ + Optional findIndexableObject(Context context, String id) throws SQLException; +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexObjectFactoryFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexObjectFactoryFactory.java new file mode 100644 index 0000000000..387e5b6d0e --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexObjectFactoryFactory.java @@ -0,0 +1,159 @@ +/** + * 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.discovery.indexobject.factory; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.content.WorkspaceItem; +import org.dspace.content.service.WorkspaceItemService; +import org.dspace.core.Constants; +import org.dspace.core.Context; +import org.dspace.discovery.IndexableObject; +import org.dspace.discovery.indexobject.IndexableClaimedTask; +import org.dspace.discovery.indexobject.IndexableCollection; +import org.dspace.discovery.indexobject.IndexableCommunity; +import org.dspace.discovery.indexobject.IndexableItem; +import org.dspace.discovery.indexobject.IndexablePoolTask; +import org.dspace.discovery.indexobject.IndexableWorkflowItem; +import org.dspace.discovery.indexobject.IndexableWorkspaceItem; +import org.dspace.services.factory.DSpaceServicesFactory; +import org.dspace.xmlworkflow.storedcomponents.ClaimedTask; +import org.dspace.xmlworkflow.storedcomponents.PoolTask; +import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; +import org.dspace.xmlworkflow.storedcomponents.service.ClaimedTaskService; +import org.dspace.xmlworkflow.storedcomponents.service.PoolTaskService; +import org.dspace.xmlworkflow.storedcomponents.service.XmlWorkflowItemService; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Abstract factory to get the IndexFactory objects + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public abstract class IndexObjectFactoryFactory { + + @Autowired + protected WorkspaceItemService workspaceItemService; + @Autowired + protected XmlWorkflowItemService xmlWorkflowItemService; + @Autowired + protected ClaimedTaskService claimedTaskService; + @Autowired + protected PoolTaskService poolTaskService; + + /** + * Return the list of all the available implementations of the IndexableObjectService interface + * + * @return the list of IndexableObjectService + */ + public abstract List getIndexFactories(); + + /** + * Retrieve the IndexFactory implementation for the given indexable object + * @param indexableObject the indexable object for which we need our factory + * @return An IndexFactory implementation + */ + public IndexFactory getIndexableObjectFactory(IndexableObject indexableObject) { + return getIndexableObjectFactory(indexableObject.getType()); + } + + /** + * Retrieve the IndexFactory implementation for the given indexable object unique identifier + * @param indexableObjectUniqueString the unique identifier of an indexable object + * @return An IndexFactory implementation + */ + public IndexFactory getIndexableObjectFactory(String indexableObjectUniqueString) { + // The unique identifier of an IndexableObject will always be {type}-{identifier} + return getIndexFactoryByType(StringUtils.substringBefore(indexableObjectUniqueString, "-")); + } + + /** + * Retrieve the IndexFactory implementation for the given indexable object type + * @param indexableFactoryType the object type of the indexable object + * @return An IndexFactory implementation + */ + public IndexFactory getIndexFactoryByType(String indexableFactoryType) { + for (IndexFactory indexableObjectFactory : getIndexFactories()) { + if (indexableObjectFactory.getType().equals(indexableFactoryType)) { + return indexableObjectFactory; + } + } + return null; + } + + /** + * Retrieve all the indexable objects for the provided object + * @param context DSpace context object + * @param object The object we want to retrieve our indexable objects for + * @return A list of indexable objects + */ + public List getIndexableObjects(Context context, Object object) throws SQLException { + List results = new ArrayList<>(); + if (object instanceof DSpaceObject) { + switch ((((DSpaceObject) object).getType())) { + case Constants.COMMUNITY: + results.add(new IndexableCommunity((Community) object)); + break; + case Constants.COLLECTION: + results.add(new IndexableCollection((Collection) object)); + break; + case Constants.ITEM: + final Item item = (Item) object; + if (item.isArchived() || item.isWithdrawn()) { + // We only want to index an item as an item if it is not in workflow + results.add(new IndexableItem(item)); + } else { + // Check if we have a workflow / workspace item + final WorkspaceItem workspaceItem = workspaceItemService.findByItem(context, item); + if (workspaceItem != null) { + results.add(new IndexableWorkspaceItem(workspaceItem)); + } else { + // Check if we a workflow item + final XmlWorkflowItem xmlWorkflowItem = xmlWorkflowItemService.findByItem(context, item); + if (xmlWorkflowItem != null) { + results.add(new IndexableWorkflowItem(xmlWorkflowItem)); + List claimedTasks = claimedTaskService.find(context, xmlWorkflowItem); + List pools = poolTaskService.find(context, xmlWorkflowItem); + for (PoolTask poolTask : pools) { + results.add(new IndexablePoolTask(poolTask)); + } + for (ClaimedTask claimedTask : claimedTasks) { + results.add(new IndexableClaimedTask(claimedTask)); + } + } + } + } + break; + default: + throw new IllegalArgumentException("The object: " + object.getClass().getName() + + " cannot be indexed"); + + + } + } else { + throw new IllegalArgumentException("The object: " + object.getClass().getName() + + " cannot be indexed"); + } + return results; + } + + /** + * Retrieve an implementation instance for this factory + * @return an IndexObjectServiceFactory bean + */ + public static IndexObjectFactoryFactory getInstance() { + return DSpaceServicesFactory.getInstance().getServiceManager() + .getServiceByName("indexObjectFactoryFactory", IndexObjectFactoryFactory.class); + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexObjectFactoryFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexObjectFactoryFactoryImpl.java new file mode 100644 index 0000000000..a199424991 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexObjectFactoryFactoryImpl.java @@ -0,0 +1,27 @@ +/** + * 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.discovery.indexobject.factory; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Abstract factory implementation to get the IndexFactory objects + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class IndexObjectFactoryFactoryImpl extends IndexObjectFactoryFactory { + + @Autowired + List indexableObjectServices; + + @Override + public List getIndexFactories() { + return indexableObjectServices; + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/InprogressSubmissionIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/InprogressSubmissionIndexFactory.java new file mode 100644 index 0000000000..8b26cc7220 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/InprogressSubmissionIndexFactory.java @@ -0,0 +1,34 @@ +/** + * 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.discovery.indexobject.factory; + +import java.sql.SQLException; + +import org.apache.solr.common.SolrInputDocument; +import org.dspace.content.InProgressSubmission; +import org.dspace.core.Context; +import org.dspace.discovery.indexobject.IndexableInProgressSubmission; + +/** + * Factory interface for indexing/retrieving InProgresssSubmission objects in the search core + * + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public interface InprogressSubmissionIndexFactory + extends IndexFactory { + + /** + * Store common fields between workspace / workflow items in the solr document + * @param context DSpace context object + * @param doc Solr input document which will be written to our discovery solr core + * @param inProgressSubmission the workspace / workflow item + * @throws SQLException If database error + */ + void storeInprogressItemFields(Context context, SolrInputDocument doc, InProgressSubmission inProgressSubmission) + throws SQLException; +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/ItemIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/ItemIndexFactory.java new file mode 100644 index 0000000000..8708eb5585 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/ItemIndexFactory.java @@ -0,0 +1,41 @@ +/** + * 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.discovery.indexobject.factory; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.List; + +import org.apache.solr.common.SolrInputDocument; +import org.dspace.content.Item; +import org.dspace.core.Context; +import org.dspace.discovery.configuration.DiscoveryConfiguration; +import org.dspace.discovery.indexobject.IndexableItem; + +/** + * Factory interface for indexing/retrieving items in the search core + * + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public interface ItemIndexFactory extends DSpaceObjectIndexFactory { + + /** + * Store item fields in the solr document + * @param doc Solr input document which will be written to our discovery solr core + * @param context DSpace context object + * @param item Item for which we want to index our fields in the provided solr document + * @param discoveryConfigurations The discovery configuration which holds information + * for which item fields we should index + * @throws SQLException If database error + * @throws IOException If IO error + */ + void addDiscoveryFields(SolrInputDocument doc, Context context, Item item, + List discoveryConfigurations) + throws SQLException, IOException; + +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/PoolTaskIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/PoolTaskIndexFactory.java new file mode 100644 index 0000000000..86b340d8b4 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/PoolTaskIndexFactory.java @@ -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.discovery.indexobject.factory; + +import org.dspace.discovery.indexobject.IndexablePoolTask; + +/** + * Factory interface for indexing/retrieving Pooltask objects in the search core + * + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public interface PoolTaskIndexFactory extends IndexFactory { +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/WorkflowItemIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/WorkflowItemIndexFactory.java new file mode 100644 index 0000000000..c2eb0c8310 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/WorkflowItemIndexFactory.java @@ -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.discovery.indexobject.factory; + +import org.dspace.discovery.indexobject.IndexableWorkflowItem; + +/** + * Factory interface for indexing/retrieving workflow items objects in the search core + * + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public interface WorkflowItemIndexFactory extends InprogressSubmissionIndexFactory { +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/WorkspaceItemIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/WorkspaceItemIndexFactory.java new file mode 100644 index 0000000000..f86fc5f676 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/WorkspaceItemIndexFactory.java @@ -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.discovery.indexobject.factory; + +import org.dspace.discovery.indexobject.IndexableWorkspaceItem; + +/** + * Factory interface for indexing/retrieving workspace item objects in the search core + * + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public interface WorkspaceItemIndexFactory extends InprogressSubmissionIndexFactory { +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/search/Harvest.java b/dspace-api/src/main/java/org/dspace/search/Harvest.java index 493a7d39a6..a0b3698592 100644 --- a/dspace-api/src/main/java/org/dspace/search/Harvest.java +++ b/dspace-api/src/main/java/org/dspace/search/Harvest.java @@ -31,6 +31,8 @@ import org.dspace.discovery.DiscoverResult; import org.dspace.discovery.IndexableObject; import org.dspace.discovery.SearchServiceException; import org.dspace.discovery.SearchUtils; +import org.dspace.discovery.indexobject.IndexableDSpaceObject; +import org.dspace.discovery.indexobject.IndexableItem; import org.dspace.eperson.Group; import org.dspace.handle.factory.HandleServiceFactory; import org.dspace.handle.service.HandleService; @@ -97,7 +99,7 @@ public class Harvest { boolean items, boolean collections, boolean withdrawn, boolean nonAnon) throws SQLException, ParseException { DiscoverQuery discoverQuery = new DiscoverQuery(); - discoverQuery.addFilterQueries("search.resourcetype:" + Constants.ITEM); + discoverQuery.addFilterQueries("search.resourcetype:" + IndexableItem.TYPE); if (scope != null) { if (scope instanceof Community) { @@ -143,13 +145,13 @@ public class Harvest { Iterator dsoIterator = discoverResult.getIndexableObjects().iterator(); while (dsoIterator.hasNext() && ((limit == 0) || (itemCounter < limit))) { // the query is limited to ITEM - DSpaceObject dso = (DSpaceObject) dsoIterator.next(); + IndexableDSpaceObject indexableDSpaceObject = (IndexableDSpaceObject) dsoIterator.next(); HarvestedItemInfo itemInfo = new HarvestedItemInfo(); itemInfo.context = context; - itemInfo.handle = dso.getHandle(); - itemInfo.itemID = dso.getID(); - itemInfo.datestamp = ((Item) dso).getLastModified(); - itemInfo.withdrawn = ((Item) dso).isWithdrawn(); + itemInfo.handle = indexableDSpaceObject.getIndexedObject().getHandle(); + itemInfo.itemID = indexableDSpaceObject.getID(); + itemInfo.datestamp = ((IndexableItem) indexableDSpaceObject).getIndexedObject().getLastModified(); + itemInfo.withdrawn = ((IndexableItem) indexableDSpaceObject).getIndexedObject().isWithdrawn(); if (collections) { // Add collections data diff --git a/dspace-api/src/main/java/org/dspace/workflow/WorkflowItem.java b/dspace-api/src/main/java/org/dspace/workflow/WorkflowItem.java index 44315db7e8..e3d5ccde9a 100644 --- a/dspace-api/src/main/java/org/dspace/workflow/WorkflowItem.java +++ b/dspace-api/src/main/java/org/dspace/workflow/WorkflowItem.java @@ -8,13 +8,12 @@ package org.dspace.workflow; import org.dspace.content.InProgressSubmission; -import org.dspace.core.ReloadableEntity; /** * Interface representing a workflowitem, each workflowItem implementation must implement this interface. * * @author kevinvandevelde at atmire.com */ -public interface WorkflowItem extends InProgressSubmission, ReloadableEntity { +public interface WorkflowItem extends InProgressSubmission { public int getState(); } diff --git a/dspace-api/src/main/java/org/dspace/workflow/WorkflowItemService.java b/dspace-api/src/main/java/org/dspace/workflow/WorkflowItemService.java index 0a5a8297fe..48ee20b9ad 100644 --- a/dspace-api/src/main/java/org/dspace/workflow/WorkflowItemService.java +++ b/dspace-api/src/main/java/org/dspace/workflow/WorkflowItemService.java @@ -26,7 +26,7 @@ import org.dspace.eperson.EPerson; * * @author kevinvandevelde at atmire.com */ -public interface WorkflowItemService extends InProgressSubmissionService { +public interface WorkflowItemService extends InProgressSubmissionService { public T create(Context context, Item item, Collection collection) throws SQLException, AuthorizeException; diff --git a/dspace-api/src/main/java/org/dspace/workflowbasic/BasicWorkflowItem.java b/dspace-api/src/main/java/org/dspace/workflowbasic/BasicWorkflowItem.java index cdcf13ba6f..065cae25fc 100644 --- a/dspace-api/src/main/java/org/dspace/workflowbasic/BasicWorkflowItem.java +++ b/dspace-api/src/main/java/org/dspace/workflowbasic/BasicWorkflowItem.java @@ -7,8 +7,6 @@ */ package org.dspace.workflowbasic; -import java.sql.SQLException; - import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; @@ -23,7 +21,6 @@ import javax.persistence.Table; import org.dspace.content.Collection; import org.dspace.content.Item; -import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.eperson.EPerson; import org.dspace.workflow.WorkflowItem; @@ -152,7 +149,7 @@ public class BasicWorkflowItem implements WorkflowItem { } @Override - public EPerson getSubmitter() throws SQLException { + public EPerson getSubmitter() { return item.getSubmitter(); } @@ -185,10 +182,4 @@ public class BasicWorkflowItem implements WorkflowItem { public void setPublishedBefore(boolean b) { this.publishedBefore = b; } - - @Override - public int getType() { - return Constants.WORKFLOWITEM; - } - } diff --git a/dspace-api/src/main/java/org/dspace/workflowbasic/BasicWorkflowItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/workflowbasic/BasicWorkflowItemServiceImpl.java index 8fcd64da83..2751fd33e1 100644 --- a/dspace-api/src/main/java/org/dspace/workflowbasic/BasicWorkflowItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/workflowbasic/BasicWorkflowItemServiceImpl.java @@ -17,7 +17,6 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.content.Collection; import org.dspace.content.Item; import org.dspace.content.service.ItemService; -import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.LogManager; import org.dspace.eperson.EPerson; @@ -53,11 +52,6 @@ public class BasicWorkflowItemServiceImpl implements BasicWorkflowItemService { } - @Override - public int getSupportsIndexableObjectTypeConstant() { - return Constants.WORKFLOWITEM; - } - @Override public BasicWorkflowItem create(Context context, Item item, Collection collection) throws SQLException, AuthorizeException { @@ -90,14 +84,6 @@ public class BasicWorkflowItemServiceImpl implements BasicWorkflowItemService { return workflowItem; } - @Override - public BasicWorkflowItem findIndexableObject(Context context, Integer id) throws SQLException { - if (id != null) { - return find(context, id); - } - return null; - } - @Override public List findAll(Context context) throws SQLException { return workflowItemDAO.findAll(context, BasicWorkflowItem.class); diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/ClaimedTask.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/ClaimedTask.java index b527fc5701..8882055f82 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/ClaimedTask.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/ClaimedTask.java @@ -18,10 +18,8 @@ import javax.persistence.ManyToOne; import javax.persistence.SequenceGenerator; import javax.persistence.Table; -import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; -import org.dspace.discovery.IndexableObject; import org.dspace.eperson.EPerson; /** @@ -34,7 +32,7 @@ import org.dspace.eperson.EPerson; */ @Entity @Table(name = "cwf_claimtask") -public class ClaimedTask implements ReloadableEntity, IndexableObject { +public class ClaimedTask implements ReloadableEntity { @Id @Column(name = "claimtask_id") @@ -116,10 +114,4 @@ public class ClaimedTask implements ReloadableEntity, IndexableObject findAll(Context context) throws SQLException { + return claimedTaskDAO.findAll(context, ClaimedTask.class); } @Override diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTask.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTask.java index 5c9c2e79a1..2a87de51cb 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTask.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/PoolTask.java @@ -19,10 +19,8 @@ import javax.persistence.OneToOne; import javax.persistence.SequenceGenerator; import javax.persistence.Table; -import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.ReloadableEntity; -import org.dspace.discovery.IndexableObject; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; @@ -36,7 +34,7 @@ import org.dspace.eperson.Group; */ @Entity @Table(name = "cwf_pooltask") -public class PoolTask implements ReloadableEntity, IndexableObject { +public class PoolTask implements ReloadableEntity { @Id @Column(name = "pooltask_id") @@ -131,10 +129,4 @@ public class PoolTask implements ReloadableEntity, IndexableObject findAll(Context context) throws SQLException { + return poolTaskDAO.findAll(context, PoolTask.class); } @Override @@ -141,14 +140,6 @@ public class PoolTaskServiceImpl implements PoolTaskService { return poolTaskDAO.findByID(context, PoolTask.class, id); } - @Override - public PoolTask findIndexableObject(Context context, Integer id) throws SQLException { - if (id == null) { - return null; - } - return find(context, id.intValue()); - } - @Override public void update(Context context, PoolTask poolTask) throws SQLException, AuthorizeException { update(context, Collections.singletonList(poolTask)); diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/XmlWorkflowItem.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/XmlWorkflowItem.java index a0e6836656..4108500707 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/XmlWorkflowItem.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/XmlWorkflowItem.java @@ -7,8 +7,6 @@ */ package org.dspace.xmlworkflow.storedcomponents; -import java.sql.SQLException; - import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; @@ -23,10 +21,7 @@ import javax.persistence.Table; import org.dspace.content.Collection; import org.dspace.content.Item; -import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.core.ReloadableEntity; -import org.dspace.discovery.IndexableObject; import org.dspace.eperson.EPerson; import org.dspace.workflow.WorkflowItem; @@ -40,7 +35,7 @@ import org.dspace.workflow.WorkflowItem; */ @Entity @Table(name = "cwf_workflowitem") -public class XmlWorkflowItem implements WorkflowItem, ReloadableEntity, IndexableObject { +public class XmlWorkflowItem implements WorkflowItem { @Id @Column(name = "workflowitem_id") @@ -103,7 +98,7 @@ public class XmlWorkflowItem implements WorkflowItem, ReloadableEntity, } @Override - public EPerson getSubmitter() throws SQLException { + public EPerson getSubmitter() { return item.getSubmitter(); } @@ -143,10 +138,4 @@ public class XmlWorkflowItem implements WorkflowItem, ReloadableEntity, // simplified return 0; } - - @Override - public int getType() { - return Constants.WORKFLOWITEM; - } - } diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/XmlWorkflowItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/XmlWorkflowItemServiceImpl.java index 4545a5f0ce..010c310ba6 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/XmlWorkflowItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/XmlWorkflowItemServiceImpl.java @@ -17,7 +17,6 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.content.Collection; import org.dspace.content.Item; import org.dspace.content.service.ItemService; -import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.LogManager; import org.dspace.eperson.EPerson; @@ -63,11 +62,6 @@ public class XmlWorkflowItemServiceImpl implements XmlWorkflowItemService { } - @Override - public int getSupportsIndexableObjectTypeConstant() { - return Constants.WORKFLOWITEM; - } - @Override public XmlWorkflowItem create(Context context, Item item, Collection collection) throws SQLException, AuthorizeException { @@ -95,14 +89,6 @@ public class XmlWorkflowItemServiceImpl implements XmlWorkflowItemService { return workflowItem; } - @Override - public XmlWorkflowItem findIndexableObject(Context context, Integer id) throws SQLException { - if (id != null) { - return find(context, id); - } - return null; - } - @Override public List findAll(Context context) throws SQLException { return xmlWorkflowItemDAO.findAll(context, XmlWorkflowItem.class); diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/service/ClaimedTaskService.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/service/ClaimedTaskService.java index 4f85731472..667ca898b5 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/service/ClaimedTaskService.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/service/ClaimedTaskService.java @@ -11,7 +11,6 @@ import java.sql.SQLException; import java.util.List; import org.dspace.authorize.AuthorizeException; -import org.dspace.content.service.IndexableObjectService; import org.dspace.core.Context; import org.dspace.eperson.EPerson; import org.dspace.service.DSpaceCRUDService; @@ -25,8 +24,7 @@ import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; * * @author kevinvandevelde at atmire.com */ -public interface ClaimedTaskService extends DSpaceCRUDService, - IndexableObjectService { +public interface ClaimedTaskService extends DSpaceCRUDService { public List findByWorkflowItem(Context context, XmlWorkflowItem workflowItem) throws SQLException; @@ -49,4 +47,6 @@ public interface ClaimedTaskService extends DSpaceCRUDService, public void deleteByWorkflowItem(Context context, XmlWorkflowItem workflowItem) throws SQLException, AuthorizeException; + + List findAll(Context context) throws SQLException; } diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/service/PoolTaskService.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/service/PoolTaskService.java index 2ff61d8b07..d0de6bef38 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/service/PoolTaskService.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/storedcomponents/service/PoolTaskService.java @@ -12,7 +12,6 @@ import java.sql.SQLException; import java.util.List; import org.dspace.authorize.AuthorizeException; -import org.dspace.content.service.IndexableObjectService; import org.dspace.core.Context; import org.dspace.eperson.EPerson; import org.dspace.service.DSpaceCRUDService; @@ -26,7 +25,10 @@ import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; * * @author kevinvandevelde at atmire.com */ -public interface PoolTaskService extends DSpaceCRUDService, IndexableObjectService { +public interface PoolTaskService extends DSpaceCRUDService { + + public List findAll(Context context) throws SQLException; + public List findByEperson(Context context, EPerson ePerson) throws SQLException, AuthorizeException, IOException; diff --git a/dspace-api/src/test/data/dspaceFolder/config/spring/api/solr-services.xml b/dspace-api/src/test/data/dspaceFolder/config/spring/api/solr-services.xml index 654f6284a6..5ad031b688 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/spring/api/solr-services.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/spring/api/solr-services.xml @@ -19,7 +19,7 @@ - + @@ -27,6 +27,8 @@ + + diff --git a/dspace-api/src/test/java/org/dspace/discovery/MockSolrServiceImpl.java b/dspace-api/src/test/java/org/dspace/discovery/MockSolrSearchCore.java similarity index 86% rename from dspace-api/src/test/java/org/dspace/discovery/MockSolrServiceImpl.java rename to dspace-api/src/test/java/org/dspace/discovery/MockSolrSearchCore.java index ecbc0ed44b..1934ba9f0f 100644 --- a/dspace-api/src/test/java/org/dspace/discovery/MockSolrServiceImpl.java +++ b/dspace-api/src/test/java/org/dspace/discovery/MockSolrSearchCore.java @@ -14,7 +14,7 @@ import org.springframework.stereotype.Service; * Mock SOLR service for the Search Core */ @Service -public class MockSolrServiceImpl extends SolrServiceImpl implements InitializingBean { +public class MockSolrSearchCore extends SolrSearchCore implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/OpenSearchController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/OpenSearchController.java index 3ae879564e..fd123acf15 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/OpenSearchController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/OpenSearchController.java @@ -12,7 +12,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.UUID; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -112,7 +111,7 @@ public class OpenSearchController { } // then the rest - we are processing the query - IndexableObject container = null; + IndexableObject container = null; // support pagination parameters DiscoverQuery queryArgs = new DiscoverQuery(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/AInprogressItemConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/AInprogressItemConverter.java index 4ad8b5743a..e589bc1b22 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/AInprogressItemConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/AInprogressItemConverter.java @@ -7,8 +7,6 @@ */ package org.dspace.app.rest.converter; -import java.io.Serializable; -import java.sql.SQLException; import java.util.List; import org.apache.commons.lang3.StringUtils; @@ -38,11 +36,9 @@ import org.springframework.beans.factory.annotation.Autowired; * the DSpace API inprogressSubmission object * @param * the DSpace REST inprogressSubmission representation - * @param - * the Serializable class used as primary key */ -public abstract class AInprogressItemConverter, - R extends AInprogressSubmissionRest, ID extends Serializable> +public abstract class AInprogressItemConverter implements IndexableObjectConverter { private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(AInprogressItemConverter.class); @@ -66,11 +62,7 @@ public abstract class AInprogressItemConverter converter : converters) { - if (converter.supportsModel(dspaceObject)) { - return converter.convert(dspaceObject, projection); + private RestAddressableModel convertDSpaceObject(final IndexableObject indexableObject, + final Projection projection) { + for (IndexableObjectConverter converter : converters) { + if (converter.supportsModel(indexableObject)) { + return converter.convert(indexableObject.getIndexedObject(), projection); } } return null; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/IndexableObjectConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/IndexableObjectConverter.java index b4e789ab1f..784bb8fa6e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/IndexableObjectConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/IndexableObjectConverter.java @@ -17,11 +17,11 @@ import org.dspace.discovery.IndexableObject; * @param the Class in the DSpace REST data model * @author Andrea Bollini (andrea.bollini at 4science.it) */ -public interface IndexableObjectConverter extends DSpaceConverter { /** - * + * * @param idxo * the IndexableObject to check * @return true if the actual converter implementation is able to manage the supplied IndexableObject diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java index 1df7af79bf..15a18384eb 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ItemConverter.java @@ -82,6 +82,6 @@ public class ItemConverter @Override public boolean supportsModel(IndexableObject idxo) { - return idxo instanceof Item; + return idxo.getIndexedObject() instanceof Item; } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/PoolTaskConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/PoolTaskConverter.java index e6530d6d6b..7a58fda864 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/PoolTaskConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/PoolTaskConverter.java @@ -53,8 +53,7 @@ public class PoolTaskConverter } @Override - public boolean supportsModel(IndexableObject object) { - return object instanceof PoolTask; + public boolean supportsModel(IndexableObject idxo) { + return idxo.getIndexedObject() instanceof PoolTask; } - } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/WorkflowItemConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/WorkflowItemConverter.java index 7ed1d27b46..22e902b4ca 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/WorkflowItemConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/WorkflowItemConverter.java @@ -23,7 +23,7 @@ import org.springframework.stereotype.Component; */ @Component public class WorkflowItemConverter - extends AInprogressItemConverter { + extends AInprogressItemConverter { public WorkflowItemConverter() throws SubmissionConfigReaderException { super(); @@ -44,6 +44,6 @@ public class WorkflowItemConverter @Override public boolean supportsModel(IndexableObject object) { - return object instanceof XmlWorkflowItem; + return object.getIndexedObject() instanceof XmlWorkflowItem; } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/WorkspaceItemConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/WorkspaceItemConverter.java index 24252d1449..388ef7e032 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/WorkspaceItemConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/WorkspaceItemConverter.java @@ -22,7 +22,7 @@ import org.springframework.stereotype.Component; */ @Component public class WorkspaceItemConverter - extends AInprogressItemConverter { + extends AInprogressItemConverter { public WorkspaceItemConverter() throws SubmissionConfigReaderException { super(); @@ -47,6 +47,6 @@ public class WorkspaceItemConverter @Override public boolean supportsModel(IndexableObject object) { - return object instanceof WorkspaceItem; + return object.getIndexedObject() instanceof WorkspaceItem; } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/AInprogressSubmissionRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/AInprogressSubmissionRest.java index e142567e71..903e2866c8 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/AInprogressSubmissionRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/AInprogressSubmissionRest.java @@ -19,10 +19,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore; * * @author Andrea Bollini (andrea.bollini at 4science.it) * - * @param - * the serializable class used as primary key */ -public abstract class AInprogressSubmissionRest extends BaseObjectRest { +public abstract class AInprogressSubmissionRest extends BaseObjectRest { private Date lastModified = new Date(); private Map sections; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowItemRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowItemRest.java index 831baefec1..bf00ba0e4f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowItemRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkflowItemRest.java @@ -14,7 +14,7 @@ import org.dspace.app.rest.RestResourceController; * * @author Andrea Bollini (andrea.bollini at 4science.it) */ -public class WorkflowItemRest extends AInprogressSubmissionRest { +public class WorkflowItemRest extends AInprogressSubmissionRest { public static final String NAME = "workflowitem"; public static final String CATEGORY = RestAddressableModel.WORKFLOW; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkspaceItemRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkspaceItemRest.java index 3fac0eeef1..69fefd1a9b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkspaceItemRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/WorkspaceItemRest.java @@ -14,7 +14,7 @@ import org.dspace.app.rest.RestResourceController; * * @author Andrea Bollini (andrea.bollini at 4science.it) */ -public class WorkspaceItemRest extends AInprogressSubmissionRest { +public class WorkspaceItemRest extends AInprogressSubmissionRest { public static final String NAME = "workspaceitem"; public static final String CATEGORY = RestAddressableModel.SUBMISSION; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BrowseItemLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BrowseItemLinkRepository.java index 8692bd6804..951bbf2a11 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BrowseItemLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BrowseItemLinkRepository.java @@ -145,8 +145,8 @@ public class BrowseItemLinkRepository extends AbstractDSpaceRestRepository Pageable pageResultInfo = new PageRequest((binfo.getStart() - 1) / binfo.getResultsPerPage(), binfo.getResultsPerPage()); List tmpResult = new ArrayList(); - for (IndexableObject bb : binfo.getBrowseItemResults()) { - tmpResult.add((Item) bb); + for (Item bb : binfo.getBrowseItemResults()) { + tmpResult.add(bb); } return converter.toRestPage(tmpResult, pageResultInfo, binfo.getTotal(), projection); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ClaimedTaskRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ClaimedTaskRestPermissionEvaluatorPlugin.java index 8304277dff..f189eebeda 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ClaimedTaskRestPermissionEvaluatorPlugin.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/ClaimedTaskRestPermissionEvaluatorPlugin.java @@ -10,8 +10,8 @@ package org.dspace.app.rest.security; import java.io.Serializable; import java.sql.SQLException; +import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.utils.ContextUtil; -import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.eperson.EPerson; import org.dspace.eperson.service.EPersonService; @@ -49,7 +49,7 @@ public class ClaimedTaskRestPermissionEvaluatorPlugin extends RestObjectPermissi public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, DSpaceRestPermission permission) { - if (Constants.getTypeID(targetType) != Constants.CLAIMEDTASK) { + if (!StringUtils.equals("CLAIMEDTASK", targetType)) { return false; } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/PoolTaskRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/PoolTaskRestPermissionEvaluatorPlugin.java index 34b1bbf2cb..129457a911 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/PoolTaskRestPermissionEvaluatorPlugin.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/PoolTaskRestPermissionEvaluatorPlugin.java @@ -11,9 +11,9 @@ import java.io.IOException; import java.io.Serializable; import java.sql.SQLException; +import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.utils.ContextUtil; import org.dspace.authorize.AuthorizeException; -import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.eperson.EPerson; import org.dspace.eperson.service.EPersonService; @@ -51,7 +51,7 @@ public class PoolTaskRestPermissionEvaluatorPlugin extends RestObjectPermissionE public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType, DSpaceRestPermission permission) { - if (Constants.getTypeID(targetType) != Constants.POOLTASK) { + if (!StringUtils.equals("POOLTASK", targetType)) { return false; } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WorkflowRestPermissionEvaluatorPlugin.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WorkflowRestPermissionEvaluatorPlugin.java index 54040fb5f0..6358fafa9a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WorkflowRestPermissionEvaluatorPlugin.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/WorkflowRestPermissionEvaluatorPlugin.java @@ -11,9 +11,9 @@ import java.io.IOException; import java.io.Serializable; import java.sql.SQLException; +import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.utils.ContextUtil; import org.dspace.authorize.AuthorizeException; -import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.eperson.EPerson; import org.dspace.eperson.service.EPersonService; @@ -62,7 +62,7 @@ public class WorkflowRestPermissionEvaluatorPlugin extends RestObjectPermissionE //This plugin currently only evaluates READ access DSpaceRestPermission restPermission = DSpaceRestPermission.convert(permission); if (!DSpaceRestPermission.READ.equals(restPermission) - || Constants.getTypeID(targetType) != Constants.WORKFLOWITEM) { + || !StringUtils.equals(targetType, "WORKFLOWITEM")) { return false; } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/DiscoverQueryBuilder.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/DiscoverQueryBuilder.java index 5d4d773a82..30fc88c1b4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/DiscoverQueryBuilder.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/DiscoverQueryBuilder.java @@ -12,13 +12,11 @@ import java.util.ArrayList; import java.util.List; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.converter.query.SearchQueryConverter; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.parameter.SearchFilter; -import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.LogManager; import org.dspace.discovery.DiscoverFacetField; @@ -35,6 +33,7 @@ import org.dspace.discovery.configuration.DiscoverySearchFilter; import org.dspace.discovery.configuration.DiscoverySearchFilterFacet; import org.dspace.discovery.configuration.DiscoverySortConfiguration; import org.dspace.discovery.configuration.DiscoverySortFieldConfiguration; +import org.dspace.discovery.indexobject.factory.IndexFactory; import org.dspace.services.ConfigurationService; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; @@ -56,6 +55,9 @@ public class DiscoverQueryBuilder implements InitializingBean { @Autowired private ConfigurationService configurationService; + @Autowired + private List indexableFactories; + private int pageSizeLimit; @Override @@ -182,7 +184,7 @@ public class DiscoverQueryBuilder implements InitializingBean { //Limit results to DSO type if (StringUtils.isNotBlank(dsoType)) { - queryArgs.setDSpaceObjectFilter(getDsoTypeId(dsoType)); + queryArgs.setDSpaceObjectFilter(getDsoType(dsoType)); } return queryArgs; } @@ -269,12 +271,17 @@ public class DiscoverQueryBuilder implements InitializingBean { } } - private int getDsoTypeId(String dsoType) throws DSpaceBadRequestException { - int index = ArrayUtils.indexOf(Constants.typeText, dsoType.toUpperCase()); - if (index < 0) { - throw new DSpaceBadRequestException(dsoType + " is not a valid DSpace Object type"); + private String getDsoType(String dsoType) throws DSpaceBadRequestException { + for (IndexFactory indexFactory : indexableFactories) { + if (StringUtils.equalsIgnoreCase(indexFactory.getType(), dsoType)) { + return indexFactory.getType(); + } } - return index; + throw new DSpaceBadRequestException(dsoType + " is not a valid DSpace Object type"); + } + + public void setIndexableFactories(List indexableFactories) { + this.indexableFactories = indexableFactories; } private String[] convertFilters(Context context, DiscoveryConfiguration discoveryConfiguration, diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/ScopeResolver.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/ScopeResolver.java index ffc6b16d2d..658a3e996a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/ScopeResolver.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/ScopeResolver.java @@ -16,6 +16,8 @@ import org.dspace.content.service.CollectionService; import org.dspace.content.service.CommunityService; import org.dspace.core.Context; import org.dspace.discovery.IndexableObject; +import org.dspace.discovery.indexobject.IndexableCollection; +import org.dspace.discovery.indexobject.IndexableCommunity; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -33,14 +35,14 @@ public class ScopeResolver { @Autowired CommunityService communityService; - public IndexableObject resolveScope(Context context, String scope) { - IndexableObject scopeObj = null; + public IndexableObject resolveScope(Context context, String scope) { + IndexableObject scopeObj = null; if (StringUtils.isNotBlank(scope)) { try { UUID uuid = UUID.fromString(scope); - scopeObj = communityService.find(context, uuid); - if (scopeObj == null) { - scopeObj = collectionService.find(context, uuid); + scopeObj = new IndexableCommunity(communityService.find(context, uuid)); + if (scopeObj.getIndexedObject() == null) { + scopeObj = new IndexableCollection(collectionService.find(context, uuid)); } } catch (IllegalArgumentException ex) { log.warn("The given scope string " + StringUtils.trimToEmpty(scope) + " is not a UUID", ex); diff --git a/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/solr-services.xml b/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/solr-services.xml new file mode 100644 index 0000000000..b0eb2191c7 --- /dev/null +++ b/dspace-server-webapp/src/test/data/dspaceFolder/config/spring/api/solr-services.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java index cdee407282..5caf202861 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java @@ -918,7 +918,7 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest //These search results have to be shown in the embedded.objects section as these are the items // given in the structure defined above. //Seeing as everything fits onto one page, they have to all be present - .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.containsInAnyOrder( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.hasItems( SearchResultMatcher.match("core", "community", "communities"), SearchResultMatcher.match("core", "community", "communities"), //This has to be like this because collections don't have anything else @@ -1000,7 +1000,7 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest ))) //All elements have to be present in the embedded.objects section, these are the ones we made in // the structure defined above - .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.containsInAnyOrder( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.hasItems( SearchResultMatcher.match("core", "community", "communities"), SearchResultMatcher.match("core", "community", "communities"), //Match without any parameters because collections don't have anything special to check in the @@ -1089,7 +1089,7 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest PageMatcher.pageEntryWithTotalPagesAndElements(0, 20, 1, 7) ))) //All the elements created in the structure above have to be present in the embedded.objects section - .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.containsInAnyOrder( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.hasItems( SearchResultMatcher.match("core", "community", "communities"), SearchResultMatcher.match("core", "community", "communities"), //Collections are specified like this because they don't have any special properties @@ -1251,7 +1251,7 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest //The scope property has to be set to the value we entered in the parameters .andExpect(jsonPath("$.scope", is("test"))) //All the elements created in the structure above have to be present in the embedded.objects section - .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.containsInAnyOrder( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.hasItems( SearchResultMatcher.match("core", "community", "communities"), SearchResultMatcher.match("core", "community", "communities"), //Collections are specified like this because they don't have any special properties @@ -1319,7 +1319,7 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest //An anonymous user browses this endpoint to find the the objects in the system //With a dsoType 'item' getClient().perform(get("/api/discover/search/objects") - .param("dsoType", "item")) + .param("dsoType", "Item")) //** THEN ** //The status has to be 200 OK @@ -1396,7 +1396,7 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest //With a dsoType 'item' //And a sort on the dc.title ascending getClient().perform(get("/api/discover/search/objects") - .param("dsoType", "item") + .param("dsoType", "Item") .param("sort", "dc.title,ASC")) //** THEN ** @@ -1794,7 +1794,7 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest PageMatcher.pageEntry(0, 20) ))) //These are the items that aren't set to private - .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.containsInAnyOrder( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.hasItems( SearchResultMatcher.match("core", "community", "communities"), SearchResultMatcher.match("core", "community", "communities"), //Collections are specified like this because they don't have any special properties diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractIntegrationTestWithDatabase.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractIntegrationTestWithDatabase.java index 02bbbadf36..2e6fbceafb 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractIntegrationTestWithDatabase.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractIntegrationTestWithDatabase.java @@ -20,8 +20,8 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.content.Community; import org.dspace.core.Context; import org.dspace.core.I18nUtil; -import org.dspace.discovery.MockSolrServiceImpl; -import org.dspace.discovery.SearchService; +import org.dspace.discovery.MockSolrSearchCore; +import org.dspace.discovery.SolrSearchCore; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; import org.dspace.eperson.factory.EPersonServiceFactory; @@ -179,10 +179,9 @@ public class AbstractIntegrationTestWithDatabase extends AbstractDSpaceIntegrati cleanupContext(); // Clear the search core. - MockSolrServiceImpl searchService = DSpaceServicesFactory.getInstance() - .getServiceManager() - .getServiceByName(SearchService.class.getName(), - MockSolrServiceImpl.class); + MockSolrSearchCore searchService = DSpaceServicesFactory.getInstance() + .getServiceManager() + .getServiceByName(SolrSearchCore.class.getName(), MockSolrSearchCore.class); searchService.reset(); // Reload our ConfigurationService (to reset configs to defaults again) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/utils/DiscoverQueryBuilderTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/utils/DiscoverQueryBuilderTest.java index 0ece5c9016..54a1f0e4f7 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/utils/DiscoverQueryBuilderTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/utils/DiscoverQueryBuilderTest.java @@ -20,12 +20,12 @@ import static org.mockito.Mockito.when; import java.sql.SQLException; import java.util.Arrays; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.parameter.SearchFilter; -import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.discovery.DiscoverFacetField; import org.dspace.discovery.DiscoverFilterQuery; @@ -42,6 +42,8 @@ import org.dspace.discovery.configuration.DiscoverySearchFilterFacet; import org.dspace.discovery.configuration.DiscoverySortConfiguration; import org.dspace.discovery.configuration.DiscoverySortFieldConfiguration; import org.dspace.discovery.configuration.HierarchicalSidebarFacetConfiguration; +import org.dspace.discovery.indexobject.IndexableItem; +import org.dspace.discovery.indexobject.factory.IndexFactory; import org.dspace.services.ConfigurationService; import org.junit.Before; import org.junit.Test; @@ -74,6 +76,9 @@ public class DiscoverQueryBuilderTest { @Mock private IndexableObject scope; + @Mock + private IndexFactory indexFactory; + private DiscoveryConfiguration discoveryConfiguration; private String query; private SearchFilter searchFilter; @@ -81,6 +86,10 @@ public class DiscoverQueryBuilderTest { @Before public void setUp() throws Exception { + queryBuilder.setIndexableFactories(Collections.singletonList(indexFactory)); + + when(indexFactory.getType()).thenReturn(IndexableItem.TYPE); + when(configurationService.getIntProperty(eq("rest.search.max.results"), anyInt())).thenReturn(100); when(searchService.escapeQueryChars(any(String.class))).then(invocation -> invocation.getArguments()[0]); @@ -165,7 +174,7 @@ public class DiscoverQueryBuilderTest { assertThat(discoverQuery.getFilterQueries(), containsInAnyOrder("archived:true", "subject:\"Java\"")); assertThat(discoverQuery.getQuery(), is(query)); - assertThat(discoverQuery.getDSpaceObjectFilter(), is(Constants.ITEM)); + assertThat(discoverQuery.getDSpaceObjectFilter(), is(IndexableItem.TYPE)); assertThat(discoverQuery.getSortField(), is("dc.title_sort")); assertThat(discoverQuery.getSortOrder(), is(DiscoverQuery.SORT_ORDER.asc)); assertThat(discoverQuery.getMaxResults(), is(10)); @@ -191,7 +200,7 @@ public class DiscoverQueryBuilderTest { assertThat(discoverQuery.getFilterQueries(), containsInAnyOrder("archived:true")); assertThat(discoverQuery.getQuery(), isEmptyOrNullString()); - assertThat(discoverQuery.getDSpaceObjectFilter(), is(-1)); + assertThat(discoverQuery.getDSpaceObjectFilter(), isEmptyOrNullString()); //Note this should actually be "dc.date.accessioned_dt" but remember that our searchService is just a stupid // mock assertThat(discoverQuery.getSortField(), is("dc.date.accessioned_sort")); @@ -221,7 +230,7 @@ public class DiscoverQueryBuilderTest { assertThat(discoverQuery.getFilterQueries(), containsInAnyOrder("archived:true")); assertThat(discoverQuery.getQuery(), isEmptyOrNullString()); - assertThat(discoverQuery.getDSpaceObjectFilter(), is(-1)); + assertThat(discoverQuery.getDSpaceObjectFilter(), is(isEmptyOrNullString())); //Note this should actually be "dc.date.accessioned_dt" but remember that our searchService is just a stupid // mock assertThat(discoverQuery.getSortField(), is("score_sort")); @@ -281,7 +290,7 @@ public class DiscoverQueryBuilderTest { assertThat(discoverQuery.getFilterQueries(), containsInAnyOrder("archived:true", "subject:\"Java\"")); assertThat(discoverQuery.getQuery(), is(query)); - assertThat(discoverQuery.getDSpaceObjectFilter(), is(Constants.ITEM)); + assertThat(discoverQuery.getDSpaceObjectFilter(), is(IndexableItem.TYPE)); assertThat(discoverQuery.getSortField(), isEmptyOrNullString()); assertThat(discoverQuery.getMaxResults(), is(0)); assertThat(discoverQuery.getStart(), is(0)); diff --git a/dspace-server-webapp/src/test/java/org/dspace/discovery/MockSolrServiceImpl.java b/dspace-server-webapp/src/test/java/org/dspace/discovery/MockSolrSearchCore.java similarity index 92% rename from dspace-server-webapp/src/test/java/org/dspace/discovery/MockSolrServiceImpl.java rename to dspace-server-webapp/src/test/java/org/dspace/discovery/MockSolrSearchCore.java index 6081731d94..0aca4ea355 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/discovery/MockSolrServiceImpl.java +++ b/dspace-server-webapp/src/test/java/org/dspace/discovery/MockSolrSearchCore.java @@ -22,7 +22,7 @@ import org.springframework.stereotype.Service; * magic makes this work. */ @Service -public class MockSolrServiceImpl extends SolrServiceImpl implements InitializingBean, DisposableBean { +public class MockSolrSearchCore extends SolrSearchCore implements InitializingBean, DisposableBean { private MockSolrServer mockSolrServer; diff --git a/dspace/config/spring/api/core-factory-services.xml b/dspace/config/spring/api/core-factory-services.xml index de404cb971..85a9daea13 100644 --- a/dspace/config/spring/api/core-factory-services.xml +++ b/dspace/config/spring/api/core-factory-services.xml @@ -47,4 +47,6 @@ + + diff --git a/dspace/config/spring/api/core-services.xml b/dspace/config/spring/api/core-services.xml index e7e28884c2..6a6e1b9bae 100644 --- a/dspace/config/spring/api/core-services.xml +++ b/dspace/config/spring/api/core-services.xml @@ -117,6 +117,14 @@ + + + + + + + + diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index 130fc8c947..61dd448cde 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -20,7 +20,7 @@ http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd" - default-autowire-candidates="*Service,*DAO,javax.sql.DataSource"> + default-autowire-candidates="*Service,*DAO,javax.sql.DataSource,*Plugin" default-lazy-init="true"> @@ -31,7 +31,7 @@ - + @@ -157,7 +157,7 @@ - search.resourcetype:2 OR search.resourcetype:3 OR search.resourcetype:4 + search.resourcetype:Item OR search.resourcetype:Collection OR search.resourcetype:Community @@ -298,7 +298,7 @@ - search.resourcetype:2 OR search.resourcetype:3 OR search.resourcetype:4 + search.resourcetype:Item OR search.resourcetype:Collection OR search.resourcetype:Community @@ -403,7 +403,7 @@ - search.resourcetype:2 OR search.resourcetype:[8 TO 9] + search.resourcetype:Item OR search.resourcetype:WorkspaceItem OR search.resourcetype:XmlWorkflowItem @@ -480,7 +480,7 @@ - search.resourcetype:[10 TO 11] + search.resourcetype:PoolTask OR search.resourcetype:ClaimedTask @@ -568,7 +568,7 @@ - search.resourcetype:2 AND entityType_keyword:Publication + search.resourcetype:Item AND entityType_keyword:Publication @@ -631,7 +631,7 @@ - search.resourcetype:2 AND entityType_keyword:Person + search.resourcetype:Item AND entityType_keyword:Person @@ -750,7 +750,7 @@ - search.resourcetype:2 AND entityType_keyword:OrgUnit + search.resourcetype:Item AND entityType_keyword:OrgUnit @@ -811,7 +811,7 @@ - search.resourcetype:2 AND entityType_keyword:JournalIssue + search.resourcetype:Item AND entityType_keyword:JournalIssue @@ -871,7 +871,7 @@ - search.resourcetype:2 AND entityType_keyword:JournalVolume + search.resourcetype:Item AND entityType_keyword:JournalVolume @@ -931,7 +931,7 @@ - search.resourcetype:2 AND entityType_keyword:Journal + search.resourcetype:Item AND entityType_keyword:Journal diff --git a/dspace/config/spring/api/solr-services.xml b/dspace/config/spring/api/solr-services.xml index 0377d5bd58..a22b5d7f45 100644 --- a/dspace/config/spring/api/solr-services.xml +++ b/dspace/config/spring/api/solr-services.xml @@ -19,6 +19,7 @@ + diff --git a/dspace/solr/search/conf/schema.xml b/dspace/solr/search/conf/schema.xml index f9ace7461a..65de4cd7b5 100644 --- a/dspace/solr/search/conf/schema.xml +++ b/dspace/solr/search/conf/schema.xml @@ -240,7 +240,7 @@ - + From 73fb57374243f3774b2486f25650c511b29c2e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Tue, 3 Dec 2019 12:06:31 +0000 Subject: [PATCH 032/125] address submission forms changes --- dspace/config/submission-forms.xml | 83 ++++++++++++++++++------------ 1 file changed, 50 insertions(+), 33 deletions(-) diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index 293d6af62c..c040f08670 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -51,7 +51,7 @@ isAuthorOfPublication - personConfiguration + person true Add an author @@ -490,7 +490,7 @@ isVolumeOfJournal - periodicalConfiguration + periodical creativework.publisher:somepublishername Select the journal related to this volume. @@ -782,8 +782,6 @@ Enter the start page number. - - oaire citation @@ -820,8 +818,6 @@ select "Not Applicable (or Unknown)". - - dc language @@ -886,7 +882,7 @@ isProjectOfPublication - projectConfiguration + project true Add a related Funding @@ -928,7 +924,7 @@ false - textarea + onebox Enter the coverage of the item, like a period, jurisdiction, etc. @@ -956,8 +952,6 @@ onebox Enter the last name of the person - - person givenName @@ -969,10 +963,10 @@ dc - Title - + title + onebox - Enter the name of the person + Enter the preferred name of this person regarding the authorship @@ -980,6 +974,7 @@ person affiliation name + true onebox Enter the first name of the person @@ -989,6 +984,7 @@ person email + true onebox Enter the email of the person @@ -1016,7 +1012,7 @@ dc title - + onebox Enter the name of the project @@ -1026,31 +1022,15 @@ dc identifier uri - + onebox Enter the URL of the project webpage - - - dc - identifier - - onebox - Enter the identifier of the project - - - oaire - fundingStream - - textarea - Enter the name of the funding stream of the project - - isFundingAgencyOfProject - fundingAgencyConfiguration + openAIREfundingAgencyConfiguration false Add a Funding Agency @@ -1063,6 +1043,22 @@ One funding agency is required + + + oaire + fundingStream + + onebox + Enter the name of the funding stream of the project + + + dc + identifier + + onebox + Enter the identifier of the project + +

@@ -1070,7 +1066,7 @@ organization legalName - + onebox Enter the name of the orgunit or organization @@ -1090,6 +1086,16 @@ + + + dc + type + + dropdown + Choose the attributes of the Organization + + + dc @@ -1771,6 +1777,17 @@ + + + N/A + + + + Is a Funding Organization + FundingOrganization + + + \ No newline at end of file From db1408b796af3d10a2906d47f14e24d736e4ec36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Tue, 3 Dec 2019 15:07:37 +0000 Subject: [PATCH 033/125] OpenAIRE default discovery settings --- dspace/config/spring/api/discovery.xml | 132 +++++++++++++++++++++++++ dspace/config/submission-forms.xml | 2 +- 2 files changed, 133 insertions(+), 1 deletion(-) diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index 130fc8c947..d42f47bbad 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -61,6 +61,11 @@ + + + + @@ -950,6 +955,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:2 AND entityType_keyword:OrgUnit + search.resourcetype:2 AND entityType_keyword:Person + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:2 AND entityType_keyword:OrgUnit AND dc.type:FundingOrganization + + + + + + + + @@ -1664,4 +1792,8 @@ + + + + diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index c040f08670..272f8e8dcd 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -1030,7 +1030,7 @@ isFundingAgencyOfProject - openAIREfundingAgencyConfiguration + openAIREFundingAgencyConfiguration false Add a Funding Agency From 4ceed51567f3928584987ab5dfac71ecf72a9b76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Tue, 3 Dec 2019 15:09:16 +0000 Subject: [PATCH 034/125] OpenAIRE default discovery settings --- dspace/config/spring/api/discovery.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index d42f47bbad..b8381c325e 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -1012,8 +1012,7 @@ - search.resourcetype:2 AND entityType_keyword:OrgUnit - search.resourcetype:2 AND entityType_keyword:Person + search.resourcetype:2 AND (entityType_keyword:OrgUnit OR entityType_keyword:Person) From 5e163f3beb803b039afb6919f45429c3f63af3ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Tue, 3 Dec 2019 15:21:51 +0000 Subject: [PATCH 035/125] new openaire discovery search filters --- dspace/config/spring/api/discovery.xml | 45 ++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index b8381c325e..0253e56272 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -1044,6 +1044,7 @@ + @@ -1739,6 +1740,50 @@ + + + + + relation.isContributorOfPublication + + + + + + + + + + + relation.isPublicationOfContributor + + + + + + + + + + + relation.isFundingAgencyOfProject + + + + + + + + + + + relation.isProjectOfFundingAgency + + + + + + From d4a59d8214a598973105c67f83021871f6191bc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Tue, 3 Dec 2019 15:50:52 +0000 Subject: [PATCH 036/125] initial virtual metadata --- dspace/config/spring/api/virtual-metadata.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/dspace/config/spring/api/virtual-metadata.xml b/dspace/config/spring/api/virtual-metadata.xml index 363b076773..c4c93d75d5 100644 --- a/dspace/config/spring/api/virtual-metadata.xml +++ b/dspace/config/spring/api/virtual-metadata.xml @@ -21,6 +21,10 @@ + + + + @@ -219,6 +223,20 @@ , + + + + + + + + + dc.title + + + search.resourcetype:2 OR search.resourcetype:3 OR search.resourcetype:4 + NOT(withdrawn:true) + NOT(discoverable:false) @@ -244,7 +247,7 @@ - + @@ -295,8 +298,9 @@ queries done by discovery for this configuration --> - + search.resourcetype:2 + withdrawn:true OR discoverable:false @@ -545,6 +549,8 @@ search.resourcetype:2 OR search.resourcetype:[8 TO 9] + NOT(withdrawn:true) + NOT(discoverable:false) @@ -622,6 +628,8 @@ search.resourcetype:[10 TO 11] + NOT(withdrawn:true) + NOT(discoverable:false) @@ -775,6 +783,8 @@ search.resourcetype:2 AND entityType_keyword:Person + NOT(withdrawn:true) + NOT(discoverable:false) From 50794b60155cfa6ba7c6b4a9fc9bdf93c3b86089 Mon Sep 17 00:00:00 2001 From: Michael W Spalti Date: Tue, 3 Dec 2019 18:06:24 -0800 Subject: [PATCH 040/125] Fixed style check error. --- .../java/org/dspace/app/rest/DiscoveryRestControllerIT.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java index 7ea17612ea..8f99a1df63 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java @@ -3705,7 +3705,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest PageMatcher.pageEntry(0, 20) ))) //The search results should be an empty list. - .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", Matchers.containsInAnyOrder( + .andExpect(jsonPath("$._embedded.searchResult._embedded.objects", + Matchers.containsInAnyOrder( SearchResultMatcher.matchOnItemName("item", "items", "Private Test item 2"), SearchResultMatcher.matchOnItemName("item", "items", "Withdrawn Test 2") ))) From da216d12bf6d7acdd9cb1f6a933e1675d8bcafef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Wed, 4 Dec 2019 17:34:58 +0000 Subject: [PATCH 041/125] field descriptions --- dspace/config/submission-forms.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index 272f8e8dcd..d74891bec5 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -950,14 +950,14 @@ familyName onebox - Enter the last name of the person + Enter surname or last name of the person person givenName onebox - Enter the first name of the person + Enter personal or first name of the person @@ -977,7 +977,7 @@ true onebox - Enter the first name of the person + Enter the organizational or institutional affiliation of this person From dd570ead94d040e0580019d359422cf9486545b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Wed, 4 Dec 2019 17:35:34 +0000 Subject: [PATCH 042/125] new filter --- dspace/config/spring/api/discovery.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index 0253e56272..b29c59246c 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -964,6 +964,7 @@ + @@ -1024,7 +1025,7 @@ - + From 9c5f1c1e11ad50a7dee8599a55bb526be4473fd2 Mon Sep 17 00:00:00 2001 From: Michael W Spalti Date: Wed, 4 Dec 2019 10:31:50 -0800 Subject: [PATCH 043/125] Renamed discovery configuration and added error message. --- .../java/org/dspace/browse/SolrBrowseDAO.java | 2 +- .../app/rest/DiscoveryRestControllerIT.java | 14 ++++++------ dspace/config/spring/api/discovery.xml | 22 +------------------ 3 files changed, 9 insertions(+), 29 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java index 735fb8eedf..087ec42774 100644 --- a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java +++ b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java @@ -230,7 +230,7 @@ public class SolrBrowseDAO implements BrowseDAO { query.addFilterQueries(searcher.createLocationQueryForAdministrableItems(context)); } } catch (SQLException ex) { - log.error(ex); + log.error("Error looking up authorization rights of current user", ex); } } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java index 8f99a1df63..1212704c92 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/DiscoveryRestControllerIT.java @@ -3597,7 +3597,7 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest .build(); Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build(); Collection col2 = CollectionBuilder.createCollection(context, child1).withName("Collection 2").build(); - //2. Two public items that are readable by Anonymous with different subjects and one private item + //2. One public item, one private, one withdrawn. Item publicItem1 = ItemBuilder.createItem(context, col1) .withTitle("Test") .withIssueDate("2010-10-17") @@ -3624,10 +3624,10 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest String query = "Test"; //** WHEN ** - //An anonymous user browses this endpoint to find the the withdrawn or private objects in the system + //A non-admin user browses this endpoint to find the withdrawn or private objects in the system //With a query stating 'Test' getClient().perform(get("/api/discover/search/objects") - .param("configuration", "showUnDiscoverableItems") + .param("configuration", "undiscoverable") .param("query", query)) //** THEN ** //The status has to be 200 OK @@ -3662,7 +3662,7 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest .build(); Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build(); Collection col2 = CollectionBuilder.createCollection(context, child1).withName("Collection 2").build(); - //2. Two public items that are readable by Anonymous with different subjects and one private item + //2. One public item, one private, one withdrawn. Item publicItem1 = ItemBuilder.createItem(context, col1) .withTitle("Test") .withIssueDate("2010-10-17") @@ -3690,10 +3690,10 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest String query = "Test"; String adminToken = getAuthToken(admin.getEmail(), password); //** WHEN ** - //A system admin user browses this endpoint to find the withdrawn or private objects in the system - //With a query stating 'Test' + // A system admin user browses this endpoint to find the withdrawn or private objects in the system + // With a query stating 'Test' getClient(adminToken).perform(get("/api/discover/search/objects") - .param("configuration", "showUnDiscoverableItems") + .param("configuration", "undiscoverable") .param("query", query)) //** THEN ** //The status has to be 200 OK diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index c81d2963e8..7416c3287c 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -54,7 +54,7 @@ - + @@ -158,8 +158,6 @@ search.resourcetype:2 OR search.resourcetype:3 OR search.resourcetype:4 - NOT(withdrawn:true) - NOT(discoverable:false) @@ -442,8 +440,6 @@ search.resourcetype:2 OR search.resourcetype:3 OR search.resourcetype:4 - NOT(withdrawn:true) - NOT(discoverable:false) @@ -549,8 +545,6 @@ search.resourcetype:2 OR search.resourcetype:[8 TO 9] - NOT(withdrawn:true) - NOT(discoverable:false) @@ -628,8 +622,6 @@ search.resourcetype:[10 TO 11] - NOT(withdrawn:true) - NOT(discoverable:false) @@ -718,8 +710,6 @@ search.resourcetype:2 AND entityType_keyword:Publication - NOT(withdrawn:true) - NOT(discoverable:false) @@ -783,8 +773,6 @@ search.resourcetype:2 AND entityType_keyword:Person - NOT(withdrawn:true) - NOT(discoverable:false) @@ -849,8 +837,6 @@ search.resourcetype:2 AND entityType_keyword:OrgUnit - NOT(withdrawn:true) - NOT(discoverable:false) @@ -912,8 +898,6 @@ search.resourcetype:2 AND entityType_keyword:JournalIssue - NOT(withdrawn:true) - NOT(discoverable:false) @@ -974,8 +958,6 @@ search.resourcetype:2 AND entityType_keyword:JournalVolume - NOT(withdrawn:true) - NOT(discoverable:false) @@ -1036,8 +1018,6 @@ search.resourcetype:2 AND entityType_keyword:Journal - NOT(withdrawn:true) - NOT(discoverable:false) From 4b64105962a1f9a4793e43cacdce912d7bb6fa4b Mon Sep 17 00:00:00 2001 From: Michael W Spalti Date: Wed, 4 Dec 2019 11:54:55 -0800 Subject: [PATCH 044/125] Added check for commuity/collection admins to solr plugin for private items. --- .../discovery/SolrServicePrivateItemPlugin.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServicePrivateItemPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServicePrivateItemPlugin.java index 82481a6877..47dea08fc8 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServicePrivateItemPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServicePrivateItemPlugin.java @@ -28,14 +28,22 @@ public class SolrServicePrivateItemPlugin implements SolrServiceSearchPlugin { @Autowired(required = true) protected AuthorizeService authorizeService; + + @Autowired(required = true) + protected SearchService searchService; + @Override public void additionalSearchParameters(Context context, DiscoverQuery discoveryQuery, SolrQuery solrQuery) { try { - if (!authorizeService.isAdmin(context)) { + // 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)) { solrQuery.addFilterQuery("NOT(discoverable:false)"); } - } catch (SQLException e) { - log.error(LogManager.getHeader(context, "Error while adding non-administrator filters to query", ""), e); + } catch (SQLException ex) { + log.error(LogManager.getHeader(context, "Error looking up authorization rights of current user", + ""), ex); } } } \ No newline at end of file From 7b36453c587e6bbe07eab87fb7eda43865567c66 Mon Sep 17 00:00:00 2001 From: Michael W Spalti Date: Wed, 4 Dec 2019 12:46:36 -0800 Subject: [PATCH 045/125] Minor update in discovery.xml --- dspace/config/spring/api/discovery.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index e2c2ecddbc..1b5b4d3b4b 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -54,7 +54,7 @@ - + @@ -247,7 +247,7 @@ - + From b0cdb3907d7dea5a0c8276b5804ca16d81daca03 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Thu, 5 Dec 2019 11:03:11 +0100 Subject: [PATCH 046/125] Renamed copyLeft and copyRight, added defaults for them in the test Relationship-types file and added a test for the place check after deleting a relationship and keeping the virtual metadata --- .../dspace/app/util/InitializeEntities.java | 30 +++++++------- .../content/RelationshipServiceImpl.java | 26 ++++++++---- .../org/dspace/content/RelationshipType.java | 40 +++++++++---------- .../content/RelationshipTypeServiceImpl.java | 6 +-- .../service/RelationshipTypeService.java | 2 +- ....13__relationship_type_copy_left_right.sql | 4 +- ....13__relationship_type_copy_left_right.sql | 4 +- ....13__relationship_type_copy_left_right.sql | 4 +- .../config/entities/relationship-types.dtd | 4 +- .../config/entities/relationship-types.xml | 5 +++ .../RelationshipMetadataServiceTest.java | 4 +- .../converter/RelationshipTypeConverter.java | 4 +- .../app/rest/model/RelationshipTypeRest.java | 36 ++++++++--------- .../RelationshipDeleteRestRepositoryIT.java | 32 +++++++++++++++ .../rest/builder/RelationshipTypeBuilder.java | 8 ++-- .../rest/matcher/RelationshipTypeMatcher.java | 14 +++---- .../test/AbstractEntityIntegrationTest.java | 10 ++--- 17 files changed, 141 insertions(+), 92 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java b/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java index 23b99f3e8a..6087c4f4b0 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java +++ b/dspace-api/src/main/java/org/dspace/app/util/InitializeEntities.java @@ -130,20 +130,20 @@ public class InitializeEntities { String rightType = eElement.getElementsByTagName("rightType").item(0).getTextContent(); String leftwardType = eElement.getElementsByTagName("leftwardType").item(0).getTextContent(); String rightwardType = eElement.getElementsByTagName("rightwardType").item(0).getTextContent(); - Node copyLeftNode = eElement.getElementsByTagName("copyLeft").item(0); - Boolean copyLeft; - if (copyLeftNode == null) { - copyLeft = false; + Node copyToLeftNode = eElement.getElementsByTagName("copyToLeft").item(0); + Boolean copyToLeft; + if (copyToLeftNode == null) { + copyToLeft = false; } else { - copyLeft = Boolean.valueOf(copyLeftNode.getTextContent()); + copyToLeft = Boolean.valueOf(copyToLeftNode.getTextContent()); } - Node copyRightNode = eElement.getElementsByTagName("copyRight").item(0); - Boolean copyRight; - if (copyRightNode == null) { - copyRight = false; + Node copyToRightNode = eElement.getElementsByTagName("copyToRight").item(0); + Boolean copyToRight; + if (copyToRightNode == null) { + copyToRight = false; } else { - copyRight = Boolean.valueOf(copyRightNode.getTextContent()); + copyToRight = Boolean.valueOf(copyToRightNode.getTextContent()); } NodeList leftCardinalityList = eElement.getElementsByTagName("leftCardinality"); @@ -170,7 +170,7 @@ public class InitializeEntities { } populateRelationshipType(context, leftType, rightType, leftwardType, rightwardType, leftCardinalityMin, leftCardinalityMax, - rightCardinalityMin, rightCardinalityMax, copyLeft, copyRight); + rightCardinalityMin, rightCardinalityMax, copyToLeft, copyToRight); } @@ -190,7 +190,7 @@ public class InitializeEntities { private void populateRelationshipType(Context context, String leftType, String rightType, String leftwardType, String rightwardType, String leftCardinalityMin, String leftCardinalityMax, String rightCardinalityMin, String rightCardinalityMax, - Boolean copyLeft, Boolean copyRight) + Boolean copyToLeft, Boolean copyToRight) throws SQLException, AuthorizeException { EntityType leftEntityType = entityTypeService.findByEntityType(context,leftType); @@ -231,10 +231,10 @@ public class InitializeEntities { relationshipTypeService.create(context, leftEntityType, rightEntityType, leftwardType, rightwardType, leftCardinalityMinInteger, leftCardinalityMaxInteger, rightCardinalityMinInteger, rightCardinalityMaxInteger, - copyLeft, copyRight); + copyToLeft, copyToRight); } else { - relationshipType.setCopyLeft(copyLeft); - relationshipType.setCopyRight(copyRight); + relationshipType.setCopyToLeft(copyToLeft); + relationshipType.setCopyToRight(copyToRight); relationshipType.setLeftMinCardinality(leftCardinalityMinInteger); relationshipType.setLeftMaxCardinality(leftCardinalityMaxInteger); relationshipType.setRightMinCardinality(rightCardinalityMinInteger); diff --git a/dspace-api/src/main/java/org/dspace/content/RelationshipServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/RelationshipServiceImpl.java index 5e63a7c0b9..0f08b15635 100644 --- a/dspace-api/src/main/java/org/dspace/content/RelationshipServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/RelationshipServiceImpl.java @@ -317,8 +317,8 @@ public class RelationshipServiceImpl implements RelationshipService { @Override public void delete(Context context, Relationship relationship) throws SQLException, AuthorizeException { - delete(context, relationship, relationship.getRelationshipType().isCopyLeft(), - relationship.getRelationshipType().isCopyRight()); + delete(context, relationship, relationship.getRelationshipType().isCopyToLeft(), + relationship.getRelationshipType().isCopyToRight()); } @Override @@ -364,9 +364,14 @@ public class RelationshipServiceImpl implements RelationshipService { relationshipMetadataService.findRelationshipMetadataValueForItemRelationship(context, relationship.getLeftItem(), entityTypeString, relationship, true); for (RelationshipMetadataValue relationshipMetadataValue : relationshipMetadataValues) { - itemService.addMetadata(context, relationship.getLeftItem(), - relationshipMetadataValue.getMetadataField(), null, - relationshipMetadataValue.getValue() ); + itemService.addAndShiftRightMetadata(context, relationship.getLeftItem(), + relationshipMetadataValue.getMetadataField(). + getMetadataSchema().getName(), + relationshipMetadataValue.getMetadataField().getElement(), + relationshipMetadataValue.getMetadataField().getQualifier(), + relationshipMetadataValue.getLanguage(), + relationshipMetadataValue.getValue(), null, -1, + relationshipMetadataValue.getPlace()); } itemService.update(context, relationship.getLeftItem()); } @@ -377,9 +382,14 @@ public class RelationshipServiceImpl implements RelationshipService { relationshipMetadataService.findRelationshipMetadataValueForItemRelationship(context, relationship.getRightItem(), entityTypeString, relationship, true); for (RelationshipMetadataValue relationshipMetadataValue : relationshipMetadataValues) { - itemService.addMetadata(context, relationship.getRightItem(), - relationshipMetadataValue.getMetadataField(), null, - relationshipMetadataValue.getValue() ); + itemService.addAndShiftRightMetadata(context, relationship.getRightItem(), + relationshipMetadataValue.getMetadataField(). + getMetadataSchema().getName(), + relationshipMetadataValue.getMetadataField().getElement(), + relationshipMetadataValue.getMetadataField().getQualifier(), + relationshipMetadataValue.getLanguage(), + relationshipMetadataValue.getValue(), null, -1, + relationshipMetadataValue.getPlace()); } itemService.update(context, relationship.getRightItem()); } diff --git a/dspace-api/src/main/java/org/dspace/content/RelationshipType.java b/dspace-api/src/main/java/org/dspace/content/RelationshipType.java index 4390825bb1..5f16870bc6 100644 --- a/dspace-api/src/main/java/org/dspace/content/RelationshipType.java +++ b/dspace-api/src/main/java/org/dspace/content/RelationshipType.java @@ -105,14 +105,14 @@ public class RelationshipType implements ReloadableEntity { /** * The boolean indicating whether the metadata should be copied on left item or not */ - @Column(name = "copy_left", nullable = false) - private boolean copyLeft; + @Column(name = "copy_to_left", nullable = false) + private boolean copyToLeft; /** * The boolean indicating whether the metadata should be copied on right item or not */ - @Column(name = "copy_right", nullable = false) - private boolean copyRight; + @Column(name = "copy_to_right", nullable = false) + private boolean copyToRight; /** * Protected constructor, create object using: * {@link org.dspace.content.service.RelationshipTypeService#create(Context)} } @@ -256,35 +256,35 @@ public class RelationshipType implements ReloadableEntity { } /** - * Generic getter for the copyLeft - * @return the copyLeft value of this RelationshipType + * Generic getter for the copyToLeft + * @return the copyToLeft value of this RelationshipType */ - public boolean isCopyLeft() { - return copyLeft; + public boolean isCopyToLeft() { + return copyToLeft; } /** - * Generic setter for the copyLeft - * @param copyLeft The copyLeft to be set on this RelationshipType + * Generic setter for the copyToLeft + * @param copyToLeft The copyToLeft to be set on this RelationshipType */ - public void setCopyLeft(boolean copyLeft) { - this.copyLeft = copyLeft; + public void setCopyToLeft(boolean copyToLeft) { + this.copyToLeft = copyToLeft; } /** - * Generic getter for the copyRight - * @return the copyRight value of this RelationshipType + * Generic getter for the copyToRight + * @return the copyToRight value of this RelationshipType */ - public boolean isCopyRight() { - return copyRight; + public boolean isCopyToRight() { + return copyToRight; } /** - * Generic setter for the copyRight - * @param copyRight The copyRight to be set on this RelationshipType + * Generic setter for the copyToRight + * @param copyToRight The copyToRight to be set on this RelationshipType */ - public void setCopyRight(boolean copyRight) { - this.copyRight = copyRight; + public void setCopyToRight(boolean copyToRight) { + this.copyToRight = copyToRight; } /** diff --git a/dspace-api/src/main/java/org/dspace/content/RelationshipTypeServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/RelationshipTypeServiceImpl.java index 992eb2a14d..2600fd90b2 100644 --- a/dspace-api/src/main/java/org/dspace/content/RelationshipTypeServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/RelationshipTypeServiceImpl.java @@ -121,15 +121,15 @@ public class RelationshipTypeServiceImpl implements RelationshipTypeService { public RelationshipType create(Context context, EntityType leftEntityType, EntityType rightEntityType, String leftwardType, String rightwardType, Integer leftCardinalityMinInteger, Integer leftCardinalityMaxInteger, Integer rightCardinalityMinInteger, - Integer rightCardinalityMaxInteger, Boolean copyLeft, Boolean copyRight) + Integer rightCardinalityMaxInteger, Boolean copyToLeft, Boolean copyToRight) throws SQLException, AuthorizeException { RelationshipType relationshipType = new RelationshipType(); relationshipType.setLeftType(leftEntityType); relationshipType.setRightType(rightEntityType); relationshipType.setLeftwardType(leftwardType); relationshipType.setRightwardType(rightwardType); - relationshipType.setCopyLeft(copyLeft); - relationshipType.setCopyRight(copyRight); + relationshipType.setCopyToLeft(copyToLeft); + relationshipType.setCopyToRight(copyToRight); relationshipType.setLeftMinCardinality(leftCardinalityMinInteger); relationshipType.setLeftMaxCardinality(leftCardinalityMaxInteger); relationshipType.setRightMinCardinality(rightCardinalityMinInteger); diff --git a/dspace-api/src/main/java/org/dspace/content/service/RelationshipTypeService.java b/dspace-api/src/main/java/org/dspace/content/service/RelationshipTypeService.java index a56104ec4e..6eee264848 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/RelationshipTypeService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/RelationshipTypeService.java @@ -174,6 +174,6 @@ public interface RelationshipTypeService extends DSpaceCRUDService - + + + diff --git a/dspace-api/src/test/data/dspaceFolder/config/entities/relationship-types.xml b/dspace-api/src/test/data/dspaceFolder/config/entities/relationship-types.xml index fcf00ac928..122e6ccdd6 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/entities/relationship-types.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/entities/relationship-types.xml @@ -13,6 +13,7 @@ 0 + true Publication @@ -25,6 +26,7 @@ 0 + true Publication @@ -37,6 +39,7 @@ 0 + true Person @@ -110,6 +113,7 @@ 0 + true JournalIssue @@ -123,5 +127,6 @@ 0 1 + true \ No newline at end of file diff --git a/dspace-api/src/test/java/org/dspace/content/RelationshipMetadataServiceTest.java b/dspace-api/src/test/java/org/dspace/content/RelationshipMetadataServiceTest.java index 65d35c53cb..6290d010e0 100644 --- a/dspace-api/src/test/java/org/dspace/content/RelationshipMetadataServiceTest.java +++ b/dspace-api/src/test/java/org/dspace/content/RelationshipMetadataServiceTest.java @@ -126,7 +126,7 @@ public class RelationshipMetadataServiceTest extends AbstractUnitTest { * Common function to convert leftItem to a publication item, convert rightItem to an author item, * and relating them to each other stored in the relationship field */ - private void initPublicationAuthorWithCopyParams(boolean copyLeft, boolean copyRight) + private void initPublicationAuthorWithCopyParams(boolean copyToLeft, boolean copyToRight) throws SQLException, AuthorizeException { context.turnOffAuthorisationSystem(); itemService.addMetadata(context, leftItem, "relationship", "type", null, null, "Publication"); @@ -138,7 +138,7 @@ public class RelationshipMetadataServiceTest extends AbstractUnitTest { RelationshipType isAuthorOfPublication = relationshipTypeService .create(context, publicationEntityType, authorEntityType, "isAuthorOfPublication", "isPublicationOfAuthor", - null, null, null, null, copyLeft, copyRight); + null, null, null, null, copyToLeft, copyToRight); relationship = relationshipService.create(context, leftItem, rightItem, isAuthorOfPublication, 0, 0); context.restoreAuthSystemState(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RelationshipTypeConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RelationshipTypeConverter.java index f500123d22..c20249c025 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RelationshipTypeConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RelationshipTypeConverter.java @@ -31,8 +31,8 @@ public class RelationshipTypeConverter implements DSpaceConverter { private String leftwardType; private String rightwardType; - private boolean copyLeft; - private boolean copyRight; + private boolean copyToLeft; + private boolean copyToRight; private Integer leftMinCardinality; private Integer leftMaxCardinality; private Integer rightMinCardinality; @@ -60,35 +60,35 @@ public class RelationshipTypeRest extends BaseObjectRest { } /** - * Generic getter for the copyLeft - * @return the copyLeft value of this RelationshipTypeRest + * Generic getter for the copyToLeft + * @return the copyToLeft value of this RelationshipTypeRest */ - public boolean isCopyLeft() { - return copyLeft; + public boolean isCopyToLeft() { + return copyToLeft; } /** - * Generic setter for the copyLeft - * @param copyLeft The copyLeft to be set on this RelationshipTypeRest + * Generic setter for the copyToLeft + * @param copyToLeft The copyToLeft to be set on this RelationshipTypeRest */ - public void setCopyLeft(boolean copyLeft) { - this.copyLeft = copyLeft; + public void setCopyToLeft(boolean copyToLeft) { + this.copyToLeft = copyToLeft; } /** - * Generic getter for the copyRight - * @return the copyRight value of this RelationshipTypeRest + * Generic getter for the copyToRight + * @return the copyToRight value of this RelationshipTypeRest */ - public boolean isCopyRight() { - return copyRight; + public boolean isCopyToRight() { + return copyToRight; } /** - * Generic setter for the copyRight - * @param copyRight The copyRight to be set on this RelationshipTypeRest + * Generic setter for the copyToRight + * @param copyToRight The copyToRight to be set on this RelationshipTypeRest */ - public void setCopyRight(boolean copyRight) { - this.copyRight = copyRight; + public void setCopyToRight(boolean copyToRight) { + this.copyToRight = copyToRight; } public Integer getLeftMinCardinality() { diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipDeleteRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipDeleteRestRepositoryIT.java index 202bce38c6..87d9c16e12 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipDeleteRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/RelationshipDeleteRestRepositoryIT.java @@ -632,4 +632,36 @@ public class RelationshipDeleteRestRepositoryIT extends AbstractEntityIntegratio assertThat(projectRelationships.size(), equalTo(0)); } + @Test + public void deleteItemCopyVirtualMetadataToCorrectPlace() throws Exception { + initPersonProjectPublication(); + + context.turnOffAuthorisationSystem(); + itemService.addMetadata(context, publicationItem, "dc", "contributor", "author", null, "Test Author"); + itemService.update(context, publicationItem); + context.restoreAuthSystemState(); + getClient(adminAuthToken).perform( + delete("/api/core/items/" + personItem.getID() + "?copyVirtualMetadata=" + + publicationPersonRelationshipType.getID())) + .andExpect(status().isNoContent()); + + publicationItem = itemService.find(context, publicationItem.getID()); + List publicationAuthorList = itemService.getMetadata(publicationItem, + "dc", "contributor", "author", Item.ANY); + assertThat(publicationAuthorList.size(), equalTo(2)); + assertThat(publicationAuthorList.get(0).getValue(), equalTo("Smith, Donald")); + assertNull(publicationAuthorList.get(0).getAuthority()); + List publicationRelationships = itemService.getMetadata(publicationItem, + "relation", "isAuthorOfPublication", Item.ANY, Item.ANY); + assertThat(publicationRelationships.size(), equalTo(0)); + + projectItem = itemService.find(context, projectItem.getID()); + List projectAuthorList = itemService.getMetadata(projectItem, + "dc", "contributor", "author", Item.ANY); + assertThat(projectAuthorList.size(), equalTo(0)); + List projectRelationships = itemService.getMetadata(projectItem, + "relation", "isPersonOfProject", Item.ANY, Item.ANY); + assertThat(projectRelationships.size(), equalTo(0)); + } + } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/builder/RelationshipTypeBuilder.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/builder/RelationshipTypeBuilder.java index b532d03d60..c03deeb7bc 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/builder/RelationshipTypeBuilder.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/builder/RelationshipTypeBuilder.java @@ -107,12 +107,12 @@ public class RelationshipTypeBuilder extends AbstractBuilder matchExplicitRelationshipTypeValuesAndExplicitEntityType(int id, String leftwardType, String rightwardType, Integer leftMinCardinality, Integer leftMaxCardinality, Integer rightMinCardinality, Integer rightMaxCardinality, - EntityType leftEntityType, EntityType rightEntityType, boolean copyLeft, boolean copyRight) { + EntityType leftEntityType, EntityType rightEntityType, boolean copyToLeft, boolean copyToRight) { return matchExplicitRelationshipTypeValuesAndExplicitEntityTypeValues(id, leftwardType, rightwardType, leftMinCardinality, leftMaxCardinality, rightMinCardinality, @@ -62,19 +62,19 @@ public class RelationshipTypeMatcher { leftEntityType.getLabel(), rightEntityType.getID(), rightEntityType.getLabel(), - copyLeft, copyRight); + copyToLeft, copyToRight); } private static Matcher matchExplicitRelationshipTypeValuesAndExplicitEntityTypeValues(int id, String leftwardType, String rightwardType, Integer leftMinCardinality, Integer leftMaxCardinality, Integer rightMinCardinality, Integer rightMaxCardinality, int leftEntityTypeId, String leftEntityTypeLabel, - int rightEntityTypeId, String rightEntityTypeLabel, boolean copyLeft, boolean copyRight) { + int rightEntityTypeId, String rightEntityTypeLabel, boolean copyToLeft, boolean copyToRight) { return allOf( hasJsonPath("$.id", is(id)), hasJsonPath("$.leftwardType", is(leftwardType)), hasJsonPath("$.rightwardType", is(rightwardType)), - hasJsonPath("$.copyLeft", is(copyLeft)), - hasJsonPath("$.copyRight", is(copyRight)), + hasJsonPath("$.copyToLeft", is(copyToLeft)), + hasJsonPath("$.copyToRight", is(copyToRight)), hasJsonPath("$.leftMinCardinality", is(leftMinCardinality)), hasJsonPath("$.leftMaxCardinality", is(leftMaxCardinality)), hasJsonPath("$.rightMinCardinality", is(rightMinCardinality)), diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractEntityIntegrationTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractEntityIntegrationTest.java index 0b1d81a40e..dec2461779 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractEntityIntegrationTest.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/AbstractEntityIntegrationTest.java @@ -58,19 +58,19 @@ public class AbstractEntityIntegrationTest extends AbstractControllerIntegration RelationshipTypeBuilder.createRelationshipTypeBuilder(context, publication, person, "isAuthorOfPublication", "isPublicationOfAuthor", 0, null, 0, - null).withCopyLeft(false).withCopyRight(true).build(); + null).withCopyToLeft(false).withCopyToRight(true).build(); RelationshipTypeBuilder.createRelationshipTypeBuilder(context, publication, project, "isProjectOfPublication", "isPublicationOfProject", 0, null, 0, - null).withCopyRight(true).build(); + null).withCopyToRight(true).build(); RelationshipTypeBuilder.createRelationshipTypeBuilder(context, publication, orgUnit, "isOrgUnitOfPublication", "isPublicationOfOrgUnit", 0, null, 0, - null).withCopyLeft(false).build(); + null).withCopyToLeft(false).build(); RelationshipTypeBuilder.createRelationshipTypeBuilder(context, person, project, "isProjectOfPerson", "isPersonOfProject", 0, null, 0, - null).withCopyLeft(true).withCopyRight(true).build(); + null).withCopyToLeft(true).withCopyToRight(true).build(); RelationshipTypeBuilder.createRelationshipTypeBuilder(context, person, orgUnit, "isOrgUnitOfPerson", "isPersonOfOrgUnit", 0, null, 0, @@ -82,7 +82,7 @@ public class AbstractEntityIntegrationTest extends AbstractControllerIntegration RelationshipTypeBuilder.createRelationshipTypeBuilder(context, journal, journalVolume, "isVolumeOfJournal", "isJournalOfVolume", 0, null, 1, - null).withCopyLeft(true).build(); + null).withCopyToLeft(true).build(); RelationshipTypeBuilder.createRelationshipTypeBuilder(context, journalVolume, journalIssue, "isIssueOfJournalVolume", "isJournalVolumeOfIssue", 0, From bd14a517f20c5e945b2908c018863ecf1c079ccf Mon Sep 17 00:00:00 2001 From: Ben Bosman Date: Thu, 5 Dec 2019 15:06:17 +0100 Subject: [PATCH 047/125] Avoid setting the virtual metadata language to ANY (*) --- .../org/dspace/content/RelationshipMetadataServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/content/RelationshipMetadataServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/RelationshipMetadataServiceImpl.java index 9a7ec9704b..3e01003578 100644 --- a/dspace-api/src/main/java/org/dspace/content/RelationshipMetadataServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/RelationshipMetadataServiceImpl.java @@ -240,7 +240,7 @@ public class RelationshipMetadataServiceImpl implements RelationshipMetadataServ return null; } metadataValue.setMetadataField(metadataField); - metadataValue.setLanguage(Item.ANY); + //metadataValue.setLanguage(Item.ANY); return metadataValue; } From 533b0b9838114b78691072ebafcef7a1c43850ba Mon Sep 17 00:00:00 2001 From: Ben Bosman Date: Fri, 6 Dec 2019 09:48:12 +0100 Subject: [PATCH 048/125] Avoid setting the virtual metadata language to ANY (*) --- .../java/org/dspace/content/RelationshipMetadataServiceImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/content/RelationshipMetadataServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/RelationshipMetadataServiceImpl.java index 3e01003578..bc466c5b83 100644 --- a/dspace-api/src/main/java/org/dspace/content/RelationshipMetadataServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/RelationshipMetadataServiceImpl.java @@ -240,7 +240,6 @@ public class RelationshipMetadataServiceImpl implements RelationshipMetadataServ return null; } metadataValue.setMetadataField(metadataField); - //metadataValue.setLanguage(Item.ANY); return metadataValue; } From 5585d27991599669c6139f88aa33accc30e39a39 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Fri, 6 Dec 2019 10:36:12 +0100 Subject: [PATCH 049/125] Refactored the UriListHandler and its implementations and supported the workspace item creation from ExternalDataObjects --- .../external/service/ExternalDataService.java | 5 +- .../service/impl/ExternalDataServiceImpl.java | 11 +- .../WorkspaceItemRestRepository.java | 15 ++ ...SourceEntryArchivedItemUriListHandler.java | 94 ++++++++ ...xternalSourceEntryItemUriListHandler.java} | 37 +-- ...ourceEntryWorkspaceItemUriListHandler.java | 48 ++++ .../repository/handler/UriListHandler.java | 6 +- .../service/UriListHandlerService.java | 4 +- .../app/rest/submit/SubmissionService.java | 2 +- .../rest/WorkspaceItemRestRepositoryIT.java | 214 +++++++++++++++++- 10 files changed, 391 insertions(+), 45 deletions(-) create mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryArchivedItemUriListHandler.java rename dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/{ExternalSourceEntryUriListHandler.java => ExternalSourceEntryItemUriListHandler.java} (78%) create mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryWorkspaceItemUriListHandler.java diff --git a/dspace-api/src/main/java/org/dspace/external/service/ExternalDataService.java b/dspace-api/src/main/java/org/dspace/external/service/ExternalDataService.java index bfcfeb6407..e5c3f31784 100644 --- a/dspace-api/src/main/java/org/dspace/external/service/ExternalDataService.java +++ b/dspace-api/src/main/java/org/dspace/external/service/ExternalDataService.java @@ -13,7 +13,7 @@ import java.util.Optional; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Collection; -import org.dspace.content.Item; +import org.dspace.content.WorkspaceItem; import org.dspace.core.Context; import org.dspace.external.model.ExternalDataObject; import org.dspace.external.provider.ExternalDataProvider; @@ -75,6 +75,7 @@ public interface ExternalDataService { * @throws AuthorizeException If something goes wrong * @throws SQLException If something goes wrong */ - Item createItemFromExternalDataObject(Context context, ExternalDataObject externalDataObject, Collection collection) + WorkspaceItem createWorkspaceItemFromExternalDataObject(Context context, ExternalDataObject externalDataObject, + Collection collection) throws AuthorizeException, SQLException; } diff --git a/dspace-api/src/main/java/org/dspace/external/service/impl/ExternalDataServiceImpl.java b/dspace-api/src/main/java/org/dspace/external/service/impl/ExternalDataServiceImpl.java index 587fe5cd0e..6375334fd2 100644 --- a/dspace-api/src/main/java/org/dspace/external/service/impl/ExternalDataServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/external/service/impl/ExternalDataServiceImpl.java @@ -18,7 +18,6 @@ import org.dspace.content.Collection; import org.dspace.content.Item; import org.dspace.content.WorkspaceItem; import org.dspace.content.dto.MetadataValueDTO; -import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; import org.dspace.content.service.WorkspaceItemService; import org.dspace.core.Context; @@ -44,9 +43,6 @@ public class ExternalDataServiceImpl implements ExternalDataService { @Autowired private WorkspaceItemService workspaceItemService; - @Autowired - private InstallItemService installItemService; - @Autowired private AuthorizeService authorizeService; @@ -95,8 +91,9 @@ public class ExternalDataServiceImpl implements ExternalDataService { @Override - public Item createItemFromExternalDataObject(Context context, ExternalDataObject externalDataObject, - Collection collection) + public WorkspaceItem createWorkspaceItemFromExternalDataObject(Context context, + ExternalDataObject externalDataObject, + Collection collection) throws AuthorizeException, SQLException { if (!authorizeService.isAdmin(context)) { throw new AuthorizeException("You have to be an admin to create an Item from an ExternalDataObject"); @@ -113,6 +110,6 @@ public class ExternalDataServiceImpl implements ExternalDataService { log.info(LogManager.getHeader(context, "create_item_from_externalDataObject", "Created item" + "with id: " + item.getID() + " from source: " + externalDataObject.getSource() + " with identifier: " + externalDataObject.getId())); - return installItemService.installItem(context, workspaceItem); + return workspaceItem; } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java index 9aa8df3492..7f89e2edee 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java @@ -26,11 +26,13 @@ import org.dspace.app.rest.Parameter; import org.dspace.app.rest.SearchRestMethod; import org.dspace.app.rest.converter.WorkspaceItemConverter; import org.dspace.app.rest.exception.DSpaceBadRequestException; +import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException; import org.dspace.app.rest.model.ErrorRest; import org.dspace.app.rest.model.WorkspaceItemRest; import org.dspace.app.rest.model.patch.Operation; import org.dspace.app.rest.model.patch.Patch; import org.dspace.app.rest.projection.Projection; +import org.dspace.app.rest.repository.handler.service.UriListHandlerService; import org.dspace.app.rest.submit.AbstractRestProcessingStep; import org.dspace.app.rest.submit.SubmissionService; import org.dspace.app.rest.submit.UploadableStep; @@ -109,6 +111,9 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository stringList) + throws AuthorizeException, SQLException, RepositoryMethodNotImplementedException { + + HttpServletRequest req = getRequestService().getCurrentRequest().getHttpServletRequest(); + WorkspaceItem workspaceItem = uriListHandlerService.handle(context, req, stringList, WorkspaceItem.class); + return converter.toRest(workspaceItem, Projection.DEFAULT); + } + + } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryArchivedItemUriListHandler.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryArchivedItemUriListHandler.java new file mode 100644 index 0000000000..1f9a8ead77 --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryArchivedItemUriListHandler.java @@ -0,0 +1,94 @@ +/** + * 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.rest.repository.handler; + +import java.sql.SQLException; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import javax.servlet.http.HttpServletRequest; + +import org.apache.logging.log4j.Logger; +import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.service.AuthorizeService; +import org.dspace.content.Item; +import org.dspace.content.WorkspaceItem; +import org.dspace.content.service.CollectionService; +import org.dspace.content.service.InstallItemService; +import org.dspace.core.Context; +import org.dspace.external.service.ExternalDataService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestMethod; + +/** + * This class will handle ExternalSourceEntryUriList and it'll create Item objects based on them + */ +@Component +public class ExternalSourceEntryArchivedItemUriListHandler extends ExternalSourceEntryItemUriListHandler { + + private List allowedRequestMethods = new LinkedList<>(Arrays.asList(RequestMethod.POST)); + + @Autowired + private AuthorizeService authorizeService; + + @Autowired + private ExternalDataService externalDataService; + + @Autowired + private CollectionService collectionService; + + @Autowired + private InstallItemService installItemService; + + private static final Logger log = org.apache.logging.log4j.LogManager + .getLogger(ExternalSourceEntryItemUriListHandler.class); + + @Override + public boolean supports(List uriList, String method, Class clazz) { + if (!super.supports(uriList, method, clazz)) { + return false; + } + if (clazz != Item.class) { + return false; + } + return true; + } + + @Override + public boolean validate(Context context, HttpServletRequest request, List uriList) + throws AuthorizeException { + if (!super.validate(context, request, uriList)) { + return false; + } + try { + if (!authorizeService.isAdmin(context)) { + throw new AuthorizeException("Only admins are allowed to create items using external data"); + } + } catch (SQLException e) { + log.error("context isAdmin check resulted in an error", e); + return false; + } + return true; + } + + @Override + public Item handle(Context context, HttpServletRequest request, List uriList) + throws SQLException, AuthorizeException { + String owningCollectionUuid = request.getParameter("owningCollection"); + try { + WorkspaceItem workspaceItem = super.createWorkspaceItem(context, request, uriList); + return installItemService.installItem(context, workspaceItem); + } catch (AuthorizeException | SQLException e) { + log.error("An error occured when trying to create item in collection with uuid: " + owningCollectionUuid, + e); + throw e; + } + } + +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryUriListHandler.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryItemUriListHandler.java similarity index 78% rename from dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryUriListHandler.java rename to dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryItemUriListHandler.java index cce12e63a6..a40f436e28 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryUriListHandler.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryItemUriListHandler.java @@ -23,21 +23,16 @@ import org.dspace.app.rest.model.ExternalSourceRest; import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.service.AuthorizeService; import org.dspace.content.Collection; -import org.dspace.content.Item; +import org.dspace.content.WorkspaceItem; import org.dspace.content.service.CollectionService; import org.dspace.core.Context; import org.dspace.external.model.ExternalDataObject; import org.dspace.external.service.ExternalDataService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ResourceNotFoundException; -import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestMethod; -/** - * This class will handle ExternalSourceEntryUriList and it'll create Item objects based on them - */ -@Component -public class ExternalSourceEntryUriListHandler implements UriListHandler { +public abstract class ExternalSourceEntryItemUriListHandler implements UriListHandler { private List allowedRequestMethods = new LinkedList<>(Arrays.asList(RequestMethod.POST)); @@ -51,11 +46,9 @@ public class ExternalSourceEntryUriListHandler implements UriListHandler { private CollectionService collectionService; private static final Logger log = org.apache.logging.log4j.LogManager - .getLogger(ExternalSourceEntryUriListHandler.class); + .getLogger(ExternalSourceEntryItemUriListHandler.class); - - @Override - public boolean supports(List uriList, String method) { + public boolean supports(List uriList, String method, Class clazz) { if (!allowedRequestMethods.contains(RequestMethod.valueOf(method))) { return false; } @@ -68,23 +61,16 @@ public class ExternalSourceEntryUriListHandler implements UriListHandler { return true; } - @Override - public boolean validate(Context context, HttpServletRequest request, List uriList, - Class clazz) throws AuthorizeException { + public boolean validate(Context context, HttpServletRequest request, List uriList) + throws AuthorizeException { if (uriList.size() > 1) { return false; } - if (clazz != Item.class) { - return false; - } String owningCollectionString = request.getParameter("owningCollection"); if (StringUtils.isBlank(owningCollectionString)) { return false; } try { - if (!authorizeService.isAdmin(context)) { - throw new AuthorizeException("Only admins are allowed to create items using external data"); - } Collection collection = collectionService.find(context, UUID.fromString(owningCollectionString)); if (collection == null) { return false; @@ -97,23 +83,19 @@ public class ExternalSourceEntryUriListHandler implements UriListHandler { return true; } - @Override - public Item handle(Context context, HttpServletRequest request, List uriList) + public WorkspaceItem createWorkspaceItem(Context context, HttpServletRequest request, List uriList) throws SQLException, AuthorizeException { ExternalDataObject dataObject = getExternalDataObjectFromUriList(uriList); String owningCollectionUuid = request.getParameter("owningCollection"); - Collection collection = null; - Item item = null; try { - collection = collectionService.find(context, UUID.fromString(owningCollectionUuid)); - item = externalDataService.createItemFromExternalDataObject(context, dataObject, collection); + Collection collection = collectionService.find(context, UUID.fromString(owningCollectionUuid)); + return externalDataService.createWorkspaceItemFromExternalDataObject(context, dataObject, collection); } catch (AuthorizeException | SQLException e) { log.error("An error occured when trying to create item in collection with uuid: " + owningCollectionUuid, e); throw e; } - return item; } /** @@ -138,5 +120,4 @@ public class ExternalSourceEntryUriListHandler implements UriListHandler { "Couldn't find an ExternalSource for source: " + externalSourceIdentifer + " and ID: " + id)); } - } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryWorkspaceItemUriListHandler.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryWorkspaceItemUriListHandler.java new file mode 100644 index 0000000000..353f24814e --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryWorkspaceItemUriListHandler.java @@ -0,0 +1,48 @@ +/** + * 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.rest.repository.handler; + +import java.sql.SQLException; +import java.util.List; +import javax.servlet.http.HttpServletRequest; + +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.WorkspaceItem; +import org.dspace.core.Context; +import org.springframework.stereotype.Component; + +@Component +public class ExternalSourceEntryWorkspaceItemUriListHandler + extends ExternalSourceEntryItemUriListHandler { + + @Override + public boolean supports(List uriList, String method, Class clazz) { + if (!super.supports(uriList, method, clazz)) { + return false; + } + if (clazz != WorkspaceItem.class) { + return false; + } + return true; + } + + @Override + public boolean validate(Context context, HttpServletRequest request, List uriList) + throws AuthorizeException { + + if (!super.validate(context, request, uriList)) { + return false; + } + return true; + } + + public WorkspaceItem handle(Context context, HttpServletRequest request, List uriList) + throws SQLException, AuthorizeException { + return super.createWorkspaceItem(context, request, uriList); + } +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/UriListHandler.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/UriListHandler.java index f3702f45ac..84d6522845 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/UriListHandler.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/UriListHandler.java @@ -25,9 +25,10 @@ public interface UriListHandler { * can handle this input or not * @param uriList The list of UriList Strings to be checked if they're supported * @param method The request method to be checked if it's supported + * @param clazz The class to be returned by the handle method * @return A boolean indicating whether the implementing UriListHandler can handle this input */ - boolean supports(List uriList, String method); + boolean supports(List uriList, String method, Class clazz); /** * This method will take all the required input and validate them to see if there are any issues before @@ -35,10 +36,9 @@ public interface UriListHandler { * @param context The relevant DSpace context * @param request The current request * @param uriList The list of UriList Strings - * @param clazz The class to be returned by the handle method * @return A boolean indicating whether all this input is valid for the implementing UriListHandler */ - boolean validate(Context context, HttpServletRequest request, List uriList, Class clazz) + boolean validate(Context context, HttpServletRequest request, List uriList) throws AuthorizeException; /** diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/service/UriListHandlerService.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/service/UriListHandlerService.java index 38139d31b7..30887fd4b1 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/service/UriListHandlerService.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/service/UriListHandlerService.java @@ -47,9 +47,9 @@ public class UriListHandlerService { // Loop all the uriListHandlers for (UriListHandler uriListHandler : uriListHandlers) { // Does the class support the given uri list and the request method - if (uriListHandler.supports(uriList, request.getMethod())) { + if (uriListHandler.supports(uriList, request.getMethod(), clazz)) { // Can the class handle the given uri list and can the given class, params and authorization be handled - if (uriListHandler.validate(context, request, uriList, clazz)) { + if (uriListHandler.validate(context, request, uriList)) { // If all these things succeed, call handle return (T) uriListHandler.handle(context, request, uriList); } else { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/SubmissionService.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/SubmissionService.java index 04da631083..59ae72f432 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/SubmissionService.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/SubmissionService.java @@ -92,7 +92,7 @@ public class SubmissionService { public WorkspaceItem createWorkspaceItem(Context context, Request request) throws SQLException, AuthorizeException { WorkspaceItem wsi = null; Collection collection = null; - String collectionUUID = request.getHttpServletRequest().getParameter("collection"); + String collectionUUID = request.getHttpServletRequest().getParameter("owningCollection"); if (StringUtils.isBlank(collectionUUID)) { collectionUUID = configurationService.getProperty("submission.default.collection"); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java index b797e489c5..847b582fcf 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java @@ -9,6 +9,8 @@ package org.dspace.app.rest; import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath; import static org.hamcrest.Matchers.is; +import static org.springframework.data.rest.webmvc.RestMediaTypes.TEXT_URI_LIST_VALUE; +import static org.springframework.http.MediaType.parseMediaType; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.fileUpload; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -26,6 +28,7 @@ import java.util.UUID; import javax.ws.rs.core.MediaType; +import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.CharEncoding; import org.dspace.app.rest.builder.BitstreamBuilder; @@ -35,6 +38,7 @@ import org.dspace.app.rest.builder.EPersonBuilder; import org.dspace.app.rest.builder.WorkspaceItemBuilder; import org.dspace.app.rest.matcher.CollectionMatcher; import org.dspace.app.rest.matcher.ItemMatcher; +import org.dspace.app.rest.matcher.MetadataMatcher; import org.dspace.app.rest.matcher.WorkspaceItemMatcher; import org.dspace.app.rest.model.patch.AddOperation; import org.dspace.app.rest.model.patch.Operation; @@ -50,6 +54,7 @@ import org.dspace.eperson.EPerson; import org.hamcrest.Matchers; import org.junit.Test; import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MvcResult; /** * Test suite for the WorkspaceItem endpoint @@ -445,14 +450,14 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration // create a workspaceitem explicitly in the col1 getClient(authToken).perform(post("/api/submission/workspaceitems") - .param("collection", col1.getID().toString()) + .param("owningCollection", col1.getID().toString()) .contentType(org.springframework.http.MediaType.APPLICATION_JSON)) .andExpect(status().isCreated()) .andExpect(jsonPath("$._embedded.collection.id", is(col1.getID().toString()))); // create a workspaceitem explicitly in the col2 getClient(authToken).perform(post("/api/submission/workspaceitems") - .param("collection", col2.getID().toString()) + .param("owningCollection", col2.getID().toString()) .contentType(org.springframework.http.MediaType.APPLICATION_JSON)) .andExpect(status().isCreated()) .andExpect(jsonPath("$._embedded.collection.id", is(col2.getID().toString()))); @@ -1625,4 +1630,209 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration ; } + + + + + + + + + @Test + public void createWorkspaceItemFromExternalSources() throws Exception { + //We turn off the authorization system in order to create the structure as defined below + context.turnOffAuthorisationSystem(); + //** GIVEN ** + //1. A community-collection structure with one parent community with sub-community and two collections. + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity) + .withName("Sub Community") + .build(); + Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build(); + + context.restoreAuthSystemState(); + + ObjectMapper mapper = new ObjectMapper(); + String token = getAuthToken(admin.getEmail(), password); + MvcResult mvcResult = getClient(token).perform(post("/api/submission/workspaceitems?owningCollection=" + + col1.getID().toString()) + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content("https://localhost:8080/server/api/integration/" + + "externalsources/mock/entryValues/one")) + .andExpect(status().isCreated()).andReturn(); + + String content = mvcResult.getResponse().getContentAsString(); + Map map = mapper.readValue(content, Map.class); + Integer workspaceItemId = (Integer) map.get("id"); + String itemUuidString = String.valueOf(((Map) ((Map) map.get("_embedded")).get("item")).get("uuid")); + + getClient(token).perform(get("/api/submission/workspaceitems/" + workspaceItemId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$", Matchers.allOf( + hasJsonPath("$.id", is(workspaceItemId)), + hasJsonPath("$.type", is("workspaceitem")), + hasJsonPath("$._embedded.item", Matchers.allOf( + hasJsonPath("$.id", is(itemUuidString)), + hasJsonPath("$.uuid", is(itemUuidString)), + hasJsonPath("$.type", is("item")), + hasJsonPath("$.metadata", Matchers.allOf( + MetadataMatcher.matchMetadata("dc.contributor.author", "Donald, Smith") + ))))) + )); + } + + @Test + public void createWorkspaceItemFromExternalSourcesNoOwningCollectionUuidBadRequest() throws Exception { + String token = getAuthToken(admin.getEmail(), password); + getClient(token).perform(post("/api/submission/workspaceitems") + .contentType(parseMediaType( + TEXT_URI_LIST_VALUE)) + .content("https://localhost:8080/server/api/integration/externalsources/" + + "mock/entryValues/one")) + .andExpect(status().isBadRequest()).andReturn(); + } + + @Test + public void createWorkspaceItemFromExternalSourcesRandomOwningCollectionUuidBadRequest() throws Exception { + String token = getAuthToken(admin.getEmail(), password); + getClient(token).perform(post("/api/submission/workspaceitems?owningCollection=" + UUID.randomUUID()) + .contentType(parseMediaType( + TEXT_URI_LIST_VALUE)) + .content("https://localhost:8080/server/api/integration/externalsources/" + + "mock/entryValues/one")) + .andExpect(status().isBadRequest()).andReturn(); + } + + @Test + public void createWorkspaceItemFromExternalSourcesWrongUriList() throws Exception { + //We turn off the authorization system in order to create the structure as defined below + context.turnOffAuthorisationSystem(); + //** GIVEN ** + //1. A community-collection structure with one parent community with sub-community and two collections. + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity) + .withName("Sub Community") + .build(); + Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build(); + + context.restoreAuthSystemState(); + + ObjectMapper mapper = new ObjectMapper(); + String token = getAuthToken(admin.getEmail(), password); + getClient(token).perform(post("/api/submission/workspaceitems?owningCollection=" + + col1.getID().toString()) + .contentType(parseMediaType( + TEXT_URI_LIST_VALUE)) + .content("https://localhost:8080/server/mock/mock/mock/" + + "mock/entryValues/one")).andExpect(status().isBadRequest()); + } + + @Test + public void createWorkspaceItemFromExternalSourcesWrongSourceBadRequest() throws Exception { + //We turn off the authorization system in order to create the structure as defined below + context.turnOffAuthorisationSystem(); + //** GIVEN ** + //1. A community-collection structure with one parent community with sub-community and two collections. + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity) + .withName("Sub Community") + .build(); + Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build(); + + context.restoreAuthSystemState(); + + String token = getAuthToken(admin.getEmail(), password); + getClient(token).perform(post("/api/submission/workspaceitems?owningCollection=" + + col1.getID().toString()) + .contentType(parseMediaType( + TEXT_URI_LIST_VALUE)) + .content("https://localhost:8080/server/api/integration/externalsources/" + + "mockWrongSource/entryValues/one")) + .andExpect(status().isBadRequest()); + + } + + @Test + public void createWorkspaceItemFromExternalSourcesWrongIdResourceNotFound() throws Exception { + //We turn off the authorization system in order to create the structure as defined below + context.turnOffAuthorisationSystem(); + //** GIVEN ** + //1. A community-collection structure with one parent community with sub-community and two collections. + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity) + .withName("Sub Community") + .build(); + Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build(); + + context.restoreAuthSystemState(); + + String token = getAuthToken(admin.getEmail(), password); + getClient(token).perform(post("/api/submission/workspaceitems?owningCollection=" + + col1.getID().toString()) + .contentType(parseMediaType( + TEXT_URI_LIST_VALUE)) + .content("https://localhost:8080/server/api/integration/externalsources/" + + "mock/entryValues/azeazezaezeaz")) + .andExpect(status().is(404)); + + } + + @Test + public void createWorkspaceItemFromExternalSourcesForbidden() throws Exception { + //We turn off the authorization system in order to create the structure as defined below + context.turnOffAuthorisationSystem(); + //** GIVEN ** + //1. A community-collection structure with one parent community with sub-community and two collections. + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity) + .withName("Sub Community") + .build(); + Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build(); + + context.restoreAuthSystemState(); + + String token = getAuthToken(eperson.getEmail(), password); + getClient(token).perform(post("/api/submission/workspaceitems?owningCollection=" + + col1.getID().toString()) + .contentType(parseMediaType( + TEXT_URI_LIST_VALUE)) + .content("https://localhost:8080/server/api/integration/externalsources/" + + "mock/entryValues/one")) + .andExpect(status().isForbidden()); + } + + @Test + public void createWorkspaceItemFromExternalSourcesUnauthorized() throws Exception { + //We turn off the authorization system in order to create the structure as defined below + context.turnOffAuthorisationSystem(); + //** GIVEN ** + //1. A community-collection structure with one parent community with sub-community and two collections. + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity) + .withName("Sub Community") + .build(); + Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build(); + + context.restoreAuthSystemState(); + + getClient().perform(post("/api/submission/workspaceitems?owningCollection=" + + col1.getID().toString()) + .contentType(parseMediaType( + TEXT_URI_LIST_VALUE)) + .content("https://localhost:8080/server/api/integration/externalsources/" + + "mock/entryValues/one")) + .andExpect(status().isUnauthorized()); + } } From e348cf031a380f789bb1231e2299b0f965f1cb3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Fri, 6 Dec 2019 11:21:26 +0000 Subject: [PATCH 050/125] setting name variants parameter --- dspace/config/submission-forms.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index d74891bec5..877e8615e0 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -616,6 +616,7 @@ isAuthorOfPublication openAIRECreatorConfiguration true + true Add an author @@ -884,6 +885,7 @@ isProjectOfPublication project true + false Add a related Funding @@ -1032,6 +1034,7 @@ isFundingAgencyOfProject openAIREFundingAgencyConfiguration false + false Add a Funding Agency @@ -1756,6 +1759,10 @@ ISNI - International Standard Name Identifier isni + + Other + + From 929262e9a6a3b482eef43557c3181b6b1d8fa74b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Fri, 6 Dec 2019 11:25:11 +0000 Subject: [PATCH 051/125] Indentation fix and allowing openAIRE specific discovery search configurations --- dspace/config/spring/api/discovery.xml | 2014 +++--------------------- 1 file changed, 217 insertions(+), 1797 deletions(-) diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index b29c59246c..3929c48711 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -1,1844 +1,264 @@ + - + + + + + + + + + + + + + + - 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/ - ---> - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - dc.rights - - - - - - - - - - - - - - - dc.rights - - - - - - - - dc.description.provenance - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - search.resourcetype:2 OR search.resourcetype:3 OR search.resourcetype:4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - dc.title - dc.contributor.author - dc.creator - dc.subject - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - search.resourcetype:2 OR search.resourcetype:3 OR search.resourcetype:4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - search.resourcetype:2 OR search.resourcetype:[8 TO 9] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - search.resourcetype:[10 TO 11] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - search.resourcetype:2 AND entityType_keyword:Publication - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - search.resourcetype:2 AND entityType_keyword:Person - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - search.resourcetype:2 AND entityType_keyword:Project - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - search.resourcetype:2 AND entityType_keyword:OrgUnit - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - search.resourcetype:2 AND entityType_keyword:JournalIssue - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - search.resourcetype:2 AND entityType_keyword:JournalVolume - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - search.resourcetype:2 AND entityType_keyword:Journal - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - search.resourcetype:2 AND (entityType_keyword:OrgUnit OR entityType_keyword:Person) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - search.resourcetype:2 AND entityType_keyword:OrgUnit AND dc.type:FundingOrganization - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - dc.title - - - - - - - - - - - relation.isAuthorOfPublication - - - - - - - - - - - relation.isProjectOfPublication - - - - - - - - - - - - relation.isOrgUnitOfPublication - - - - - - - - - - - relation.isPublicationOfJournalIssue - - - - - - - - - - - relation.isJournalOfPublication - - - - - - - - - - - dc.contributor.author - dc.creator - - - - - - - - - - - - - - - relationship.type - - - - - - - - - - - - - - dc.subject.* - - - - - - - - - - - - - - dc.date.issued - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - dc.type - - - - - - - - - dc.identifier - - - - - - - - - placeholder.placeholder.placeholder - - - - - - - - - - placeholder.placeholder.placeholder - - - - - - - - - person.jobTitle - - - - - - - - - - - - - - - person.knowsLanguage - - - - - - - - - - - - - person.birthDate - - - - - - - - - - - - - - - - + + + + + + + + person.familyName - - - - - - - - - - person.givenName - - - - - - - - - - - relation.isOrgUnitOfPerson - - - - - - - - - - - relation.isProjectOfPerson - - - - - - - - - - - relation.isPublicationOfAuthor - - - - - - - - - - - - organization.address.addressCountry - - - - - - - - - - - - - - - organization.address.addressLocality - - - - - - - - - - - - - - - organization.foundingDate - - - - - - - - - - - - - - - organization.legalName - + - - + + , + + + - - - - - relation.isPersonOfOrgUnit - + + + + + + + + organization.legalName + - - - - - - - relation.isProjectOfOrgUnit - + + + + + + + + person.familyName + person.givenName + + + + , - - - - - - - relation.isPublicationOfOrgUnit - + + + + + + + + organization.legalName + - - - - - - - creativework.keywords - + + + + + + + organization.legalName + - - - - - - - - - - - creativework.datePublished - + + + + + + + + + + publicationvolume.volumeNumber + - - - - - - - + + + + + + - - - - + + + + + + + + + + + + + + creativeworkseries.issn + + + + + + + dc.title + + + + + + + + + + + + + publicationissue.issueNumber - - - - - - - - - - - relation.isPublicationOfJournalIssue - - - - - - - - - - - publicationVolume.volumeNumber - - - - - - - - - - - relation.isIssueOfJournalVolume - - - - - - - - - - - relation.isJournalOfVolume - - - - - - - - - - - creativework.publisher - - - - - - - - - - - - - - - creativework.editor - - - - - - - - - - - - - - - relation.isVolumeOfJournal - - - - - - - - - - - - - - placeholder.placeholder.placeholder - + - - - - - - relation.isOrgUnitOfProject - + + + + + + + + + + dc.title + - - - - - - - - - - relation.isPersonOfProject - + + , - - - - - - - - relation.isPublicationOfProject - - - - + + + + + - - - - - relation.isContributorOfPublication - - - - + + + + - - - - - relation.isPublicationOfContributor - - - - + + + + - - - - - relation.isFundingAgencyOfProject - - - - + + + + - - - - - relation.isProjectOfFundingAgency - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + \ No newline at end of file From 7ec0733de0f2be4f3ff233a3c212cf8eb78d67da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Fri, 6 Dec 2019 11:26:17 +0000 Subject: [PATCH 052/125] reverting virtual metadata changes (they will be moved to oai_openaire PR) --- dspace/config/spring/api/virtual-metadata.xml | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/dspace/config/spring/api/virtual-metadata.xml b/dspace/config/spring/api/virtual-metadata.xml index c4c93d75d5..853d945a44 100644 --- a/dspace/config/spring/api/virtual-metadata.xml +++ b/dspace/config/spring/api/virtual-metadata.xml @@ -44,6 +44,19 @@ This value-ref should be a bean of type VirtualMetadataConfiguration --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dc.rights + + + + + + + + + + + + + + + dc.rights + + + + + + + + dc.description.provenance + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:2 OR search.resourcetype:3 OR search.resourcetype:4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dc.title + dc.contributor.author + dc.creator + dc.subject + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:2 OR search.resourcetype:3 OR search.resourcetype:4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:2 OR search.resourcetype:[8 TO 9] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:[10 TO 11] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:2 AND entityType_keyword:Publication + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:2 AND entityType_keyword:Person + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:2 AND entityType_keyword:Project + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:2 AND entityType_keyword:OrgUnit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:2 AND entityType_keyword:JournalIssue + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:2 AND entityType_keyword:JournalVolume + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:2 AND entityType_keyword:Journal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:2 AND (entityType_keyword:OrgUnit OR entityType_keyword:Person) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:2 AND entityType_keyword:OrgUnit AND dc.type:FundingOrganization + + + + + + + + + + + + + + + + + + - - - - - - - - - person.familyName - person.givenName - organization.legalName - - - - , - - - - - - - - - - - - - organization.legalName - + + + + + + + + + - - - - - - - - person.familyName - person.givenName - - - - , - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - organization.legalName - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - organization.legalName - - - - - - - - - - - - - - publicationvolume.volumeNumber - - - - - - - - - - - - - - - - - - - - - - - - creativeworkseries.issn - - - - - - + + + + + dc.title - + + + + + + + + + + + relation.isAuthorOfPublication + + + + + + + + + + + relation.isProjectOfPublication + + + + + + + + + + + + relation.isOrgUnitOfPublication + + + + + + + + + + + relation.isPublicationOfJournalIssue + + + + + + + + + + + relation.isJournalOfPublication + + + + + + + + + + + dc.contributor.author + dc.creator + + + + + + + + + + + + + + + relationship.type + + + + + + + + + + + + + + dc.subject.* + + + + + + + + + + + + + + dc.date.issued + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + - - - - - - + + + + + dc.type + + + + + + + + + dc.identifier + + + + + + + + + placeholder.placeholder.placeholder + + + + + + + + + + placeholder.placeholder.placeholder + + + + + + + + + person.jobTitle + + + + + + + + + + + + + + + person.knowsLanguage + + + + + + + + + + + + + person.birthDate + + + + + + + + + + + + + + + + + person.familyName + + + + + + + + + + + person.givenName + + + + + + + + + + + relation.isOrgUnitOfPerson + + + + + + + + + + + relation.isProjectOfPerson + + + + + + + + + + + relation.isPublicationOfAuthor + + + + + + + + + + + + organization.address.addressCountry + + + + + + + + + + + + + + + organization.address.addressLocality + + + + + + + + + + + + + + + organization.foundingDate + + + + + + + + + + + + + + + + organization.legalName + + + + + + + + + + + relation.isPersonOfOrgUnit + + + + + + + + + + + relation.isProjectOfOrgUnit + + + + + + + + + + + relation.isPublicationOfOrgUnit + + + + + + + + + + + creativework.keywords + + + + + + + + + + + + + + + creativework.datePublished + + + + + + + + + + + + + + + publicationissue.issueNumber - + + + + + + + + + + + relation.isPublicationOfJournalIssue + + + + + + + + + + + publicationVolume.volumeNumber + + + + + + + + + + + relation.isIssueOfJournalVolume + + + + + + + + + + + relation.isJournalOfVolume + + + + + + + + + + + creativework.publisher + + + + + + + + + + + + + + + creativework.editor + + + + + + + + + + + + + + + relation.isVolumeOfJournal + + + + + + + + + + + + + + placeholder.placeholder.placeholder + - - - - - - - - - - dc.title - + + + + + + relation.isOrgUnitOfProject + - - , + + + + + + + + + + relation.isPersonOfProject + + + - - - - - + + + + + + relation.isPublicationOfProject + + + + - - - - + + + + + relation.isContributorOfPublication + + + + - - - - + + + + + relation.isPublicationOfContributor + + + + - - - - + + + + + relation.isFundingAgencyOfProject + + + + - - - - + + + + + relation.isProjectOfFundingAgency + + + + - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dspace/config/spring/api/virtual-metadata.xml b/dspace/config/spring/api/virtual-metadata.xml index 853d945a44..3929c48711 100644 --- a/dspace/config/spring/api/virtual-metadata.xml +++ b/dspace/config/spring/api/virtual-metadata.xml @@ -21,10 +21,6 @@ - - - - @@ -44,19 +40,6 @@ This value-ref should be a bean of type VirtualMetadataConfiguration --> - - - - - - - - - - - - - - - - - - - - dc.title - - - - + From 0505ed9aa8480be69d5f4053901e0b03ac48c704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Mon, 9 Dec 2019 17:25:52 +0000 Subject: [PATCH 057/125] virtual metadata default settings and oai_openaire4 default transformation --- .../oai/metadataFormats/oai_openaire.xsl | 1866 ++--------------- .../crosswalks/oai/transformers/openaire4.xsl | 79 + dspace/config/crosswalks/oai/xoai.xml | 74 +- .../spring/api/virtual-metadata.xml.openaire4 | 448 ++++ 4 files changed, 817 insertions(+), 1650 deletions(-) create mode 100644 dspace/config/crosswalks/oai/transformers/openaire4.xsl create mode 100644 dspace/config/spring/api/virtual-metadata.xml.openaire4 diff --git a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl index 34f7f0865d..a450bf75a2 100644 --- a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl +++ b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl @@ -11,1663 +11,239 @@ --> - + xmlns:oaire="http://namespace.openaire.eu/schema/oaire/" xmlns:datacite="http://datacite.org/schema/kernel-4" + xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:doc="http://www.lyncode.com/xoai" + xmlns:rdf="http://www.w3.org/TR/rdf-concepts/" version="1.0"> + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - e-mail - - - mailto: - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + + + + + + + + + + + + + - - - - + + + + - + - - - - - - + + + + + + - - - - - - - AlternativeTitle - - - Subtitle - - - TranslatedTitle - - - Other - - - - + + + + + + + AlternativeTitle + + + Subtitle + + + TranslatedTitle + + + Other + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Supervisor - - - Editor - - - Other - - - - - - - - - - - - - - - - - - - - - - - - Supervisor - - - Editor - - - Other - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - http://doi.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - European Commission - Fundação para a Ciência e Tecnologia - Welcome Trust - - - - - - - - - 10.13039/501100008530 - 10.13039/501100001871 - 10.13039/100010269 - - - - - - - - - - - - - - - - - - - Available - - - - - Collected - - - - - Copyrighted - - - - - Created - - - - - - Submitted - - - - - Updated - - - - - Valid - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - http://purl.org/coar/resource_type/c_1162 - - annotation - - - - http://purl.org/coar/resource_type/c_0640 - - journal - - - - http://purl.org/coar/resource_type/c_6501 - - - literature - - journal article - - - - http://purl.org/coar/resource_type/c_b239 - - editorial - - - - http://purl.org/coar/resource_type/c_7a1f - - bachelor thesis - - - - http://purl.org/coar/resource_type/c_86bc - - bibliography - - - - http://purl.org/coar/resource_type/c_2f33 - - - literature - - book - - - - http://purl.org/coar/resource_type/c_3248 - - book part - - - - http://purl.org/coar/resource_type/c_ba08 - - book review - - - - http://purl.org/coar/resource_type/c_7ad9 - - website - - - - http://purl.org/coar/resource_type/c_e9a0 - - interactive resource - - - - http://purl.org/coar/resource_type/c_f744 - - conference proceedings - - - - http://purl.org/coar/resource_type/c_c94f - - conference object - - - - http://purl.org/coar/resource_type/c_5794 - - conference paper - - - - http://purl.org/coar/resource_type/c_6670 - - conference poster - - - - http://purl.org/coar/resource_type/c_3e5a - - contribution to journal - - - - http://purl.org/coar/resource_type/c_beb9 - - data paper - - - - http://purl.org/coar/resource_type/c_ddb1 - - - dataset - - dataset - - - - http://purl.org/coar/resource_type/c_db06 - - doctoral thesis - - - - http://purl.org/coar/resource_type/c_c513 - - image - - - - http://purl.org/coar/resource_type/c_8544 - - lecture - - - - http://purl.org/coar/resource_type/c_0857 - - letter - - - - http://purl.org/coar/resource_type/c_bdcc - - master thesis - - - - http://purl.org/coar/resource_type/c_8a7e - - moving image - - - - http://purl.org/coar/resource_type/c_2659 - - periodical - - - - http://purl.org/coar/resource_type/c_545b - - letter to the editor - - - - http://purl.org/coar/resource_type/c_15cd - - patent - - - - http://purl.org/coar/resource_type/c_816b - - preprint - - - - http://purl.org/coar/resource_type/c_93fc - - report - - - - http://purl.org/coar/resource_type/c_ba1f - - report part - - - - http://purl.org/coar/resource_type/c_baaf - - research proposal - - - - http://purl.org/coar/resource_type/c_efa0 - - review - - - - http://purl.org/coar/resource_type/c_5ce6 - - - software - - software - - - - http://purl.org/coar/resource_type/c_ecc8 - - still image - - - - http://purl.org/coar/resource_type/c_71bd - - technical documentation - - - - http://purl.org/coar/resource_type/c_393c - - workflow - - - - http://purl.org/coar/resource_type/c_8042 - - working paper - - - - http://purl.org/coar/resource_type/c_46ec - - thesis - - - - http://purl.org/coar/resource_type/c_12cc - - cartographic material - - - - http://purl.org/coar/resource_type/c_12cd - - map - - - - http://purl.org/coar/resource_type/c_12ce - - video - - - - http://purl.org/coar/resource_type/c_18cc - - sound - - - - http://purl.org/coar/resource_type/c_18cd - - musical composition - - - - http://purl.org/coar/resource_type/c_18cf - - text - - - - http://purl.org/coar/resource_type/c_18cp - - conference paper not in proceedings - - - - http://purl.org/coar/resource_type/c_18co - - conference poster not in proceedings - - - - http://purl.org/coar/resource_type/c_18cw - - musical notation - - - - http://purl.org/coar/resource_type/c_18ww - - internal report - - - - http://purl.org/coar/resource_type/c_18wz - - memorandum - - - - http://purl.org/coar/resource_type/c_18wq - - other type of report - - - - http://purl.org/coar/resource_type/c_186u - - policy report - - - - http://purl.org/coar/resource_type/c_18op - - project deliverable - - - - http://purl.org/coar/resource_type/c_18hj - - report to funding agency - - - - http://purl.org/coar/resource_type/c_18ws - - research report - - - - http://purl.org/coar/resource_type/c_18gh - - technical report - - - - http://purl.org/coar/resource_type/c_dcae04bc - - review article - - - - http://purl.org/coar/resource_type/c_2df8fbb1 - - research article - - - - http://purl.org/coar/resource_type/c_1843 - - - other research product - - other - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - http://purl.org/coar/access_right/c_abf2 - - - http://purl.org/coar/access_right/c_f1cf - - - http://purl.org/coar/access_right/c_16ec - - - http://purl.org/coar/access_right/c_14cb - - - - - - - - - - - - - - - open access - - - embargoed access - - - restricted access - - - metadata only access - - - - - - - - - - - - - - - - Handle - - - - - - DOI - - - - - - URL - - - - - - - - - - - - - - - - - - - - - - - - - - Creative Commons Attribution-NonCommercial-ShareAlike - - - Creative Commons Attribution-NonCommercial-NoDerivs - - - Creative Commons Attribution-NonCommercial - - - Creative Commons Attribution-ShareAlike - - - Creative Commons Attribution-NoDerivs - - - Creative Commons Attribution - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FOS - - - FOS - - - FOS - - - - - - - - - - - - - - - - - - - - - - - - - fulltext - - - - other - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ARK - - - arXiv - - - bibcode - - - DOI - - - EAN13 - - - EISSN - - - Handle - - - IGSN - - - ISBN - - - ISSN - - - ISTC - - - LISSN - - - LSID - - - PMID - - - PURL - - - UPC - - - URL - - - URN - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DOI - - - URL - - - - - IsVersionOf - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - http://purl.org/coar/version/c_ab4af688f83e57aa - - - http://purl.org/coar/version/c_970fb48d4fbd8a85 - - - http://purl.org/coar/version/c_b1a7d7d4d402bcce - - - http://purl.org/coar/version/c_71e4c1898caa6e32 - - - http://purl.org/coar/version/c_e19f295774971610 - - - http://purl.org/coar/version/c_be7fb7dd8ff6fe43 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dspace/config/crosswalks/oai/transformers/openaire4.xsl b/dspace/config/crosswalks/oai/transformers/openaire4.xsl new file mode 100644 index 0000000000..1b910d83e1 --- /dev/null +++ b/dspace/config/crosswalks/oai/transformers/openaire4.xsl @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + info:eu-repo/semantics/openAccess + + + info:eu-repo/semantics/openAccess + + + info:eu-repo/semantics/restrictedAccess + + + info:eu-repo/semantics/embargoedAccess + + + info:eu-repo/semantics/restrictedAccess + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dspace/config/crosswalks/oai/xoai.xml b/dspace/config/crosswalks/oai/xoai.xml index 9f83be4615..b2d227c5b3 100644 --- a/dspace/config/crosswalks/oai/xoai.xml +++ b/dspace/config/crosswalks/oai/xoai.xml @@ -20,7 +20,7 @@ - + This is the default context of the DSpace OAI-PMH data provider. @@ -71,7 +71,28 @@ This contexts complies with OpenAIRE Guidelines for Literature Repositories v3.0. - + + + + + + + + + + + This contexts complies with OpenAIRE Guidelines for Literature Repositories v4.0. + + + @@ -160,7 +181,7 @@ - + oai_openaire metadataFormats/oai_openaire.xsl http://namespace.openaire.eu/schema/oaire/ @@ -175,6 +196,9 @@ transformers/openaire.xsl + + transformers/openaire4.xsl + @@ -284,6 +308,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dspace/config/spring/api/virtual-metadata.xml.openaire4 b/dspace/config/spring/api/virtual-metadata.xml.openaire4 new file mode 100644 index 0000000000..a0cf0ca4fa --- /dev/null +++ b/dspace/config/spring/api/virtual-metadata.xml.openaire4 @@ -0,0 +1,448 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + person.familyName + person.givenName + organization.legalName + + + + , + + + + + + + + person.givenName + + + + + + + person.familyName + + + + + + + person.affiliation.name + + + + + + + person.identifier.scopus-author-id + + + + + + + person.identifier.rid + + + + + + + person.identifier.ciencia-id + + + + + + + person.identifier.gsid + + + + + + + person.identifier.orcid + + + + + + + person.identifier.isni + + + + + + + organization.legalName + + + + + + + organization.identifier + + + + + + + + + + + + organization.legalName + + + + + + + + + + + + person.familyName + person.givenName + + + + , + + + + + + + + + + + + + + organization.legalName + + + + + + + + organization.identifier + + + + + + + + + + + organization.legalName + + + + + + + + + + + + + + publicationvolume.volumeNumber + + + + + + + + + + + + + + + + + + + + + + + + creativeworkseries.issn + + + + + + + dc.title + + + + + + + + + + + + + + publicationissue.issueNumber + + + + + + + + + + + + + + dc.title + + + + , + + + + + + + + + + + + + + + + + dc.title + + + + + + + oaire.fundingStream + + + + + + + dc.identifier + + + + + + + dc.identifier.uri + + + + + + + organization.legalName + + + + + + + organization.identifier + + + + + + + + + + + + + organization.legalName + + + + + + + organization.identifier + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From f6d17aa0ba8d4cdc121f4a293d667c2daac70cdc Mon Sep 17 00:00:00 2001 From: Andrew Wood Date: Mon, 9 Dec 2019 16:04:55 -0500 Subject: [PATCH 058/125] DS-4401 Enforce relational place ordering when place direction is known --- .../java/org/dspace/content/dao/impl/RelationshipDAOImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dspace-api/src/main/java/org/dspace/content/dao/impl/RelationshipDAOImpl.java b/dspace-api/src/main/java/org/dspace/content/dao/impl/RelationshipDAOImpl.java index ed5a4260e8..53a2a0fb0b 100644 --- a/dspace-api/src/main/java/org/dspace/content/dao/impl/RelationshipDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/dao/impl/RelationshipDAOImpl.java @@ -145,11 +145,13 @@ public class RelationshipDAOImpl extends AbstractHibernateDAO impl .where(criteriaBuilder.equal(relationshipRoot.get(Relationship_.relationshipType), relationshipType), criteriaBuilder.equal(relationshipRoot.get(Relationship_.leftItem), item)); + criteriaQuery.orderBy(criteriaBuilder.asc(relationshipRoot.get(Relationship_.leftPlace))); } else { criteriaQuery .where(criteriaBuilder.equal(relationshipRoot.get(Relationship_.relationshipType), relationshipType), criteriaBuilder.equal(relationshipRoot.get(Relationship_.rightItem), item)); + criteriaQuery.orderBy(criteriaBuilder.asc(relationshipRoot.get(Relationship_.rightPlace))); } return list(context, criteriaQuery, true, Relationship.class, limit, offset); } From 5bf433f71b31ff9b3e7fc4a9a58acb50ad071a23 Mon Sep 17 00:00:00 2001 From: Kevin Van de Velde Date: Tue, 10 Dec 2019 14:16:54 +0100 Subject: [PATCH 059/125] DS-4351 Upgrade spring (boot) & hibernate to newer versions: Fixing issues with the latest master merge & fixing the tests --- .../dspace/content/EntityServiceImplTest.java | 17 ----------------- .../content/EntityTypeServiceImplTest.java | 3 --- .../content/RelationshipServiceImplTest.java | 3 --- .../org/dspace/content/virtual/RelatedTest.java | 1 - .../app/rest/BitstreamBundleController.java | 3 ++- .../rest/BundleUploadBitstreamController.java | 3 ++- .../rest/CollectionItemtemplateController.java | 3 ++- .../app/rest/CollectionLogoController.java | 3 ++- .../app/rest/CommunityLogoController.java | 3 ++- .../app/rest/ItemAddBundleController.java | 3 ++- .../app/rest/ItemtemplateRestController.java | 3 ++- .../dspace/app/rest/RestResourceController.java | 3 +-- .../app/rest/ScriptProcessesController.java | 3 ++- .../repository/CollectionRestRepository.java | 3 ++- .../repository/CommunityRestRepository.java | 3 ++- .../rest/repository/EPersonRestRepository.java | 3 ++- .../ExternalSourceRestRepository.java | 3 ++- .../rest/repository/GroupRestRepository.java | 3 ++- .../ItemRelationshipLinkRepository.java | 2 +- .../app/rest/repository/ItemRestRepository.java | 3 ++- .../rest/repository/ProcessRestRepository.java | 3 ++- .../repository/RelationshipRestRepository.java | 6 +++--- .../app/rest/AuthorityRestRepositoryIT.java | 2 +- .../rest/BitstreamFormatRestRepositoryIT.java | 2 +- .../dspace/app/rest/BundleRestRepositoryIT.java | 4 ++-- 25 files changed, 39 insertions(+), 49 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java b/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java index ce3838fbba..e56dfffd90 100644 --- a/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java +++ b/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java @@ -68,7 +68,6 @@ public class EntityServiceImplTest { // Mock the state of objects utilized in findByItemId() to meet the success criteria of an invocation when(itemService.find(any(), any())).thenReturn(item); when(item.getName()).thenReturn("ItemName"); - when(relationshipService.findByItem(any(), any())).thenReturn(relationshipList); // The returned Entity's item should match the mocked item's name assertEquals("TestFindByItem 0", "ItemName", @@ -142,9 +141,6 @@ public class EntityServiceImplTest { relationshipList.add(relationship); // Mock the state of objects utilized in getRelationsByType() to meet the success criteria of an invocation - when(relationshipService.findAll(context, -1, -1)).thenReturn(relationshipList); - when(relationship.getRelationshipType()).thenReturn(relationshipType); - when(relationshipType.getLeftwardType()).thenReturn("leftwardType"); when(relationshipService.findByTypeName(context, "leftwardType", -1, -1)).thenReturn(relationshipList); // The relation(s) reported from our defined type should match our relationshipList @@ -174,10 +170,6 @@ public class EntityServiceImplTest { when(metadataValue.getValue()).thenReturn("testType"); when(entity.getItem()).thenReturn(item); when(itemService.getMetadata(item, "relationship", "type", null, Item.ANY)).thenReturn(list); - when(relationshipTypeDAO.findAll(context, RelationshipType.class, -1, -1)).thenReturn(relationshipTypeList); - when(relationshipTypeService.findAll(context, -1, -1)).thenReturn(relationshipTypeList); - when(relationshipType.getLeftType()).thenReturn(leftType); - when(leftType.getID()).thenReturn(0); when(entityService.getType(context, entity)).thenReturn(leftType); // Mock when(relationshipTypeService.findByEntityType(context, entityService.getType(context, entity), -1, -1)) .thenReturn(relationshipTypeList); @@ -206,9 +198,6 @@ public class EntityServiceImplTest { // to meet the success criteria of the invocation when(itemService.getMetadata(any(), any(), any(), any(), any())).thenReturn(metsList); when(entity.getItem()).thenReturn(item); - when(entityType.getID()).thenReturn(0); - when(relationshipTypeService.findAll(context, -1, -1)).thenReturn(relationshipTypeList); - when(relationshipType.getLeftType()).thenReturn(entityType); when(entityService.getType(context, entity)).thenReturn(entityType); when(entityTypeService.findByEntityType(any(), any())).thenReturn(entityType); when(relationshipTypeService.findByEntityType(context, entityService.getType(context, entity), true, -1, -1)) @@ -238,9 +227,6 @@ public class EntityServiceImplTest { // to meet the success criteria of the invocation when(itemService.getMetadata(any(), any(), any(), any(), any())).thenReturn(metsList); when(entity.getItem()).thenReturn(item); - when(entityType.getID()).thenReturn(0); - when(relationshipTypeService.findAll(context, -1, -1)).thenReturn(relationshipTypeList); - when(relationshipType.getRightType()).thenReturn(entityType); when(entityService.getType(context, entity)).thenReturn(entityType); when(entityTypeService.findByEntityType(any(), any())).thenReturn(entityType); when(relationshipTypeService.findByEntityType(context, entityService.getType(context, entity), false, -1, -1)) @@ -261,9 +247,6 @@ public class EntityServiceImplTest { // Mock the state of objects utilized in getRelationshipTypesByTypeName() // to meet the success criteria of the invocation - when(relationshipTypeService.findAll(context, -1, -1)).thenReturn(list); - when(relationshipType.getLeftwardType()).thenReturn("leftwardType"); - when(relationshipType.getRightwardType()).thenReturn("rightwardType"); when(relationshipTypeService.findByLeftwardOrRightwardTypeName(context, "leftwardType", -1, -1)) .thenReturn(list); diff --git a/dspace-api/src/test/java/org/dspace/content/EntityTypeServiceImplTest.java b/dspace-api/src/test/java/org/dspace/content/EntityTypeServiceImplTest.java index 35cb147aa8..707323deb5 100644 --- a/dspace-api/src/test/java/org/dspace/content/EntityTypeServiceImplTest.java +++ b/dspace-api/src/test/java/org/dspace/content/EntityTypeServiceImplTest.java @@ -60,9 +60,6 @@ public class EntityTypeServiceImplTest { // Declare objects utilized in unit test List entityTypeList = new ArrayList<>(); - // Mock DAO to return our mocked entityTypeList - when(entityTypeDAO.findAll(context, EntityType.class)).thenReturn(entityTypeList); - // The EntityType(s) reported from our mocked state should match our entityTypeList assertEquals("TestFindAll 0", entityTypeList, entityTypeService.findAll(context)); } diff --git a/dspace-api/src/test/java/org/dspace/content/RelationshipServiceImplTest.java b/dspace-api/src/test/java/org/dspace/content/RelationshipServiceImplTest.java index 54affbc030..244f58bc6d 100644 --- a/dspace-api/src/test/java/org/dspace/content/RelationshipServiceImplTest.java +++ b/dspace-api/src/test/java/org/dspace/content/RelationshipServiceImplTest.java @@ -262,9 +262,6 @@ public class RelationshipServiceImplTest { .thenReturn(leftTypelist); when(relationshipService.findByItemAndRelationshipType(context, rightItem, testRel, false)) .thenReturn(rightTypelist); - when(itemService.getMetadata(leftItem, "relationship", "type", null, Item.ANY)).thenReturn(metsList); - when(itemService.getMetadata(rightItem, "relationship", "type", null, Item.ANY)).thenReturn(metsList); - when(relationshipDAO.create(any(), any())).thenReturn(relationship); when(relationshipService.find(context,0)).thenReturn(relationship); // Invoke delete() diff --git a/dspace-api/src/test/java/org/dspace/content/virtual/RelatedTest.java b/dspace-api/src/test/java/org/dspace/content/virtual/RelatedTest.java index 5a1a489a94..d24824fbd9 100644 --- a/dspace-api/src/test/java/org/dspace/content/virtual/RelatedTest.java +++ b/dspace-api/src/test/java/org/dspace/content/virtual/RelatedTest.java @@ -132,7 +132,6 @@ public class RelatedTest { // Mock the state of objects utilized in getRelationsByLabel() to meet the success criteria of an invocation when(item.getID()).thenReturn(UUID.randomUUID()); when(relationshipType.getLeftwardType()).thenReturn("LeftwardType"); - when(relationshipType.getRightwardType()).thenReturn("RightwardType"); when(relationshipType.getLeftType()).thenReturn(entityType); when(entityService.getAllRelationshipTypes(context, entity)).thenReturn(relationshipTypeList); when(entityService.findByItemId(context, item.getID())).thenReturn(entity); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamBundleController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamBundleController.java index a28ec5a9a7..ac29bf7699 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamBundleController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BitstreamBundleController.java @@ -36,6 +36,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ControllerUtils; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.hateoas.ResourceSupport; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PostAuthorize; @@ -109,7 +110,7 @@ public class BitstreamBundleController { BundleResource bundleResource = converter.toResource( converter.toRest(bundles.get(0), utils.obtainProjection())); - return ControllerUtils.toResponseEntity(HttpStatus.OK, null, bundleResource); + return ControllerUtils.toResponseEntity(HttpStatus.OK, new HttpHeaders(), bundleResource); } /** diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java index d7c0109e0c..7035e329f2 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java @@ -32,6 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ControllerUtils; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.hateoas.ResourceSupport; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -112,6 +113,6 @@ public class BundleUploadBitstreamController { context, bundle, uploadfile.getOriginalFilename(), fileInputStream, properties); BitstreamResource bitstreamResource = converter.toResource(bitstreamRest); - return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, bitstreamResource); + return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), bitstreamResource); } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionItemtemplateController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionItemtemplateController.java index 5bde7b3b91..eef1d3eec0 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionItemtemplateController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionItemtemplateController.java @@ -32,6 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ControllerUtils; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.hateoas.ResourceSupport; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -118,7 +119,7 @@ public class CollectionItemtemplateController { ItemRest templateItem = collectionRestRepository.createTemplateItem(context, collection, inputItemRest); context.commit(); - return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, + return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), new ItemResource(templateItem, utils)); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionLogoController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionLogoController.java index 15ada98ba4..76dec0555e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionLogoController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CollectionLogoController.java @@ -27,6 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ControllerUtils; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.hateoas.ResourceSupport; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -106,7 +107,7 @@ public class CollectionLogoController { BitstreamResource bitstreamResource = new BitstreamResource(bitstream, utils); context.complete(); - return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, bitstreamResource); + return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), bitstreamResource); } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CommunityLogoController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CommunityLogoController.java index b99c54e2a3..4b11320f97 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/CommunityLogoController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/CommunityLogoController.java @@ -28,6 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ControllerUtils; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.hateoas.ResourceSupport; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -108,7 +109,7 @@ public class CommunityLogoController { BitstreamResource bitstreamResource = new BitstreamResource(bitstream, utils); context.complete(); - return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, bitstreamResource); + return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), bitstreamResource); } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java index 8354e0048b..0532ff2d29 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java @@ -35,6 +35,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ControllerUtils; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.hateoas.ResourceSupport; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -108,7 +109,7 @@ public class ItemAddBundleController { Bundle bundle = itemRestRepository.addBundleToItem(context, item, bundleRest); BundleResource bundleResource = converter.toResource(converter.toRest(bundle, Projection.DEFAULT)); - return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, bundleResource); + return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), bundleResource); } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemtemplateRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemtemplateRestController.java index a47a5ce58a..c7979ff47f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemtemplateRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemtemplateRestController.java @@ -30,6 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ControllerUtils; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.hateoas.ResourceSupport; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -125,7 +126,7 @@ public class ItemtemplateRestController { ItemRest templateItem = itemRestRepository.patchTemplateItem(item, jsonNode); context.commit(); - return ControllerUtils.toResponseEntity(HttpStatus.OK, null, + return ControllerUtils.toResponseEntity(HttpStatus.OK, new HttpHeaders(), new ItemResource(templateItem, utils)); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/RestResourceController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/RestResourceController.java index 7e730c279c..1ed65887aa 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/RestResourceController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/RestResourceController.java @@ -70,7 +70,6 @@ import org.springframework.hateoas.PagedResources; import org.springframework.hateoas.ResourceSupport; import org.springframework.hateoas.Resources; import org.springframework.hateoas.UriTemplate; -import org.springframework.hateoas.mvc.ControllerLinkBuilder; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -229,7 +228,7 @@ public class RestResourceController implements InitializingBean { if (!modelObject.isPresent()) { throw new ResourceNotFoundException(apiCategory + "." + model + " with id: " + id + " not found"); } - return converter.toResource(modelObject); + return converter.toResource(modelObject.get()); } /** diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ScriptProcessesController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ScriptProcessesController.java index 0b0e1922b8..43788dfd1f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ScriptProcessesController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ScriptProcessesController.java @@ -17,6 +17,7 @@ import org.dspace.app.rest.repository.ScriptRestRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ControllerUtils; import org.springframework.hateoas.ResourceSupport; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -56,7 +57,7 @@ public class ScriptProcessesController { } ProcessRest processRest = scriptRestRepository.startProcess(scriptName); ProcessResource processResource = converter.toResource(processRest); - return ControllerUtils.toResponseEntity(HttpStatus.ACCEPTED, null, processResource); + return ControllerUtils.toResponseEntity(HttpStatus.ACCEPTED, new HttpHeaders(), processResource); } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionRestRepository.java index dac574d2ee..8c8853e6e7 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CollectionRestRepository.java @@ -95,7 +95,8 @@ public class CollectionRestRepository extends DSpaceObjectRestRepository findAll(Context context, Pageable pageable) { try { long total = cs.countTotal(context); - List collections = cs.findAll(context, pageable.getPageSize(), Math.toIntExact(pageable.getOffset())); + List collections = cs.findAll(context, pageable.getPageSize(), + Math.toIntExact(pageable.getOffset())); return converter.toRestPage(collections, pageable, total, utils.obtainProjection(true)); } catch (SQLException e) { throw new RuntimeException(e.getMessage(), e); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityRestRepository.java index c50d212dfa..94d5670713 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/CommunityRestRepository.java @@ -149,7 +149,8 @@ public class CommunityRestRepository extends DSpaceObjectRestRepository findAll(Context context, Pageable pageable) { try { long total = cs.countTotal(context); - List communities = cs.findAll(context, pageable.getPageSize(), Math.toIntExact(pageable.getOffset())); + List communities = cs.findAll(context, pageable.getPageSize(), + Math.toIntExact(pageable.getOffset())); return converter.toRestPage(communities, pageable, total, utils.obtainProjection(true)); } catch (SQLException e) { throw new RuntimeException(e.getMessage(), e); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EPersonRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EPersonRestRepository.java index 1499d4b80f..3153574cac 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EPersonRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EPersonRestRepository.java @@ -112,7 +112,8 @@ public class EPersonRestRepository extends DSpaceObjectRestRepository findAll(Context context, Pageable pageable) { try { long total = es.countTotal(context); - List epersons = es.findAll(context, EPerson.EMAIL, pageable.getPageSize(), Math.toIntExact(pageable.getOffset())); + List epersons = es.findAll(context, EPerson.EMAIL, pageable.getPageSize(), + Math.toIntExact(pageable.getOffset())); return converter.toRestPage(epersons, pageable, total, utils.obtainProjection(true)); } catch (SQLException e) { throw new RuntimeException(e.getMessage(), e); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ExternalSourceRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ExternalSourceRestRepository.java index 5bf84a3d57..5032a73645 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ExternalSourceRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ExternalSourceRestRepository.java @@ -70,7 +70,8 @@ public class ExternalSourceRestRepository extends DSpaceRestRepository externalDataObjects = externalDataService - .searchExternalDataObjects(externalSourceName, query, pageable.getOffset(), pageable.getPageSize()); + .searchExternalDataObjects(externalSourceName, query, Math.toIntExact(pageable.getOffset()), + pageable.getPageSize()); int numberOfResults = externalDataService.getNumberOfResults(externalSourceName, query); return converter.toRestPage(externalDataObjects, pageable, numberOfResults, utils.obtainProjection(true)); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupRestRepository.java index 31e4585f2c..274180d1bf 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/GroupRestRepository.java @@ -98,7 +98,8 @@ public class GroupRestRepository extends DSpaceObjectRestRepository findAll(Context context, Pageable pageable) { try { long total = gs.countTotal(context); - List groups = gs.findAll(context, null, pageable.getPageSize(), Math.toIntExact(pageable.getOffset())); + List groups = gs.findAll(context, null, pageable.getPageSize(), + Math.toIntExact(pageable.getOffset())); return converter.toRestPage(groups, pageable, total, utils.obtainProjection(true)); } catch (SQLException e) { throw new RuntimeException(e.getMessage(), e); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRelationshipLinkRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRelationshipLinkRepository.java index 4c76dc2274..f51a39258e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRelationshipLinkRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRelationshipLinkRepository.java @@ -53,7 +53,7 @@ public class ItemRelationshipLinkRepository extends AbstractDSpaceRestRepository } Pageable pageable = optionalPageable != null ? optionalPageable : new PageRequest(0, 20); Integer limit = pageable == null ? null : pageable.getPageSize(); - Integer offset = pageable == null ? null : pageable.getOffset(); + Integer offset = pageable == null ? null : Math.toIntExact(pageable.getOffset()); int total = relationshipService.countByItem(context, item); List relationships = relationshipService.findByItem(context, item, limit, offset); return converter.toRestPage(relationships, pageable, total, projection); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java index 6db62a5dbc..1ee570c4a9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ItemRestRepository.java @@ -122,7 +122,8 @@ public class ItemRestRepository extends DSpaceObjectRestRepository findAll(Context context, Pageable pageable) { try { long total = itemService.countTotal(context); - Iterator it = itemService.findAll(context, pageable.getPageSize(), Math.toIntExact(pageable.getOffset())); + Iterator it = itemService.findAll(context, pageable.getPageSize(), + Math.toIntExact(pageable.getOffset())); List items = new ArrayList<>(); while (it.hasNext()) { items.add(it.next()); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ProcessRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ProcessRestRepository.java index ebfdb4d2a6..e49e33f9fe 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ProcessRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ProcessRestRepository.java @@ -52,7 +52,8 @@ public class ProcessRestRepository extends DSpaceRestRepository findAll(Context context, Pageable pageable) { try { int total = processService.countTotal(context); - List processes = processService.findAll(context, pageable.getPageSize(), pageable.getOffset()); + List processes = processService.findAll(context, pageable.getPageSize(), + Math.toIntExact(pageable.getOffset())); return converter.toRestPage(processes, pageable, total, utils.obtainProjection(true)); } catch (SQLException e) { throw new RuntimeException(e.getMessage(), e); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RelationshipRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RelationshipRestRepository.java index d0921a0b34..55bdb1d620 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RelationshipRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RelationshipRestRepository.java @@ -85,7 +85,7 @@ public class RelationshipRestRepository extends DSpaceRestRepository relationships = relationshipService.findAll(context, - pageable.getPageSize(), pageable.getOffset()); + pageable.getPageSize(), Math.toIntExact(pageable.getOffset())); return converter.toRestPage(relationships, pageable, total, utils.obtainProjection(true)); } catch (SQLException e) { throw new RuntimeException(e.getMessage(), e); @@ -353,13 +353,13 @@ public class RelationshipRestRepository extends DSpaceRestRepository Date: Tue, 10 Dec 2019 14:55:48 +0100 Subject: [PATCH 060/125] Entities submission configuration --- .../src/test/data/dspaceFolder/config/submission-forms.xml | 2 +- .../java/org/dspace/app/rest/SubmissionFormsControllerIT.java | 2 +- dspace/config/submission-forms.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml b/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml index e0ec2dc60a..50855a76ea 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml @@ -52,7 +52,7 @@ isAuthorOfPublication - personConfiguration + person true true diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionFormsControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionFormsControllerIT.java index 756d86d798..4b36b4190a 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionFormsControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionFormsControllerIT.java @@ -116,7 +116,7 @@ public class SubmissionFormsControllerIT extends AbstractControllerIntegrationTe SubmissionFormFieldMatcher.matchFormOpenRelationshipFieldDefinition("name", "Author", null, true,"Add an author", "dc.contributor.author", "isAuthorOfPublication", null, - "personConfiguration", true)))) + "person", true)))) ; } diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index 52d4cf4ce9..60c281a10b 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -51,7 +51,7 @@ isAuthorOfPublication - personConfiguration + person true Add an author From 7130e5d3d255ce5600a252d9806a0e6239cc6ab6 Mon Sep 17 00:00:00 2001 From: Ben Bosman Date: Tue, 10 Dec 2019 15:05:44 +0100 Subject: [PATCH 061/125] Entities submission configuration --- .../dspaceFolder/config/submission-forms.xml | 2 +- .../app/rest/SubmissionFormsControllerIT.java | 2 +- dspace/config/submission-forms.xml | 26 ++++++++++++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml b/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml index 50855a76ea..6ddfef9b83 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml @@ -238,7 +238,7 @@ it, please enter the types and the actual numbers or codes. isVolumeOfJournal - periodicalConfiguration + periodical creativework.publisher:somepublishername Select the journal related to this volume. diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionFormsControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionFormsControllerIT.java index 4b36b4190a..f024d38c92 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionFormsControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SubmissionFormsControllerIT.java @@ -139,7 +139,7 @@ public class SubmissionFormsControllerIT extends AbstractControllerIntegrationTe .andExpect(jsonPath("$.rows[0].fields", contains( SubmissionFormFieldMatcher.matchFormClosedRelationshipFieldDefinition("Journal", null, false,"Select the journal related to this volume.", "isVolumeOfJournal", - "creativework.publisher:somepublishername", "periodicalConfiguration", false)))) + "creativework.publisher:somepublishername", "periodical", false)))) ; } } diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index 60c281a10b..423d3f2da6 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -188,6 +188,22 @@
+ + + isJournalIssueOfPublication + publicationIssue + + Select the journal issue related to this publication. + + + + + isOrgUnitOfPublication + organization + + Select the Organizational Unit related to this publication. + + dc @@ -306,6 +322,14 @@ Enter the job title of the person + + + isOrgUnitOfPerson + organization + + Select the Organizational Unit this is part of. + +
@@ -491,7 +515,7 @@ isVolumeOfJournal - periodicalConfiguration + periodical creativework.publisher:somepublishername Select the journal related to this volume. From eda9a8fcaa12c08830d4e5009181ad29d1e6e927 Mon Sep 17 00:00:00 2001 From: Ben Bosman Date: Tue, 10 Dec 2019 15:47:46 +0100 Subject: [PATCH 062/125] Entities submission configuration --- dspace/config/submission-forms.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index 423d3f2da6..b2ffc23758 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -200,6 +200,7 @@ isOrgUnitOfPublication organization + true Select the Organizational Unit related to this publication. From 1c6d262c03a3772cdb625494f9606d0f10a5bcda Mon Sep 17 00:00:00 2001 From: Kevin Van de Velde Date: Tue, 10 Dec 2019 15:58:11 +0100 Subject: [PATCH 063/125] DS-4351 Upgrade spring (boot) & hibernate to newer versions: Fixing issues with the latest master merge --- dspace-server-webapp/pom.xml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/dspace-server-webapp/pom.xml b/dspace-server-webapp/pom.xml index 6a947544e4..d75511028e 100644 --- a/dspace-server-webapp/pom.xml +++ b/dspace-server-webapp/pom.xml @@ -209,6 +209,18 @@ provided
--> + + org.springframework.boot + spring-boot-starter-web + ${spring-boot.version} + + + org.springframework.boot + spring-boot-starter-tomcat + provided + ${spring-boot.version} + + org.springframework.boot spring-boot-starter-data-rest @@ -273,6 +285,11 @@ dspace-api + + org.dspace + dspace-services + + @@ -292,6 +309,14 @@ dspace-swordv2 + + org.apache.commons + commons-collections4 + + + joda-time + joda-time + com.fasterxml.jackson.core jackson-databind From d687ff33909c06d7030dd19cc3dda21baaa59e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Tue, 10 Dec 2019 17:34:44 +0000 Subject: [PATCH 064/125] enhancing comments and rename bean from openAIREAuthor to a more generic personOrOrganization --- dspace/config/spring/api/discovery.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index b29c59246c..3389287ffc 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -63,8 +63,8 @@ - - + + @@ -955,9 +955,9 @@ - - + @@ -1069,7 +1069,7 @@ queries done by discovery for this configuration --> - + search.resourcetype:2 AND entityType_keyword:OrgUnit AND dc.type:FundingOrganization From 713f0caa89a6fc27981f04f0c5a6aa8dafb4fa3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Tue, 10 Dec 2019 17:35:59 +0000 Subject: [PATCH 065/125] removing form-value-pairs for language iso 3 and replacing with the default also adding portuguese to the default languages list --- dspace/config/submission-forms.xml | 61 +++++------------------------- 1 file changed, 9 insertions(+), 52 deletions(-) diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index 877e8615e0..3bc523909d 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -825,7 +825,7 @@ iso false - dropdown + dropdown Select the language of the main content of the item. If the language does not appear in the list, please select 'Other'. If the content does not really have a language (for example, if it is a dataset or an image) please select 'N/A'. @@ -1289,6 +1289,14 @@ Turkish tr + + Portuguese + pt + + + Turkish + tr + (Other) other @@ -1664,57 +1672,6 @@ - - - N/A - - - - English (United States) - eng - - - English - eng - - - Spanish - spa - - - German - deu - - - French - fra - - - Italian - ita - - - Japanese - jpn - - - Chinese - zho - - - Portuguese - por - - - Turkish - tur - - - (Other) - other - - - open access From 35d743601a20807ad3f634b948cc1e9c2cd64b0d Mon Sep 17 00:00:00 2001 From: Ben Bosman Date: Tue, 10 Dec 2019 18:39:03 +0100 Subject: [PATCH 066/125] Entities submission configuration --- dspace/config/submission-forms.xml | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index b2ffc23758..e15d28276a 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -188,23 +188,6 @@
- - - isJournalIssueOfPublication - publicationIssue - - Select the journal issue related to this publication. - - - - - isOrgUnitOfPublication - organization - true - - Select the Organizational Unit related to this publication. - - dc @@ -323,14 +306,6 @@ Enter the job title of the person - - - isOrgUnitOfPerson - organization - - Select the Organizational Unit this is part of. - -
From cbfc5c826d8622cd32c369c90e79354c67be268c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Tue, 10 Dec 2019 17:46:04 +0000 Subject: [PATCH 067/125] moving openAIRE submission steps to just before the sample item --- dspace/config/item-submission.xml | 55 +++++++++++++++---------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/dspace/config/item-submission.xml b/dspace/config/item-submission.xml index 9e33987789..af707162ae 100644 --- a/dspace/config/item-submission.xml +++ b/dspace/config/item-submission.xml @@ -106,34 +106,6 @@ submission - - - submit.progressbar.describe.stepone - org.dspace.app.rest.submit.step.DescribeStep - submission-form - - - - submit.progressbar.describe.stepone - org.dspace.app.rest.submit.step.DescribeStep - submission-form - - - submit.progressbar.describe.stepone - org.dspace.app.rest.submit.step.DescribeStep - submission-form - - - submit.progressbar.describe.stepone - org.dspace.app.rest.submit.step.DescribeStep - submission-form - - - submit.progressbar.describe.stepone - org.dspace.app.rest.submit.step.DescribeStep - submission-form - - + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + + submit.progressbar.describe.stepone + org.dspace.app.rest.submit.step.DescribeStep + submission-form + + Sample From 351c3debac9c14dd0c7878d12b431958d17b0312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Tue, 10 Dec 2019 17:55:08 +0000 Subject: [PATCH 068/125] adding a catch all person.identifier field --- dspace/config/registries/schema-person-types.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dspace/config/registries/schema-person-types.xml b/dspace/config/registries/schema-person-types.xml index 09cfbb6036..aa975b9132 100644 --- a/dspace/config/registries/schema-person-types.xml +++ b/dspace/config/registries/schema-person-types.xml @@ -88,6 +88,11 @@ + + person + identifier + Generic Identifier + person From ea914a42aed8a86d0f395bafbc5c4c26193a7553 Mon Sep 17 00:00:00 2001 From: Ben Bosman Date: Wed, 11 Dec 2019 14:52:15 +0100 Subject: [PATCH 069/125] Default Entities relationship types used for the demos --- .../entities/openaire4-relationships.xml | 2 +- ...lationships.dtd => relationship-types.dtd} | 4 +- dspace/config/entities/relationship-types.xml | 135 ++++++++++++++++++ 3 files changed, 139 insertions(+), 2 deletions(-) rename dspace/config/entities/{relationships.dtd => relationship-types.dtd} (76%) create mode 100644 dspace/config/entities/relationship-types.xml diff --git a/dspace/config/entities/openaire4-relationships.xml b/dspace/config/entities/openaire4-relationships.xml index f1c57658c5..daa0e2c1da 100644 --- a/dspace/config/entities/openaire4-relationships.xml +++ b/dspace/config/entities/openaire4-relationships.xml @@ -1,5 +1,5 @@ - + diff --git a/dspace/config/entities/relationships.dtd b/dspace/config/entities/relationship-types.dtd similarity index 76% rename from dspace/config/entities/relationships.dtd rename to dspace/config/entities/relationship-types.dtd index 1a050d7b55..bf434a4462 100644 --- a/dspace/config/entities/relationships.dtd +++ b/dspace/config/entities/relationship-types.dtd @@ -2,11 +2,13 @@ - + + + diff --git a/dspace/config/entities/relationship-types.xml b/dspace/config/entities/relationship-types.xml new file mode 100644 index 0000000000..4840afdc0e --- /dev/null +++ b/dspace/config/entities/relationship-types.xml @@ -0,0 +1,135 @@ + + + + + + + + Publication + Person + isAuthorOfPublication + isPublicationOfAuthor + + 0 + + + 0 + + true + + + Publication + Project + isProjectOfPublication + isPublicationOfProject + + 0 + + + 0 + + true + + + Publication + OrgUnit + isOrgUnitOfPublication + isPublicationOfOrgUnit + + 0 + + + 0 + + true + + + Person + Project + isProjectOfPerson + isPersonOfProject + + 0 + + + 0 + + + + Person + OrgUnit + isOrgUnitOfPerson + isPersonOfOrgUnit + + 0 + + + 0 + + + + Project + OrgUnit + isOrgUnitOfProject + isProjectOfOrgUnit + + 0 + + + 0 + + + + Journal + JournalVolume + isVolumeOfJournal + isJournalOfVolume + + 0 + + + 1 + + + + JournalVolume + JournalIssue + isIssueOfJournalVolume + isJournalVolumeOfIssue + + 0 + + + 1 + 1 + + + + Publication + OrgUnit + isAuthorOfPublication + isPublicationOfAuthor + + 0 + + + 0 + + true + + + JournalIssue + Publication + isPublicationOfJournalIssue + isJournalIssueOfPublication + + 0 + + + 0 + 1 + + true + + \ No newline at end of file From 35e9e3ed5d7b4df4cdac0fb58e33f78591229db2 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Wed, 11 Dec 2019 15:23:17 +0100 Subject: [PATCH 070/125] [Task 67817] first fix for the relationshiptypes for entitytype endpoint --- .../rest/RelationshipTypeRestController.java | 31 +++++++++---------- .../relation/EntityTypeHalLinkFactory.java | 2 +- ...shipTypeResourceWrapperHalLinkFactory.java | 2 +- .../model/RelationshipTypeRestWrapper.java | 4 +++ 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/RelationshipTypeRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/RelationshipTypeRestController.java index 490eefb6c4..a1a0525b2f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/RelationshipTypeRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/RelationshipTypeRestController.java @@ -17,6 +17,7 @@ import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.link.HalLinkService; import org.dspace.app.rest.model.RelationshipTypeRest; import org.dspace.app.rest.model.RelationshipTypeRestWrapper; +import org.dspace.app.rest.model.hateoas.RelationshipTypeResource; import org.dspace.app.rest.model.hateoas.RelationshipTypeResourceWrapper; import org.dspace.app.rest.projection.Projection; import org.dspace.app.rest.utils.ContextUtil; @@ -27,6 +28,10 @@ import org.dspace.content.service.EntityTypeService; import org.dspace.content.service.RelationshipTypeService; import org.dspace.core.Context; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.web.PagedResourcesAssembler; +import org.springframework.hateoas.PagedResources; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -68,28 +73,22 @@ public class RelationshipTypeRestController { * @throws SQLException If something goes wrong */ @RequestMapping(method = RequestMethod.GET) - public RelationshipTypeResourceWrapper retrieve(@PathVariable Integer id, - HttpServletResponse response, - HttpServletRequest request) throws SQLException { + public PagedResources retrieve(@PathVariable Integer id, + HttpServletResponse response, + HttpServletRequest request, + Pageable pageable, + PagedResourcesAssembler assembler) throws SQLException { Context context = ContextUtil.obtainContext(request); EntityType entityType = entityTypeService.find(context, id); List list = relationshipTypeService.findByEntityType(context, entityType, -1, -1); - List relationshipTypeRests = new LinkedList<>(); + Page relationshipTypeRestPage = converter.toRestPage(list, pageable, list.size(), utils.obtainProjection(true)); - Projection projection = utils.obtainProjection(); - for (RelationshipType relationshipType : list) { - relationshipTypeRests.add(converter.toRest(relationshipType, projection)); - } + Page relationshipTypeResources = relationshipTypeRestPage.map(relationshipTypeRest -> new RelationshipTypeResource(relationshipTypeRest, utils)); + relationshipTypeResources.forEach(halLinkService::addLinks); + PagedResources result = assembler.toResource(relationshipTypeResources); + return result; - RelationshipTypeRestWrapper relationshipTypeRestWrapper = new RelationshipTypeRestWrapper(); - relationshipTypeRestWrapper.setProjection(projection); - relationshipTypeRestWrapper.setEntityTypeId(id); - relationshipTypeRestWrapper.setEntityTypeLabel(entityType.getLabel()); - relationshipTypeRestWrapper.setRelationshipTypeRestList(relationshipTypeRests); - RelationshipTypeResourceWrapper relationshipTypeResourceWrapper = - converter.toResource(relationshipTypeRestWrapper); - return relationshipTypeResourceWrapper; } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/relation/EntityTypeHalLinkFactory.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/relation/EntityTypeHalLinkFactory.java index 326caa7eef..d2741181c1 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/relation/EntityTypeHalLinkFactory.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/relation/EntityTypeHalLinkFactory.java @@ -28,7 +28,7 @@ public class EntityTypeHalLinkFactory extends HalLinkFactory list) throws Exception { list.add(buildLink("relationshiptypes", getMethodOn().retrieve( - halResource.getContent().getId(), null, null))); + halResource.getContent().getId(), null, null, null, null))); } @Override diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/relation/RelationshipTypeResourceWrapperHalLinkFactory.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/relation/RelationshipTypeResourceWrapperHalLinkFactory.java index f3dccbddbd..2fbf9c7c13 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/relation/RelationshipTypeResourceWrapperHalLinkFactory.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/relation/RelationshipTypeResourceWrapperHalLinkFactory.java @@ -30,7 +30,7 @@ public class RelationshipTypeResourceWrapperHalLinkFactory protected void addLinks(RelationshipTypeResourceWrapper halResource, Pageable pageable, LinkedList list) throws Exception { list.add(buildLink(Link.REL_SELF, getMethodOn() - .retrieve(halResource.getContent().getEntityTypeId(), null, null))); + .retrieve(halResource.getContent().getEntityTypeId(), null, null, null, null))); } @Override diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipTypeRestWrapper.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipTypeRestWrapper.java index 2aa0891005..dcb604d605 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipTypeRestWrapper.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipTypeRestWrapper.java @@ -10,6 +10,7 @@ package org.dspace.app.rest.model; import java.util.List; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import org.dspace.app.rest.RelationshipTypeRestController; /** @@ -23,7 +24,9 @@ public class RelationshipTypeRestWrapper extends RestAddressableModel { @JsonIgnore private List relationshipTypeRestList; + @JsonIgnore private String entityTypeLabel; + @JsonIgnore private Integer entityTypeId; public List getRelationshipTypeRestList() { @@ -43,6 +46,7 @@ public class RelationshipTypeRestWrapper extends RestAddressableModel { return RelationshipTypeRestController.class; } + @JsonIgnore public String getType() { return "relationshiptype"; } From 2f870cbe78428e64813c63adb9363dc7aa52fc86 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Wed, 11 Dec 2019 16:07:38 +0100 Subject: [PATCH 071/125] [Task 67817] cleaned up code --- .../rest/RelationshipTypeRestController.java | 12 ++-- ...shipTypeResourceWrapperHalLinkFactory.java | 45 ------------ .../model/RelationshipTypeRestWrapper.java | 69 ------------------- .../RelationshipTypeResourceWrapper.java | 41 ----------- 4 files changed, 5 insertions(+), 162 deletions(-) delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/link/relation/RelationshipTypeResourceWrapperHalLinkFactory.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipTypeRestWrapper.java delete mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/model/hateoas/RelationshipTypeResourceWrapper.java diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/RelationshipTypeRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/RelationshipTypeRestController.java index a1a0525b2f..1512102c3d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/RelationshipTypeRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/RelationshipTypeRestController.java @@ -8,7 +8,6 @@ package org.dspace.app.rest; import java.sql.SQLException; -import java.util.LinkedList; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -16,10 +15,7 @@ import javax.servlet.http.HttpServletResponse; import org.dspace.app.rest.converter.ConverterService; import org.dspace.app.rest.link.HalLinkService; import org.dspace.app.rest.model.RelationshipTypeRest; -import org.dspace.app.rest.model.RelationshipTypeRestWrapper; import org.dspace.app.rest.model.hateoas.RelationshipTypeResource; -import org.dspace.app.rest.model.hateoas.RelationshipTypeResourceWrapper; -import org.dspace.app.rest.projection.Projection; import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.Utils; import org.dspace.content.EntityType; @@ -69,7 +65,7 @@ public class RelationshipTypeRestController { * @param id The ID of the EntityType objects that we'll use to retrieve the RelationshipTypes * @param response The response object * @param request The request object - * @return The wrapped resource containing the list of RelationshipType objects as defined above + * @return The wrapped resource containing the list of RelationshipType objects as defined above * @throws SQLException If something goes wrong */ @RequestMapping(method = RequestMethod.GET) @@ -82,9 +78,11 @@ public class RelationshipTypeRestController { EntityType entityType = entityTypeService.find(context, id); List list = relationshipTypeService.findByEntityType(context, entityType, -1, -1); - Page relationshipTypeRestPage = converter.toRestPage(list, pageable, list.size(), utils.obtainProjection(true)); + Page relationshipTypeRestPage = converter + .toRestPage(list, pageable, list.size(), utils.obtainProjection(true)); - Page relationshipTypeResources = relationshipTypeRestPage.map(relationshipTypeRest -> new RelationshipTypeResource(relationshipTypeRest, utils)); + Page relationshipTypeResources = relationshipTypeRestPage + .map(relationshipTypeRest -> new RelationshipTypeResource(relationshipTypeRest, utils)); relationshipTypeResources.forEach(halLinkService::addLinks); PagedResources result = assembler.toResource(relationshipTypeResources); return result; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/relation/RelationshipTypeResourceWrapperHalLinkFactory.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/relation/RelationshipTypeResourceWrapperHalLinkFactory.java deleted file mode 100644 index 2fbf9c7c13..0000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/link/relation/RelationshipTypeResourceWrapperHalLinkFactory.java +++ /dev/null @@ -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.app.rest.link.relation; - -import java.util.LinkedList; - -import org.dspace.app.rest.RelationshipTypeRestController; -import org.dspace.app.rest.link.HalLinkFactory; -import org.dspace.app.rest.model.hateoas.RelationshipTypeResourceWrapper; -import org.springframework.data.domain.Pageable; -import org.springframework.hateoas.Link; -import org.springframework.stereotype.Component; - -/** - * This class' purpose is to add the links to the RelationshipTypeResourceWrapper. - * This function and class will be called and used - * when the HalLinkService addLinks methods is called as it'll iterate over all the different factories and check - * whether - * these are allowed to create links for said resource or not. - */ -@Component -public class RelationshipTypeResourceWrapperHalLinkFactory - extends HalLinkFactory { - @Override - protected void addLinks(RelationshipTypeResourceWrapper halResource, Pageable pageable, LinkedList list) - throws Exception { - list.add(buildLink(Link.REL_SELF, getMethodOn() - .retrieve(halResource.getContent().getEntityTypeId(), null, null, null, null))); - } - - @Override - protected Class getControllerClass() { - return RelationshipTypeRestController.class; - } - - @Override - protected Class getResourceClass() { - return RelationshipTypeResourceWrapper.class; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipTypeRestWrapper.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipTypeRestWrapper.java deleted file mode 100644 index dcb604d605..0000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RelationshipTypeRestWrapper.java +++ /dev/null @@ -1,69 +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.rest.model; - -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import org.dspace.app.rest.RelationshipTypeRestController; - -/** - * This is the RestWrapper object for the RelationshipTypeRestResource class. This will contain all the data that is - * used in that resource and more specifically, the entityTypeLabel, entityTypeId and list of - * RelationshipTypeRest objects - * The other methods are generic getters and setters - */ -public class RelationshipTypeRestWrapper extends RestAddressableModel { - - @JsonIgnore - private List relationshipTypeRestList; - - @JsonIgnore - private String entityTypeLabel; - @JsonIgnore - private Integer entityTypeId; - - public List getRelationshipTypeRestList() { - return relationshipTypeRestList; - } - - public void setRelationshipTypeRestList( - List relationshipTypeRestList) { - this.relationshipTypeRestList = relationshipTypeRestList; - } - - public String getCategory() { - return "core"; - } - - public Class getController() { - return RelationshipTypeRestController.class; - } - - @JsonIgnore - public String getType() { - return "relationshiptype"; - } - - public String getEntityTypeLabel() { - return entityTypeLabel; - } - - public void setEntityTypeLabel(String label) { - this.entityTypeLabel = label; - } - - public Integer getEntityTypeId() { - return entityTypeId; - } - - public void setEntityTypeId(Integer entityTypeId) { - this.entityTypeId = entityTypeId; - } -} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/hateoas/RelationshipTypeResourceWrapper.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/hateoas/RelationshipTypeResourceWrapper.java deleted file mode 100644 index 57f722d3ca..0000000000 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/hateoas/RelationshipTypeResourceWrapper.java +++ /dev/null @@ -1,41 +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.rest.model.hateoas; - -import java.util.LinkedList; -import java.util.List; - -import org.dspace.app.rest.model.RelationshipTypeRest; -import org.dspace.app.rest.model.RelationshipTypeRestWrapper; -import org.dspace.app.rest.utils.Utils; - -/** - * This is the RelationshipTypeResourceWrapper class which will take the - * RelationshipTypeRestWrapper's data and transform this into a resource with the data, embeds and links. - */ -public class RelationshipTypeResourceWrapper extends HALResource { - - /** - * The constructor for the RelationshipTypeResourceWrapper - * This will call the HALResource constructor and additionally add embeds to the resource - * @param content The RelationshipTypeRestWrapper object that contains the data - */ - public RelationshipTypeResourceWrapper(RelationshipTypeRestWrapper content, Utils utils) { - super(content); - addEmbeds(content, utils); - } - - private void addEmbeds(RelationshipTypeRestWrapper content, Utils utils) { - List list = new LinkedList<>(); - for (RelationshipTypeRest relationshipTypeRest : content.getRelationshipTypeRestList()) { - list.add(new RelationshipTypeResource(relationshipTypeRest, utils)); - } - - embedResource("relationshiptypes", list); - } -} From f1ba87474f55acfb3ee464584a41e8e3fbd725b6 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 11 Dec 2019 09:43:55 -0600 Subject: [PATCH 072/125] Update Entities sample data SQL and assetstore --- dspace/src/main/docker-compose/cli.assetstore.yml | 2 +- dspace/src/main/docker-compose/db.entities.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace/src/main/docker-compose/cli.assetstore.yml b/dspace/src/main/docker-compose/cli.assetstore.yml index cacac86ce7..e4dac3a841 100644 --- a/dspace/src/main/docker-compose/cli.assetstore.yml +++ b/dspace/src/main/docker-compose/cli.assetstore.yml @@ -11,7 +11,7 @@ version: "3.7" services: dspace-cli: environment: - - LOADASSETS=https://www.dropbox.com/s/zv7lj8j2lp3egjs/assetstore.tar.gz?dl=1 + - LOADASSETS=https://www.dropbox.com/s/v3ahfcuatklbmi0/assetstore-2019-11-28.tar.gz?dl=1 entrypoint: - /bin/bash - '-c' diff --git a/dspace/src/main/docker-compose/db.entities.yml b/dspace/src/main/docker-compose/db.entities.yml index 91d96bd72b..0762d900ba 100644 --- a/dspace/src/main/docker-compose/db.entities.yml +++ b/dspace/src/main/docker-compose/db.entities.yml @@ -13,4 +13,4 @@ services: image: dspace/dspace-postgres-pgcrypto:loadsql environment: # Double underbars in env names will be replaced with periods for apache commons - - LOADSQL=https://www.dropbox.com/s/xh3ack0vg0922p2/configurable-entities-2019-05-08.sql?dl=1 + - LOADSQL=https://www.dropbox.com/s/4ap1y6deseoc8ws/dspace7-entities-2019-11-28.sql?dl=1 From c76994a3a0f546d0d788b4ab3dd8619bf11a6662 Mon Sep 17 00:00:00 2001 From: Andrew Wood Date: Wed, 11 Dec 2019 14:48:32 -0500 Subject: [PATCH 073/125] DS-4401 apply place ordering in findByLabel for RelationshipRestRepository --- .../RelationshipRestRepository.java | 6 ++++- .../rest/RelationshipRestRepositoryIT.java | 26 ++++++++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RelationshipRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RelationshipRestRepository.java index d0921a0b34..efcba6fbd8 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RelationshipRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/RelationshipRestRepository.java @@ -351,9 +351,13 @@ public class RelationshipRestRepository extends DSpaceRestRepository Date: Thu, 12 Dec 2019 13:28:37 +0000 Subject: [PATCH 074/125] adding a new dspace url as a field element --- dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java b/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java index c233c30ef2..5169b5523f 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/util/ItemUtils.java @@ -176,7 +176,7 @@ public class ItemUtils { } /** - * This method will add all sub-elements to a top element, like: dc, or dcterms, ... + * This method will add all sub-elements to a top element, like: dc, or dcterms, ... * * @param schema Element argument passed by reference that will be changed * @param val Metadatavalue that will be processed * @throws SQLException @@ -284,6 +284,7 @@ public class ItemUtils { // Repository Info Element repository = create("repository"); + repository.getField().add(createValue("url", ConfigurationManager.getProperty("dspace.baseUrl"))); repository.getField().add(createValue("name", ConfigurationManager.getProperty("dspace.name"))); repository.getField().add(createValue("mail", ConfigurationManager.getProperty("mail.admin"))); metadata.getElement().add(repository); From ea2e3e2a02453dc0e7c838ff33880f0fa4b2fed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Thu, 12 Dec 2019 15:57:25 +0000 Subject: [PATCH 075/125] Changing XOAI dependency to version that solves an existing bug --- dspace-oai/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index 0e7f2bd0eb..48822bc04a 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -15,7 +15,7 @@ ${basedir}/.. - 3.2.10 + 3.2.11 5.86.1.RELEASE From bd5efcd4e9102a130c10fd7337b142e39cbe3183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Thu, 12 Dec 2019 15:58:26 +0000 Subject: [PATCH 076/125] removing unsed filter --- dspace/config/crosswalks/oai/xoai.xml | 40 --------------------------- 1 file changed, 40 deletions(-) diff --git a/dspace/config/crosswalks/oai/xoai.xml b/dspace/config/crosswalks/oai/xoai.xml index b2d227c5b3..c791324da5 100644 --- a/dspace/config/crosswalks/oai/xoai.xml +++ b/dspace/config/crosswalks/oai/xoai.xml @@ -308,46 +308,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -51,89 +63,411 @@ - - - - - - - - AlternativeTitle - - - Subtitle - - - TranslatedTitle - - - Other - - + + + + + + + + + + + + + + AlternativeTitle + + + Subtitle + + + TranslatedTitle + + + Other + + + + + + + match="doc:element[@name='dc']/doc:element[@name='contributor']/doc:element[@name='author']" mode="datacite"> - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + Organizational + + + Personal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Organizational + + + + Personal + + + + + + + + + + + + + + + + + + + + + + + + + + Supervisor + + + Editor + + + Other + + + + + + + + + + + + + + + e-mail + + + + + + + + + + + + + + + + + + - + + + - + + + - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Available + + + Collected + + + Copyrighted + + + Created + + + Submitted + + + Updated + + + Valid + + + @@ -164,6 +498,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + select="//doc:element[@name='date']/doc:element[@name='issued']/doc:element/doc:field[@name='value']/text()"/> + + + + + - - + + + + \ No newline at end of file From 525a586e53be22e17150b8a3e0aae735d322ae76 Mon Sep 17 00:00:00 2001 From: Raf Ponsaerts Date: Fri, 13 Dec 2019 16:23:02 +0100 Subject: [PATCH 078/125] Applied feedback to the external sources entities post workspace item feature --- .../external/service/ExternalDataService.java | 3 +-- ...SourceEntryArchivedItemUriListHandler.java | 16 ++------------ ...ExternalSourceEntryItemUriListHandler.java | 22 +++++++++++++++---- ...ourceEntryWorkspaceItemUriListHandler.java | 6 +++++ .../rest/WorkspaceItemRestRepositoryIT.java | 8 ------- 5 files changed, 27 insertions(+), 28 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/external/service/ExternalDataService.java b/dspace-api/src/main/java/org/dspace/external/service/ExternalDataService.java index e5c3f31784..e0c241ba4a 100644 --- a/dspace-api/src/main/java/org/dspace/external/service/ExternalDataService.java +++ b/dspace-api/src/main/java/org/dspace/external/service/ExternalDataService.java @@ -66,8 +66,7 @@ public interface ExternalDataService { public int getNumberOfResults(String source, String query); /** - * This method will create an Item in the given Collection based on the given ExternalDataObject. - * Note that this Item will be Archived + * This method will create a WorkspaceItem in the given Collection based on the given ExternalDataObject. * @param context The relevant DSpace context * @param externalDataObject The relevant ExternalDataObject to be used * @param collection The Collection in which the item will be present diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryArchivedItemUriListHandler.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryArchivedItemUriListHandler.java index 1f9a8ead77..86189933d9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryArchivedItemUriListHandler.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryArchivedItemUriListHandler.java @@ -8,8 +8,6 @@ package org.dspace.app.rest.repository.handler; import java.sql.SQLException; -import java.util.Arrays; -import java.util.LinkedList; import java.util.List; import javax.servlet.http.HttpServletRequest; @@ -18,31 +16,21 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.service.AuthorizeService; import org.dspace.content.Item; import org.dspace.content.WorkspaceItem; -import org.dspace.content.service.CollectionService; import org.dspace.content.service.InstallItemService; import org.dspace.core.Context; -import org.dspace.external.service.ExternalDataService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.springframework.web.bind.annotation.RequestMethod; /** - * This class will handle ExternalSourceEntryUriList and it'll create Item objects based on them + * This class will handle ExternalSourceEntryUriList and it'll create Item objects based on them. + * This will create Archived items and thus only Admin users can use it */ @Component public class ExternalSourceEntryArchivedItemUriListHandler extends ExternalSourceEntryItemUriListHandler { - private List allowedRequestMethods = new LinkedList<>(Arrays.asList(RequestMethod.POST)); - @Autowired private AuthorizeService authorizeService; - @Autowired - private ExternalDataService externalDataService; - - @Autowired - private CollectionService collectionService; - @Autowired private InstallItemService installItemService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryItemUriListHandler.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryItemUriListHandler.java index a40f436e28..3ad9b7a193 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryItemUriListHandler.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryItemUriListHandler.java @@ -21,7 +21,6 @@ import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.model.ExternalSourceRest; import org.dspace.authorize.AuthorizeException; -import org.dspace.authorize.service.AuthorizeService; import org.dspace.content.Collection; import org.dspace.content.WorkspaceItem; import org.dspace.content.service.CollectionService; @@ -32,13 +31,15 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.web.bind.annotation.RequestMethod; +/** + * This provides an abstract class for the Item and WorkspaceItemUriListHandlers to extend and provide shared logic + * to reduce code duplication + * @param The type of Object we're dealing with + */ public abstract class ExternalSourceEntryItemUriListHandler implements UriListHandler { private List allowedRequestMethods = new LinkedList<>(Arrays.asList(RequestMethod.POST)); - @Autowired - private AuthorizeService authorizeService; - @Autowired private ExternalDataService externalDataService; @@ -48,6 +49,7 @@ public abstract class ExternalSourceEntryItemUriListHandler implements UriLis private static final Logger log = org.apache.logging.log4j.LogManager .getLogger(ExternalSourceEntryItemUriListHandler.class); + @Override public boolean supports(List uriList, String method, Class clazz) { if (!allowedRequestMethods.contains(RequestMethod.valueOf(method))) { return false; @@ -61,6 +63,7 @@ public abstract class ExternalSourceEntryItemUriListHandler implements UriLis return true; } + @Override public boolean validate(Context context, HttpServletRequest request, List uriList) throws AuthorizeException { if (uriList.size() > 1) { @@ -83,6 +86,17 @@ public abstract class ExternalSourceEntryItemUriListHandler implements UriLis return true; } + /** + * This method will create a WorkspaceItem made from the ExternalDataObject that will be created from the given + * uriList. The Collection for the WorkspaceItem will be retrieved through the request. + * + * @param context The relevant DSpace context + * @param request The relevant Request + * @param uriList The uriList that contains the data for the ExternalDataObject + * @return A WorkspaceItem created from the given information + * @throws SQLException If something goes wrong + * @throws AuthorizeException If something goes wrong + */ public WorkspaceItem createWorkspaceItem(Context context, HttpServletRequest request, List uriList) throws SQLException, AuthorizeException { ExternalDataObject dataObject = getExternalDataObjectFromUriList(uriList); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryWorkspaceItemUriListHandler.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryWorkspaceItemUriListHandler.java index 353f24814e..6491ec0fd6 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryWorkspaceItemUriListHandler.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/handler/ExternalSourceEntryWorkspaceItemUriListHandler.java @@ -16,6 +16,11 @@ import org.dspace.content.WorkspaceItem; import org.dspace.core.Context; import org.springframework.stereotype.Component; +/** + * This class extends the {@link ExternalSourceEntryItemUriListHandler} abstract class and implements it specifically + * for the WorkspaceItem objects. It'll add extra checks and validations based on a WorkspaceItem and call the super + * functions. + */ @Component public class ExternalSourceEntryWorkspaceItemUriListHandler extends ExternalSourceEntryItemUriListHandler { @@ -41,6 +46,7 @@ public class ExternalSourceEntryWorkspaceItemUriListHandler return true; } + @Override public WorkspaceItem handle(Context context, HttpServletRequest request, List uriList) throws SQLException, AuthorizeException { return super.createWorkspaceItem(context, request, uriList); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java index 847b582fcf..82b3c9fb20 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/WorkspaceItemRestRepositoryIT.java @@ -1630,14 +1630,6 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration ; } - - - - - - - - @Test public void createWorkspaceItemFromExternalSources() throws Exception { //We turn off the authorization system in order to create the structure as defined below From dcaad7584b0e58bef5664a42ff304ea1edbf7a55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Fri, 13 Dec 2019 16:31:22 +0000 Subject: [PATCH 079/125] modifying default values and add more openaire4 support --- .../oai/metadataFormats/oai_openaire.xsl | 1015 +++++++++++++++-- .../crosswalks/oai/transformers/openaire4.xsl | 437 +++++-- 2 files changed, 1282 insertions(+), 170 deletions(-) diff --git a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl index 9a1af9d35a..fbe512c587 100644 --- a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl +++ b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl @@ -17,32 +17,69 @@ - + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -78,31 +115,8 @@ - - - - - - - - - - AlternativeTitle - - - Subtitle - - - TranslatedTitle - - - Other - - - - - + @@ -169,7 +183,9 @@ + + @@ -240,27 +256,7 @@ - - - - - - - - - - Supervisor - - - Editor - - - Other - - - - - @@ -314,13 +310,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -378,8 +431,9 @@ - - + + @@ -388,7 +442,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -399,6 +529,7 @@ + @@ -437,6 +568,257 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fulltext + + + + other + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AlternativeTitle + + + Subtitle + + + TranslatedTitle + + + Other + + + + + + + + + + + + + + Supervisor + + + Editor + + + Other + + + + @@ -469,35 +851,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + ARK + + + arXiv + + + bibcode + + + DOI + + + EAN13 + + + EISSN + + + Handle + + + IGSN + + + ISBN + + + ISSN + + + ISTC + + + LISSN + + + LSID + + + PMID + + + PURL + + + UPC + + + URL + + + URN + + + + + + - + - - - - - - - + + + + + + - - - - + + + - - - - - - - - - + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Handle + + + DOI + + + URL + + + N/A + + + + + + + + + + + + + + literature + + + literature + + + literature + + + literature + + + literature + + + dataset + + + software + + other research product + + + + + + + + + + + + + http://purl.org/coar/resource_type/c_1162 + + + http://purl.org/coar/resource_type/c_0640 + + + http://purl.org/coar/resource_type/c_6501 + + + http://purl.org/coar/resource_type/c_6501 + + + http://purl.org/coar/resource_type/c_b239 + + + http://purl.org/coar/resource_type/c_7a1f + + + http://purl.org/coar/resource_type/c_86bc + + + http://purl.org/coar/resource_type/c_2f33 + + + http://purl.org/coar/resource_type/c_3248 + + + http://purl.org/coar/resource_type/c_ba08 + + + http://purl.org/coar/resource_type/c_7ad9 + + + http://purl.org/coar/resource_type/c_e9a0 + + + http://purl.org/coar/resource_type/c_f744 + + + http://purl.org/coar/resource_type/c_c94f + + + http://purl.org/coar/resource_type/c_5794 + + + http://purl.org/coar/resource_type/c_6670 + + + http://purl.org/coar/resource_type/c_3e5a + + + http://purl.org/coar/resource_type/c_beb9 + + + http://purl.org/coar/resource_type/c_ddb1 + + + http://purl.org/coar/resource_type/c_db06 + + + http://purl.org/coar/resource_type/c_c513 + + + http://purl.org/coar/resource_type/c_8544 + + + http://purl.org/coar/resource_type/c_0857 + + + http://purl.org/coar/resource_type/c_bdcc + + + http://purl.org/coar/resource_type/c_8a7e + + + http://purl.org/coar/resource_type/c_2659 + + + http://purl.org/coar/resource_type/c_545b + + + http://purl.org/coar/resource_type/c_15cd + + + http://purl.org/coar/resource_type/c_816b + + + http://purl.org/coar/resource_type/c_93fc + + + http://purl.org/coar/resource_type/c_ba1f + + + http://purl.org/coar/resource_type/c_baaf + + + http://purl.org/coar/resource_type/c_efa0 + + + http://purl.org/coar/resource_type/c_5ce6 + + + http://purl.org/coar/resource_type/c_ecc8 + + + http://purl.org/coar/resource_type/c_71bd + + + http://purl.org/coar/resource_type/c_393c + + + http://purl.org/coar/resource_type/c_8042 + + + http://purl.org/coar/resource_type/c_46ec + + + http://purl.org/coar/resource_type/c_12cc + + + http://purl.org/coar/resource_type/c_12cd + + + http://purl.org/coar/resource_type/c_12ce + + + http://purl.org/coar/resource_type/c_18cc + + + http://purl.org/coar/resource_type/c_18cd + + + http://purl.org/coar/resource_type/c_18cf + + + http://purl.org/coar/resource_type/c_18cp + + + http://purl.org/coar/resource_type/c_18co + + + http://purl.org/coar/resource_type/c_18cw + + + http://purl.org/coar/resource_type/c_18ww + + + http://purl.org/coar/resource_type/c_18wz + + + http://purl.org/coar/resource_type/c_18wq + + + http://purl.org/coar/resource_type/c_186u + + + http://purl.org/coar/resource_type/c_18op + + + http://purl.org/coar/resource_type/c_18hj + + + http://purl.org/coar/resource_type/c_18ws + + + http://purl.org/coar/resource_type/c_18gh + + + http://purl.org/coar/resource_type/c_dcae04bc + + + http://purl.org/coar/resource_type/c_2df8fbb1 + + + + http://purl.org/coar/resource_type/c_1843 + + + + + + + + + + + + + + http://purl.org/coar/access_right/c_abf2 + + + http://purl.org/coar/access_right/c_f1cf + + + http://purl.org/coar/access_right/c_16ec + + + http://purl.org/coar/access_right/c_14cb + + + + @@ -605,19 +1433,12 @@ - - - - - - - - + + diff --git a/dspace/config/crosswalks/oai/transformers/openaire4.xsl b/dspace/config/crosswalks/oai/transformers/openaire4.xsl index 1b910d83e1..b633ae5146 100644 --- a/dspace/config/crosswalks/oai/transformers/openaire4.xsl +++ b/dspace/config/crosswalks/oai/transformers/openaire4.xsl @@ -1,79 +1,370 @@ - - - + + + - - - - - + + + + + - - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - info:eu-repo/semantics/openAccess - - - info:eu-repo/semantics/openAccess - - - info:eu-repo/semantics/restrictedAccess - - - info:eu-repo/semantics/embargoedAccess - - - info:eu-repo/semantics/restrictedAccess - - - + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + eng + + + eng + + + spa + + + deu + + + fra + + + ita + + + jap + + + zho + + + por + + + tur + + + + + + + + + + + + + + + + + + + open access + + + embargoed access + + + restricted access + + + metadata only access + + + + + + + + + + + + + + + + + + annotation + + + journal + + + journal article + + + editorial + + + bachelor thesis + + + bibliography + + + book + + + book part + + + book review + + + website + + + interactive resource + + + conference proceedings + + + conference object + + + conference paper + + + conference poster + + + contribution to journal + + + data paper + + + dataset + + + doctoral thesis + + + image + + + lecture + + + letter + + + master thesis + + + moving image + + + periodical + + + letter to the editor + + + patent + + + preprint + + + report + + + report part + + + research proposal + + + review + + + software + + + still image + + + technical documentation + + + workflow + + + working paper + + + thesis + + + cartographic material + + + map + + + video + + + sound + + + musical composition + + + text + + + conference paper not in proceedings + + + conference poster not in proceedings + + + musical notation + + + internal report + + + memorandum + + + other type of report + + + policy report + + + project deliverable + + + report to funding agency + + + research report + + + technical report + + + review article + + + research article + + + other + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 1e0743c251328f0d75965d4c15e1308114e9e030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Mon, 16 Dec 2019 11:27:03 +0000 Subject: [PATCH 080/125] fixing errors with earlier transformation/normalization --- dspace/config/crosswalks/oai/transformers/openaire4.xsl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dspace/config/crosswalks/oai/transformers/openaire4.xsl b/dspace/config/crosswalks/oai/transformers/openaire4.xsl index b633ae5146..13c56da192 100644 --- a/dspace/config/crosswalks/oai/transformers/openaire4.xsl +++ b/dspace/config/crosswalks/oai/transformers/openaire4.xsl @@ -20,7 +20,7 @@ + match="/doc:metadata/doc:element[@name='dc']/doc:element[@name='language']/doc:element[@name='iso']/doc:element/doc:field/text()"> @@ -58,7 +58,9 @@ tur - + + + @@ -69,7 +71,7 @@ - + From 5831f4cbde2ec3070965818bdfdd0bc6ec55980f Mon Sep 17 00:00:00 2001 From: Marie Verdonck Date: Mon, 16 Dec 2019 12:48:34 +0100 Subject: [PATCH 081/125] 67824: EntityType by label endpoint and integration tests --- .../rest/EntityTypeLabelRestController.java | 67 +++++++++++++++++++ .../dspace/app/rest/model/EntityTypeRest.java | 1 + .../rest/EntityTypeLabelRestControllerIT.java | 48 +++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 dspace-server-webapp/src/main/java/org/dspace/app/rest/EntityTypeLabelRestController.java create mode 100644 dspace-server-webapp/src/test/java/org/dspace/app/rest/EntityTypeLabelRestControllerIT.java diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/EntityTypeLabelRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/EntityTypeLabelRestController.java new file mode 100644 index 0000000000..14d01b8c76 --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/EntityTypeLabelRestController.java @@ -0,0 +1,67 @@ +/** + * 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.rest; + +import java.sql.SQLException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.dspace.app.rest.converter.ConverterService; +import org.dspace.app.rest.model.EntityTypeRest; +import org.dspace.app.rest.utils.ContextUtil; +import org.dspace.app.rest.utils.Utils; +import org.dspace.content.EntityType; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.EntityTypeService; +import org.dspace.core.Context; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.rest.webmvc.ResourceNotFoundException; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * This controller will handle all the incoming calls on the /api/core/entitytypes/label/<:entity-type-label> endpoint + * where the entity-type-label parameter can be filled in to match a specific entityType by label + * There's always at most one entity type per label. + *

+ * It responds with: + *

+ * The single entity type if there's a match + * 404 if the entity type doesn't exist + * + * @author Maria Verdonck (Atmire) on 2019-12-13 + */ +@RestController +@RequestMapping("/api/" + EntityTypeRest.CATEGORY + "/" + EntityTypeRest.NAME_PLURAL) +public class EntityTypeLabelRestController { + + protected final EntityTypeService entityTypeService = ContentServiceFactory.getInstance().getEntityTypeService(); + + @Autowired + protected ConverterService converter; + + @Autowired + protected Utils utils; + + @GetMapping("/label/{entity-type-label}") + public EntityTypeRest get(HttpServletRequest request, HttpServletResponse response, + @PathVariable("entity-type-label") String label) { + Context context = ContextUtil.obtainContext(request); + try { + EntityType entityType = this.entityTypeService.findByEntityType(context, label); + if (entityType == null) { + throw new ResourceNotFoundException("There was no entityType found with label: " + label); + } + return converter.toRest(entityType, utils.obtainProjection()); + } catch (SQLException e) { + throw new RuntimeException(e.getMessage(), e); + } + } +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EntityTypeRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EntityTypeRest.java index fecd065815..454e5a82b6 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EntityTypeRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/EntityTypeRest.java @@ -17,6 +17,7 @@ import org.dspace.app.rest.RestResourceController; public class EntityTypeRest extends BaseObjectRest { public static final String NAME = "entitytype"; + public static final String NAME_PLURAL = "entitytypes"; public static final String CATEGORY = "core"; public String getCategory() { diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/EntityTypeLabelRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/EntityTypeLabelRestControllerIT.java new file mode 100644 index 0000000000..e75d639cd7 --- /dev/null +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/EntityTypeLabelRestControllerIT.java @@ -0,0 +1,48 @@ +/** + * 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.rest; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.dspace.app.rest.test.AbstractEntityIntegrationTest; +import org.dspace.content.EntityType; +import org.dspace.content.service.EntityTypeService; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Integration tests for the {@link org.dspace.app.rest.EntityTypeLabelRestController} controlled endpoints + * + * @author Maria Verdonck (Atmire) on 16/12/2019 + */ +public class EntityTypeLabelRestControllerIT extends AbstractEntityIntegrationTest { + + @Autowired + private EntityTypeService entityTypeService; + + @Test + public void testGetEntityTypeByLabel_ExistingLabel() throws Exception { + String testLabel = "Person"; + EntityType entityType = entityTypeService.findByEntityType(context, testLabel); + getClient().perform(get("/api/core/entitytypes/label/" + testLabel)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(entityType.getID()))) + .andExpect(jsonPath("$.label", containsString(testLabel))); + } + + @Test + public void testGetEntityTypeByLabel_NonExistentLabel() throws Exception { + String testLabel = "Person2"; + getClient().perform(get("/api/core/entitytypes/label" + testLabel)) + .andExpect(status().isNotFound()); + } +} From a696d6ec435d350b18edf2f1d28a27d84ef95ae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Mon, 16 Dec 2019 12:06:59 +0000 Subject: [PATCH 082/125] removing 'configuration' word from openaire configuration naming and fixing wrong element and qualifier names --- dspace/config/spring/api/discovery.xml | 4 ++-- dspace/config/submission-forms.xml | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index 3389287ffc..265fc51b99 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -63,9 +63,9 @@ - + - + diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index 3bc523909d..96c0d1a498 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -614,7 +614,7 @@ isAuthorOfPublication - openAIRECreatorConfiguration + openAIRECreator true true @@ -664,7 +664,7 @@ dc relation - HasVersion + hasversion false onebox @@ -675,8 +675,8 @@ dc - relation - References + dcterms + references false onebox @@ -1032,7 +1032,7 @@ isFundingAgencyOfProject - openAIREFundingAgencyConfiguration + openAIREFundingAgency false false From 0d427faa2026c6dc0f527798fa790010d244a867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Mon, 16 Dec 2019 15:32:14 +0000 Subject: [PATCH 083/125] adding a specific filter for openaire4 --- dspace/config/crosswalks/oai/xoai.xml | 99 +++++++++++++++++++-------- 1 file changed, 69 insertions(+), 30 deletions(-) diff --git a/dspace/config/crosswalks/oai/xoai.xml b/dspace/config/crosswalks/oai/xoai.xml index c791324da5..7a4737cc72 100644 --- a/dspace/config/crosswalks/oai/xoai.xml +++ b/dspace/config/crosswalks/oai/xoai.xml @@ -1,7 +1,6 @@ + maxListSetsSize="100" stylesheet="static/style.xsl" xmlns="http://www.lyncode.com/XOAIConfiguration"> @@ -85,7 +84,7 @@ - + @@ -321,6 +320,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -476,8 +515,8 @@ - - + + From f3673b132dd6c1ccee84afc16e2ad3a68527dfff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Mon, 16 Dec 2019 15:34:44 +0000 Subject: [PATCH 084/125] removing trailling whitespaces --- dspace/config/crosswalks/oai/xoai.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dspace/config/crosswalks/oai/xoai.xml b/dspace/config/crosswalks/oai/xoai.xml index 7a4737cc72..b75b2b2c97 100644 --- a/dspace/config/crosswalks/oai/xoai.xml +++ b/dspace/config/crosswalks/oai/xoai.xml @@ -320,7 +320,7 @@ - org.dspace.xoai.filter.DSpaceMetadataExistsFilter @@ -501,7 +501,7 @@ relationship.type - + From 129a411a257c08f6d146e591828a42b54f33737b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Mon, 16 Dec 2019 17:06:51 +0000 Subject: [PATCH 085/125] remove oai_openaire metadata format from the default context --- dspace/config/crosswalks/oai/xoai.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/dspace/config/crosswalks/oai/xoai.xml b/dspace/config/crosswalks/oai/xoai.xml index b75b2b2c97..551041e1d6 100644 --- a/dspace/config/crosswalks/oai/xoai.xml +++ b/dspace/config/crosswalks/oai/xoai.xml @@ -19,7 +19,6 @@ - This is the default context of the DSpace OAI-PMH data provider. From ff61bb15211851576fccdadb3c4f417d1da4201b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Tue, 17 Dec 2019 10:18:51 +0000 Subject: [PATCH 086/125] replacing openAIRECreator with personOrOrganization --- dspace/config/spring/api/discovery.xml | 2 +- dspace/config/submission-forms.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index 265fc51b99..63c4ffb19e 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -61,9 +61,9 @@ + - diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index 96c0d1a498..fb5398e1ae 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -614,7 +614,7 @@ isAuthorOfPublication - openAIRECreator + personOrOrganization true true From 93ed485c7a1fe0b9e307697bdb96d3f74048ba80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Tue, 17 Dec 2019 10:24:29 +0000 Subject: [PATCH 087/125] changing comment --- dspace/config/spring/api/discovery.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index 63c4ffb19e..3da454ba09 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -61,9 +61,8 @@ + - From b892e883edb46d4ebae63b6458c1180710065f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Tue, 17 Dec 2019 15:55:11 +0000 Subject: [PATCH 088/125] support for subjects and publihsers --- .../oai/metadataFormats/oai_openaire.xsl | 97 +++++++++++++------ 1 file changed, 68 insertions(+), 29 deletions(-) diff --git a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl index fbe512c587..e43de2c136 100644 --- a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl +++ b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl @@ -42,6 +42,16 @@ + + + + + + @@ -59,13 +69,9 @@ - + - - + select="doc:metadata/doc:element[@name='dc']/doc:element[@name='subject']" mode="datacite"/> @@ -500,21 +506,42 @@ - - - - - - - - - - + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -579,6 +606,15 @@ + + + + + + + + + @@ -939,9 +975,10 @@ - - - + + + @@ -1201,7 +1238,9 @@ software - other research product + + other research product + @@ -1403,19 +1442,19 @@ - http://purl.org/coar/access_right/c_abf2 + http://purl.org/coar/access_right/c_abf2 - http://purl.org/coar/access_right/c_f1cf + http://purl.org/coar/access_right/c_f1cf - http://purl.org/coar/access_right/c_16ec + http://purl.org/coar/access_right/c_16ec - http://purl.org/coar/access_right/c_14cb + http://purl.org/coar/access_right/c_14cb - + From f42f1c2a6487fae96a622396b1d9a1b938d796df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Tue, 17 Dec 2019 16:01:07 +0000 Subject: [PATCH 089/125] removing extra Turkish entry --- dspace/config/submission-forms.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index fb5398e1ae..1a6ddcf049 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -1285,10 +1285,6 @@ Chinese zh - - Turkish - tr - Portuguese pt From 754d02378e1bc3aaa15e49ef697a3aa5d752169e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Wed, 18 Dec 2019 11:38:15 +0000 Subject: [PATCH 090/125] fixing missing funder relationship --- .../spring/api/virtual-metadata.xml.openaire4 | 71 ++++++++++--------- 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/dspace/config/spring/api/virtual-metadata.xml.openaire4 b/dspace/config/spring/api/virtual-metadata.xml.openaire4 index a0cf0ca4fa..5a17f16193 100644 --- a/dspace/config/spring/api/virtual-metadata.xml.openaire4 +++ b/dspace/config/spring/api/virtual-metadata.xml.openaire4 @@ -24,7 +24,7 @@ - + @@ -47,7 +47,7 @@ - + @@ -98,6 +98,13 @@ + + + + person.identifier + + + @@ -192,11 +199,11 @@ - - - + + + - - - - - - + + + + + + @@ -366,28 +373,27 @@ - - - - organization.legalName - - + + + + + - - - - organization.identifier - - + + + + + - + - - - - + + + + + @@ -401,8 +407,7 @@ organization.identifier - - + + + relation + isContributorOfPublication + + + + relation + isPublicationOfContributor + + + + relation + isFundingAgencyOfProject + + + + relation + isProjectOfFundingAgency + + + From 6970f4278a176d279a107e032928f6bc49423c3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Wed, 18 Dec 2019 14:22:25 +0000 Subject: [PATCH 092/125] adding comments --- .../crosswalks/oai/transformers/openaire4.xsl | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/dspace/config/crosswalks/oai/transformers/openaire4.xsl b/dspace/config/crosswalks/oai/transformers/openaire4.xsl index 13c56da192..81829025a5 100644 --- a/dspace/config/crosswalks/oai/transformers/openaire4.xsl +++ b/dspace/config/crosswalks/oai/transformers/openaire4.xsl @@ -9,8 +9,12 @@ - - + + @@ -18,7 +22,10 @@ - + @@ -63,12 +70,18 @@ - + - + + @@ -100,7 +113,11 @@ - + @@ -332,7 +349,12 @@ - + From 859eebf624ffb19894e8889c8ef2b292917ecb75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Wed, 18 Dec 2019 14:23:03 +0000 Subject: [PATCH 093/125] openaire4 transformer configuration --- dspace/config/crosswalks/oai/xoai.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace/config/crosswalks/oai/xoai.xml b/dspace/config/crosswalks/oai/xoai.xml index 551041e1d6..3d79520eef 100644 --- a/dspace/config/crosswalks/oai/xoai.xml +++ b/dspace/config/crosswalks/oai/xoai.xml @@ -81,7 +81,7 @@ --> - + From 7814a9a1df632f03d9d97191637e722078bba317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Wed, 18 Dec 2019 16:52:19 +0000 Subject: [PATCH 094/125] adding comments for each template --- .../oai/metadataFormats/oai_openaire.xsl | 63 +++++++++++++++++-- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl index e43de2c136..4f0cfcaad2 100644 --- a/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl +++ b/dspace/config/crosswalks/oai/metadataFormats/oai_openaire.xsl @@ -87,6 +87,7 @@ + @@ -298,24 +299,28 @@ + + + + @@ -323,12 +328,14 @@ + + + @@ -344,6 +352,7 @@ + @@ -351,6 +360,7 @@ + @@ -358,12 +368,14 @@ + + @@ -371,6 +383,7 @@ + @@ -408,18 +421,21 @@ + + + @@ -427,12 +443,14 @@ + + @@ -444,6 +462,7 @@ + @@ -699,6 +718,8 @@ + + @@ -812,6 +833,7 @@ + @@ -835,6 +857,7 @@ + @@ -855,6 +878,7 @@ + @@ -887,6 +911,11 @@ + + @@ -999,7 +1028,7 @@ @@ -1019,7 +1048,13 @@ this template will try to look for all "virtual::" and rebuild an "Entity" based on all virtual fields in the source data. - This will retrieve something like + This will retrieve something like: + + Doe, John + John + Doe + 3f685bbd-07d9-403e-9de2-b8f0fabe27a7 + --> @@ -1051,9 +1086,9 @@ @@ -1209,6 +1244,11 @@ + @@ -1244,6 +1284,12 @@ + @@ -1433,6 +1479,12 @@ + @@ -1458,6 +1510,7 @@ + From 817b8b1f4514b4246cca801aeac7f492d81cdfb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Wed, 18 Dec 2019 16:53:41 +0000 Subject: [PATCH 095/125] changing the relation type to fetch the required funding sub fields --- dspace/config/spring/api/virtual-metadata.xml.openaire4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dspace/config/spring/api/virtual-metadata.xml.openaire4 b/dspace/config/spring/api/virtual-metadata.xml.openaire4 index 5a17f16193..b3236398e9 100644 --- a/dspace/config/spring/api/virtual-metadata.xml.openaire4 +++ b/dspace/config/spring/api/virtual-metadata.xml.openaire4 @@ -375,13 +375,13 @@ - + - + From d08fe3e4f5897a90721a2291c79676b06698e0f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Gra=C3=A7a?= Date: Thu, 19 Dec 2019 16:38:14 +0000 Subject: [PATCH 096/125] remove openaire4 unused beans --- .../spring/api/virtual-metadata.xml.openaire4 | 237 +----------------- 1 file changed, 10 insertions(+), 227 deletions(-) diff --git a/dspace/config/spring/api/virtual-metadata.xml.openaire4 b/dspace/config/spring/api/virtual-metadata.xml.openaire4 index b3236398e9..909468e088 100644 --- a/dspace/config/spring/api/virtual-metadata.xml.openaire4 +++ b/dspace/config/spring/api/virtual-metadata.xml.openaire4 @@ -12,15 +12,6 @@ are to be added to the item that has a relationship with this relationship type--> - - - - - - - - - @@ -39,8 +30,9 @@ - @@ -162,179 +154,10 @@ - - - - - - - - organization.legalName - - - - - - - - - - - - person.familyName - person.givenName - - - - , - - - - - - - - - - - - - - organization.legalName - - - - - - - organization.identifier - - - - - - - - - - - organization.legalName - - - - - - - - - - - - - - publicationvolume.volumeNumber - - - - - - - - - - - - - - - - - - - - - - - - creativeworkseries.issn - - - - - - - dc.title - - - - - - - - - - - - - - publicationissue.issueNumber - - - - - - - - - - - - - - dc.title - - - - , - - - - @@ -374,6 +197,8 @@ + @@ -385,9 +210,9 @@ - + @@ -408,46 +233,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 0d41de5bf70ec69986bcc2ed7afa5f334fce4140 Mon Sep 17 00:00:00 2001 From: Kevin Van de Velde Date: Fri, 20 Dec 2019 16:38:52 +0100 Subject: [PATCH 097/125] DS-4351 Upgrade spring (boot) & hibernate to newer versions: Removing unused mock --- .../src/test/java/org/dspace/content/EntityServiceImplTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java b/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java index f51e417894..b7f26a10d5 100644 --- a/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java +++ b/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java @@ -170,7 +170,6 @@ public class EntityServiceImplTest { when(metadataValue.getValue()).thenReturn("testType"); when(entity.getItem()).thenReturn(item); when(itemService.getMetadata(item, "relationship", "type", null, Item.ANY)).thenReturn(list); - when(entityService.getType(context, entity)).thenReturn(leftType); // Mock when(relationshipTypeService.findByEntityType(context, entityService.getType(context, entity), -1, -1)) .thenReturn(relationshipTypeList); From a5ca3813b7b98ea94c9258e01d410d1337267c2e Mon Sep 17 00:00:00 2001 From: Kevin Van de Velde Date: Fri, 20 Dec 2019 17:03:45 +0100 Subject: [PATCH 098/125] DS-4351 Upgrade spring (boot) & hibernate to newer versions: Removing unused mock --- .../test/java/org/dspace/content/EntityServiceImplTest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java b/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java index b7f26a10d5..5aa9d97b79 100644 --- a/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java +++ b/dspace-api/src/test/java/org/dspace/content/EntityServiceImplTest.java @@ -167,9 +167,7 @@ public class EntityServiceImplTest { // Mock the state of objects utilized in getAllRelationshipTypes() // to meet the success criteria of the invocation - when(metadataValue.getValue()).thenReturn("testType"); when(entity.getItem()).thenReturn(item); - when(itemService.getMetadata(item, "relationship", "type", null, Item.ANY)).thenReturn(list); when(relationshipTypeService.findByEntityType(context, entityService.getType(context, entity), -1, -1)) .thenReturn(relationshipTypeList); @@ -198,7 +196,6 @@ public class EntityServiceImplTest { when(itemService.getMetadata(item, "relationship", "type", null, Item.ANY, false)).thenReturn(metsList); when(entity.getItem()).thenReturn(item); when(entityService.getType(context, entity)).thenReturn(entityType); - when(entityTypeService.findByEntityType(any(), any())).thenReturn(entityType); when(relationshipTypeService.findByEntityType(context, entityService.getType(context, entity), true, -1, -1)) .thenReturn(relationshipTypeList); @@ -227,7 +224,6 @@ public class EntityServiceImplTest { when(itemService.getMetadata(item, "relationship", "type", null, Item.ANY, false)).thenReturn(metsList); when(entity.getItem()).thenReturn(item); when(entityService.getType(context, entity)).thenReturn(entityType); - when(entityTypeService.findByEntityType(any(), any())).thenReturn(entityType); when(relationshipTypeService.findByEntityType(context, entityService.getType(context, entity), false, -1, -1)) .thenReturn(relationshipTypeList); From 87515d6debe10eb75164332d9a8b45680cf45c1b Mon Sep 17 00:00:00 2001 From: Peter Nijs Date: Fri, 3 Jan 2020 17:54:25 +0100 Subject: [PATCH 099/125] 68007: Refactoring the IndexableObject & SolrServiceImpl --- .../org/dspace/discovery/IndexingService.java | 2 + .../org/dspace/discovery/SolrServiceImpl.java | 19 ++++-- .../ClaimedTaskIndexFactoryImpl.java | 16 ++++- .../CollectionIndexFactoryImpl.java | 18 ++++- .../CommunityIndexFactoryImpl.java | 17 ++++- .../DSpaceObjectIndexFactoryImpl.java | 5 +- .../indexobject/IndexFactoryImpl.java | 5 +- .../InprogressSubmissionIndexFactoryImpl.java | 6 +- .../indexobject/ItemIndexFactoryImpl.java | 48 ++++++++++++- .../indexobject/PoolTaskIndexFactoryImpl.java | 16 ++++- .../WorkflowItemIndexFactoryImpl.java | 38 ++++++++++- .../WorkspaceItemIndexFactoryImpl.java | 17 ++++- .../factory/ClaimedTaskIndexFactory.java | 3 +- .../factory/CollectionIndexFactory.java | 2 +- .../factory/CommunityIndexFactory.java | 3 +- .../factory/DSpaceObjectIndexFactory.java | 2 +- .../indexobject/factory/IndexFactory.java | 19 +++++- .../factory/IndexObjectFactoryFactory.java | 67 ++----------------- .../InprogressSubmissionIndexFactory.java | 4 +- .../indexobject/factory/ItemIndexFactory.java | 2 +- .../factory/PoolTaskIndexFactory.java | 3 +- .../factory/WorkflowItemIndexFactory.java | 4 +- .../factory/WorkspaceItemIndexFactory.java | 4 +- 23 files changed, 226 insertions(+), 94 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/discovery/IndexingService.java b/dspace-api/src/main/java/org/dspace/discovery/IndexingService.java index a7270be2a5..46795d759e 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/IndexingService.java +++ b/dspace-api/src/main/java/org/dspace/discovery/IndexingService.java @@ -51,6 +51,8 @@ public interface IndexingService { void updateIndex(Context context, boolean force); + void updateIndex(Context context, boolean force, String type); + void cleanIndex(boolean force) throws IOException, SQLException, SearchServiceException; diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java index b75d1c131a..d821c4247f 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java @@ -309,15 +309,22 @@ public class SolrServiceImpl implements SearchService, IndexingService { */ @Override public void updateIndex(Context context, boolean force) { + updateIndex(context, force, null); + } + + @Override + public void updateIndex(Context context, boolean force, String type) { try { final List indexableObjectServices = indexObjectServiceFactory. - getIndexFactories(); + getIndexFactories(); for (IndexFactory indexableObjectService : indexableObjectServices) { - final Iterator indexableObjects = indexableObjectService.findAll(context); - while (indexableObjects.hasNext()) { - final IndexableObject indexableObject = indexableObjects.next(); - indexContent(context, indexableObject, force); - context.uncacheEntity(indexableObject.getIndexedObject()); + if (type == null || StringUtils.equals(indexableObjectService.getType(), type)) { + final Iterator indexableObjects = indexableObjectService.findAll(context); + while (indexableObjects.hasNext()) { + final IndexableObject indexableObject = indexableObjects.next(); + indexContent(context, indexableObject, force); + context.uncacheEntity(indexableObject.getIndexedObject()); + } } } if (solrSearchCore.getSolr() != null) { diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/ClaimedTaskIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/ClaimedTaskIndexFactoryImpl.java index 4ab11d5d6b..411aa6a0fb 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/ClaimedTaskIndexFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/ClaimedTaskIndexFactoryImpl.java @@ -9,7 +9,9 @@ package org.dspace.discovery.indexobject; import java.io.IOException; import java.sql.SQLException; +import java.util.Arrays; import java.util.Iterator; +import java.util.List; import java.util.Optional; import org.apache.commons.lang3.StringUtils; @@ -26,7 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired; * Factory implementation for indexing/retrieving claimed tasks in the search core * @author Kevin Van de Velde (kevin at atmire dot com) */ -public class ClaimedTaskIndexFactoryImpl extends IndexFactoryImpl +public class ClaimedTaskIndexFactoryImpl extends IndexFactoryImpl implements ClaimedTaskIndexFactory { @Autowired @@ -58,8 +60,10 @@ public class ClaimedTaskIndexFactoryImpl extends IndexFactoryImpl findIndexableObject(Context context, String id) throws SQLException { final ClaimedTask claimedTask = claimedTaskService.find(context, Integer.parseInt(id)); diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/CollectionIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/CollectionIndexFactoryImpl.java index 3cfccc40de..4a78dc8e82 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/CollectionIndexFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/CollectionIndexFactoryImpl.java @@ -10,6 +10,7 @@ package org.dspace.discovery.indexobject; import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Optional; @@ -34,7 +35,7 @@ import org.springframework.beans.factory.annotation.Autowired; * Factory implementation for indexing/retrieving collections in the search core * @author Kevin Van de Velde (kevin at atmire dot com) */ -public class CollectionIndexFactoryImpl extends DSpaceObjectIndexFactoryImpl +public class CollectionIndexFactoryImpl extends DSpaceObjectIndexFactoryImpl implements CollectionIndexFactory { @Autowired @@ -76,11 +77,12 @@ public class CollectionIndexFactoryImpl extends DSpaceObjectIndexFactoryImpl findIndexableObject(Context context, String id) throws SQLException { final Collection collection = (collectionService.find(context, UUID.fromString(id))); diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/CommunityIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/CommunityIndexFactoryImpl.java index f4c00eeadf..ac33b4cf5a 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/CommunityIndexFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/CommunityIndexFactoryImpl.java @@ -10,6 +10,7 @@ package org.dspace.discovery.indexobject; import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Optional; @@ -30,7 +31,7 @@ import org.springframework.beans.factory.annotation.Autowired; * Factory implementation for indexing/retrieving communities in the search core * @author Kevin Van de Velde (kevin at atmire dot com) */ -public class CommunityIndexFactoryImpl extends DSpaceObjectIndexFactoryImpl +public class CommunityIndexFactoryImpl extends DSpaceObjectIndexFactoryImpl implements CommunityIndexFactory { @Autowired(required = true) @@ -62,9 +63,11 @@ public class CommunityIndexFactoryImpl extends DSpaceObjectIndexFactoryImpl findIndexableObject(Context context, String id) throws SQLException { final Community community = communityService.find(context, UUID.fromString(id)); diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/DSpaceObjectIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/DSpaceObjectIndexFactoryImpl.java index d5c65a3423..4df548c650 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/DSpaceObjectIndexFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/DSpaceObjectIndexFactoryImpl.java @@ -21,11 +21,12 @@ import org.dspace.discovery.indexobject.factory.DSpaceObjectIndexFactory; * Factory implementation for indexing/retrieving DSpaceObjects in the search core * @author Kevin Van de Velde (kevin at atmire dot com) */ -public abstract class DSpaceObjectIndexFactoryImpl - extends IndexFactoryImpl implements DSpaceObjectIndexFactory { +public abstract class DSpaceObjectIndexFactoryImpl + extends IndexFactoryImpl implements DSpaceObjectIndexFactory { @Override public SolrInputDocument buildDocument(Context context, T indexableObject) throws SQLException, IOException { + // Add the ID's, types and call the SolrServiceIndexPlugins SolrInputDocument doc = super.buildDocument(context, indexableObject); final DSpaceObject dso = indexableObject.getIndexedObject(); diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexFactoryImpl.java index a32b687026..65b0c2c22e 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/IndexFactoryImpl.java @@ -35,7 +35,7 @@ import org.springframework.beans.factory.annotation.Autowired; * Basis factory interface implementation for indexing/retrieving any IndexableObject in the search core * @author Kevin Van de Velde (kevin at atmire dot com) */ -public abstract class IndexFactoryImpl implements IndexFactory { +public abstract class IndexFactoryImpl implements IndexFactory { @Autowired protected List solrServiceIndexPlugins; @@ -190,4 +190,7 @@ public abstract class IndexFactoryImpl implements Ind public void deleteAll() throws IOException, SolrServerException { solrSearchCore.getSolr().deleteByQuery(SearchUtils.RESOURCE_TYPE_FIELD + ":" + getType()); } + + @Override + public abstract List getIndexableObjects(Context context, S object) throws SQLException; } \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/InprogressSubmissionIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/InprogressSubmissionIndexFactoryImpl.java index 7d8a1f3a48..63910a2aed 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/InprogressSubmissionIndexFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/InprogressSubmissionIndexFactoryImpl.java @@ -26,8 +26,8 @@ import org.springframework.beans.factory.annotation.Autowired; * Factory implementation for indexing/retrieving InProgressSubmissions in the search core * @author Kevin Van de Velde (kevin at atmire dot com) */ -public abstract class InprogressSubmissionIndexFactoryImpl - extends IndexFactoryImpl implements InprogressSubmissionIndexFactory { +public abstract class InprogressSubmissionIndexFactoryImpl + extends IndexFactoryImpl implements InprogressSubmissionIndexFactory { @Autowired protected CollectionIndexFactory indexableCollectionService; @@ -37,7 +37,9 @@ public abstract class InprogressSubmissionIndexFactoryImpl +public class ItemIndexFactoryImpl extends DSpaceObjectIndexFactoryImpl implements ItemIndexFactory { private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(ItemIndexFactoryImpl.class); @@ -79,6 +87,14 @@ public class ItemIndexFactoryImpl extends DSpaceObjectIndexFactoryImpl discoveryConfigurations = SearchUtils.getAllDiscoveryConfigurations(item); addDiscoveryFields(doc, context, indexableItem.getIndexedObject(), discoveryConfigurations); @@ -676,6 +694,34 @@ public class ItemIndexFactoryImpl extends DSpaceObjectIndexFactoryImpl results = new ArrayList<>(); + if (object.isArchived() || object.isWithdrawn()) { + // We only want to index an item as an item if it is not in workflow + results.addAll(Arrays.asList(new IndexableItem(object))); + } else { + // Check if we have a workflow / workspace item + final WorkspaceItem workspaceItem = workspaceItemService.findByItem(context, object); + if (workspaceItem != null) { + results.addAll(workspaceItemIndexFactory.getIndexableObjects(context, workspaceItem)); + } else { + // Check if we a workflow item + final XmlWorkflowItem xmlWorkflowItem = xmlWorkflowItemService.findByItem(context, object); + if (xmlWorkflowItem != null) { + results.addAll(workflowItemIndexFactory.getIndexableObjects(context, xmlWorkflowItem)); + } + } + } + + return results; + } + @Override public Optional findIndexableObject(Context context, String id) throws SQLException { final Item item = itemService.find(context, UUID.fromString(id)); diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/PoolTaskIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/PoolTaskIndexFactoryImpl.java index 5c9f8baf9c..e7f2f0a14c 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/PoolTaskIndexFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/PoolTaskIndexFactoryImpl.java @@ -9,7 +9,9 @@ package org.dspace.discovery.indexobject; import java.io.IOException; import java.sql.SQLException; +import java.util.Arrays; import java.util.Iterator; +import java.util.List; import java.util.Optional; import org.apache.commons.lang3.StringUtils; @@ -26,7 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired; * Factory implementation for indexing/retrieving pooled tasks in the search core * @author Kevin Van de Velde (kevin at atmire dot com) */ -public class PoolTaskIndexFactoryImpl extends IndexFactoryImpl +public class PoolTaskIndexFactoryImpl extends IndexFactoryImpl implements PoolTaskIndexFactory { @Autowired @@ -59,8 +61,10 @@ public class PoolTaskIndexFactoryImpl extends IndexFactoryImpl findIndexableObject(Context context, String id) throws SQLException { final PoolTask poolTask = poolTaskService.find(context, Integer.parseInt(id)); diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/WorkflowItemIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/WorkflowItemIndexFactoryImpl.java index b0800ecee8..46439f3919 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/WorkflowItemIndexFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/WorkflowItemIndexFactoryImpl.java @@ -9,6 +9,7 @@ package org.dspace.discovery.indexobject; import java.io.IOException; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Optional; @@ -17,11 +18,16 @@ import org.apache.commons.lang3.StringUtils; 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; +import org.dspace.xmlworkflow.storedcomponents.PoolTask; import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; +import org.dspace.xmlworkflow.storedcomponents.service.ClaimedTaskService; +import org.dspace.xmlworkflow.storedcomponents.service.PoolTaskService; import org.dspace.xmlworkflow.storedcomponents.service.XmlWorkflowItemService; import org.springframework.beans.factory.annotation.Autowired; @@ -29,11 +35,16 @@ import org.springframework.beans.factory.annotation.Autowired; * Factory implementation for indexing/retrieving workflow items in the search core * @author Kevin Van de Velde (kevin at atmire dot com) */ -public class WorkflowItemIndexFactoryImpl extends InprogressSubmissionIndexFactoryImpl +public class WorkflowItemIndexFactoryImpl + extends InprogressSubmissionIndexFactoryImpl implements WorkflowItemIndexFactory { @Autowired protected XmlWorkflowItemService workflowItemService; + @Autowired + protected ClaimedTaskService claimedTaskService; + @Autowired + protected PoolTaskService poolTaskService; @Override public Iterator findAll(Context context) throws SQLException { @@ -60,9 +71,11 @@ public class WorkflowItemIndexFactoryImpl extends InprogressSubmissionIndexFacto @Override public SolrInputDocument buildDocument(Context context, IndexableWorkflowItem indexableObject) throws SQLException, IOException { + // Add the ID's, types and call the SolrServiceIndexPlugins final SolrInputDocument doc = super.buildDocument(context, indexableObject); final XmlWorkflowItem workflowItem = indexableObject.getIndexedObject(); final Item item = workflowItem.getItem(); + // Add the item metadata as configured List discoveryConfigurations = SearchUtils .getAllDiscoveryConfigurations(workflowItem); indexableItemService.addDiscoveryFields(doc, context, item, discoveryConfigurations); @@ -77,6 +90,29 @@ public class WorkflowItemIndexFactoryImpl extends InprogressSubmissionIndexFacto return doc; } + @Override + public boolean supports(Object object) { + return object instanceof XmlWorkflowItem; + } + + @Override + public List getIndexableObjects(Context context, XmlWorkflowItem object) throws SQLException { + List results = new ArrayList<>(); + results.add(new IndexableWorkflowItem(object)); + + List pools = poolTaskService.find(context, object); + for (PoolTask poolTask : pools) { + results.add(new IndexablePoolTask(poolTask)); + } + + List claimedTasks = claimedTaskService.find(context, object); + for (ClaimedTask claimedTask : claimedTasks) { + results.add(new IndexableClaimedTask(claimedTask)); + } + + return results; + } + @Override public Optional findIndexableObject(Context context, String id) throws SQLException { final XmlWorkflowItem xmlWorkflowItem = workflowItemService.find(context, Integer.parseInt(id)); diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/WorkspaceItemIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/WorkspaceItemIndexFactoryImpl.java index 5ecc5f3528..08cb484497 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/WorkspaceItemIndexFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/WorkspaceItemIndexFactoryImpl.java @@ -9,6 +9,7 @@ package org.dspace.discovery.indexobject; import java.io.IOException; import java.sql.SQLException; +import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Optional; @@ -28,7 +29,8 @@ import org.springframework.beans.factory.annotation.Autowired; * Factory implementation for indexing/retrieving workspace items in the search core * @author Kevin Van de Velde (kevin at atmire dot com) */ -public class WorkspaceItemIndexFactoryImpl extends InprogressSubmissionIndexFactoryImpl +public class WorkspaceItemIndexFactoryImpl + extends InprogressSubmissionIndexFactoryImpl implements WorkspaceItemIndexFactory { @Autowired @@ -59,8 +61,10 @@ public class WorkspaceItemIndexFactoryImpl extends InprogressSubmissionIndexFact @Override public SolrInputDocument buildDocument(Context context, IndexableWorkspaceItem indexableObject) throws SQLException, IOException { + // Add the ID's, types and call the SolrServiceIndexPlugins final SolrInputDocument doc = super.buildDocument(context, indexableObject); + // Add the object type String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService() .getProperty("discovery.facet.namedtype.workspace"); if (StringUtils.isBlank(acvalue)) { @@ -69,6 +73,7 @@ public class WorkspaceItemIndexFactoryImpl extends InprogressSubmissionIndexFact addNamedResourceTypeIndex(doc, acvalue); final WorkspaceItem inProgressSubmission = indexableObject.getIndexedObject(); + // Add the item metadata as configured List discoveryConfigurations = SearchUtils .getAllDiscoveryConfigurations(inProgressSubmission); indexableItemService.addDiscoveryFields(doc, context, inProgressSubmission.getItem(), discoveryConfigurations); @@ -76,6 +81,16 @@ public class WorkspaceItemIndexFactoryImpl extends InprogressSubmissionIndexFact return doc; } + @Override + public boolean supports(Object object) { + return object instanceof WorkspaceItem; + } + + @Override + public List getIndexableObjects(Context context, WorkspaceItem object) { + return Arrays.asList(new IndexableWorkspaceItem(object)); + } + @Override public Optional findIndexableObject(Context context, String id) throws SQLException { final WorkspaceItem workspaceItem = workspaceItemService.find(context, Integer.parseInt(id)); diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/ClaimedTaskIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/ClaimedTaskIndexFactory.java index e5d8b1ba0d..3aac462fc2 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/ClaimedTaskIndexFactory.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/ClaimedTaskIndexFactory.java @@ -8,11 +8,12 @@ package org.dspace.discovery.indexobject.factory; import org.dspace.discovery.indexobject.IndexableClaimedTask; +import org.dspace.xmlworkflow.storedcomponents.ClaimedTask; /** * Factory interface for indexing/retrieving claimed tasks in the search core * * @author Kevin Van de Velde (kevin at atmire dot com) */ -public interface ClaimedTaskIndexFactory extends IndexFactory { +public interface ClaimedTaskIndexFactory extends IndexFactory { } \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/CollectionIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/CollectionIndexFactory.java index 52c21017f5..ef60736293 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/CollectionIndexFactory.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/CollectionIndexFactory.java @@ -19,7 +19,7 @@ import org.dspace.discovery.indexobject.IndexableCollection; * * @author Kevin Van de Velde (kevin at atmire dot com) */ -public interface CollectionIndexFactory extends DSpaceObjectIndexFactory { +public interface CollectionIndexFactory extends DSpaceObjectIndexFactory { /** * Return a list of the identifiers of the owning communities from the provided collection prepended by "m" diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/CommunityIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/CommunityIndexFactory.java index a7c72dc1d8..d0002b5267 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/CommunityIndexFactory.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/CommunityIndexFactory.java @@ -7,6 +7,7 @@ */ package org.dspace.discovery.indexobject.factory; +import org.dspace.content.Community; import org.dspace.discovery.indexobject.IndexableCommunity; /** @@ -14,5 +15,5 @@ import org.dspace.discovery.indexobject.IndexableCommunity; * * @author Kevin Van de Velde (kevin at atmire dot com) */ -public interface CommunityIndexFactory extends DSpaceObjectIndexFactory { +public interface CommunityIndexFactory extends DSpaceObjectIndexFactory { } \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/DSpaceObjectIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/DSpaceObjectIndexFactory.java index 0321a5b69e..0d5adf824a 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/DSpaceObjectIndexFactory.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/DSpaceObjectIndexFactory.java @@ -19,7 +19,7 @@ import org.dspace.discovery.indexobject.IndexableDSpaceObject; * * @author Kevin Van de Velde (kevin at atmire dot com) */ -public interface DSpaceObjectIndexFactory extends IndexFactory { +public interface DSpaceObjectIndexFactory extends IndexFactory { /** diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexFactory.java index 87147b5383..1fa435eed5 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexFactory.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexFactory.java @@ -10,6 +10,7 @@ package org.dspace.discovery.indexobject.factory; import java.io.IOException; import java.sql.SQLException; import java.util.Iterator; +import java.util.List; import java.util.Optional; import org.apache.solr.client.solrj.SolrServerException; @@ -22,7 +23,7 @@ import org.dspace.discovery.IndexableObject; * * @author Kevin Van de Velde (kevin at atmire dot com) */ -public interface IndexFactory { +public interface IndexFactory { /** * Retrieve all instances of a certain indexable object type @@ -88,4 +89,20 @@ public interface IndexFactory { * @throws SQLException If database error */ Optional findIndexableObject(Context context, String id) throws SQLException; + + /** + * Determine whether the class can handle the object + * @param object The object which should be handle + * @return True if the class can handle the given object. False if it doesn't. + */ + boolean supports(Object object); + + /** + * Retrieve all the indexable objects for the provided object + * @param context DSpace context object + * @param object The object we want to retrieve our indexable objects for + * @return A list of indexable objects + * @throws SQLException If database error + */ + List getIndexableObjects(Context context, S object) throws SQLException; } \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexObjectFactoryFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexObjectFactoryFactory.java index 387e5b6d0e..1152dffbd3 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexObjectFactoryFactory.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/IndexObjectFactoryFactory.java @@ -8,30 +8,13 @@ package org.dspace.discovery.indexobject.factory; import java.sql.SQLException; -import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.StringUtils; -import org.dspace.content.Collection; -import org.dspace.content.Community; -import org.dspace.content.DSpaceObject; -import org.dspace.content.Item; -import org.dspace.content.WorkspaceItem; import org.dspace.content.service.WorkspaceItemService; -import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.discovery.IndexableObject; -import org.dspace.discovery.indexobject.IndexableClaimedTask; -import org.dspace.discovery.indexobject.IndexableCollection; -import org.dspace.discovery.indexobject.IndexableCommunity; -import org.dspace.discovery.indexobject.IndexableItem; -import org.dspace.discovery.indexobject.IndexablePoolTask; -import org.dspace.discovery.indexobject.IndexableWorkflowItem; -import org.dspace.discovery.indexobject.IndexableWorkspaceItem; import org.dspace.services.factory.DSpaceServicesFactory; -import org.dspace.xmlworkflow.storedcomponents.ClaimedTask; -import org.dspace.xmlworkflow.storedcomponents.PoolTask; -import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; import org.dspace.xmlworkflow.storedcomponents.service.ClaimedTaskService; import org.dspace.xmlworkflow.storedcomponents.service.PoolTaskService; import org.dspace.xmlworkflow.storedcomponents.service.XmlWorkflowItemService; @@ -99,53 +82,13 @@ public abstract class IndexObjectFactoryFactory { * @return A list of indexable objects */ public List getIndexableObjects(Context context, Object object) throws SQLException { - List results = new ArrayList<>(); - if (object instanceof DSpaceObject) { - switch ((((DSpaceObject) object).getType())) { - case Constants.COMMUNITY: - results.add(new IndexableCommunity((Community) object)); - break; - case Constants.COLLECTION: - results.add(new IndexableCollection((Collection) object)); - break; - case Constants.ITEM: - final Item item = (Item) object; - if (item.isArchived() || item.isWithdrawn()) { - // We only want to index an item as an item if it is not in workflow - results.add(new IndexableItem(item)); - } else { - // Check if we have a workflow / workspace item - final WorkspaceItem workspaceItem = workspaceItemService.findByItem(context, item); - if (workspaceItem != null) { - results.add(new IndexableWorkspaceItem(workspaceItem)); - } else { - // Check if we a workflow item - final XmlWorkflowItem xmlWorkflowItem = xmlWorkflowItemService.findByItem(context, item); - if (xmlWorkflowItem != null) { - results.add(new IndexableWorkflowItem(xmlWorkflowItem)); - List claimedTasks = claimedTaskService.find(context, xmlWorkflowItem); - List pools = poolTaskService.find(context, xmlWorkflowItem); - for (PoolTask poolTask : pools) { - results.add(new IndexablePoolTask(poolTask)); - } - for (ClaimedTask claimedTask : claimedTasks) { - results.add(new IndexableClaimedTask(claimedTask)); - } - } - } - } - break; - default: - throw new IllegalArgumentException("The object: " + object.getClass().getName() - + " cannot be indexed"); - - + for (IndexFactory indexableObjectFactory : getIndexFactories()) { + if (indexableObjectFactory.supports(object)) { + return indexableObjectFactory.getIndexableObjects(context, object); } - } else { - throw new IllegalArgumentException("The object: " + object.getClass().getName() - + " cannot be indexed"); } - return results; + throw new IllegalArgumentException("The object: " + object.getClass().getName() + + " cannot be indexed"); } /** diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/InprogressSubmissionIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/InprogressSubmissionIndexFactory.java index 8b26cc7220..ef98ed01b4 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/InprogressSubmissionIndexFactory.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/InprogressSubmissionIndexFactory.java @@ -19,8 +19,8 @@ import org.dspace.discovery.indexobject.IndexableInProgressSubmission; * * @author Kevin Van de Velde (kevin at atmire dot com) */ -public interface InprogressSubmissionIndexFactory - extends IndexFactory { +public interface InprogressSubmissionIndexFactory + extends IndexFactory { /** * Store common fields between workspace / workflow items in the solr document diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/ItemIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/ItemIndexFactory.java index 8708eb5585..4bf24b3c6d 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/ItemIndexFactory.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/ItemIndexFactory.java @@ -22,7 +22,7 @@ import org.dspace.discovery.indexobject.IndexableItem; * * @author Kevin Van de Velde (kevin at atmire dot com) */ -public interface ItemIndexFactory extends DSpaceObjectIndexFactory { +public interface ItemIndexFactory extends DSpaceObjectIndexFactory { /** * Store item fields in the solr document diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/PoolTaskIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/PoolTaskIndexFactory.java index 86b340d8b4..203f13e61a 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/PoolTaskIndexFactory.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/PoolTaskIndexFactory.java @@ -8,11 +8,12 @@ package org.dspace.discovery.indexobject.factory; import org.dspace.discovery.indexobject.IndexablePoolTask; +import org.dspace.xmlworkflow.storedcomponents.PoolTask; /** * Factory interface for indexing/retrieving Pooltask objects in the search core * * @author Kevin Van de Velde (kevin at atmire dot com) */ -public interface PoolTaskIndexFactory extends IndexFactory { +public interface PoolTaskIndexFactory extends IndexFactory { } \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/WorkflowItemIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/WorkflowItemIndexFactory.java index c2eb0c8310..2a2f695ed8 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/WorkflowItemIndexFactory.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/WorkflowItemIndexFactory.java @@ -8,11 +8,13 @@ package org.dspace.discovery.indexobject.factory; import org.dspace.discovery.indexobject.IndexableWorkflowItem; +import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; /** * Factory interface for indexing/retrieving workflow items objects in the search core * * @author Kevin Van de Velde (kevin at atmire dot com) */ -public interface WorkflowItemIndexFactory extends InprogressSubmissionIndexFactory { +public interface WorkflowItemIndexFactory + extends InprogressSubmissionIndexFactory { } \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/WorkspaceItemIndexFactory.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/WorkspaceItemIndexFactory.java index f86fc5f676..0cb3b985e2 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/WorkspaceItemIndexFactory.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/factory/WorkspaceItemIndexFactory.java @@ -7,6 +7,7 @@ */ package org.dspace.discovery.indexobject.factory; +import org.dspace.content.WorkspaceItem; import org.dspace.discovery.indexobject.IndexableWorkspaceItem; /** @@ -14,5 +15,6 @@ import org.dspace.discovery.indexobject.IndexableWorkspaceItem; * * @author Kevin Van de Velde (kevin at atmire dot com) */ -public interface WorkspaceItemIndexFactory extends InprogressSubmissionIndexFactory { +public interface WorkspaceItemIndexFactory + extends InprogressSubmissionIndexFactory { } \ No newline at end of file From e01838617524b91eb1c2620d1774cb44cce98a54 Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Fri, 3 Jan 2020 16:31:27 -0500 Subject: [PATCH 100/125] [DS-4409] Remove GeoIP download Ant target, reconfigure for external provision. --- dspace/config/modules/usage-statistics.cfg | 9 +-- dspace/src/main/config/build.xml | 74 ++-------------------- 2 files changed, 11 insertions(+), 72 deletions(-) diff --git a/dspace/config/modules/usage-statistics.cfg b/dspace/config/modules/usage-statistics.cfg index 9e363a9e38..635a927bb6 100644 --- a/dspace/config/modules/usage-statistics.cfg +++ b/dspace/config/modules/usage-statistics.cfg @@ -1,13 +1,14 @@ #---------------------------------------------------------------# #--------------USAGE STATISTICS CONFIGURATIONS------------------# #---------------------------------------------------------------# -# These configs are only used by the DSpace interfaces which # -# track usage statistics (Solr) # +# These properties are only used by the DSpace interfaces which # +# track usage statistics (Solr). # # See also: solr-statistics.cfg # #---------------------------------------------------------------# -# The location for the Geo Database retrieved on update/installation -usage-statistics.dbfile = ${dspace.dir}/config/GeoLite2-City.mmdb +# The location for the database used to map client addresses to approximate +# physical locations. +usage-statistics.dbfile = /usr/share/GeoIP/GeoLite2-City.mmdb # Timeout for the resolver in the DNS lookup # Time in milliseconds, defaults to 200 for backward compatibility diff --git a/dspace/src/main/config/build.xml b/dspace/src/main/config/build.xml index 98414f0cdd..8afddb421a 100644 --- a/dspace/src/main/config/build.xml +++ b/dspace/src/main/config/build.xml @@ -79,9 +79,6 @@ Common usage: - - - @@ -104,7 +101,7 @@ Common usage: - + @@ -117,7 +114,6 @@ Common usage: - @@ -147,7 +143,7 @@ Common usage: - + @@ -176,10 +172,11 @@ Common usage: - + - - + @@ -832,8 +829,6 @@ Common usage: - - ==================================================================== The DSpace code has been installed. @@ -863,61 +858,4 @@ Common usage: - - - Downloading: ${geolite} - - - - - - - - - - - - - -==================================================================== -WARNING : FAILED TO DOWNLOAD GEOLITE DATABASE FILE - (Used for DSpace Solr Usage Statistics) - -Underlying Error: ${geolite.error} - -In order to use DSpace Solr Usage Statistics, you will need to -manually re-run: - -ant update_geolite - -OR - -You may manually install this file by following these steps: -(1) Download the latest database archive from ${geolite} -(2) Unpack it.' -(3) Copy the file 'GeoLite2-City.mmdb' to '${usage-statistics.dbfile}'. - -==================================================================== - - - - - - - - - - - - - - - - - - From 977b3f409d7542b700adc8f94334dc7332ee84f8 Mon Sep 17 00:00:00 2001 From: Kevin Van de Velde Date: Mon, 6 Jan 2020 15:52:21 +0100 Subject: [PATCH 101/125] [DS-4351] upgrade dependencies: Fixing a display issue in HAl & resolving a warning with slf4j on tomcat startup --- dspace-server-webapp/src/main/webapp/index.html | 2 +- pom.xml | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/webapp/index.html b/dspace-server-webapp/src/main/webapp/index.html index acb6b51fc5..15661c654a 100644 --- a/dspace-server-webapp/src/main/webapp/index.html +++ b/dspace-server-webapp/src/main/webapp/index.html @@ -122,7 +122,7 @@