mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-15 22:13:08 +00:00
CST-5249 dpspace.cfg conflicts fix
This commit is contained in:
@@ -7,18 +7,10 @@
|
||||
*/
|
||||
package org.dspace.app.sitemap;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
@@ -29,12 +21,8 @@ import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.CollectionService;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
@@ -43,6 +31,7 @@ import org.dspace.core.Context;
|
||||
import org.dspace.core.LogHelper;
|
||||
import org.dspace.discovery.DiscoverQuery;
|
||||
import org.dspace.discovery.DiscoverResult;
|
||||
import org.dspace.discovery.IndexableObject;
|
||||
import org.dspace.discovery.SearchService;
|
||||
import org.dspace.discovery.SearchServiceException;
|
||||
import org.dspace.discovery.SearchUtils;
|
||||
@@ -68,6 +57,7 @@ public class GenerateSitemaps {
|
||||
private static final ConfigurationService configurationService =
|
||||
DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
private static final SearchService searchService = SearchUtils.getSearchService();
|
||||
private static final int PAGE_SIZE = 100;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
@@ -87,11 +77,6 @@ public class GenerateSitemaps {
|
||||
"do not generate sitemaps.org protocol sitemap");
|
||||
options.addOption("b", "no_htmlmap", false,
|
||||
"do not generate a basic HTML sitemap");
|
||||
options.addOption("a", "ping_all", false,
|
||||
"ping configured search engines");
|
||||
options
|
||||
.addOption("p", "ping", true,
|
||||
"ping specified search engine URL");
|
||||
options
|
||||
.addOption("d", "delete", false,
|
||||
"delete sitemaps dir and its contents");
|
||||
@@ -116,14 +101,13 @@ public class GenerateSitemaps {
|
||||
}
|
||||
|
||||
/*
|
||||
* Sanity check -- if no sitemap generation or pinging to do, or deletion, print usage
|
||||
* Sanity check -- if no sitemap generation or deletion, print usage
|
||||
*/
|
||||
if (line.getArgs().length != 0 || line.hasOption('d') || line.hasOption('b')
|
||||
&& line.hasOption('s') && !line.hasOption('g')
|
||||
&& !line.hasOption('m') && !line.hasOption('y')
|
||||
&& !line.hasOption('p')) {
|
||||
&& !line.hasOption('m') && !line.hasOption('y')) {
|
||||
System.err
|
||||
.println("Nothing to do (no sitemap to generate, no search engines to ping)");
|
||||
.println("Nothing to do (no sitemap to generate)");
|
||||
hf.printHelp(usage, options);
|
||||
System.exit(1);
|
||||
}
|
||||
@@ -137,20 +121,6 @@ public class GenerateSitemaps {
|
||||
deleteSitemaps();
|
||||
}
|
||||
|
||||
if (line.hasOption('a')) {
|
||||
pingConfiguredSearchEngines();
|
||||
}
|
||||
|
||||
if (line.hasOption('p')) {
|
||||
try {
|
||||
pingSearchEngine(line.getOptionValue('p'));
|
||||
} catch (MalformedURLException me) {
|
||||
System.err
|
||||
.println("Bad search engine URL (include all except sitemap URL)");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
@@ -211,171 +181,113 @@ public class GenerateSitemaps {
|
||||
}
|
||||
|
||||
Context c = new Context(Context.Mode.READ_ONLY);
|
||||
|
||||
List<Community> comms = communityService.findAll(c);
|
||||
|
||||
for (Community comm : comms) {
|
||||
String url = uiURLStem + "communities/" + comm.getID();
|
||||
|
||||
if (makeHTMLMap) {
|
||||
html.addURL(url, null);
|
||||
}
|
||||
if (makeSitemapOrg) {
|
||||
sitemapsOrg.addURL(url, null);
|
||||
}
|
||||
|
||||
c.uncacheEntity(comm);
|
||||
}
|
||||
|
||||
List<Collection> colls = collectionService.findAll(c);
|
||||
|
||||
for (Collection coll : colls) {
|
||||
String url = uiURLStem + "collections/" + coll.getID();
|
||||
|
||||
if (makeHTMLMap) {
|
||||
html.addURL(url, null);
|
||||
}
|
||||
if (makeSitemapOrg) {
|
||||
sitemapsOrg.addURL(url, null);
|
||||
}
|
||||
|
||||
c.uncacheEntity(coll);
|
||||
}
|
||||
|
||||
Iterator<Item> allItems = itemService.findAll(c);
|
||||
int itemCount = 0;
|
||||
|
||||
while (allItems.hasNext()) {
|
||||
Item i = allItems.next();
|
||||
|
||||
DiscoverQuery entityQuery = new DiscoverQuery();
|
||||
entityQuery.setQuery("search.uniqueid:\"Item-" + i.getID() + "\" and entityType:*");
|
||||
entityQuery.addSearchField("entityType");
|
||||
|
||||
try {
|
||||
DiscoverResult discoverResult = searchService.search(c, entityQuery);
|
||||
|
||||
String url;
|
||||
if (CollectionUtils.isNotEmpty(discoverResult.getIndexableObjects())
|
||||
&& CollectionUtils.isNotEmpty(discoverResult.getSearchDocument(
|
||||
discoverResult.getIndexableObjects().get(0)).get(0).getSearchFieldValues("entityType"))
|
||||
&& StringUtils.isNotBlank(discoverResult.getSearchDocument(
|
||||
discoverResult.getIndexableObjects().get(0)).get(0).getSearchFieldValues("entityType").get(0))
|
||||
) {
|
||||
url = uiURLStem + "entities/" + StringUtils.lowerCase(discoverResult.getSearchDocument(
|
||||
discoverResult.getIndexableObjects().get(0))
|
||||
.get(0).getSearchFieldValues("entityType").get(0)) + "/" + i.getID();
|
||||
} else {
|
||||
url = uiURLStem + "items/" + i.getID();
|
||||
}
|
||||
Date lastMod = i.getLastModified();
|
||||
|
||||
if (makeHTMLMap) {
|
||||
html.addURL(url, lastMod);
|
||||
}
|
||||
if (makeSitemapOrg) {
|
||||
sitemapsOrg.addURL(url, lastMod);
|
||||
}
|
||||
} catch (SearchServiceException e) {
|
||||
log.error("Failed getting entitytype through solr for item " + i.getID() + ": " + e.getMessage());
|
||||
}
|
||||
|
||||
c.uncacheEntity(i);
|
||||
|
||||
itemCount++;
|
||||
}
|
||||
|
||||
if (makeHTMLMap) {
|
||||
int files = html.finish();
|
||||
log.info(LogHelper.getHeader(c, "write_sitemap",
|
||||
"type=html,num_files=" + files + ",communities="
|
||||
+ comms.size() + ",collections=" + colls.size()
|
||||
+ ",items=" + itemCount));
|
||||
}
|
||||
|
||||
if (makeSitemapOrg) {
|
||||
int files = sitemapsOrg.finish();
|
||||
log.info(LogHelper.getHeader(c, "write_sitemap",
|
||||
"type=html,num_files=" + files + ",communities="
|
||||
+ comms.size() + ",collections=" + colls.size()
|
||||
+ ",items=" + itemCount));
|
||||
}
|
||||
|
||||
c.abort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ping all search engines configured in {@code dspace.cfg}.
|
||||
*
|
||||
* @throws UnsupportedEncodingException theoretically should never happen
|
||||
*/
|
||||
public static void pingConfiguredSearchEngines()
|
||||
throws UnsupportedEncodingException {
|
||||
String[] engineURLs = configurationService
|
||||
.getArrayProperty("sitemap.engineurls");
|
||||
|
||||
if (ArrayUtils.isEmpty(engineURLs)) {
|
||||
log.warn("No search engine URLs configured to ping");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < engineURLs.length; i++) {
|
||||
try {
|
||||
pingSearchEngine(engineURLs[i]);
|
||||
} catch (MalformedURLException me) {
|
||||
log.warn("Bad search engine URL in configuration: "
|
||||
+ engineURLs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ping the given search engine.
|
||||
*
|
||||
* @param engineURL Search engine URL minus protocol etc, e.g.
|
||||
* {@code www.google.com}
|
||||
* @throws MalformedURLException if the passed in URL is malformed
|
||||
* @throws UnsupportedEncodingException theoretically should never happen
|
||||
*/
|
||||
public static void pingSearchEngine(String engineURL)
|
||||
throws MalformedURLException, UnsupportedEncodingException {
|
||||
// Set up HTTP proxy
|
||||
if ((StringUtils.isNotBlank(configurationService.getProperty("http.proxy.host")))
|
||||
&& (StringUtils.isNotBlank(configurationService.getProperty("http.proxy.port")))) {
|
||||
System.setProperty("proxySet", "true");
|
||||
System.setProperty("proxyHost", configurationService
|
||||
.getProperty("http.proxy.host"));
|
||||
System.getProperty("proxyPort", configurationService
|
||||
.getProperty("http.proxy.port"));
|
||||
}
|
||||
|
||||
String sitemapURL = configurationService.getProperty("dspace.ui.url")
|
||||
+ "/sitemap";
|
||||
|
||||
URL url = new URL(engineURL + URLEncoder.encode(sitemapURL, "UTF-8"));
|
||||
int offset = 0;
|
||||
long commsCount = 0;
|
||||
long collsCount = 0;
|
||||
long itemsCount = 0;
|
||||
|
||||
try {
|
||||
HttpURLConnection connection = (HttpURLConnection) url
|
||||
.openConnection();
|
||||
DiscoverQuery discoveryQuery = new DiscoverQuery();
|
||||
discoveryQuery.setMaxResults(PAGE_SIZE);
|
||||
discoveryQuery.setQuery("search.resourcetype:Community");
|
||||
do {
|
||||
discoveryQuery.setStart(offset);
|
||||
DiscoverResult discoverResult = searchService.search(c, discoveryQuery);
|
||||
List<IndexableObject> docs = discoverResult.getIndexableObjects();
|
||||
commsCount = discoverResult.getTotalSearchResults();
|
||||
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(
|
||||
connection.getInputStream()));
|
||||
for (IndexableObject doc : docs) {
|
||||
String url = uiURLStem + "communities/" + doc.getID();
|
||||
c.uncacheEntity(doc.getIndexedObject());
|
||||
|
||||
String inputLine;
|
||||
StringBuffer resp = new StringBuffer();
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
resp.append(inputLine).append("\n");
|
||||
if (makeHTMLMap) {
|
||||
html.addURL(url, null);
|
||||
}
|
||||
if (makeSitemapOrg) {
|
||||
sitemapsOrg.addURL(url, null);
|
||||
}
|
||||
}
|
||||
offset += PAGE_SIZE;
|
||||
} while (offset < commsCount);
|
||||
|
||||
offset = 0;
|
||||
discoveryQuery = new DiscoverQuery();
|
||||
discoveryQuery.setMaxResults(PAGE_SIZE);
|
||||
discoveryQuery.setQuery("search.resourcetype:Collection");
|
||||
do {
|
||||
discoveryQuery.setStart(offset);
|
||||
DiscoverResult discoverResult = searchService.search(c, discoveryQuery);
|
||||
List<IndexableObject> docs = discoverResult.getIndexableObjects();
|
||||
collsCount = discoverResult.getTotalSearchResults();
|
||||
|
||||
for (IndexableObject doc : docs) {
|
||||
String url = uiURLStem + "collections/" + doc.getID();
|
||||
c.uncacheEntity(doc.getIndexedObject());
|
||||
|
||||
if (makeHTMLMap) {
|
||||
html.addURL(url, null);
|
||||
}
|
||||
if (makeSitemapOrg) {
|
||||
sitemapsOrg.addURL(url, null);
|
||||
}
|
||||
}
|
||||
offset += PAGE_SIZE;
|
||||
} while (offset < collsCount);
|
||||
|
||||
offset = 0;
|
||||
discoveryQuery = new DiscoverQuery();
|
||||
discoveryQuery.setMaxResults(PAGE_SIZE);
|
||||
discoveryQuery.setQuery("search.resourcetype:Item");
|
||||
discoveryQuery.addSearchField("search.entitytype");
|
||||
do {
|
||||
|
||||
discoveryQuery.setStart(offset);
|
||||
DiscoverResult discoverResult = searchService.search(c, discoveryQuery);
|
||||
List<IndexableObject> docs = discoverResult.getIndexableObjects();
|
||||
itemsCount = discoverResult.getTotalSearchResults();
|
||||
|
||||
for (IndexableObject doc : docs) {
|
||||
String url;
|
||||
List<String> entityTypeFieldValues = discoverResult.getSearchDocument(doc).get(0)
|
||||
.getSearchFieldValues("search.entitytype");
|
||||
if (CollectionUtils.isNotEmpty(entityTypeFieldValues)) {
|
||||
url = uiURLStem + "entities/" + StringUtils.lowerCase(entityTypeFieldValues.get(0)) + "/"
|
||||
+ doc.getID();
|
||||
} else {
|
||||
url = uiURLStem + "items/" + doc.getID();
|
||||
}
|
||||
Date lastMod = doc.getLastModified();
|
||||
c.uncacheEntity(doc.getIndexedObject());
|
||||
|
||||
if (makeHTMLMap) {
|
||||
html.addURL(url, null);
|
||||
}
|
||||
if (makeSitemapOrg) {
|
||||
sitemapsOrg.addURL(url, null);
|
||||
}
|
||||
}
|
||||
offset += PAGE_SIZE;
|
||||
} while (offset < itemsCount);
|
||||
|
||||
if (makeHTMLMap) {
|
||||
int files = html.finish();
|
||||
log.info(LogHelper.getHeader(c, "write_sitemap",
|
||||
"type=html,num_files=" + files + ",communities="
|
||||
+ commsCount + ",collections=" + collsCount
|
||||
+ ",items=" + itemsCount));
|
||||
}
|
||||
in.close();
|
||||
|
||||
if (connection.getResponseCode() == 200) {
|
||||
log.info("Pinged " + url.toString() + " successfully");
|
||||
} else {
|
||||
log.warn("Error response pinging " + url.toString() + ":\n"
|
||||
+ resp);
|
||||
if (makeSitemapOrg) {
|
||||
int files = sitemapsOrg.finish();
|
||||
log.info(LogHelper.getHeader(c, "write_sitemap",
|
||||
"type=html,num_files=" + files + ",communities="
|
||||
+ commsCount + ",collections=" + collsCount
|
||||
+ ",items=" + itemsCount));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.warn("Error pinging " + url.toString(), e);
|
||||
} catch (SearchServiceException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
c.abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ import org.dspace.content.Collection;
|
||||
import org.dspace.content.MetadataSchemaEnum;
|
||||
import org.dspace.core.Utils;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.dspace.submit.factory.SubmissionServiceFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
@@ -158,7 +159,8 @@ public class DCInputsReader {
|
||||
throws DCInputsReaderException {
|
||||
SubmissionConfig config;
|
||||
try {
|
||||
config = new SubmissionConfigReader().getSubmissionConfigByCollection(collectionHandle);
|
||||
config = SubmissionServiceFactory.getInstance().getSubmissionConfigService()
|
||||
.getSubmissionConfigByCollection(collectionHandle);
|
||||
String formName = config.getSubmissionName();
|
||||
if (formName == null) {
|
||||
throw new DCInputsReaderException("No form designated as default");
|
||||
@@ -180,7 +182,8 @@ public class DCInputsReader {
|
||||
throws DCInputsReaderException {
|
||||
SubmissionConfig config;
|
||||
try {
|
||||
config = new SubmissionConfigReader().getSubmissionConfigByName(name);
|
||||
config = SubmissionServiceFactory.getInstance().getSubmissionConfigService()
|
||||
.getSubmissionConfigByName(name);
|
||||
String formName = config.getSubmissionName();
|
||||
if (formName == null) {
|
||||
throw new DCInputsReaderException("No form designated as default");
|
||||
|
@@ -153,6 +153,22 @@ public interface AuthenticationMethod {
|
||||
public List<Group> getSpecialGroups(Context context, HttpServletRequest request)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
* Returns true if the special groups returned by
|
||||
* {@link org.dspace.authenticate.AuthenticationMethod#getSpecialGroups(Context, HttpServletRequest)}
|
||||
* should be implicitly be added to the groups related to the current user. By
|
||||
* default this is true if the authentication method is the actual
|
||||
* authentication mechanism used by the user.
|
||||
* @param context A valid DSpace context.
|
||||
* @param request The request that started this operation, or null if not
|
||||
* applicable.
|
||||
* @return true is the special groups must be considered, false
|
||||
* otherwise
|
||||
*/
|
||||
public default boolean areSpecialGroupsApplicable(Context context, HttpServletRequest request) {
|
||||
return getName().equals(context.getAuthenticationMethod());
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate the given or implicit credentials.
|
||||
* This is the heart of the authentication method: test the
|
||||
|
@@ -179,10 +179,15 @@ public class AuthenticationServiceImpl implements AuthenticationService {
|
||||
int totalLen = 0;
|
||||
|
||||
for (AuthenticationMethod method : getAuthenticationMethodStack()) {
|
||||
List<Group> gl = method.getSpecialGroups(context, request);
|
||||
if (gl.size() > 0) {
|
||||
result.addAll(gl);
|
||||
totalLen += gl.size();
|
||||
|
||||
if (method.areSpecialGroupsApplicable(context, request)) {
|
||||
|
||||
List<Group> gl = method.getSpecialGroups(context, request);
|
||||
if (gl.size() > 0) {
|
||||
result.addAll(gl);
|
||||
totalLen += gl.size();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -252,6 +252,11 @@ public class IPAuthentication implements AuthenticationMethod {
|
||||
return groups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areSpecialGroupsApplicable(Context context, HttpServletRequest request) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int authenticate(Context context, String username, String password,
|
||||
String realm, HttpServletRequest request) throws SQLException {
|
||||
|
@@ -494,6 +494,8 @@ public class LDAPAuthentication
|
||||
try {
|
||||
SearchControls ctrls = new SearchControls();
|
||||
ctrls.setSearchScope(ldap_search_scope_value);
|
||||
// Fetch both user attributes '*' (eg. uid, cn) and operational attributes '+' (eg. memberOf)
|
||||
ctrls.setReturningAttributes(new String[] {"*", "+"});
|
||||
|
||||
String searchName;
|
||||
if (useTLS) {
|
||||
@@ -700,21 +702,21 @@ public class LDAPAuthentication
|
||||
/*
|
||||
* Add authenticated users to the group defined in dspace.cfg by
|
||||
* the authentication-ldap.login.groupmap.* key.
|
||||
*
|
||||
*
|
||||
* @param dn
|
||||
* The string containing distinguished name of the user
|
||||
*
|
||||
*
|
||||
* @param group
|
||||
* List of strings with LDAP dn of groups
|
||||
*
|
||||
*
|
||||
* @param context
|
||||
* DSpace context
|
||||
*/
|
||||
private void assignGroups(String dn, ArrayList<String> group, Context context) {
|
||||
if (StringUtils.isNotBlank(dn)) {
|
||||
System.out.println("dn:" + dn);
|
||||
int i = 1;
|
||||
String groupMap = configurationService.getProperty("authentication-ldap.login.groupmap." + i);
|
||||
int groupmapIndex = 1;
|
||||
String groupMap = configurationService.getProperty("authentication-ldap.login.groupmap." + groupmapIndex);
|
||||
boolean cmp;
|
||||
|
||||
|
||||
@@ -725,52 +727,75 @@ public class LDAPAuthentication
|
||||
String ldapSearchString = t[0];
|
||||
String dspaceGroupName = t[1];
|
||||
|
||||
// list of strings with dn from LDAP groups
|
||||
// inner loop
|
||||
Iterator<String> groupIterator = group.iterator();
|
||||
while (groupIterator.hasNext()) {
|
||||
|
||||
// save the current entry from iterator for further use
|
||||
String currentGroup = groupIterator.next();
|
||||
|
||||
// very much the old code from DSpace <= 7.5
|
||||
if (currentGroup == null) {
|
||||
cmp = StringUtils.containsIgnoreCase(dn, ldapSearchString + ",");
|
||||
} else {
|
||||
cmp = StringUtils.equalsIgnoreCase(currentGroup, ldapSearchString);
|
||||
}
|
||||
if (group == null) {
|
||||
cmp = StringUtils.containsIgnoreCase(dn, ldapSearchString + ",");
|
||||
|
||||
if (cmp) {
|
||||
// assign user to this group
|
||||
try {
|
||||
Group ldapGroup = groupService.findByName(context, dspaceGroupName);
|
||||
if (ldapGroup != null) {
|
||||
groupService.addMember(context, ldapGroup, context.getCurrentUser());
|
||||
groupService.update(context, ldapGroup);
|
||||
} else {
|
||||
// The group does not exist
|
||||
log.warn(LogHelper.getHeader(context,
|
||||
"ldap_assignGroupsBasedOnLdapDn",
|
||||
"Group defined in authentication-ldap.login.groupmap." + i
|
||||
+ " does not exist :: " + dspaceGroupName));
|
||||
}
|
||||
} catch (AuthorizeException ae) {
|
||||
log.debug(LogHelper.getHeader(context,
|
||||
"assignGroupsBasedOnLdapDn could not authorize addition to " +
|
||||
"group",
|
||||
dspaceGroupName));
|
||||
} catch (SQLException e) {
|
||||
log.debug(LogHelper.getHeader(context, "assignGroupsBasedOnLdapDn could not find group",
|
||||
dspaceGroupName));
|
||||
assignGroup(context, groupmapIndex, dspaceGroupName);
|
||||
}
|
||||
} else {
|
||||
// list of strings with dn from LDAP groups
|
||||
// inner loop
|
||||
Iterator<String> groupIterator = group.iterator();
|
||||
while (groupIterator.hasNext()) {
|
||||
|
||||
// save the current entry from iterator for further use
|
||||
String currentGroup = groupIterator.next();
|
||||
|
||||
// very much the old code from DSpace <= 7.5
|
||||
if (currentGroup == null) {
|
||||
cmp = StringUtils.containsIgnoreCase(dn, ldapSearchString + ",");
|
||||
} else {
|
||||
cmp = StringUtils.equalsIgnoreCase(currentGroup, ldapSearchString);
|
||||
}
|
||||
|
||||
if (cmp) {
|
||||
assignGroup(context, groupmapIndex, dspaceGroupName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
groupMap = configurationService.getProperty("authentication-ldap.login.groupmap." + ++i);
|
||||
groupMap = configurationService.getProperty("authentication-ldap.login.groupmap." + ++groupmapIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the current authenticated user to the specified group
|
||||
*
|
||||
* @param context
|
||||
* DSpace context
|
||||
*
|
||||
* @param groupmapIndex
|
||||
* authentication-ldap.login.groupmap.* key index defined in dspace.cfg
|
||||
*
|
||||
* @param dspaceGroupName
|
||||
* The DSpace group to add the user to
|
||||
*/
|
||||
private void assignGroup(Context context, int groupmapIndex, String dspaceGroupName) {
|
||||
try {
|
||||
Group ldapGroup = groupService.findByName(context, dspaceGroupName);
|
||||
if (ldapGroup != null) {
|
||||
groupService.addMember(context, ldapGroup, context.getCurrentUser());
|
||||
groupService.update(context, ldapGroup);
|
||||
} else {
|
||||
// The group does not exist
|
||||
log.warn(LogHelper.getHeader(context,
|
||||
"ldap_assignGroupsBasedOnLdapDn",
|
||||
"Group defined in authentication-ldap.login.groupmap." + groupmapIndex
|
||||
+ " does not exist :: " + dspaceGroupName));
|
||||
}
|
||||
} catch (AuthorizeException ae) {
|
||||
log.debug(LogHelper.getHeader(context,
|
||||
"assignGroupsBasedOnLdapDn could not authorize addition to " +
|
||||
"group",
|
||||
dspaceGroupName));
|
||||
} catch (SQLException e) {
|
||||
log.debug(LogHelper.getHeader(context, "assignGroupsBasedOnLdapDn could not find group",
|
||||
dspaceGroupName));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUsed(final Context context, final HttpServletRequest request) {
|
||||
if (request != null &&
|
||||
|
@@ -451,7 +451,7 @@ public class AuthorizeServiceImpl implements AuthorizeService {
|
||||
if (e == null) {
|
||||
return false; // anonymous users can't be admins....
|
||||
} else {
|
||||
return groupService.isMember(c, e, Group.ADMIN);
|
||||
return groupService.isMember(c, e, c.getAdminGroup());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -276,6 +276,11 @@ public class BitstreamServiceImpl extends DSpaceObjectServiceImpl<Bitstream> imp
|
||||
//Remove our bitstream from all our bundles
|
||||
final List<Bundle> bundles = bitstream.getBundles();
|
||||
for (Bundle bundle : bundles) {
|
||||
authorizeService.authorizeAction(context, bundle, Constants.REMOVE);
|
||||
//We also need to remove the bitstream id when it's set as bundle's primary bitstream
|
||||
if (bitstream.equals(bundle.getPrimaryBitstream())) {
|
||||
bundle.unsetPrimaryBitstreamID();
|
||||
}
|
||||
bundle.removeBitstream(bitstream);
|
||||
}
|
||||
|
||||
|
@@ -126,7 +126,7 @@ public class Bundle extends DSpaceObject implements DSpaceObjectLegacySupport {
|
||||
* Unset the primary bitstream ID of the bundle
|
||||
*/
|
||||
public void unsetPrimaryBitstreamID() {
|
||||
primaryBitstream = null;
|
||||
setPrimaryBitstreamID(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -25,7 +25,6 @@ import org.dspace.app.util.DCInputSet;
|
||||
import org.dspace.app.util.DCInputsReader;
|
||||
import org.dspace.app.util.DCInputsReaderException;
|
||||
import org.dspace.app.util.SubmissionConfig;
|
||||
import org.dspace.app.util.SubmissionConfigReader;
|
||||
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.MetadataValue;
|
||||
@@ -35,6 +34,8 @@ import org.dspace.core.service.PluginService;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfigurationService;
|
||||
import org.dspace.discovery.configuration.DiscoverySearchFilterFacet;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.submit.factory.SubmissionServiceFactory;
|
||||
import org.dspace.submit.service.SubmissionConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
@@ -88,7 +89,7 @@ public final class ChoiceAuthorityServiceImpl implements ChoiceAuthorityService
|
||||
protected Map<String, DSpaceControlledVocabularyIndex> vocabularyIndexMap = new HashMap<>();
|
||||
|
||||
// the item submission reader
|
||||
private SubmissionConfigReader itemSubmissionConfigReader;
|
||||
private SubmissionConfigService submissionConfigService;
|
||||
|
||||
@Autowired(required = true)
|
||||
protected ConfigurationService configurationService;
|
||||
@@ -135,7 +136,7 @@ public final class ChoiceAuthorityServiceImpl implements ChoiceAuthorityService
|
||||
private synchronized void init() {
|
||||
if (!initialized) {
|
||||
try {
|
||||
itemSubmissionConfigReader = new SubmissionConfigReader();
|
||||
submissionConfigService = SubmissionServiceFactory.getInstance().getSubmissionConfigService();
|
||||
} catch (SubmissionConfigReaderException e) {
|
||||
// the system is in an illegal state as the submission definition is not valid
|
||||
throw new IllegalStateException("Error reading the item submission configuration: " + e.getMessage(),
|
||||
@@ -240,7 +241,7 @@ public final class ChoiceAuthorityServiceImpl implements ChoiceAuthorityService
|
||||
// there is an authority configured for the metadata valid for some collections,
|
||||
// check if it is the requested collection
|
||||
Map<String, ChoiceAuthority> controllerFormDef = controllerFormDefinitions.get(fieldKey);
|
||||
SubmissionConfig submissionConfig = itemSubmissionConfigReader
|
||||
SubmissionConfig submissionConfig = submissionConfigService
|
||||
.getSubmissionConfigByCollection(collection.getHandle());
|
||||
String submissionName = submissionConfig.getSubmissionName();
|
||||
// check if the requested collection has a submission definition that use an authority for the metadata
|
||||
@@ -262,14 +263,14 @@ public final class ChoiceAuthorityServiceImpl implements ChoiceAuthorityService
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearCache() {
|
||||
public void clearCache() throws SubmissionConfigReaderException {
|
||||
controller.clear();
|
||||
authorities.clear();
|
||||
presentation.clear();
|
||||
closed.clear();
|
||||
controllerFormDefinitions.clear();
|
||||
authoritiesFormDefinitions.clear();
|
||||
itemSubmissionConfigReader = null;
|
||||
submissionConfigService.reload();
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
@@ -319,7 +320,7 @@ public final class ChoiceAuthorityServiceImpl implements ChoiceAuthorityService
|
||||
*/
|
||||
private void autoRegisterChoiceAuthorityFromInputReader() {
|
||||
try {
|
||||
List<SubmissionConfig> submissionConfigs = itemSubmissionConfigReader
|
||||
List<SubmissionConfig> submissionConfigs = submissionConfigService
|
||||
.getAllSubmissionConfigs(Integer.MAX_VALUE, 0);
|
||||
DCInputsReader dcInputsReader = new DCInputsReader();
|
||||
|
||||
@@ -490,10 +491,11 @@ public final class ChoiceAuthorityServiceImpl implements ChoiceAuthorityService
|
||||
init();
|
||||
ChoiceAuthority ma = controller.get(fieldKey);
|
||||
if (ma == null && collection != null) {
|
||||
SubmissionConfigReader configReader;
|
||||
SubmissionConfigService configReaderService;
|
||||
try {
|
||||
configReader = new SubmissionConfigReader();
|
||||
SubmissionConfig submissionName = configReader.getSubmissionConfigByCollection(collection.getHandle());
|
||||
configReaderService = SubmissionServiceFactory.getInstance().getSubmissionConfigService();
|
||||
SubmissionConfig submissionName = configReaderService
|
||||
.getSubmissionConfigByCollection(collection.getHandle());
|
||||
ma = controllerFormDefinitions.get(fieldKey).get(submissionName.getSubmissionName());
|
||||
} catch (SubmissionConfigReaderException e) {
|
||||
// the system is in an illegal state as the submission definition is not valid
|
||||
|
@@ -10,6 +10,7 @@ package org.dspace.content.authority.service;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.MetadataValue;
|
||||
import org.dspace.content.authority.Choice;
|
||||
@@ -174,7 +175,7 @@ public interface ChoiceAuthorityService {
|
||||
/**
|
||||
* This method has been created to have a way of clearing the cache kept inside the service
|
||||
*/
|
||||
public void clearCache();
|
||||
public void clearCache() throws SubmissionConfigReaderException;
|
||||
|
||||
/**
|
||||
* Should we store the authority key (if any) for such field key and collection?
|
||||
|
@@ -68,9 +68,9 @@ public class BitstreamDAOImpl extends AbstractHibernateDSODAO<Bitstream> impleme
|
||||
|
||||
@Override
|
||||
public List<Bitstream> findBitstreamsWithNoRecentChecksum(Context context) throws SQLException {
|
||||
Query query = createQuery(context,
|
||||
"select b from Bitstream b where b not in (select c.bitstream from " +
|
||||
"MostRecentChecksum c)");
|
||||
Query query = createQuery(context, "SELECT b FROM MostRecentChecksum c RIGHT JOIN Bitstream b " +
|
||||
"ON c.bitstream = b WHERE c IS NULL" );
|
||||
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
|
@@ -83,13 +83,14 @@ public abstract class AbstractHibernateDSODAO<T extends DSpaceObject> extends Ab
|
||||
if (CollectionUtils.isNotEmpty(metadataFields) || StringUtils.isNotBlank(additionalWhere)) {
|
||||
//Add the where query on metadata
|
||||
query.append(" WHERE ");
|
||||
// Group the 'OR' clauses below in outer parentheses, e.g. "WHERE (clause1 OR clause2 OR clause3)".
|
||||
// Grouping these 'OR' clauses allows for later code to append 'AND' clauses without unexpected behaviors
|
||||
query.append("(");
|
||||
for (int i = 0; i < metadataFields.size(); i++) {
|
||||
MetadataField metadataField = metadataFields.get(i);
|
||||
if (StringUtils.isNotBlank(operator)) {
|
||||
query.append(" (");
|
||||
query.append("lower(STR(" + metadataField.toString()).append(".value)) ").append(operator)
|
||||
.append(" lower(:queryParam)");
|
||||
query.append(")");
|
||||
if (i < metadataFields.size() - 1) {
|
||||
query.append(" OR ");
|
||||
}
|
||||
@@ -102,6 +103,7 @@ public abstract class AbstractHibernateDSODAO<T extends DSpaceObject> extends Ab
|
||||
}
|
||||
query.append(additionalWhere);
|
||||
}
|
||||
query.append(")");
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -128,6 +128,11 @@ public class Context implements AutoCloseable {
|
||||
|
||||
private DBConnection dbConnection;
|
||||
|
||||
/**
|
||||
* The default administrator group
|
||||
*/
|
||||
private Group adminGroup;
|
||||
|
||||
public enum Mode {
|
||||
READ_ONLY,
|
||||
READ_WRITE,
|
||||
@@ -810,6 +815,15 @@ public class Context implements AutoCloseable {
|
||||
readOnlyCache.clear();
|
||||
}
|
||||
|
||||
// When going to READ_ONLY, flush database changes to ensure that the current data is retrieved
|
||||
if (newMode == Mode.READ_ONLY && mode != Mode.READ_ONLY) {
|
||||
try {
|
||||
dbConnection.flushSession();
|
||||
} catch (SQLException ex) {
|
||||
log.warn("Unable to flush database changes after switching to READ_ONLY mode", ex);
|
||||
}
|
||||
}
|
||||
|
||||
//save the new mode
|
||||
mode = newMode;
|
||||
}
|
||||
@@ -951,4 +965,15 @@ public class Context implements AutoCloseable {
|
||||
public boolean isContextUserSwitched() {
|
||||
return currentUserPreviousState != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default "Administrator" group for DSpace administrators.
|
||||
* The result is cached in the 'adminGroup' field, so it is only looked up once.
|
||||
* This is done to improve performance, as this method is called quite often.
|
||||
*/
|
||||
public Group getAdminGroup() throws SQLException {
|
||||
return (adminGroup == null) ? EPersonServiceFactory.getInstance()
|
||||
.getGroupService()
|
||||
.findByName(this, Group.ADMIN) : adminGroup;
|
||||
}
|
||||
}
|
||||
|
@@ -148,4 +148,12 @@ public interface DBConnection<T> {
|
||||
* @throws java.sql.SQLException passed through.
|
||||
*/
|
||||
public <E extends ReloadableEntity> void uncacheEntity(E entity) throws SQLException;
|
||||
|
||||
/**
|
||||
* Do a manual flush. This synchronizes the in-memory state of the Session
|
||||
* with the database (write changes to the database)
|
||||
*
|
||||
* @throws SQLException passed through.
|
||||
*/
|
||||
public void flushSession() throws SQLException;
|
||||
}
|
||||
|
@@ -337,4 +337,17 @@ public class HibernateDBConnection implements DBConnection<Session> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a manual flush. This synchronizes the in-memory state of the Session
|
||||
* with the database (write changes to the database)
|
||||
*
|
||||
* @throws SQLException passed through.
|
||||
*/
|
||||
@Override
|
||||
public void flushSession() throws SQLException {
|
||||
if (getSession().isDirty()) {
|
||||
getSession().flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -152,17 +152,10 @@ public class Curation extends DSpaceRunnable<CurationScriptConfiguration> {
|
||||
super.handler.logInfo("Curating id: " + entry.getObjectId());
|
||||
}
|
||||
curator.clear();
|
||||
// does entry relate to a DSO or workflow object?
|
||||
if (entry.getObjectId().indexOf('/') > 0) {
|
||||
for (String taskName : entry.getTaskNames()) {
|
||||
curator.addTask(taskName);
|
||||
}
|
||||
curator.curate(context, entry.getObjectId());
|
||||
} else {
|
||||
// TODO: Remove this exception once curation tasks are supported by configurable workflow
|
||||
// e.g. see https://github.com/DSpace/DSpace/pull/3157
|
||||
throw new IllegalArgumentException("curation for workflow items is no longer supported");
|
||||
for (String taskName : entry.getTaskNames()) {
|
||||
curator.addTask(taskName);
|
||||
}
|
||||
curator.curate(context, entry.getObjectId());
|
||||
}
|
||||
queue.release(this.queue, ticket, true);
|
||||
return ticket;
|
||||
|
@@ -13,6 +13,7 @@ import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
@@ -139,40 +140,47 @@ public class XmlWorkflowCuratorServiceImpl
|
||||
item.setOwningCollection(wfi.getCollection());
|
||||
for (Task task : step.tasks) {
|
||||
curator.addTask(task.name);
|
||||
curator.curate(c, item);
|
||||
int status = curator.getStatus(task.name);
|
||||
String result = curator.getResult(task.name);
|
||||
String action = "none";
|
||||
switch (status) {
|
||||
case Curator.CURATE_FAIL:
|
||||
// task failed - notify any contacts the task has assigned
|
||||
if (task.powers.contains("reject")) {
|
||||
action = "reject";
|
||||
}
|
||||
notifyContacts(c, wfi, task, "fail", action, result);
|
||||
// if task so empowered, reject submission and terminate
|
||||
if ("reject".equals(action)) {
|
||||
workflowService.sendWorkflowItemBackSubmission(c, wfi,
|
||||
c.getCurrentUser(), null,
|
||||
task.name + ": " + result);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Curator.CURATE_SUCCESS:
|
||||
if (task.powers.contains("approve")) {
|
||||
action = "approve";
|
||||
}
|
||||
notifyContacts(c, wfi, task, "success", action, result);
|
||||
if ("approve".equals(action)) {
|
||||
// cease further task processing and advance submission
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case Curator.CURATE_ERROR:
|
||||
notifyContacts(c, wfi, task, "error", action, result);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
// Check whether the task is configured to be queued rather than automatically run
|
||||
if (StringUtils.isNotEmpty(step.queue)) {
|
||||
// queue attribute has been set in the FlowStep configuration: add task to configured queue
|
||||
curator.queue(c, item.getID().toString(), step.queue);
|
||||
} else {
|
||||
// Task is configured to be run automatically
|
||||
curator.curate(c, item);
|
||||
int status = curator.getStatus(task.name);
|
||||
String result = curator.getResult(task.name);
|
||||
String action = "none";
|
||||
switch (status) {
|
||||
case Curator.CURATE_FAIL:
|
||||
// task failed - notify any contacts the task has assigned
|
||||
if (task.powers.contains("reject")) {
|
||||
action = "reject";
|
||||
}
|
||||
notifyContacts(c, wfi, task, "fail", action, result);
|
||||
// if task so empowered, reject submission and terminate
|
||||
if ("reject".equals(action)) {
|
||||
workflowService.sendWorkflowItemBackSubmission(c, wfi,
|
||||
c.getCurrentUser(), null,
|
||||
task.name + ": " + result);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Curator.CURATE_SUCCESS:
|
||||
if (task.powers.contains("approve")) {
|
||||
action = "approve";
|
||||
}
|
||||
notifyContacts(c, wfi, task, "success", action, result);
|
||||
if ("approve".equals(action)) {
|
||||
// cease further task processing and advance submission
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case Curator.CURATE_ERROR:
|
||||
notifyContacts(c, wfi, task, "error", action, result);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
curator.clear();
|
||||
}
|
||||
|
@@ -154,7 +154,11 @@ public class IndexEventConsumer implements Consumer {
|
||||
|
||||
case Event.REMOVE:
|
||||
case Event.ADD:
|
||||
if (object == null) {
|
||||
// At this time, ADD and REMOVE actions are ignored on SITE object. They are only triggered for
|
||||
// top-level communities. No action is necessary as Community itself is indexed (or deleted) separately.
|
||||
if (event.getSubjectType() == Constants.SITE) {
|
||||
log.debug(event.getEventTypeAsString() + " event triggered for Site object. Skipping it.");
|
||||
} else if (object == null) {
|
||||
log.warn(event.getEventTypeAsString() + " event, could not get object for "
|
||||
+ event.getObjectTypeAsString() + " id="
|
||||
+ event.getObjectID()
|
||||
@@ -201,6 +205,10 @@ public class IndexEventConsumer implements Consumer {
|
||||
@Override
|
||||
public void end(Context ctx) throws Exception {
|
||||
|
||||
// Change the mode to readonly to improve performance
|
||||
Context.Mode originalMode = ctx.getCurrentMode();
|
||||
ctx.setMode(Context.Mode.READ_ONLY);
|
||||
|
||||
try {
|
||||
for (String uid : uniqueIdsToDelete) {
|
||||
try {
|
||||
@@ -230,6 +238,8 @@ public class IndexEventConsumer implements Consumer {
|
||||
uniqueIdsToDelete.clear();
|
||||
createdItemsToUpdate.clear();
|
||||
}
|
||||
|
||||
ctx.setMode(originalMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1031,9 +1031,8 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
// Add information about our search fields
|
||||
for (String field : searchFields) {
|
||||
List<String> valuesAsString = new ArrayList<>();
|
||||
for (Object o : doc.getFieldValues(field)) {
|
||||
valuesAsString.add(String.valueOf(o));
|
||||
}
|
||||
Optional.ofNullable(doc.getFieldValues(field))
|
||||
.ifPresent(l -> l.forEach(o -> valuesAsString.add(String.valueOf(o))));
|
||||
resultDoc.addSearchField(field, valuesAsString.toArray(new String[valuesAsString.size()]));
|
||||
}
|
||||
result.addSearchDocument(indexableObject, resultDoc);
|
||||
|
@@ -188,32 +188,98 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
|
||||
|
||||
@Override
|
||||
public List<EPerson> search(Context context, String query, int offset, int limit) throws SQLException {
|
||||
try {
|
||||
List<EPerson> ePerson = new ArrayList<>();
|
||||
EPerson person = find(context, UUID.fromString(query));
|
||||
if (person != null) {
|
||||
ePerson.add(person);
|
||||
}
|
||||
return ePerson;
|
||||
} catch (IllegalArgumentException e) {
|
||||
List<EPerson> ePersons = new ArrayList<>();
|
||||
UUID uuid = UUIDUtils.fromString(query);
|
||||
if (uuid == null) {
|
||||
// Search by firstname & lastname (NOTE: email will also be included automatically)
|
||||
MetadataField firstNameField = metadataFieldService.findByElement(context, "eperson", "firstname", null);
|
||||
MetadataField lastNameField = metadataFieldService.findByElement(context, "eperson", "lastname", null);
|
||||
if (StringUtils.isBlank(query)) {
|
||||
query = null;
|
||||
}
|
||||
return ePersonDAO.search(context, query, Arrays.asList(firstNameField, lastNameField),
|
||||
Arrays.asList(firstNameField, lastNameField), offset, limit);
|
||||
ePersons = ePersonDAO.search(context, query, Arrays.asList(firstNameField, lastNameField),
|
||||
Arrays.asList(firstNameField, lastNameField), offset, limit);
|
||||
} else {
|
||||
// Search by UUID
|
||||
EPerson person = find(context, uuid);
|
||||
if (person != null) {
|
||||
ePersons.add(person);
|
||||
}
|
||||
}
|
||||
return ePersons;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int searchResultCount(Context context, String query) throws SQLException {
|
||||
MetadataField firstNameField = metadataFieldService.findByElement(context, "eperson", "firstname", null);
|
||||
MetadataField lastNameField = metadataFieldService.findByElement(context, "eperson", "lastname", null);
|
||||
if (StringUtils.isBlank(query)) {
|
||||
query = null;
|
||||
int result = 0;
|
||||
UUID uuid = UUIDUtils.fromString(query);
|
||||
if (uuid == null) {
|
||||
// Count results found by firstname & lastname (email is also included automatically)
|
||||
MetadataField firstNameField = metadataFieldService.findByElement(context, "eperson", "firstname", null);
|
||||
MetadataField lastNameField = metadataFieldService.findByElement(context, "eperson", "lastname", null);
|
||||
if (StringUtils.isBlank(query)) {
|
||||
query = null;
|
||||
}
|
||||
result = ePersonDAO.searchResultCount(context, query, Arrays.asList(firstNameField, lastNameField));
|
||||
} else {
|
||||
// Search by UUID
|
||||
EPerson person = find(context, uuid);
|
||||
if (person != null) {
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
return ePersonDAO.searchResultCount(context, query, Arrays.asList(firstNameField, lastNameField));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EPerson> searchNonMembers(Context context, String query, Group excludeGroup, int offset, int limit)
|
||||
throws SQLException {
|
||||
List<EPerson> ePersons = new ArrayList<>();
|
||||
UUID uuid = UUIDUtils.fromString(query);
|
||||
if (uuid == null) {
|
||||
// Search by firstname & lastname (NOTE: email will also be included automatically)
|
||||
MetadataField firstNameField = metadataFieldService.findByElement(context, "eperson", "firstname", null);
|
||||
MetadataField lastNameField = metadataFieldService.findByElement(context, "eperson", "lastname", null);
|
||||
if (StringUtils.isBlank(query)) {
|
||||
query = null;
|
||||
}
|
||||
ePersons = ePersonDAO.searchNotMember(context, query, Arrays.asList(firstNameField, lastNameField),
|
||||
excludeGroup, Arrays.asList(firstNameField, lastNameField),
|
||||
offset, limit);
|
||||
} else {
|
||||
// Search by UUID
|
||||
EPerson person = find(context, uuid);
|
||||
// Verify EPerson is NOT a member of the given excludeGroup before adding
|
||||
if (person != null && !groupService.isDirectMember(excludeGroup, person)) {
|
||||
ePersons.add(person);
|
||||
}
|
||||
}
|
||||
|
||||
return ePersons;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int searchNonMembersCount(Context context, String query, Group excludeGroup) throws SQLException {
|
||||
int result = 0;
|
||||
UUID uuid = UUIDUtils.fromString(query);
|
||||
if (uuid == null) {
|
||||
// Count results found by firstname & lastname (email is also included automatically)
|
||||
MetadataField firstNameField = metadataFieldService.findByElement(context, "eperson", "firstname", null);
|
||||
MetadataField lastNameField = metadataFieldService.findByElement(context, "eperson", "lastname", null);
|
||||
if (StringUtils.isBlank(query)) {
|
||||
query = null;
|
||||
}
|
||||
result = ePersonDAO.searchNotMemberCount(context, query, Arrays.asList(firstNameField, lastNameField),
|
||||
excludeGroup);
|
||||
} else {
|
||||
// Search by UUID
|
||||
EPerson person = find(context, uuid);
|
||||
// Verify EPerson is NOT a member of the given excludeGroup before counting
|
||||
if (person != null && !groupService.isDirectMember(excludeGroup, person)) {
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -309,10 +375,13 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
|
||||
throw new AuthorizeException(
|
||||
"You must be an admin to delete an EPerson");
|
||||
}
|
||||
// Get all workflow-related groups that the current EPerson belongs to
|
||||
Set<Group> workFlowGroups = getAllWorkFlowGroups(context, ePerson);
|
||||
for (Group group: workFlowGroups) {
|
||||
List<EPerson> ePeople = groupService.allMembers(context, group);
|
||||
if (ePeople.size() == 1 && ePeople.contains(ePerson)) {
|
||||
// Get total number of unique EPerson objs who are a member of this group (or subgroup)
|
||||
int totalMembers = groupService.countAllMembers(context, group);
|
||||
// If only one EPerson is a member, then we cannot delete the last member of this group.
|
||||
if (totalMembers == 1) {
|
||||
throw new EmptyWorkflowGroupException(ePerson.getID(), group.getID());
|
||||
}
|
||||
}
|
||||
@@ -576,14 +645,29 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
|
||||
|
||||
@Override
|
||||
public List<EPerson> findByGroups(Context c, Set<Group> groups) throws SQLException {
|
||||
return findByGroups(c, groups, -1, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EPerson> findByGroups(Context c, Set<Group> groups, int pageSize, int offset) throws SQLException {
|
||||
//Make sure we at least have one group, if not don't even bother searching.
|
||||
if (CollectionUtils.isNotEmpty(groups)) {
|
||||
return ePersonDAO.findByGroups(c, groups);
|
||||
return ePersonDAO.findByGroups(c, groups, pageSize, offset);
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countByGroups(Context c, Set<Group> groups) throws SQLException {
|
||||
//Make sure we at least have one group, if not don't even bother counting.
|
||||
if (CollectionUtils.isNotEmpty(groups)) {
|
||||
return ePersonDAO.countByGroups(c, groups);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EPerson> findEPeopleWithSubscription(Context context) throws SQLException {
|
||||
return ePersonDAO.findAllSubscribers(context);
|
||||
|
@@ -98,7 +98,11 @@ public class Group extends DSpaceObject implements DSpaceObjectLegacySupport {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return EPerson members of a Group
|
||||
* Return EPerson members of a Group.
|
||||
* <P>
|
||||
* WARNING: This method may have bad performance for Groups with large numbers of EPerson members.
|
||||
* Therefore, only use this when you need to access every EPerson member. Instead, consider using
|
||||
* EPersonService.findByGroups() for a paginated list of EPersons.
|
||||
*
|
||||
* @return list of EPersons
|
||||
*/
|
||||
@@ -143,9 +147,13 @@ public class Group extends DSpaceObject implements DSpaceObjectLegacySupport {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return Group members of a Group.
|
||||
* Return Group members (i.e. direct subgroups) of a Group.
|
||||
* <P>
|
||||
* WARNING: This method may have bad performance for Groups with large numbers of Subgroups.
|
||||
* Therefore, only use this when you need to access every Subgroup. Instead, consider using
|
||||
* GroupService.findByParent() for a paginated list of Subgroups.
|
||||
*
|
||||
* @return list of groups
|
||||
* @return list of subgroups
|
||||
*/
|
||||
public List<Group> getMemberGroups() {
|
||||
return groups;
|
||||
|
@@ -179,8 +179,13 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
||||
for (CollectionRole collectionRole : collectionRoles) {
|
||||
if (StringUtils.equals(collectionRole.getRoleId(), role.getId())
|
||||
&& claimedTask.getWorkflowItem().getCollection() == collectionRole.getCollection()) {
|
||||
List<EPerson> ePeople = allMembers(context, group);
|
||||
if (ePeople.size() == 1 && ePeople.contains(ePerson)) {
|
||||
// Count number of EPersons who are *direct* members of this group
|
||||
int totalDirectEPersons = ePersonService.countByGroups(context, Set.of(group));
|
||||
// Count number of Groups which have this groupParent as a direct parent
|
||||
int totalChildGroups = countByParent(context, group);
|
||||
// If this group has only one direct EPerson and *zero* child groups, then we cannot delete the
|
||||
// EPerson or we will leave this group empty.
|
||||
if (totalDirectEPersons == 1 && totalChildGroups == 0) {
|
||||
throw new IllegalStateException(
|
||||
"Refused to remove user " + ePerson
|
||||
.getID() + " from workflow group because the group " + group
|
||||
@@ -191,8 +196,13 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
||||
}
|
||||
}
|
||||
if (!poolTasks.isEmpty()) {
|
||||
List<EPerson> ePeople = allMembers(context, group);
|
||||
if (ePeople.size() == 1 && ePeople.contains(ePerson)) {
|
||||
// Count number of EPersons who are *direct* members of this group
|
||||
int totalDirectEPersons = ePersonService.countByGroups(context, Set.of(group));
|
||||
// Count number of Groups which have this groupParent as a direct parent
|
||||
int totalChildGroups = countByParent(context, group);
|
||||
// If this group has only one direct EPerson and *zero* child groups, then we cannot delete the
|
||||
// EPerson or we will leave this group empty.
|
||||
if (totalDirectEPersons == 1 && totalChildGroups == 0) {
|
||||
throw new IllegalStateException(
|
||||
"Refused to remove user " + ePerson
|
||||
.getID() + " from workflow group because the group " + group
|
||||
@@ -212,9 +222,13 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
||||
if (!collectionRoles.isEmpty()) {
|
||||
List<PoolTask> poolTasks = poolTaskService.findByGroup(context, groupParent);
|
||||
if (!poolTasks.isEmpty()) {
|
||||
List<EPerson> parentPeople = allMembers(context, groupParent);
|
||||
List<EPerson> childPeople = allMembers(context, childGroup);
|
||||
if (childPeople.containsAll(parentPeople)) {
|
||||
// Count number of Groups which have this groupParent as a direct parent
|
||||
int totalChildGroups = countByParent(context, groupParent);
|
||||
// Count number of EPersons who are *direct* members of this group
|
||||
int totalDirectEPersons = ePersonService.countByGroups(context, Set.of(groupParent));
|
||||
// If this group has only one childGroup and *zero* direct EPersons, then we cannot delete the
|
||||
// childGroup or we will leave this group empty.
|
||||
if (totalChildGroups == 1 && totalDirectEPersons == 0) {
|
||||
throw new IllegalStateException(
|
||||
"Refused to remove sub group " + childGroup
|
||||
.getID() + " from workflow group because the group " + groupParent
|
||||
@@ -368,7 +382,8 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
||||
|
||||
// Get all groups which are a member of this group
|
||||
List<Group2GroupCache> group2GroupCaches = group2GroupCacheDAO.findByParent(c, g);
|
||||
Set<Group> groups = new HashSet<>();
|
||||
// Initialize HashSet based on List size to avoid Set resizing. See https://stackoverflow.com/a/21822273
|
||||
Set<Group> groups = new HashSet<>((int) (group2GroupCaches.size() / 0.75 + 1));
|
||||
for (Group2GroupCache group2GroupCache : group2GroupCaches) {
|
||||
groups.add(group2GroupCache.getChild());
|
||||
}
|
||||
@@ -381,6 +396,23 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
||||
return new ArrayList<>(childGroupChildren);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countAllMembers(Context context, Group group) throws SQLException {
|
||||
// Get all groups which are a member of this group
|
||||
List<Group2GroupCache> group2GroupCaches = group2GroupCacheDAO.findByParent(context, group);
|
||||
// Initialize HashSet based on List size + current 'group' to avoid Set resizing.
|
||||
// See https://stackoverflow.com/a/21822273
|
||||
Set<Group> groups = new HashSet<>((int) ((group2GroupCaches.size() + 1) / 0.75 + 1));
|
||||
for (Group2GroupCache group2GroupCache : group2GroupCaches) {
|
||||
groups.add(group2GroupCache.getChild());
|
||||
}
|
||||
// Append current group as well
|
||||
groups.add(group);
|
||||
|
||||
// Return total number of unique EPerson objects in any of these groups
|
||||
return ePersonService.countByGroups(context, groups);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Group find(Context context, UUID id) throws SQLException {
|
||||
if (id == null) {
|
||||
@@ -428,17 +460,17 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Group> search(Context context, String groupIdentifier) throws SQLException {
|
||||
return search(context, groupIdentifier, -1, -1);
|
||||
public List<Group> search(Context context, String query) throws SQLException {
|
||||
return search(context, query, -1, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Group> search(Context context, String groupIdentifier, int offset, int limit) throws SQLException {
|
||||
public List<Group> search(Context context, String query, int offset, int limit) throws SQLException {
|
||||
List<Group> groups = new ArrayList<>();
|
||||
UUID uuid = UUIDUtils.fromString(groupIdentifier);
|
||||
UUID uuid = UUIDUtils.fromString(query);
|
||||
if (uuid == null) {
|
||||
//Search by group name
|
||||
groups = groupDAO.findByNameLike(context, groupIdentifier, offset, limit);
|
||||
groups = groupDAO.findByNameLike(context, query, offset, limit);
|
||||
} else {
|
||||
//Search by group id
|
||||
Group group = find(context, uuid);
|
||||
@@ -451,12 +483,12 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public int searchResultCount(Context context, String groupIdentifier) throws SQLException {
|
||||
public int searchResultCount(Context context, String query) throws SQLException {
|
||||
int result = 0;
|
||||
UUID uuid = UUIDUtils.fromString(groupIdentifier);
|
||||
UUID uuid = UUIDUtils.fromString(query);
|
||||
if (uuid == null) {
|
||||
//Search by group name
|
||||
result = groupDAO.countByNameLike(context, groupIdentifier);
|
||||
result = groupDAO.countByNameLike(context, query);
|
||||
} else {
|
||||
//Search by group id
|
||||
Group group = find(context, uuid);
|
||||
@@ -468,6 +500,44 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Group> searchNonMembers(Context context, String query, Group excludeParentGroup,
|
||||
int offset, int limit) throws SQLException {
|
||||
List<Group> groups = new ArrayList<>();
|
||||
UUID uuid = UUIDUtils.fromString(query);
|
||||
if (uuid == null) {
|
||||
// Search by group name
|
||||
groups = groupDAO.findByNameLikeAndNotMember(context, query, excludeParentGroup, offset, limit);
|
||||
} else if (!uuid.equals(excludeParentGroup.getID())) {
|
||||
// Search by group id
|
||||
Group group = find(context, uuid);
|
||||
// Verify it is NOT a member of the given excludeParentGroup before adding
|
||||
if (group != null && !isMember(excludeParentGroup, group)) {
|
||||
groups.add(group);
|
||||
}
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int searchNonMembersCount(Context context, String query, Group excludeParentGroup) throws SQLException {
|
||||
int result = 0;
|
||||
UUID uuid = UUIDUtils.fromString(query);
|
||||
if (uuid == null) {
|
||||
// Search by group name
|
||||
result = groupDAO.countByNameLikeAndNotMember(context, query, excludeParentGroup);
|
||||
} else if (!uuid.equals(excludeParentGroup.getID())) {
|
||||
// Search by group id
|
||||
Group group = find(context, uuid);
|
||||
// Verify it is NOT a member of the given excludeParentGroup before adding
|
||||
if (group != null && !isMember(excludeParentGroup, group)) {
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Context context, Group group) throws SQLException {
|
||||
if (group.isPermanent()) {
|
||||
@@ -829,4 +899,20 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
||||
public String getName(Group dso) {
|
||||
return dso.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Group> findByParent(Context context, Group parent, int pageSize, int offset) throws SQLException {
|
||||
if (parent == null) {
|
||||
return null;
|
||||
}
|
||||
return groupDAO.findByParent(context, parent, pageSize, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countByParent(Context context, Group parent) throws SQLException {
|
||||
if (parent == null) {
|
||||
return 0;
|
||||
}
|
||||
return groupDAO.countByParent(context, parent);
|
||||
}
|
||||
}
|
||||
|
@@ -33,12 +33,91 @@ public interface EPersonDAO extends DSpaceObjectDAO<EPerson>, DSpaceObjectLegacy
|
||||
|
||||
public EPerson findByNetid(Context context, String netid) throws SQLException;
|
||||
|
||||
/**
|
||||
* Search all EPersons by the given MetadataField objects, sorting by the given sort fields.
|
||||
* <P>
|
||||
* NOTE: As long as a query is specified, the EPerson's email address is included in the search alongside any given
|
||||
* metadata fields.
|
||||
*
|
||||
* @param context DSpace context
|
||||
* @param query the text to search EPersons for
|
||||
* @param queryFields the metadata fields to search within (email is also included automatically)
|
||||
* @param sortFields the metadata field(s) to sort the results by
|
||||
* @param offset the position of the first result to return
|
||||
* @param limit how many results return
|
||||
* @return List of matching EPerson objects
|
||||
* @throws SQLException if an error occurs
|
||||
*/
|
||||
public List<EPerson> search(Context context, String query, List<MetadataField> queryFields,
|
||||
List<MetadataField> sortFields, int offset, int limit) throws SQLException;
|
||||
|
||||
/**
|
||||
* Count number of EPersons who match a search on the given metadata fields. This returns the count of total
|
||||
* results for the same query using the 'search()', and therefore can be used to provide pagination.
|
||||
*
|
||||
* @param context DSpace context
|
||||
* @param query the text to search EPersons for
|
||||
* @param queryFields the metadata fields to search within (email is also included automatically)
|
||||
* @return total number of EPersons who match the query
|
||||
* @throws SQLException if an error occurs
|
||||
*/
|
||||
public int searchResultCount(Context context, String query, List<MetadataField> queryFields) throws SQLException;
|
||||
|
||||
public List<EPerson> findByGroups(Context context, Set<Group> groups) throws SQLException;
|
||||
/**
|
||||
* Search all EPersons via their firstname, lastname, email (fuzzy match), limited to those EPersons which are NOT
|
||||
* a member of the given group. This may be used to search across EPersons which are valid to add as members to the
|
||||
* given group.
|
||||
*
|
||||
* @param context The DSpace context
|
||||
* @param query the text to search EPersons for
|
||||
* @param queryFields the metadata fields to search within (email is also included automatically)
|
||||
* @param excludeGroup Group to exclude results from. Members of this group will never be returned.
|
||||
* @param offset the position of the first result to return
|
||||
* @param limit how many results return
|
||||
* @return EPersons matching the query (which are not members of the given group)
|
||||
* @throws SQLException if database error
|
||||
*/
|
||||
List<EPerson> searchNotMember(Context context, String query, List<MetadataField> queryFields, Group excludeGroup,
|
||||
List<MetadataField> sortFields, int offset, int limit) throws SQLException;
|
||||
|
||||
/**
|
||||
* Count number of EPersons that match a given search (fuzzy match) across firstname, lastname and email. This
|
||||
* search is limited to those EPersons which are NOT a member of the given group. This may be used
|
||||
* (with searchNotMember()) to perform a paginated search across EPersons which are valid to add to the given group.
|
||||
*
|
||||
* @param context The DSpace context
|
||||
* @param query querystring to fuzzy match against.
|
||||
* @param queryFields the metadata fields to search within (email is also included automatically)
|
||||
* @param excludeGroup Group to exclude results from. Members of this group will never be returned.
|
||||
* @return Groups matching the query (which are not members of the given parent)
|
||||
* @throws SQLException if database error
|
||||
*/
|
||||
int searchNotMemberCount(Context context, String query, List<MetadataField> queryFields, Group excludeGroup)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
* Find all EPersons who are a member of one or more of the listed groups in a paginated fashion. This returns
|
||||
* EPersons ordered by UUID.
|
||||
*
|
||||
* @param context current Context
|
||||
* @param groups Set of group(s) to check membership in
|
||||
* @param pageSize number of EPerson objects to load at one time. Set to <=0 to disable pagination
|
||||
* @param offset number of page to load (starting with 1). Set to <=0 to disable pagination
|
||||
* @return List of all EPersons who are a member of one or more groups.
|
||||
* @throws SQLException
|
||||
*/
|
||||
List<EPerson> findByGroups(Context context, Set<Group> groups, int pageSize, int offset) throws SQLException;
|
||||
|
||||
/**
|
||||
* Count total number of EPersons who are a member of one or more of the listed groups. This provides the total
|
||||
* number of results to expect from corresponding findByGroups() for pagination purposes.
|
||||
*
|
||||
* @param context current Context
|
||||
* @param groups Set of group(s) to check membership in
|
||||
* @return total number of (unique) EPersons who are a member of one or more groups.
|
||||
* @throws SQLException
|
||||
*/
|
||||
int countByGroups(Context context, Set<Group> groups) throws SQLException;
|
||||
|
||||
public List<EPerson> findWithPasswordWithoutDigestAlgorithm(Context context) throws SQLException;
|
||||
|
||||
|
@@ -135,6 +135,38 @@ public interface GroupDAO extends DSpaceObjectDAO<Group>, DSpaceObjectLegacySupp
|
||||
*/
|
||||
int countByNameLike(Context context, String groupName) throws SQLException;
|
||||
|
||||
/**
|
||||
* Search all groups via their name (fuzzy match), limited to those groups which are NOT a member of the given
|
||||
* parent group. This may be used to search across groups which are valid to add to the given parent group.
|
||||
* <P>
|
||||
* NOTE: The parent group itself is also excluded from the search.
|
||||
*
|
||||
* @param context The DSpace context
|
||||
* @param groupName Group name to fuzzy match against.
|
||||
* @param excludeParent Parent Group to exclude results from. Groups under this parent will never be returned.
|
||||
* @param offset Offset to use for pagination (-1 to disable)
|
||||
* @param limit The maximum number of results to return (-1 to disable)
|
||||
* @return Groups matching the query (which are not members of the given parent)
|
||||
* @throws SQLException if database error
|
||||
*/
|
||||
List<Group> findByNameLikeAndNotMember(Context context, String groupName, Group excludeParent,
|
||||
int offset, int limit) throws SQLException;
|
||||
|
||||
/**
|
||||
* Count number of groups that match a given name (fuzzy match), limited to those groups which are NOT a member of
|
||||
* the given parent group. This may be used (with findByNameLikeAndNotMember()) to search across groups which are
|
||||
* valid to add to the given parent group.
|
||||
* <P>
|
||||
* NOTE: The parent group itself is also excluded from the count.
|
||||
*
|
||||
* @param context The DSpace context
|
||||
* @param groupName Group name to fuzzy match against.
|
||||
* @param excludeParent Parent Group to exclude results from. Groups under this parent will never be returned.
|
||||
* @return Groups matching the query (which are not members of the given parent)
|
||||
* @throws SQLException if database error
|
||||
*/
|
||||
int countByNameLikeAndNotMember(Context context, String groupName, Group excludeParent) throws SQLException;
|
||||
|
||||
/**
|
||||
* Find a group by its name and the membership of the given EPerson
|
||||
*
|
||||
@@ -146,4 +178,28 @@ public interface GroupDAO extends DSpaceObjectDAO<Group>, DSpaceObjectLegacySupp
|
||||
*/
|
||||
Group findByIdAndMembership(Context context, UUID id, EPerson ePerson) throws SQLException;
|
||||
|
||||
/**
|
||||
* Find all groups which are members of a given parent group.
|
||||
* This provides the same behavior as group.getMemberGroups(), but in a paginated fashion.
|
||||
*
|
||||
* @param context The DSpace context
|
||||
* @param parent Parent Group to search within
|
||||
* @param pageSize how many results return
|
||||
* @param offset the position of the first result to return
|
||||
* @return Groups matching the query
|
||||
* @throws SQLException if database error
|
||||
*/
|
||||
List<Group> findByParent(Context context, Group parent, int pageSize, int offset) throws SQLException;
|
||||
|
||||
/**
|
||||
* Returns the number of groups which are members of a given parent group.
|
||||
* This provides the same behavior as group.getMemberGroups().size(), but with better performance for large groups.
|
||||
* This method may be used with findByParent() to perform pagination.
|
||||
*
|
||||
* @param context The DSpace context
|
||||
* @param parent Parent Group to search within
|
||||
* @return Number of Groups matching the query
|
||||
* @throws SQLException if database error
|
||||
*/
|
||||
int countByParent(Context context, Group parent) throws SQLException;
|
||||
}
|
||||
|
@@ -70,17 +70,9 @@ public class EPersonDAOImpl extends AbstractHibernateDSODAO<EPerson> implements
|
||||
String queryString = "SELECT " + EPerson.class.getSimpleName()
|
||||
.toLowerCase() + " FROM EPerson as " + EPerson.class
|
||||
.getSimpleName().toLowerCase() + " ";
|
||||
if (query != null) {
|
||||
query = "%" + query.toLowerCase() + "%";
|
||||
}
|
||||
Query hibernateQuery = getSearchQuery(context, queryString, query, queryFields, sortFields, null);
|
||||
|
||||
if (0 <= offset) {
|
||||
hibernateQuery.setFirstResult(offset);
|
||||
}
|
||||
if (0 <= limit) {
|
||||
hibernateQuery.setMaxResults(limit);
|
||||
}
|
||||
Query hibernateQuery = getSearchQuery(context, queryString, query, queryFields, null,
|
||||
sortFields, null, limit, offset);
|
||||
return list(hibernateQuery);
|
||||
}
|
||||
|
||||
@@ -92,6 +84,28 @@ public class EPersonDAOImpl extends AbstractHibernateDSODAO<EPerson> implements
|
||||
return count(hibernateQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EPerson> searchNotMember(Context context, String query, List<MetadataField> queryFields,
|
||||
Group excludeGroup, List<MetadataField> sortFields,
|
||||
int offset, int limit) throws SQLException {
|
||||
String queryString = "SELECT " + EPerson.class.getSimpleName()
|
||||
.toLowerCase() + " FROM EPerson as " + EPerson.class
|
||||
.getSimpleName().toLowerCase() + " ";
|
||||
|
||||
Query hibernateQuery = getSearchQuery(context, queryString, query, queryFields, excludeGroup,
|
||||
sortFields, null, limit, offset);
|
||||
return list(hibernateQuery);
|
||||
}
|
||||
|
||||
public int searchNotMemberCount(Context context, String query, List<MetadataField> queryFields,
|
||||
Group excludeGroup) throws SQLException {
|
||||
String queryString = "SELECT count(*) FROM EPerson as " + EPerson.class.getSimpleName().toLowerCase();
|
||||
|
||||
Query hibernateQuery = getSearchQuery(context, queryString, query, queryFields, excludeGroup,
|
||||
Collections.EMPTY_LIST, null, -1, -1);
|
||||
return count(hibernateQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EPerson> findAll(Context context, MetadataField metadataSortField, String sortField, int pageSize,
|
||||
int offset) throws SQLException {
|
||||
@@ -105,19 +119,43 @@ public class EPersonDAOImpl extends AbstractHibernateDSODAO<EPerson> implements
|
||||
sortFields = Collections.singletonList(metadataSortField);
|
||||
}
|
||||
|
||||
Query query = getSearchQuery(context, queryString, null, ListUtils.EMPTY_LIST, sortFields, sortField, pageSize,
|
||||
offset);
|
||||
Query query = getSearchQuery(context, queryString, null, ListUtils.EMPTY_LIST, null,
|
||||
sortFields, sortField, pageSize, offset);
|
||||
return list(query);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EPerson> findByGroups(Context context, Set<Group> groups) throws SQLException {
|
||||
public List<EPerson> findByGroups(Context context, Set<Group> groups, int pageSize, int offset)
|
||||
throws SQLException {
|
||||
Query query = createQuery(context,
|
||||
"SELECT DISTINCT e FROM EPerson e " +
|
||||
"JOIN e.groups g " +
|
||||
"WHERE g.id IN (:idList) ");
|
||||
|
||||
List<UUID> idList = new ArrayList<>(groups.size());
|
||||
for (Group group : groups) {
|
||||
idList.add(group.getID());
|
||||
}
|
||||
query.setParameter("idList", idList);
|
||||
|
||||
if (pageSize > 0) {
|
||||
query.setMaxResults(pageSize);
|
||||
}
|
||||
if (offset > 0) {
|
||||
query.setFirstResult(offset);
|
||||
}
|
||||
|
||||
return list(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countByGroups(Context context, Set<Group> groups) throws SQLException {
|
||||
Query query = createQuery(context,
|
||||
"SELECT count(DISTINCT e) FROM EPerson e " +
|
||||
"JOIN e.groups g " +
|
||||
"WHERE g.id IN (:idList) ");
|
||||
|
||||
List<UUID> idList = new ArrayList<>(groups.size());
|
||||
for (Group group : groups) {
|
||||
idList.add(group.getID());
|
||||
@@ -125,7 +163,7 @@ public class EPersonDAOImpl extends AbstractHibernateDSODAO<EPerson> implements
|
||||
|
||||
query.setParameter("idList", idList);
|
||||
|
||||
return list(query);
|
||||
return count(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -154,43 +192,88 @@ public class EPersonDAOImpl extends AbstractHibernateDSODAO<EPerson> implements
|
||||
protected Query getSearchQuery(Context context, String queryString, String queryParam,
|
||||
List<MetadataField> queryFields, List<MetadataField> sortFields, String sortField)
|
||||
throws SQLException {
|
||||
return getSearchQuery(context, queryString, queryParam, queryFields, sortFields, sortField, -1, -1);
|
||||
return getSearchQuery(context, queryString, queryParam, queryFields, null, sortFields, sortField, -1, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a search query across EPersons based on the given metadata fields and sorted based on the given metadata
|
||||
* field(s) or database column.
|
||||
* <P>
|
||||
* NOTE: the EPerson's email address is included in the search alongside any given metadata fields.
|
||||
*
|
||||
* @param context DSpace Context
|
||||
* @param queryString String which defines the beginning "SELECT" for the SQL query
|
||||
* @param queryParam Actual text being searched for
|
||||
* @param queryFields List of metadata fields to search within
|
||||
* @param excludeGroup Optional Group which should be excluded from search. Any EPersons who are members
|
||||
* of this group will not be included in the results.
|
||||
* @param sortFields Optional List of metadata fields to sort by (should not be specified if sortField is used)
|
||||
* @param sortField Optional database column to sort on (should not be specified if sortFields is used)
|
||||
* @param pageSize how many results return
|
||||
* @param offset the position of the first result to return
|
||||
* @return built Query object
|
||||
* @throws SQLException if error occurs
|
||||
*/
|
||||
protected Query getSearchQuery(Context context, String queryString, String queryParam,
|
||||
List<MetadataField> queryFields, List<MetadataField> sortFields, String sortField,
|
||||
int pageSize, int offset) throws SQLException {
|
||||
|
||||
List<MetadataField> queryFields, Group excludeGroup,
|
||||
List<MetadataField> sortFields, String sortField,
|
||||
int pageSize, int offset) throws SQLException {
|
||||
// Initialize SQL statement using the passed in "queryString"
|
||||
StringBuilder queryBuilder = new StringBuilder();
|
||||
queryBuilder.append(queryString);
|
||||
|
||||
Set<MetadataField> metadataFieldsToJoin = new LinkedHashSet<>();
|
||||
metadataFieldsToJoin.addAll(queryFields);
|
||||
metadataFieldsToJoin.addAll(sortFields);
|
||||
|
||||
// Append necessary join information for MetadataFields we will search within
|
||||
if (!CollectionUtils.isEmpty(metadataFieldsToJoin)) {
|
||||
addMetadataLeftJoin(queryBuilder, EPerson.class.getSimpleName().toLowerCase(), metadataFieldsToJoin);
|
||||
}
|
||||
if (queryParam != null) {
|
||||
// Always append a search on EPerson "email" based on query
|
||||
if (StringUtils.isNotBlank(queryParam)) {
|
||||
addMetadataValueWhereQuery(queryBuilder, queryFields, "like",
|
||||
EPerson.class.getSimpleName().toLowerCase() + ".email like :queryParam");
|
||||
}
|
||||
// If excludeGroup is specified, exclude members of that group from results
|
||||
// This uses a subquery to find the excluded group & verify that it is not in the EPerson list of "groups"
|
||||
if (excludeGroup != null) {
|
||||
// If query params exist, then we already have a WHERE clause (see above) and just need to append an AND
|
||||
if (StringUtils.isNotBlank(queryParam)) {
|
||||
queryBuilder.append(" AND ");
|
||||
} else {
|
||||
// no WHERE clause yet, so this is the start of the WHERE
|
||||
queryBuilder.append(" WHERE ");
|
||||
}
|
||||
queryBuilder.append("(FROM Group g where g.id = :group_id) NOT IN elements (")
|
||||
.append(EPerson.class.getSimpleName().toLowerCase()).append(".groups)");
|
||||
}
|
||||
// Add sort/order by info to query, if specified
|
||||
if (!CollectionUtils.isEmpty(sortFields) || StringUtils.isNotBlank(sortField)) {
|
||||
addMetadataSortQuery(queryBuilder, sortFields, Collections.singletonList(sortField));
|
||||
}
|
||||
|
||||
// Create the final SQL SELECT statement (based on included params above)
|
||||
Query query = createQuery(context, queryBuilder.toString());
|
||||
// Set pagesize & offset for pagination
|
||||
if (pageSize > 0) {
|
||||
query.setMaxResults(pageSize);
|
||||
}
|
||||
if (offset > 0) {
|
||||
query.setFirstResult(offset);
|
||||
}
|
||||
// Set all parameters to the SQL SELECT statement (based on included params above)
|
||||
if (StringUtils.isNotBlank(queryParam)) {
|
||||
query.setParameter("queryParam", "%" + queryParam.toLowerCase() + "%");
|
||||
}
|
||||
for (MetadataField metadataField : metadataFieldsToJoin) {
|
||||
query.setParameter(metadataField.toString(), metadataField.getID());
|
||||
}
|
||||
if (excludeGroup != null) {
|
||||
query.setParameter("group_id", excludeGroup.getID());
|
||||
}
|
||||
|
||||
query.setHint("org.hibernate.cacheable", Boolean.TRUE);
|
||||
|
||||
return query;
|
||||
}
|
||||
|
@@ -164,6 +164,41 @@ public class GroupDAOImpl extends AbstractHibernateDSODAO<Group> implements Grou
|
||||
return count(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Group> findByNameLikeAndNotMember(Context context, String groupName, Group excludeParent,
|
||||
int offset, int limit) throws SQLException {
|
||||
Query query = createQuery(context,
|
||||
"FROM Group " +
|
||||
"WHERE lower(name) LIKE lower(:group_name) " +
|
||||
"AND id != :parent_id " +
|
||||
"AND (from Group g where g.id = :parent_id) not in elements (parentGroups)");
|
||||
query.setParameter("parent_id", excludeParent.getID());
|
||||
query.setParameter("group_name", "%" + StringUtils.trimToEmpty(groupName) + "%");
|
||||
|
||||
if (0 <= offset) {
|
||||
query.setFirstResult(offset);
|
||||
}
|
||||
if (0 <= limit) {
|
||||
query.setMaxResults(limit);
|
||||
}
|
||||
query.setHint("org.hibernate.cacheable", Boolean.TRUE);
|
||||
|
||||
return list(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countByNameLikeAndNotMember(Context context, String groupName, Group excludeParent) throws SQLException {
|
||||
Query query = createQuery(context,
|
||||
"SELECT count(*) FROM Group " +
|
||||
"WHERE lower(name) LIKE lower(:group_name) " +
|
||||
"AND id != :parent_id " +
|
||||
"AND (from Group g where g.id = :parent_id) not in elements (parentGroups)");
|
||||
query.setParameter("parent_id", excludeParent.getID());
|
||||
query.setParameter("group_name", "%" + StringUtils.trimToEmpty(groupName) + "%");
|
||||
|
||||
return count(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Context context, Group group) throws SQLException {
|
||||
Query query = getHibernateSession(context)
|
||||
@@ -196,4 +231,29 @@ public class GroupDAOImpl extends AbstractHibernateDSODAO<Group> implements Grou
|
||||
return count(createQuery(context, "SELECT count(*) FROM Group"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Group> findByParent(Context context, Group parent, int pageSize, int offset) throws SQLException {
|
||||
Query query = createQuery(context,
|
||||
"SELECT g FROM Group g JOIN g.parentGroups pg " +
|
||||
"WHERE pg.id = :parent_id");
|
||||
query.setParameter("parent_id", parent.getID());
|
||||
if (pageSize > 0) {
|
||||
query.setMaxResults(pageSize);
|
||||
}
|
||||
if (offset > 0) {
|
||||
query.setFirstResult(offset);
|
||||
}
|
||||
query.setHint("org.hibernate.cacheable", Boolean.TRUE);
|
||||
|
||||
return list(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countByParent(Context context, Group parent) throws SQLException {
|
||||
Query query = createQuery(context, "SELECT count(g) FROM Group g JOIN g.parentGroups pg " +
|
||||
"WHERE pg.id = :parent_id");
|
||||
query.setParameter("parent_id", parent.getID());
|
||||
|
||||
return count(query);
|
||||
}
|
||||
}
|
||||
|
@@ -98,9 +98,9 @@ public interface EPersonService extends DSpaceObjectService<EPerson>, DSpaceObje
|
||||
*
|
||||
* @param context The relevant DSpace Context.
|
||||
* @param query The search string
|
||||
* @param offset Inclusive offset
|
||||
* @param offset Inclusive offset (the position of the first result to return)
|
||||
* @param limit Maximum number of matches returned
|
||||
* @return array of EPerson objects
|
||||
* @return List of matching EPerson objects
|
||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||
*/
|
||||
public List<EPerson> search(Context context, String query, int offset, int limit)
|
||||
@@ -118,6 +118,34 @@ public interface EPersonService extends DSpaceObjectService<EPerson>, DSpaceObje
|
||||
public int searchResultCount(Context context, String query)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
* Find the EPersons that match the search query which are NOT currently members of the given Group. The search
|
||||
* query is run against firstname, lastname or email.
|
||||
*
|
||||
* @param context DSpace context
|
||||
* @param query The search string
|
||||
* @param excludeGroup Group to exclude results from. Members of this group will never be returned.
|
||||
* @param offset Inclusive offset (the position of the first result to return)
|
||||
* @param limit Maximum number of matches returned
|
||||
* @return List of matching EPerson objects
|
||||
* @throws SQLException if error
|
||||
*/
|
||||
List<EPerson> searchNonMembers(Context context, String query, Group excludeGroup,
|
||||
int offset, int limit) throws SQLException;
|
||||
|
||||
/**
|
||||
* Returns the total number of EPersons that match the search query which are NOT currently members of the given
|
||||
* Group. The search query is run against firstname, lastname or email. Can be used with searchNonMembers() to
|
||||
* support pagination
|
||||
*
|
||||
* @param context DSpace context
|
||||
* @param query The search string
|
||||
* @param excludeGroup Group to exclude results from. Members of this group will never be returned.
|
||||
* @return List of matching EPerson objects
|
||||
* @throws SQLException if error
|
||||
*/
|
||||
int searchNonMembersCount(Context context, String query, Group excludeGroup) throws SQLException;
|
||||
|
||||
/**
|
||||
* Find all the {@code EPerson}s in a specific order by field.
|
||||
* The sortable fields are:
|
||||
@@ -252,14 +280,42 @@ public interface EPersonService extends DSpaceObjectService<EPerson>, DSpaceObje
|
||||
public List<String> getDeleteConstraints(Context context, EPerson ePerson) throws SQLException;
|
||||
|
||||
/**
|
||||
* Retrieve all accounts which belong to at least one of the specified groups.
|
||||
* Retrieve all EPerson accounts which belong to at least one of the specified groups.
|
||||
* <P>
|
||||
* WARNING: This method may have bad performance issues for Groups with a very large number of members,
|
||||
* as it will load all member EPerson objects into memory.
|
||||
* <P>
|
||||
* For better performance, use the paginated version of this method.
|
||||
*
|
||||
* @param c The relevant DSpace Context.
|
||||
* @param groups set of eperson groups
|
||||
* @return a list of epeople
|
||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||
*/
|
||||
public List<EPerson> findByGroups(Context c, Set<Group> groups) throws SQLException;
|
||||
List<EPerson> findByGroups(Context c, Set<Group> groups) throws SQLException;
|
||||
|
||||
/**
|
||||
* Retrieve all EPerson accounts which belong to at least one of the specified groups, in a paginated fashion.
|
||||
*
|
||||
* @param c The relevant DSpace Context.
|
||||
* @param groups Set of group(s) to check membership in
|
||||
* @param pageSize number of EPerson objects to load at one time. Set to <=0 to disable pagination
|
||||
* @param offset number of page to load (starting with 1). Set to <=0 to disable pagination
|
||||
* @return a list of epeople
|
||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||
*/
|
||||
List<EPerson> findByGroups(Context c, Set<Group> groups, int pageSize, int offset) throws SQLException;
|
||||
|
||||
/**
|
||||
* Count all EPerson accounts which belong to at least one of the specified groups. This provides the total
|
||||
* number of results to expect from corresponding findByGroups() for pagination purposes.
|
||||
*
|
||||
* @param c The relevant DSpace Context.
|
||||
* @param groups Set of group(s) to check membership in
|
||||
* @return total number of (unique) EPersons who are a member of one or more groups.
|
||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||
*/
|
||||
int countByGroups(Context c, Set<Group> groups) throws SQLException;
|
||||
|
||||
/**
|
||||
* Retrieve all accounts which are subscribed to receive information about new items.
|
||||
|
@@ -189,9 +189,11 @@ public interface GroupService extends DSpaceObjectService<Group>, DSpaceObjectLe
|
||||
Set<Group> allMemberGroupsSet(Context context, EPerson ePerson) throws SQLException;
|
||||
|
||||
/**
|
||||
* Get all of the epeople who are a member of the
|
||||
* specified group, or a member of a sub-group of the
|
||||
* Get all of the EPerson objects who are a member of the specified group, or a member of a subgroup of the
|
||||
* specified group, etc.
|
||||
* <P>
|
||||
* WARNING: This method may have bad performance for Groups with a very large number of members, as it will load
|
||||
* all member EPerson objects into memory. Only use if you need access to *every* EPerson object at once.
|
||||
*
|
||||
* @param context The relevant DSpace Context.
|
||||
* @param group Group object
|
||||
@@ -200,6 +202,18 @@ public interface GroupService extends DSpaceObjectService<Group>, DSpaceObjectLe
|
||||
*/
|
||||
public List<EPerson> allMembers(Context context, Group group) throws SQLException;
|
||||
|
||||
/**
|
||||
* Count all of the EPerson objects who are a member of the specified group, or a member of a subgroup of the
|
||||
* specified group, etc.
|
||||
* In other words, this will return the size of "allMembers()" without having to load all EPerson objects into
|
||||
* memory.
|
||||
* @param context current DSpace context
|
||||
* @param group Group object
|
||||
* @return count of EPerson object members
|
||||
* @throws SQLException if error
|
||||
*/
|
||||
int countAllMembers(Context context, Group group) throws SQLException;
|
||||
|
||||
/**
|
||||
* Find the group by its name - assumes name is unique
|
||||
*
|
||||
@@ -247,37 +261,67 @@ public interface GroupService extends DSpaceObjectService<Group>, DSpaceObjectLe
|
||||
public List<Group> findAll(Context context, int sortField) throws SQLException;
|
||||
|
||||
/**
|
||||
* Find the groups that match the search query across eperson_group_id or name
|
||||
* Find the Groups that match the query across both Group name and Group ID. This is an unpaginated search,
|
||||
* which means it will load all matching groups into memory at once. This may provide POOR PERFORMANCE when a large
|
||||
* number of groups are matched.
|
||||
*
|
||||
* @param context DSpace context
|
||||
* @param groupIdentifier The group name or group ID
|
||||
* @return array of Group objects
|
||||
* @param context DSpace context
|
||||
* @param query The search string used to search across group name or group ID
|
||||
* @return List of matching Group objects
|
||||
* @throws SQLException if error
|
||||
*/
|
||||
public List<Group> search(Context context, String groupIdentifier) throws SQLException;
|
||||
List<Group> search(Context context, String query) throws SQLException;
|
||||
|
||||
/**
|
||||
* Find the groups that match the search query across eperson_group_id or name
|
||||
* Find the Groups that match the query across both Group name and Group ID. This method supports pagination,
|
||||
* which provides better performance than the above non-paginated search() method.
|
||||
*
|
||||
* @param context DSpace context
|
||||
* @param groupIdentifier The group name or group ID
|
||||
* @param offset Inclusive offset
|
||||
* @param limit Maximum number of matches returned
|
||||
* @return array of Group objects
|
||||
* @param context DSpace context
|
||||
* @param query The search string used to search across group name or group ID
|
||||
* @param offset Inclusive offset (the position of the first result to return)
|
||||
* @param limit Maximum number of matches returned
|
||||
* @return List of matching Group objects
|
||||
* @throws SQLException if error
|
||||
*/
|
||||
public List<Group> search(Context context, String groupIdentifier, int offset, int limit) throws SQLException;
|
||||
List<Group> search(Context context, String query, int offset, int limit) throws SQLException;
|
||||
|
||||
/**
|
||||
* Returns the total number of groups returned by a specific query, without the overhead
|
||||
* of creating the Group objects to store the results.
|
||||
* Returns the total number of Groups returned by a specific query. Search is performed based on Group name
|
||||
* and Group ID. May be used with search() above to support pagination of matching Groups.
|
||||
*
|
||||
* @param context DSpace context
|
||||
* @param query The search string
|
||||
* @param query The search string used to search across group name or group ID
|
||||
* @return the number of groups matching the query
|
||||
* @throws SQLException if error
|
||||
*/
|
||||
public int searchResultCount(Context context, String query) throws SQLException;
|
||||
int searchResultCount(Context context, String query) throws SQLException;
|
||||
|
||||
/**
|
||||
* Find the groups that match the search query which are NOT currently members (subgroups)
|
||||
* of the given parentGroup
|
||||
*
|
||||
* @param context DSpace context
|
||||
* @param query The search string used to search across group name or group ID
|
||||
* @param excludeParentGroup Parent group to exclude results from
|
||||
* @param offset Inclusive offset (the position of the first result to return)
|
||||
* @param limit Maximum number of matches returned
|
||||
* @return List of matching Group objects
|
||||
* @throws SQLException if error
|
||||
*/
|
||||
List<Group> searchNonMembers(Context context, String query, Group excludeParentGroup,
|
||||
int offset, int limit) throws SQLException;
|
||||
|
||||
/**
|
||||
* Returns the total number of groups that match the search query which are NOT currently members (subgroups)
|
||||
* of the given parentGroup. Can be used with searchNonMembers() to support pagination.
|
||||
*
|
||||
* @param context DSpace context
|
||||
* @param query The search string used to search across group name or group ID
|
||||
* @param excludeParentGroup Parent group to exclude results from
|
||||
* @return the number of Groups matching the query
|
||||
* @throws SQLException if error
|
||||
*/
|
||||
int searchNonMembersCount(Context context, String query, Group excludeParentGroup) throws SQLException;
|
||||
|
||||
/**
|
||||
* Return true if group has no direct or indirect members
|
||||
@@ -327,4 +371,29 @@ public interface GroupService extends DSpaceObjectService<Group>, DSpaceObjectLe
|
||||
*/
|
||||
List<Group> findByMetadataField(Context context, String searchValue, MetadataField metadataField)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
* Find all groups which are a member of the given Parent group
|
||||
*
|
||||
* @param context The relevant DSpace Context.
|
||||
* @param parent The parent Group to search on
|
||||
* @param pageSize how many results return
|
||||
* @param offset the position of the first result to return
|
||||
* @return List of all groups which are members of the parent group
|
||||
* @throws SQLException database exception if error
|
||||
*/
|
||||
List<Group> findByParent(Context context, Group parent, int pageSize, int offset)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
* Return number of groups which are a member of the given Parent group.
|
||||
* Can be used with findByParent() for pagination of all groups within a given Parent group.
|
||||
*
|
||||
* @param context The relevant DSpace Context.
|
||||
* @param parent The parent Group to search on
|
||||
* @return number of groups which are members of the parent group
|
||||
* @throws SQLException database exception if error
|
||||
*/
|
||||
int countByParent(Context context, Group parent)
|
||||
throws SQLException;
|
||||
}
|
||||
|
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.submit.consumer;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.discovery.IndexingService;
|
||||
import org.dspace.discovery.indexobject.IndexableCollection;
|
||||
import org.dspace.event.Consumer;
|
||||
import org.dspace.event.Event;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.dspace.submit.factory.SubmissionServiceFactory;
|
||||
|
||||
/**
|
||||
* Consumer implementation to be used for Item Submission Configuration
|
||||
*
|
||||
* @author paulo.graca at fccn.pt
|
||||
*/
|
||||
public class SubmissionConfigConsumer implements Consumer {
|
||||
/**
|
||||
* log4j logger
|
||||
*/
|
||||
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(SubmissionConfigConsumer.class);
|
||||
|
||||
IndexingService indexer = DSpaceServicesFactory.getInstance().getServiceManager()
|
||||
.getServiceByName(IndexingService.class.getName(),
|
||||
IndexingService.class);
|
||||
|
||||
@Override
|
||||
public void initialize() throws Exception {
|
||||
// No-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consume(Context ctx, Event event) throws Exception {
|
||||
int st = event.getSubjectType();
|
||||
int et = event.getEventType();
|
||||
|
||||
|
||||
if ( st == Constants.COLLECTION ) {
|
||||
switch (et) {
|
||||
case Event.MODIFY_METADATA:
|
||||
// Submission configuration it's based on solr
|
||||
// for collection's entity type but, at this point
|
||||
// that info isn't indexed yet, we need to force it
|
||||
DSpaceObject subject = event.getSubject(ctx);
|
||||
Collection collectionFromDSOSubject = (Collection) subject;
|
||||
indexer.indexContent(ctx, new IndexableCollection (collectionFromDSOSubject), true, false, false);
|
||||
indexer.commit();
|
||||
|
||||
log.debug("SubmissionConfigConsumer occured: " + event.toString());
|
||||
// reload submission configurations
|
||||
SubmissionServiceFactory.getInstance().getSubmissionConfigService().reload();
|
||||
break;
|
||||
|
||||
default:
|
||||
log.debug("SubmissionConfigConsumer occured: " + event.toString());
|
||||
// reload submission configurations
|
||||
SubmissionServiceFactory.getInstance().getSubmissionConfigService().reload();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end(Context ctx) throws Exception {
|
||||
// No-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(Context ctx) throws Exception {
|
||||
// No-op
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.submit.factory;
|
||||
|
||||
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.dspace.submit.service.SubmissionConfigService;
|
||||
|
||||
/**
|
||||
* Abstract factory to get services for submission, use SubmissionServiceFactory.getInstance() to retrieve an
|
||||
* implementation
|
||||
*
|
||||
* @author paulo.graca at fccn.pt
|
||||
*/
|
||||
public abstract class SubmissionServiceFactory {
|
||||
|
||||
public abstract SubmissionConfigService getSubmissionConfigService() throws SubmissionConfigReaderException;
|
||||
|
||||
public static SubmissionServiceFactory getInstance() {
|
||||
return DSpaceServicesFactory.getInstance().getServiceManager()
|
||||
.getServiceByName("submissionServiceFactory", SubmissionServiceFactory.class);
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.submit.factory;
|
||||
|
||||
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||
import org.dspace.submit.service.SubmissionConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Factory implementation to get services for submission, use SubmissionServiceFactory.getInstance() to
|
||||
* retrieve an implementation
|
||||
*
|
||||
* @author paulo.graca at fccn.pt
|
||||
*/
|
||||
public class SubmissionServiceFactoryImpl extends SubmissionServiceFactory {
|
||||
@Autowired(required = true)
|
||||
private SubmissionConfigService submissionConfigService;
|
||||
|
||||
@Override
|
||||
public SubmissionConfigService getSubmissionConfigService() throws SubmissionConfigReaderException {
|
||||
return submissionConfigService;
|
||||
}
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.submit.service;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.app.util.SubmissionConfig;
|
||||
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||
import org.dspace.app.util.SubmissionStepConfig;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Item Submission Configuration Service
|
||||
* enables interaction with a submission config like
|
||||
* getting a config by a collection name or handle
|
||||
* as also retrieving submission configuration steps
|
||||
*
|
||||
* @author paulo.graca at fccn.pt
|
||||
*/
|
||||
public interface SubmissionConfigService {
|
||||
|
||||
public void reload() throws SubmissionConfigReaderException;
|
||||
|
||||
public String getDefaultSubmissionConfigName();
|
||||
|
||||
public List<SubmissionConfig> getAllSubmissionConfigs(Integer limit, Integer offset);
|
||||
|
||||
public int countSubmissionConfigs();
|
||||
|
||||
public SubmissionConfig getSubmissionConfigByCollection(String collectionHandle);
|
||||
|
||||
public SubmissionConfig getSubmissionConfigByName(String submitName);
|
||||
|
||||
public SubmissionStepConfig getStepConfig(String stepID)
|
||||
throws SubmissionConfigReaderException;
|
||||
|
||||
public List<Collection> getCollectionsBySubmissionConfig(Context context, String submitName)
|
||||
throws IllegalStateException, SQLException, SubmissionConfigReaderException;
|
||||
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.submit.service;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.app.util.SubmissionConfig;
|
||||
import org.dspace.app.util.SubmissionConfigReader;
|
||||
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||
import org.dspace.app.util.SubmissionStepConfig;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* An implementation for Submission Config service
|
||||
*
|
||||
* @author paulo.graca at fccn.pt
|
||||
*/
|
||||
public class SubmissionConfigServiceImpl implements SubmissionConfigService, InitializingBean {
|
||||
|
||||
protected SubmissionConfigReader submissionConfigReader;
|
||||
|
||||
public SubmissionConfigServiceImpl () throws SubmissionConfigReaderException {
|
||||
submissionConfigReader = new SubmissionConfigReader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
submissionConfigReader.reload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() throws SubmissionConfigReaderException {
|
||||
submissionConfigReader.reload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultSubmissionConfigName() {
|
||||
return submissionConfigReader.getDefaultSubmissionConfigName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SubmissionConfig> getAllSubmissionConfigs(Integer limit, Integer offset) {
|
||||
return submissionConfigReader.getAllSubmissionConfigs(limit, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countSubmissionConfigs() {
|
||||
return submissionConfigReader.countSubmissionConfigs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubmissionConfig getSubmissionConfigByCollection(String collectionHandle) {
|
||||
return submissionConfigReader.getSubmissionConfigByCollection(collectionHandle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubmissionConfig getSubmissionConfigByName(String submitName) {
|
||||
return submissionConfigReader.getSubmissionConfigByName(submitName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubmissionStepConfig getStepConfig(String stepID) throws SubmissionConfigReaderException {
|
||||
return submissionConfigReader.getStepConfig(stepID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Collection> getCollectionsBySubmissionConfig(Context context, String submitName)
|
||||
throws IllegalStateException, SQLException {
|
||||
return submissionConfigReader.getCollectionsBySubmissionConfig(context, submitName);
|
||||
}
|
||||
|
||||
}
|
@@ -35,6 +35,8 @@ public class SolrUtils {
|
||||
* @return date formatter compatible with Solr.
|
||||
*/
|
||||
public static DateFormat getDateFormatter() {
|
||||
return new SimpleDateFormat(SolrUtils.SOLR_DATE_FORMAT);
|
||||
DateFormat formatter = new SimpleDateFormat(SolrUtils.SOLR_DATE_FORMAT);
|
||||
formatter.setTimeZone(SOLR_TIME_ZONE);
|
||||
return formatter;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user