diff --git a/dspace-api/src/main/java/org/dspace/app/util/OpenSearchServiceImpl.java b/dspace-api/src/main/java/org/dspace/app/util/OpenSearchServiceImpl.java index bea53c22ff..4ff93680d4 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/OpenSearchServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/app/util/OpenSearchServiceImpl.java @@ -22,6 +22,7 @@ import com.sun.syndication.feed.module.opensearch.impl.OpenSearchModuleImpl; import com.sun.syndication.io.FeedException; import org.apache.logging.log4j.Logger; import org.dspace.app.util.service.OpenSearchService; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.content.DSpaceObject; import org.dspace.core.Constants; import org.dspace.core.Context; @@ -118,7 +119,7 @@ public class OpenSearchServiceImpl implements OpenSearchService { @Override public String getResultsString(Context context, String format, String query, int totalResults, int start, int pageSize, - DSpaceObject scope, List results, + DSpaceObject scope, List results, Map labels) throws IOException { try { return getResults(context, format, query, totalResults, start, pageSize, scope, results, labels) @@ -132,7 +133,7 @@ public class OpenSearchServiceImpl implements OpenSearchService { @Override public Document getResultsDoc(Context context, String format, String query, int totalResults, int start, int pageSize, - DSpaceObject scope, List results, Map labels) + DSpaceObject scope, List results, Map labels) throws IOException { try { return getResults(context, format, query, totalResults, start, pageSize, scope, results, labels) @@ -144,8 +145,8 @@ public class OpenSearchServiceImpl implements OpenSearchService { } protected SyndicationFeed getResults(Context context, String format, String query, int totalResults, int start, - int pageSize, - DSpaceObject scope, List results, Map labels) { + int pageSize, DSpaceObject scope, + List results, Map labels) { // Encode results in requested format if ("rss".equals(format)) { format = "rss_2.0"; diff --git a/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java b/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java index 3e0caee543..d60787937e 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java +++ b/dspace-api/src/main/java/org/dspace/app/util/SyndicationFeed.java @@ -37,6 +37,7 @@ import com.sun.syndication.io.SyndFeedOutput; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.Collection; @@ -184,7 +185,7 @@ public class SyndicationFeed { * @param labels label map */ public void populate(HttpServletRequest request, Context context, DSpaceObject dso, - List items, Map labels) { + List items, Map labels) { String logoURL = null; String objectURL = null; String defaultTitle = null; @@ -247,7 +248,7 @@ public class SyndicationFeed { // add entries for items if (items != null) { List entries = new ArrayList(); - for (DSpaceObject itemDSO : items) { + for (BrowsableDSpaceObject itemDSO : items) { if (itemDSO.getType() != Constants.ITEM) { continue; } diff --git a/dspace-api/src/main/java/org/dspace/app/util/Util.java b/dspace-api/src/main/java/org/dspace/app/util/Util.java index 7d4a5e8182..564300358c 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/Util.java +++ b/dspace-api/src/main/java/org/dspace/app/util/Util.java @@ -473,6 +473,26 @@ public class Util { return toReturn; } + /** + * Split a list in an array of i sub-lists uniformly sized + * + * @param idsList the list to split + * @param i the number of sublists to return + * + * @return an array of sub-lists of fixed size + */ + public static List[] splitList(List idsList, int i) { + int setmin = idsList.size() / i; + List[] result = new List[i]; + int offset = 0; + for (int idx = 0; idx < i - 1; idx++) { + result[idx] = idsList.subList(offset, offset + setmin); + offset += setmin; + } + result[i - 1] = idsList.subList(offset, idsList.size()); + return result; + } + public static List differenceInSubmissionFields(Collection fromCollection, Collection toCollection) throws DCInputsReaderException { DCInputsReader reader = new DCInputsReader(); diff --git a/dspace-api/src/main/java/org/dspace/app/util/service/OpenSearchService.java b/dspace-api/src/main/java/org/dspace/app/util/service/OpenSearchService.java index 45259de8c0..7732ed944b 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/service/OpenSearchService.java +++ b/dspace-api/src/main/java/org/dspace/app/util/service/OpenSearchService.java @@ -12,6 +12,7 @@ import java.sql.SQLException; import java.util.List; import java.util.Map; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.content.DSpaceObject; import org.dspace.core.Context; import org.w3c.dom.Document; @@ -91,7 +92,7 @@ public interface OpenSearchService { */ public String getResultsString(Context context, String format, String query, int totalResults, int start, int pageSize, - DSpaceObject scope, List results, + DSpaceObject scope, List results, Map labels) throws IOException; /** @@ -111,7 +112,7 @@ public interface OpenSearchService { */ public Document getResultsDoc(Context context, String format, String query, int totalResults, int start, int pageSize, - DSpaceObject scope, List results, Map labels) + DSpaceObject scope, List results, Map labels) throws IOException; public DSpaceObject resolveScope(Context context, String scope) throws SQLException; diff --git a/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java b/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java index 936a7d6492..2384a260da 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/authorize/AuthorizeServiceImpl.java @@ -767,4 +767,10 @@ public class AuthorizeServiceImpl implements AuthorizeService { return policy; } + @Override + public List getPoliciesActionFilterExceptRpType(Context c, DSpaceObject o, int actionID, + String rpType) throws SQLException { + return resourcePolicyService.findExceptRpType(c, o, actionID, rpType); + } + } diff --git a/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java b/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java index 4693599c31..a7a8a25bfc 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicyServiceImpl.java @@ -307,4 +307,10 @@ public class ResourcePolicyServiceImpl implements ResourcePolicyService { context.restoreAuthSystemState(); } } + + @Override + public List findExceptRpType(Context c, DSpaceObject o, int actionID, String rpType) + throws SQLException { + return resourcePolicyDAO.findByDSoAndActionExceptRpType(c, o, actionID, rpType); + } } diff --git a/dspace-api/src/main/java/org/dspace/authorize/dao/ResourcePolicyDAO.java b/dspace-api/src/main/java/org/dspace/authorize/dao/ResourcePolicyDAO.java index ecaeef18e7..0ab7e0dd9b 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/dao/ResourcePolicyDAO.java +++ b/dspace-api/src/main/java/org/dspace/authorize/dao/ResourcePolicyDAO.java @@ -66,4 +66,17 @@ public interface ResourcePolicyDAO extends GenericDAO { public void deleteByDsoEPersonPolicies(Context context, DSpaceObject dso, EPerson ePerson) throws SQLException; public void deleteByDsoAndTypeNotEqualsTo(Context c, DSpaceObject o, String type) throws SQLException; + + /** + * Return a list of policies for an object that match the action except the record labeled with the rpType + * + * @param c context + * @param o DSpaceObject policies relate to + * @param actionID action (defined in class Constants) + * @param rpType the resource policy type + * @return list of resource policies + * @throws SQLException if there's a database problem + */ + public List findByDSoAndActionExceptRpType(Context c, DSpaceObject o, int actionID, + String rpType) throws SQLException; } diff --git a/dspace-api/src/main/java/org/dspace/authorize/dao/impl/ResourcePolicyDAOImpl.java b/dspace-api/src/main/java/org/dspace/authorize/dao/impl/ResourcePolicyDAOImpl.java index a0f69dc526..a981f1a5f8 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/dao/impl/ResourcePolicyDAOImpl.java +++ b/dspace-api/src/main/java/org/dspace/authorize/dao/impl/ResourcePolicyDAOImpl.java @@ -201,4 +201,21 @@ public class ResourcePolicyDAOImpl extends AbstractHibernateDAO query.setParameter("rptype", type); query.executeUpdate(); } + + @Override + public List findByDSoAndActionExceptRpType(Context context, DSpaceObject dso, int action, + String rpType) throws SQLException { + CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); + CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, ResourcePolicy.class); + + Root resourcePolicyRoot = criteriaQuery.from(ResourcePolicy.class); + criteriaQuery.select(resourcePolicyRoot); + criteriaQuery.where( + criteriaBuilder.and(criteriaBuilder.equal(resourcePolicyRoot.get(ResourcePolicy_.dSpaceObject), dso), + criteriaBuilder.equal(resourcePolicyRoot.get(ResourcePolicy_.actionId), action), + criteriaBuilder.notEqual(resourcePolicyRoot.get(ResourcePolicy_.rptype), rpType) + ) + ); + return list(context, criteriaQuery, false, ResourcePolicy.class, 1, -1); + } } diff --git a/dspace-api/src/main/java/org/dspace/authorize/service/AuthorizeService.java b/dspace-api/src/main/java/org/dspace/authorize/service/AuthorizeService.java index 092460f10f..9e739e2585 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/service/AuthorizeService.java +++ b/dspace-api/src/main/java/org/dspace/authorize/service/AuthorizeService.java @@ -312,6 +312,18 @@ public interface AuthorizeService { */ public List getPoliciesActionFilter(Context c, DSpaceObject o, int actionID) throws SQLException; + /** + * Return a list of policies for an object that match the action except the record labeled with the rpType + * + * @param c context + * @param o DSpaceObject policies relate to + * @param actionID action (defined in class Constants) + * @param rpType the resource policy type + * @return list of resource policies + * @throws SQLException if there's a database problem + */ + public List getPoliciesActionFilterExceptRpType(Context c, DSpaceObject o, int actionID, + String rpType) throws SQLException; /** * Add policies to an object to match those from a previous object * diff --git a/dspace-api/src/main/java/org/dspace/authorize/service/ResourcePolicyService.java b/dspace-api/src/main/java/org/dspace/authorize/service/ResourcePolicyService.java index 689898daa2..3da8beb130 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/service/ResourcePolicyService.java +++ b/dspace-api/src/main/java/org/dspace/authorize/service/ResourcePolicyService.java @@ -76,4 +76,16 @@ public interface ResourcePolicyService extends DSpaceCRUDService public void removeDsoAndTypeNotEqualsToPolicies(Context c, DSpaceObject o, String type) throws SQLException, AuthorizeException; + /** + * Return a list of policies for an object that match the action except the record labeled with the rpType + * + * @param c context + * @param o DSpaceObject policies relate to + * @param actionID action (defined in class Constants) + * @param rpType the resource policy type + * @return list of resource policies + * @throws SQLException if there's a database problem + */ + public List findExceptRpType(Context c, DSpaceObject o, int actionID, String rpType) + throws SQLException; } diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowserScope.java b/dspace-api/src/main/java/org/dspace/browse/BrowserScope.java index aecfacd594..09eead59b8 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowserScope.java +++ b/dspace-api/src/main/java/org/dspace/browse/BrowserScope.java @@ -114,6 +114,8 @@ public class BrowserScope { private String authority = null; + private String userLocale = null; + /** * Construct a new BrowserScope using the given Context * @@ -131,7 +133,7 @@ public class BrowserScope { * @param dso the container object; a Community or Collection * @throws BrowseException if browse error */ - public void setBrowseContainer(DSpaceObject dso) + public void setBrowseContainer(BrowsableDSpaceObject dso) throws BrowseException { if (dso instanceof Collection) { this.collection = (Collection) dso; @@ -582,4 +584,12 @@ public class BrowserScope { public void setAuthorityValue(String value) { authority = value; } + + public void setUserLocale(String userLocale) { + this.userLocale = userLocale; + } + + public String getUserLocale() { + return userLocale; + } } diff --git a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java index 98d5b8bbcb..6efb88adf8 100644 --- a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java +++ b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java @@ -19,7 +19,6 @@ import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.dspace.authorize.factory.AuthorizeServiceFactory; import org.dspace.authorize.service.AuthorizeService; -import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.core.Constants; import org.dspace.core.Context; @@ -308,7 +307,7 @@ public class SolrBrowseDAO implements BrowseDAO { DiscoverResult resp = getSolrResponse(); List bitems = new ArrayList<>(); - for (DSpaceObject solrDoc : resp.getDspaceObjects()) { + for (BrowsableDSpaceObject solrDoc : resp.getDspaceObjects()) { // FIXME introduce project, don't retrieve Item immediately when // processing the query... Item item = (Item) solrDoc; diff --git a/dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java b/dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java index 94a41f6195..e428021356 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java +++ b/dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java @@ -69,6 +69,8 @@ public class DiscoverQuery { **/ private Map> properties; + private String discoveryConfigurationName; + public DiscoverQuery() { //Initialize all our lists this.filterQueries = new ArrayList(); @@ -331,6 +333,7 @@ public class DiscoverQuery { // Example: 2001 and a gap from 10 we need the following result: 2010 - 2000 ; 2000 - 1990 hence the top // year int topYear = getTopYear(newestYear, gap); + if (gap == 1) { //We need a list of our years //We have a date range add faceting for our field @@ -376,4 +379,11 @@ public class DiscoverQuery { return (int) (Math.ceil((float) (newestYear) / gap) * gap); } + public String getDiscoveryConfigurationName() { + return discoveryConfigurationName; + } + + public void setDiscoveryConfigurationName(String discoveryConfigurationName) { + this.discoveryConfigurationName = discoveryConfigurationName; + } } diff --git a/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java b/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java index 9004b27f95..18e60d7adf 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java +++ b/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java @@ -15,7 +15,7 @@ import java.util.List; import java.util.Map; import org.apache.commons.collections4.ListUtils; -import org.dspace.content.DSpaceObject; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.discovery.configuration.DiscoveryConfigurationParameters; import org.dspace.discovery.configuration.DiscoverySearchFilterFacet; @@ -28,8 +28,11 @@ public class DiscoverResult { private long totalSearchResults; private int start; - private List dspaceObjects; + private List dspaceObjects; private Map> facetResults; + private Map> facetQueryResults; + private Map> facetFieldResults; + /** * A map that contains all the documents sougth after, the key is a string representation of the DSpace object */ @@ -39,20 +42,20 @@ public class DiscoverResult { private Map highlightedResults; private String spellCheckQuery; - public DiscoverResult() { - dspaceObjects = new ArrayList(); + dspaceObjects = new ArrayList(); facetResults = new LinkedHashMap>(); + facetQueryResults = new LinkedHashMap>(); + facetFieldResults = new LinkedHashMap>(); searchDocuments = new LinkedHashMap>(); highlightedResults = new HashMap(); } - - public void addDSpaceObject(DSpaceObject dso) { + public void addDSpaceObject(BrowsableDSpaceObject dso) { this.dspaceObjects.add(dso); } - public List getDspaceObjects() { + public List getDspaceObjects() { return dspaceObjects; } @@ -101,25 +104,59 @@ public class DiscoverResult { return facetResults; } + public List getFacetQueryResult(String facet) { + return facetQueryResults.get(facet) == null ? new ArrayList() : facetQueryResults.get(facet); + } + + public void addFacetQueryResult(String facetField, FacetResult... facetResults) { + List facetValues = this.facetQueryResults.get(facetField); + if (facetValues == null) { + facetValues = new ArrayList(); + } + facetValues.addAll(Arrays.asList(facetResults)); + this.facetQueryResults.put(facetField, facetValues); + } + + public Map> getFacetQueryResults() { + return facetQueryResults; + } + + public List getFacetFieldResult(String facet) { + return facetFieldResults.get(facet) == null ? new ArrayList() : facetFieldResults.get(facet); + } + + public void addFacetFieldResult(String facetField, FacetResult... facetResults) { + List facetValues = this.facetFieldResults.get(facetField); + if (facetValues == null) { + facetValues = new ArrayList(); + } + facetValues.addAll(Arrays.asList(facetResults)); + this.facetFieldResults.put(facetField, facetValues); + } + + public Map> getFacetFieldResults() { + return facetFieldResults; + } + public List getFacetResult(String facet) { return ListUtils.emptyIfNull(facetResults.get(facet)); } public List getFacetResult(DiscoverySearchFilterFacet field) { List facetValues = getFacetResult(field.getIndexFieldName()); - //Check if we are dealing with a date, sometimes the facet values arrive as dates ! + // Check if we are dealing with a date, sometimes the facet values arrive as dates ! if (facetValues.size() == 0 && field.getType().equals(DiscoveryConfigurationParameters.TYPE_DATE)) { facetValues = getFacetResult(field.getIndexFieldName() + ".year"); } return ListUtils.emptyIfNull(facetValues); } - public DSpaceObjectHighlightResult getHighlightedResults(DSpaceObject dso) { - return highlightedResults.get(dso.getHandle()); + public DSpaceObjectHighlightResult getHighlightedResults(BrowsableDSpaceObject dso) { + return highlightedResults.get(dso.getUniqueIndexID()); } - public void addHighlightedResult(DSpaceObject dso, DSpaceObjectHighlightResult highlightedResult) { - this.highlightedResults.put(dso.getHandle(), highlightedResult); + public void addHighlightedResult(BrowsableDSpaceObject dso, DSpaceObjectHighlightResult highlightedResult) { + this.highlightedResults.put(dso.getUniqueIndexID(), highlightedResult); } public static final class FacetResult { @@ -131,7 +168,7 @@ public class DiscoverResult { private String fieldType; public FacetResult(String asFilterQuery, String displayedValue, String authorityKey, String sortValue, - long count, String fieldType) { + long count, String fieldType) { this.asFilterQuery = asFilterQuery; this.displayedValue = displayedValue; this.authorityKey = authorityKey; @@ -141,6 +178,10 @@ public class DiscoverResult { } public String getAsFilterQuery() { + if (asFilterQuery == null) { + // missing facet filter query + return "[* TO *]"; + } return asFilterQuery; } @@ -161,7 +202,7 @@ public class DiscoverResult { } public String getFilterType() { - return authorityKey != null ? "authority" : "equals"; + return authorityKey != null ? "authority" : asFilterQuery != null ? "equals" : "notequals"; } public String getFieldType() { @@ -178,15 +219,18 @@ public class DiscoverResult { } public static final class DSpaceObjectHighlightResult { - private DSpaceObject dso; + private BrowsableDSpaceObject dso; private Map> highlightResults; + private Map> highlightResultsWithAuthority; - public DSpaceObjectHighlightResult(DSpaceObject dso, Map> highlightResults) { + public DSpaceObjectHighlightResult(BrowsableDSpaceObject dso, Map> highlightResults, + Map> highlightResultsWithAuthority) { this.dso = dso; this.highlightResults = highlightResults; + this.highlightResultsWithAuthority = highlightResultsWithAuthority; } - public DSpaceObject getDso() { + public BrowsableDSpaceObject getDso() { return dso; } @@ -194,12 +238,16 @@ public class DiscoverResult { return highlightResults.get(metadataKey); } + public List getHighlightResultsWithAuthority(String metadataKey) { + return highlightResultsWithAuthority.get(metadataKey); + } + public Map> getHighlightResults() { return highlightResults; } } - public void addSearchDocument(DSpaceObject dso, SearchDocument searchDocument) { + public void addSearchDocument(BrowsableDSpaceObject dso, SearchDocument searchDocument) { String dsoString = SearchDocument.getDspaceObjectStringRepresentation(dso); List docs = searchDocuments.get(dsoString); if (docs == null) { @@ -212,10 +260,11 @@ public class DiscoverResult { /** * Returns all the sought after search document values * - * @param dso the dspace object we want our search documents for + * @param dso + * the dspace object we want our search documents for * @return the search documents list */ - public List getSearchDocument(DSpaceObject dso) { + public List getSearchDocument(BrowsableDSpaceObject dso) { String dsoString = SearchDocument.getDspaceObjectStringRepresentation(dso); List result = searchDocuments.get(dsoString); if (result == null) { @@ -256,7 +305,7 @@ public class DiscoverResult { } } - public static String getDspaceObjectStringRepresentation(DSpaceObject dso) { + public static String getDspaceObjectStringRepresentation(BrowsableDSpaceObject dso) { return dso.getType() + ":" + dso.getID(); } } diff --git a/dspace-api/src/main/java/org/dspace/discovery/FacetYearRange.java b/dspace-api/src/main/java/org/dspace/discovery/FacetYearRange.java index 311d1814c5..e6638ee0c5 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/FacetYearRange.java +++ b/dspace-api/src/main/java/org/dspace/discovery/FacetYearRange.java @@ -11,7 +11,7 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.dspace.content.DSpaceObject; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.core.Context; import org.dspace.discovery.configuration.DiscoverySearchFilterFacet; @@ -46,8 +46,8 @@ public class FacetYearRange { return oldestYear != -1 && newestYear != -1; } - public void calculateRange(Context context, List filterQueries, DSpaceObject scope, - SearchService searchService) throws SearchServiceException { + public void calculateRange(Context context, List filterQueries, BrowsableDSpaceObject scope, + SearchService searchService, DiscoverQuery parentQuery) throws SearchServiceException { dateFacet = facet.getIndexFieldName() + ".year"; //Get a range query so we can create facet queries ranging from our first to our last date //Attempt to determine our oldest & newest year by checking for previously selected filters @@ -55,7 +55,7 @@ public class FacetYearRange { //Check if we have found a range, if not then retrieve our first & last year using Solr if (oldestYear == -1 && newestYear == -1) { - calculateNewRangeBasedOnSearchIndex(context, filterQueries, scope, searchService); + calculateNewRangeBasedOnSearchIndex(context, filterQueries, scope, searchService, parentQuery); } } @@ -93,9 +93,11 @@ public class FacetYearRange { } } - private void calculateNewRangeBasedOnSearchIndex(Context context, List filterQueries, DSpaceObject scope, - SearchService searchService) throws SearchServiceException { + private void calculateNewRangeBasedOnSearchIndex(Context context, List filterQueries, + BrowsableDSpaceObject scope, SearchService searchService, + DiscoverQuery parentQuery) throws SearchServiceException { DiscoverQuery yearRangeQuery = new DiscoverQuery(); + yearRangeQuery.setDiscoveryConfigurationName(parentQuery.getDiscoveryConfigurationName()); yearRangeQuery.setMaxResults(1); //Set our query to anything that has this value yearRangeQuery.addFieldPresentQueries(dateFacet); diff --git a/dspace-api/src/main/java/org/dspace/discovery/IndexClient.java b/dspace-api/src/main/java/org/dspace/discovery/IndexClient.java index 1381e4dda2..eb3ca84e91 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/IndexClient.java +++ b/dspace-api/src/main/java/org/dspace/discovery/IndexClient.java @@ -7,9 +7,16 @@ */ package org.dspace.discovery; +import java.io.BufferedReader; +import java.io.DataInputStream; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStreamReader; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; +import java.util.UUID; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.HelpFormatter; @@ -17,12 +24,13 @@ import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.cli.PosixParser; import org.apache.logging.log4j.Logger; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.content.Collection; import org.dspace.content.Community; -import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.ItemService; +import org.dspace.core.ConfigurationManager; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.handle.factory.HandleServiceFactory; @@ -58,8 +66,8 @@ public class IndexClient { Context context = new Context(Context.Mode.READ_ONLY); context.turnOffAuthorisationSystem(); - String usage = "org.dspace.discovery.IndexClient [-cbhf] | [-r ] | [-i ] or nothing to " + - "update/clean an existing index."; + String usage = "org.dspace.discovery.IndexClient [-cbhf] | [-r ] | [-i ] | [-item_uuid " + + "] or nothing to update/clean an existing index."; Options options = new Options(); HelpFormatter formatter = new HelpFormatter(); CommandLine line = null; @@ -71,6 +79,9 @@ public class IndexClient { "remove an Item, Collection or Community from index based on its handle") .create("r")); + options.addOption(OptionBuilder.withArgName("item uuid to index").hasArg(true) + .withDescription("add an Item based on its uuid").create("item_uuid")); + options.addOption(OptionBuilder .withArgName("handle to add or update") .hasArg(true) @@ -78,6 +89,11 @@ public class IndexClient { "add or update an Item, Collection or Community based on its handle") .create("i")); + options.addOption(OptionBuilder.isRequired(false).hasArg(true) + .withDescription("update an Item, Collection or Community from index based on its handle, use with -f " + + "to force clean") + .create("u")); + options.addOption(OptionBuilder .isRequired(false) .withDescription( @@ -111,6 +127,8 @@ public class IndexClient { options.addOption(OptionBuilder.isRequired(false).withDescription( "optimize search core").create("o")); + options.addOption("e", "readfile", true, "Read the identifier from a file"); + try { line = new PosixParser().parse(options, args); } catch (Exception e) { @@ -150,10 +168,55 @@ public class IndexClient { indexer.optimize(); } else if (line.hasOption('s')) { checkRebuildSpellCheck(line, indexer); + } else if (line.hasOption("item_uuid")) { + String itemUUID = line.getOptionValue("item_uuid"); + Item item = ContentServiceFactory.getInstance().getItemService().find(context, UUID.fromString(itemUUID)); + indexer.indexContent(context, item, line.hasOption("f")); + } else if (line.hasOption("u")) { + String optionValue = line.getOptionValue("u"); + String[] identifiers = optionValue.split("\\s*,\\s*"); + for (String id : identifiers) { + if (id.startsWith(ConfigurationManager.getProperty("handle.prefix")) || id.startsWith("123456789/")) { + BrowsableDSpaceObject dso = (BrowsableDSpaceObject) HandleServiceFactory.getInstance() + .getHandleService().resolveToObject(context, id); + indexer.indexContent(context, dso, line.hasOption("f")); + } + } + } else if (line.hasOption('e')) { + try { + String filename = line.getOptionValue('e'); + FileInputStream fstream = new FileInputStream(filename); + // Get the object of DataInputStream + DataInputStream in = new DataInputStream(fstream); + BufferedReader br = new BufferedReader(new InputStreamReader(in)); + String strLine; + // Read File Line By Line + + UUID item_id = null; + List ids = new ArrayList(); + + while ((strLine = br.readLine()) != null) { + item_id = UUID.fromString(strLine.trim()); + ids.add(item_id); + } + + in.close(); + + int type = -1; + if (line.hasOption('t')) { + type = Integer.parseInt(line.getOptionValue("t")); + } else { + // force to item + type = Constants.ITEM; + } + indexer.updateIndex(context, ids, line.hasOption("f"), type); + } catch (Exception e) { + log.error("Error: " + e.getMessage()); + } } else if (line.hasOption('i')) { final String handle = line.getOptionValue('i'); - final DSpaceObject dso = HandleServiceFactory.getInstance().getHandleService() - .resolveToObject(context, handle); + final BrowsableDSpaceObject dso = (BrowsableDSpaceObject) HandleServiceFactory.getInstance() + .getHandleService().resolveToObject(context, handle); if (dso == null) { throw new IllegalArgumentException("Cannot resolve " + handle + " to a DSpace object"); } @@ -186,7 +249,7 @@ public class IndexClient { private static long indexAll(final IndexingService indexingService, final ItemService itemService, final Context context, - final DSpaceObject dso) + final BrowsableDSpaceObject dso) throws IOException, SearchServiceException, SQLException { long count = 0; diff --git a/dspace-api/src/main/java/org/dspace/discovery/IndexEventConsumer.java b/dspace-api/src/main/java/org/dspace/discovery/IndexEventConsumer.java index 9117dd7ad2..dda91ce23a 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/IndexEventConsumer.java +++ b/dspace-api/src/main/java/org/dspace/discovery/IndexEventConsumer.java @@ -11,6 +11,7 @@ import java.util.HashSet; import java.util.Set; import org.apache.logging.log4j.Logger; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.content.Bundle; import org.dspace.content.DSpaceObject; import org.dspace.core.Constants; @@ -33,10 +34,10 @@ public class IndexEventConsumer implements Consumer { private static Logger log = org.apache.logging.log4j.LogManager.getLogger(IndexEventConsumer.class); // collect Items, Collections, Communities that need indexing - private Set objectsToUpdate = null; + private Set objectsToUpdate = null; - // handles to delete since IDs are not useful by now. - private Set handlesToDelete = null; + // unique search IDs to delete + private Set uniqueIdsToDelete = null; IndexingService indexer = DSpaceServicesFactory.getInstance().getServiceManager() .getServiceByName(IndexingService.class.getName(), @@ -58,8 +59,8 @@ public class IndexEventConsumer implements Consumer { public void consume(Context ctx, Event event) throws Exception { if (objectsToUpdate == null) { - objectsToUpdate = new HashSet(); - handlesToDelete = new HashSet(); + objectsToUpdate = new HashSet(); + uniqueIdsToDelete = new HashSet(); } int st = event.getSubjectType(); @@ -107,7 +108,7 @@ public class IndexEventConsumer implements Consumer { + ", perhaps it has been deleted."); } else { log.debug("consume() adding event to update queue: " + event.toString()); - objectsToUpdate.add(subject); + objectsToUpdate.add((BrowsableDSpaceObject)subject); } break; @@ -120,17 +121,17 @@ public class IndexEventConsumer implements Consumer { + ", perhaps it has been deleted."); } else { log.debug("consume() adding event to update queue: " + event.toString()); - objectsToUpdate.add(object); + objectsToUpdate.add((BrowsableDSpaceObject)object); } break; case Event.DELETE: - String detail = event.getDetail(); - if (detail == null) { - log.warn("got null detail on DELETE event, skipping it."); + if (event.getSubjectType() == -1 || event.getSubjectID() == null) { + log.warn("got null subject type and/or ID on DELETE event, skipping it."); } else { + String detail = event.getSubjectType() + "-" + event.getSubjectID().toString(); log.debug("consume() adding event to delete queue: " + event.toString()); - handlesToDelete.add(detail); + uniqueIdsToDelete.add(detail); } break; default: @@ -151,37 +152,37 @@ public class IndexEventConsumer implements Consumer { @Override public void end(Context ctx) throws Exception { - if (objectsToUpdate != null && handlesToDelete != null) { + if (objectsToUpdate != null && uniqueIdsToDelete != null) { // update the changed Items not deleted because they were on create list - for (DSpaceObject o : objectsToUpdate) { + for (BrowsableDSpaceObject iu : objectsToUpdate) { /* we let all types through here and * allow the search indexer to make * decisions on indexing and/or removal */ - DSpaceObject iu = ctx.reloadEntity(o); - String hdl = iu.getHandle(); - if (hdl != null && !handlesToDelete.contains(hdl)) { + // iu = ctx.reloadEntity(o); + String uniqueIndexID = iu.getUniqueIndexID(); + if (uniqueIndexID != null && !uniqueIdsToDelete.contains(uniqueIndexID)) { try { - indexer.indexContent(ctx, iu, true); + indexer.indexContent(ctx, iu, true, true); log.debug("Indexed " + Constants.typeText[iu.getType()] + ", id=" + String.valueOf(iu.getID()) - + ", handle=" + hdl); + + ", unique_id=" + uniqueIndexID); } catch (Exception e) { log.error("Failed while indexing object: ", e); } } } - for (String hdl : handlesToDelete) { + for (String uid : uniqueIdsToDelete) { try { - indexer.unIndexContent(ctx, hdl, true); + indexer.unIndexContent(ctx, uid, true); if (log.isDebugEnabled()) { - log.debug("UN-Indexed Item, handle=" + hdl); + log.debug("UN-Indexed Item, handle=" + uid); } } catch (Exception e) { - log.error("Failed while UN-indexing object: " + hdl, e); + log.error("Failed while UN-indexing object: " + uid, e); } } @@ -190,7 +191,7 @@ public class IndexEventConsumer implements Consumer { // "free" the resources objectsToUpdate = null; - handlesToDelete = null; + uniqueIdsToDelete = null; } @Override diff --git a/dspace-api/src/main/java/org/dspace/discovery/IndexingService.java b/dspace-api/src/main/java/org/dspace/discovery/IndexingService.java index eaa885edf4..38c35802df 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/IndexingService.java +++ b/dspace-api/src/main/java/org/dspace/discovery/IndexingService.java @@ -9,12 +9,14 @@ package org.dspace.discovery; import java.io.IOException; import java.sql.SQLException; +import java.util.List; +import java.util.UUID; -import org.dspace.content.DSpaceObject; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.core.Context; /** - * Interface used for indexing dspaceobject into discovery + * Interface used for indexing BrowsableDSpaceObject into discovery * * @author Kevin Van de Velde (kevin at atmire dot com) * @author Mark Diggory (markd at atmire dot com) @@ -22,28 +24,28 @@ import org.dspace.core.Context; */ public interface IndexingService { - void indexContent(Context context, DSpaceObject dso) + void indexContent(Context context, BrowsableDSpaceObject dso) throws SQLException; - void indexContent(Context context, DSpaceObject dso, + void indexContent(Context context, BrowsableDSpaceObject dso, boolean force) throws SQLException; - void indexContent(Context context, DSpaceObject dso, + void indexContent(Context context, BrowsableDSpaceObject dso, boolean force, boolean commit) throws SQLException, SearchServiceException; - void unIndexContent(Context context, DSpaceObject dso) + void unIndexContent(Context context, BrowsableDSpaceObject dso) throws SQLException, IOException; - void unIndexContent(Context context, DSpaceObject dso, boolean commit) + void unIndexContent(Context context, BrowsableDSpaceObject dso, boolean commit) throws SQLException, IOException; - void unIndexContent(Context context, String handle) - throws SQLException, IOException; + void unIndexContent(Context context, String uniqueSearchID) + throws IOException; - void unIndexContent(Context context, String handle, boolean commit) - throws SQLException, IOException; + void unIndexContent(Context context, String uniqueSearchID, boolean commit) + throws IOException; - void reIndexContent(Context context, DSpaceObject dso) + void reIndexContent(Context context, BrowsableDSpaceObject dso) throws SQLException, IOException; void createIndex(Context context) throws SQLException, IOException; @@ -52,9 +54,16 @@ public interface IndexingService { void updateIndex(Context context, boolean force); + void updateIndex(Context context, boolean force, int type); + + void updateIndex(Context context, List ids, boolean force, int type); + void cleanIndex(boolean force) throws IOException, SQLException, SearchServiceException; + void cleanIndex(boolean force, int type) throws IOException, + SQLException, SearchServiceException; + void commit() throws SearchServiceException; void optimize() throws SearchServiceException; diff --git a/dspace-api/src/main/java/org/dspace/discovery/SearchService.java b/dspace-api/src/main/java/org/dspace/discovery/SearchService.java index a955234e1e..9b246045e5 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SearchService.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SearchService.java @@ -7,11 +7,10 @@ */ package org.dspace.discovery; -import java.io.InputStream; import java.sql.SQLException; import java.util.List; -import org.dspace.content.DSpaceObject; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.content.Item; import org.dspace.core.Context; import org.dspace.discovery.configuration.DiscoveryMoreLikeThisConfiguration; @@ -50,7 +49,7 @@ public interface SearchService { * @return discovery search result object * @throws SearchServiceException if search error */ - DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery query) + DiscoverResult search(Context context, BrowsableDSpaceObject dso, DiscoverQuery query) throws SearchServiceException; /** @@ -74,19 +73,11 @@ public interface SearchService { * @return discovery search result object * @throws SearchServiceException if search error */ - DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery query, boolean includeWithdrawn) + DiscoverResult search(Context context, BrowsableDSpaceObject dso, DiscoverQuery query, boolean includeWithdrawn) throws SearchServiceException; - - InputStream searchJSON(Context context, DiscoverQuery query, String jsonIdentifier) throws SearchServiceException; - - InputStream searchJSON(Context context, DiscoverQuery query, DSpaceObject dso, String jsonIdentifier) - throws SearchServiceException; - - - List search(Context context, String query, String orderfield, boolean ascending, int offset, int max, - String... filterquery); - + List search(Context context, String query, String orderfield, boolean ascending, int offset, + int max, String... filterquery); /** * Transforms the given string field and value into a filter query @@ -138,8 +129,9 @@ public interface SearchService { */ String escapeQueryChars(String query); - FacetYearRange getFacetYearRange(Context context, DSpaceObject scope, DiscoverySearchFilterFacet facet, - List filterQueries) throws SearchServiceException; + FacetYearRange getFacetYearRange(Context context, BrowsableDSpaceObject scope, DiscoverySearchFilterFacet facet, + List filterQueries, DiscoverQuery parentQuery) + throws SearchServiceException; /** * This method returns us either the highest or lowest value for the field that we give to it diff --git a/dspace-api/src/main/java/org/dspace/discovery/SearchUtils.java b/dspace-api/src/main/java/org/dspace/discovery/SearchUtils.java index aa465dd1bc..a83891ea25 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SearchUtils.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SearchUtils.java @@ -8,6 +8,7 @@ package org.dspace.discovery; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -16,10 +17,12 @@ import java.util.Map; import org.dspace.content.Collection; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; +import org.dspace.content.WorkspaceItem; import org.dspace.discovery.configuration.DiscoveryConfiguration; import org.dspace.discovery.configuration.DiscoveryConfigurationService; import org.dspace.kernel.ServiceManager; import org.dspace.services.factory.DSpaceServicesFactory; +import org.dspace.workflow.WorkflowItem; /** * Util methods used by discovery @@ -48,13 +51,26 @@ public class SearchUtils { } public static DiscoveryConfiguration getDiscoveryConfiguration() { - return getDiscoveryConfiguration(null); + return getDiscoveryConfiguration(null, null); } public static DiscoveryConfiguration getDiscoveryConfiguration(DSpaceObject dso) { + return getDiscoveryConfiguration(null, dso); + } + + public static DiscoveryConfiguration getDiscoveryConfiguration(String prefix, DSpaceObject dso) { + if (prefix != null) { + return getDiscoveryConfigurationByName(dso != null ? prefix + "." + dso.getHandle() : prefix); + } else { + return getDiscoveryConfigurationByName(dso != null ? dso.getHandle() : null); + } + } + + public static DiscoveryConfiguration getDiscoveryConfigurationByName( + String configurationName) { DiscoveryConfigurationService configurationService = getConfigurationService(); - return configurationService.getDiscoveryConfiguration(dso); + return configurationService.getDiscoveryConfiguration(configurationName); } public static DiscoveryConfigurationService getConfigurationService() { @@ -76,23 +92,45 @@ public class SearchUtils { * @throws SQLException An exception that provides information on a database access error or other errors. */ public static List getAllDiscoveryConfigurations(Item item) throws SQLException { + List collections = item.getCollections(); + return getAllDiscoveryConfigurations(null, collections, item); + } + + public static List getAllDiscoveryConfigurations(WorkspaceItem witem) throws SQLException { + List collections = new ArrayList(); + collections.add(witem.getCollection()); + return getAllDiscoveryConfigurations("workspace", collections, witem.getItem()); + } + + public static List getAllDiscoveryConfigurations(WorkflowItem witem) throws SQLException { + List collections = new ArrayList(); + collections.add(witem.getCollection()); + return getAllDiscoveryConfigurations("workflow", collections, witem.getItem()); + } + + private static List getAllDiscoveryConfigurations(String prefix, + List collections, Item item) + throws SQLException { Map result = new HashMap(); - List collections = item.getCollections(); for (Collection collection : collections) { - DiscoveryConfiguration configuration = getDiscoveryConfiguration(collection); + DiscoveryConfiguration configuration = getDiscoveryConfiguration(prefix, collection); if (!result.containsKey(configuration.getId())) { result.put(configuration.getId(), configuration); } } //Also add one for the default - DiscoveryConfiguration configuration = getDiscoveryConfiguration(null); - if (!result.containsKey(configuration.getId())) { - result.put(configuration.getId(), configuration); - } + addConfigurationIfExists(result, prefix); return Arrays.asList(result.values().toArray(new DiscoveryConfiguration[result.size()])); } + private static void addConfigurationIfExists(Map result, String confName) { + DiscoveryConfiguration configurationExtra = getDiscoveryConfigurationByName(confName); + if (!result.containsKey(configurationExtra.getId())) { + result.put(configurationExtra.getId(), configurationExtra); + } + } + } diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceContentInOriginalBundleFilterPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceContentInOriginalBundleFilterPlugin.java index c43b0e6245..737ec63770 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceContentInOriginalBundleFilterPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceContentInOriginalBundleFilterPlugin.java @@ -10,9 +10,9 @@ package org.dspace.discovery; import java.util.List; import org.apache.solr.common.SolrInputDocument; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; -import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.core.Context; @@ -30,7 +30,7 @@ import org.dspace.core.Context; public class SolrServiceContentInOriginalBundleFilterPlugin implements SolrServiceIndexPlugin { @Override - public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument document) { + public void additionalIndex(Context context, BrowsableDSpaceObject dso, SolrInputDocument document) { if (dso instanceof Item) { Item item = (Item) dso; boolean hasOriginalBundleWithContent = hasOriginalBundleWithContent(item); diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceFileInfoPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceFileInfoPlugin.java index 979c577b2b..226044b8c6 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceFileInfoPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceFileInfoPlugin.java @@ -10,9 +10,9 @@ package org.dspace.discovery; import java.util.List; import org.apache.solr.common.SolrInputDocument; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; -import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.core.Context; @@ -41,7 +41,7 @@ public class SolrServiceFileInfoPlugin implements SolrServiceIndexPlugin { private static final String SOLR_FIELD_NAME_FOR_DESCRIPTIONS = "original_bundle_descriptions"; @Override - public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument document) { + public void additionalIndex(Context context, BrowsableDSpaceObject dso, SolrInputDocument document) { if (dso instanceof Item) { Item item = (Item) dso; List bundles = item.getBundles(); diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java index 9a19bf0646..3d6685a0c8 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java @@ -10,8 +10,8 @@ package org.dspace.discovery; import static org.dspace.discovery.configuration.DiscoverySortConfiguration.SCORE; import java.io.IOException; -import java.io.InputStream; import java.io.PrintWriter; +import java.io.Serializable; import java.io.StringWriter; import java.sql.SQLException; import java.text.ParseException; @@ -33,6 +33,10 @@ import java.util.Set; import java.util.TimeZone; import java.util.UUID; import java.util.Vector; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.google.common.collect.ImmutableList; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; @@ -41,12 +45,6 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.commons.validator.routines.UrlValidator; -import org.apache.http.HttpResponse; -import org.apache.http.NameValuePair; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.message.BasicNameValuePair; import org.apache.logging.log4j.Logger; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrRequest; @@ -61,7 +59,6 @@ import org.apache.solr.client.solrj.util.ClientUtils; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrInputDocument; -import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.FacetParams; import org.apache.solr.common.params.HighlightParams; import org.apache.solr.common.params.ModifiableSolrParams; @@ -69,8 +66,10 @@ import org.apache.solr.common.params.MoreLikeThisParams; import org.apache.solr.common.params.SpellingParams; import org.apache.solr.common.util.NamedList; import org.apache.solr.handler.extraction.ExtractingParams; +import org.dspace.app.util.Util; import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.factory.AuthorizeServiceFactory; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.DSpaceObject; @@ -78,6 +77,7 @@ import org.dspace.content.Item; import org.dspace.content.MetadataField; import org.dspace.content.MetadataSchema; import org.dspace.content.MetadataValue; +import org.dspace.content.WorkspaceItem; import org.dspace.content.authority.Choices; import org.dspace.content.authority.service.ChoiceAuthorityService; import org.dspace.content.authority.service.MetadataAuthorityService; @@ -85,6 +85,7 @@ import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.CollectionService; import org.dspace.content.service.CommunityService; import org.dspace.content.service.ItemService; +import org.dspace.content.service.WorkspaceItemService; import org.dspace.core.ConfigurationManager; import org.dspace.core.Constants; import org.dspace.core.Context; @@ -108,6 +109,15 @@ import org.dspace.handle.service.HandleService; import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.storage.rdbms.DatabaseUtils; import org.dspace.util.MultiFormatDateParser; +import org.dspace.workflow.WorkflowItem; +import org.dspace.xmlworkflow.WorkflowConfigurationException; +import org.dspace.xmlworkflow.factory.XmlWorkflowFactory; +import org.dspace.xmlworkflow.storedcomponents.ClaimedTask; +import org.dspace.xmlworkflow.storedcomponents.PoolTask; +import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; +import org.dspace.xmlworkflow.storedcomponents.service.ClaimedTaskService; +import org.dspace.xmlworkflow.storedcomponents.service.PoolTaskService; +import org.dspace.xmlworkflow.storedcomponents.service.XmlWorkflowItemService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -138,6 +148,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { protected static final String LAST_INDEXED_FIELD = "SolrIndexer.lastIndexed"; protected static final String HANDLE_FIELD = "handle"; + protected static final String RESOURCE_UNIQUE_ID = "search.uniqueid"; protected static final String RESOURCE_TYPE_FIELD = "search.resourcetype"; protected static final String RESOURCE_ID_FIELD = "search.resourceid"; @@ -149,6 +160,8 @@ public class SolrServiceImpl implements SearchService, IndexingService { public static final String VARIANTS_STORE_SEPARATOR = "###"; + private static final String REGEX = "\\S+(?:\\s*\\|\\|\\|(\\s*\\S+))+"; + @Autowired(required = true) protected ContentServiceFactory contentServiceFactory; @Autowired(required = true) @@ -163,6 +176,16 @@ public class SolrServiceImpl implements SearchService, IndexingService { protected HandleService handleService; @Autowired(required = true) protected MetadataAuthorityService metadataAuthorityService; + @Autowired(required = true) + protected WorkspaceItemService workspaceItemService; + @Autowired(required = true) + protected XmlWorkflowItemService workflowItemService; + @Autowired(required = true) + protected ClaimedTaskService claimedTaskService; + @Autowired(required = true) + protected PoolTaskService poolTaskService; + @Autowired(required = true) + protected XmlWorkflowFactory workflowFactory; /** * Non-Static SolrServer for processing indexing events. @@ -221,7 +244,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { * @throws SQLException if error */ @Override - public void indexContent(Context context, DSpaceObject dso) + public void indexContent(Context context, BrowsableDSpaceObject dso) throws SQLException { indexContent(context, dso, false); } @@ -237,16 +260,11 @@ public class SolrServiceImpl implements SearchService, IndexingService { * @throws SQLException if error */ @Override - public void indexContent(Context context, DSpaceObject dso, + public void indexContent(Context context, BrowsableDSpaceObject dso, boolean force) throws SQLException { - String handle = dso.getHandle(); - - if (handle == null) { - handle = handleService.findHandle(context, dso); - } - try { + String uuid = dso.getID().toString(); switch (dso.getType()) { case Constants.ITEM: Item item = (Item) dso; @@ -254,29 +272,33 @@ public class SolrServiceImpl implements SearchService, IndexingService { /** * If the item is in the repository now, add it to the index */ - if (requiresIndexing(handle, ((Item) dso).getLastModified()) - || force) { - unIndexContent(context, handle); + if (force || requiresIndexing(dso.getUniqueIndexID(), ((Item) dso).getLastModified())) { + unIndexContent(context, dso); buildDocument(context, (Item) dso); } } else { /** * Make sure the item is not in the index if it is not in - * archive or withwrawn. + * archive or withdrawn. */ - unIndexContent(context, item); - log.info("Removed Item: " + handle + " from Index"); + unIndexContent(context, dso); + log.info("Removed Item: " + uuid + " from Index"); + + /** + * reindex any in progress submission tasks associated with the item + */ + indexInProgressSubmissionItem(context, (Item) dso); } break; case Constants.COLLECTION: buildDocument(context, (Collection) dso); - log.info("Wrote Collection: " + handle + " to Index"); + log.info("Wrote Collection: " + uuid + " to Index"); break; case Constants.COMMUNITY: buildDocument(context, (Community) dso); - log.info("Wrote Community: " + handle + " to Index"); + log.info("Wrote Community: " + uuid + " to Index"); break; default: @@ -298,7 +320,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { * @throws IOException if IO error */ @Override - public void unIndexContent(Context context, DSpaceObject dso) + public void unIndexContent(Context context, BrowsableDSpaceObject dso) throws SQLException, IOException { unIndexContent(context, dso, false); } @@ -307,20 +329,24 @@ public class SolrServiceImpl implements SearchService, IndexingService { * unIndex removes an Item, Collection, or Community * * @param context The relevant DSpace Context. - * @param dso DSpace Object, can be Community, Item, or Collection + * @param dso extension of DSpace Object, can be Community, Item, Collection or InProgressSubmission * @param commit if true force an immediate commit on SOLR * @throws SQLException if database error * @throws IOException if IO error */ @Override - public void unIndexContent(Context context, DSpaceObject dso, boolean commit) + public void unIndexContent(Context context, BrowsableDSpaceObject dso, boolean commit) throws SQLException, IOException { try { if (dso == null) { return; } - String uniqueID = dso.getType() + "-" + dso.getID(); + String uniqueID = dso.getUniqueIndexID(); + log.debug("Try to delete uniqueID:" + uniqueID); getSolr().deleteById(uniqueID); + if (Constants.ITEM == dso.getType()) { + deleteInProgressSubmissionByItemID(uniqueID); + } if (commit) { getSolr().commit(); } @@ -332,32 +358,33 @@ public class SolrServiceImpl implements SearchService, IndexingService { /** * Unindex a Document in the Lucene index. - * + * * @param context the dspace context - * @param handle the handle of the object to be deleted + * @param searchUniqueID the search uniqueID of the document to be deleted * @throws IOException if IO error - * @throws SQLException if database error */ @Override - public void unIndexContent(Context context, String handle) throws IOException, SQLException { - unIndexContent(context, handle, false); + public void unIndexContent(Context context, String searchUniqueID) throws IOException { + unIndexContent(context, searchUniqueID, false); } /** * Unindex a Document in the Lucene Index. - * + * * @param context the dspace context - * @param handle the handle of the object to be deleted - * @throws SQLException if database error + * @param searchUniqueID the search uniqueID of the document to be deleted * @throws IOException if IO error */ @Override - public void unIndexContent(Context context, String handle, boolean commit) - throws SQLException, IOException { + public void unIndexContent(Context context, String searchUniqueID, boolean commit) + throws IOException { try { if (getSolr() != null) { - getSolr().deleteByQuery(HANDLE_FIELD + ":\"" + handle + "\""); + getSolr().deleteById(searchUniqueID); + if (searchUniqueID.startsWith(Constants.ITEM + "-")) { + deleteInProgressSubmissionByItemID(searchUniqueID); + } if (commit) { getSolr().commit(); } @@ -374,7 +401,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { * @param dso object to re-index */ @Override - public void reIndexContent(Context context, DSpaceObject dso) + public void reIndexContent(Context context, BrowsableDSpaceObject dso) throws SQLException, IOException { try { indexContent(context, dso); @@ -425,23 +452,44 @@ public class SolrServiceImpl implements SearchService, IndexingService { */ @Override public void updateIndex(Context context, boolean force) { + updateIndex(context, force, Constants.ITEM); + updateIndex(context, force, Constants.COLLECTION); + updateIndex(context, force, Constants.COMMUNITY); + } + + + public void updateIndex(Context context, List ids, boolean force, int type) { + if (type != Constants.ITEM) { + throw new RuntimeException("Only ITEM is supported in this mode - type founded: " + type); + } try { - Iterator items = null; - for (items = itemService.findAllUnfiltered(context); items.hasNext(); ) { - Item item = items.next(); - indexContent(context, item, force); - //To prevent memory issues, discard an object from the cache after processing - context.uncacheEntity(item); - } + startMultiThreadIndex(context, force, ids); + } catch (SQLException e) { + log.error(e.getMessage(), e); + } + } - List collections = collectionService.findAll(context); - for (Collection collection : collections) { - indexContent(context, collection, force); - } - - List communities = communityService.findAll(context); - for (Community community : communities) { - indexContent(context, community, force); + @Override + public void updateIndex(Context context, boolean force, int type) { + try { + switch (type) { + case Constants.ITEM: + startMultiThreadIndex(context, force, null); + break; + case Constants.COLLECTION: + List collections = collectionService.findAll(context); + for (Collection collection : collections) { + indexContent(context, collection, force); + } + break; + case Constants.COMMUNITY: + List communities = communityService.findAll(context); + for (Community community : communities) { + indexContent(context, community, force); + } + break; + default: + throw new RuntimeException("No type known: " + type); } if (getSolr() != null) { @@ -453,6 +501,40 @@ public class SolrServiceImpl implements SearchService, IndexingService { } } + private void startMultiThreadIndex(Context context, boolean force, List ids) throws SQLException { + int numThreads = ConfigurationManager.getIntProperty("discovery", "indexer.items.threads", 5); + + if (ids == null) { + ids = new ArrayList<>(); + Iterator items = itemService.findAllUnfiltered(context); + for (Item item : ImmutableList.copyOf(items)) { + ids.add(item.getID()); + } + + for (WorkspaceItem wsi : workspaceItemService.findAll(context)) { + ids.add(wsi.getItem().getID()); + } + + for (WorkflowItem wfi : workflowItemService.findAll(context)) { + ids.add(wfi.getItem().getID()); + } + } + List[] arrayIDList = Util.splitList(ids, numThreads); + List threads = new ArrayList(); + for (List hl : arrayIDList) { + IndexerThread thread = new IndexerThread(hl, force); + thread.start(); + threads.add(thread); + } + boolean finished = false; + while (!finished) { + finished = true; + for (IndexerThread thread : threads) { + finished = finished && !thread.isAlive(); + } + } + } + /** * Iterates over all documents in the Lucene index and verifies they are in * database, if not, they are removed. @@ -463,9 +545,27 @@ public class SolrServiceImpl implements SearchService, IndexingService { * @throws SearchServiceException occurs when something went wrong with querying the solr server */ @Override - public void cleanIndex(boolean force) throws IOException, - SQLException, SearchServiceException { + public void cleanIndex(boolean force) throws IOException, SQLException, SearchServiceException { + if (force) { + try { + getSolr().deleteByQuery( + "search.resourcetype:[" + Constants.ITEM + " TO " + Constants.WORKFLOW_CLAIMED + "]"); + } catch (Exception e) { + throw new SearchServiceException(e.getMessage(), e); + } + } else { + cleanIndex(false, Constants.ITEM); + cleanIndex(false, Constants.COLLECTION); + cleanIndex(false, Constants.COMMUNITY); + cleanIndex(false, Constants.WORKSPACEITEM); + cleanIndex(false, Constants.WORKFLOW_POOL); + cleanIndex(false, Constants.WORKFLOW_CLAIMED); + cleanIndex(false, Constants.WORKFLOWITEM); + } + } + @Override + public void cleanIndex(boolean force, int type) throws IOException, SQLException, SearchServiceException { Context context = new Context(); context.turnOffAuthorisationSystem(); @@ -474,13 +574,13 @@ public class SolrServiceImpl implements SearchService, IndexingService { return; } if (force) { - getSolr().deleteByQuery(RESOURCE_TYPE_FIELD + ":[2 TO 4]"); + getSolr().deleteByQuery(RESOURCE_TYPE_FIELD + ":" + type); } else { SolrQuery query = new SolrQuery(); // Query for all indexed Items, Collections and Communities, // returning just their handle query.setFields(HANDLE_FIELD); - query.setQuery(RESOURCE_TYPE_FIELD + ":[2 TO 4]"); + query.setQuery(RESOURCE_TYPE_FIELD + ":" + type); QueryResponse rsp = getSolr().query(query, SolrRequest.METHOD.POST); SolrDocumentList docs = rsp.getResults(); @@ -489,30 +589,27 @@ public class SolrServiceImpl implements SearchService, IndexingService { SolrDocument doc = (SolrDocument) iter.next(); - String handle = (String) doc.getFieldValue(HANDLE_FIELD); + String uniqueID = (String) doc.getFieldValue(RESOURCE_UNIQUE_ID); - DSpaceObject o = handleService.resolveToObject(context, handle); + BrowsableDSpaceObject o = findDSpaceObject(context, doc); if (o == null) { - log.info("Deleting: " + handle); + log.info("Deleting: " + uniqueID); /* * Use IndexWriter to delete, its easier to manage * write.lock */ - unIndexContent(context, handle); + unIndexContent(context, uniqueID); } else { - log.debug("Keeping: " + handle); + log.debug("Keeping: " + o.getUniqueIndexID()); } } } } catch (Exception e) { - - throw new SearchServiceException(e.getMessage(), e); + log.error("Error cleaning discovery index: " + e.getMessage(), e); } finally { context.abort(); } - - } /** @@ -615,7 +712,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { boolean inIndex = false; SolrQuery query = new SolrQuery(); - query.setQuery(HANDLE_FIELD + ":" + handle); + query.setQuery(RESOURCE_UNIQUE_ID + ":" + handle); // Specify that we ONLY want the LAST_INDEXED_FIELD returned in the field list (fl) query.setFields(LAST_INDEXED_FIELD); QueryResponse rsp; @@ -692,6 +789,19 @@ public class SolrServiceImpl implements SearchService, IndexingService { return locations; } + protected List getCommunityLocations(Community target) throws SQLException { + List locations = new Vector(); + // build list of community ids + List communities = target.getParentCommunities(); + + // now put those into strings + for (Community community : communities) { + locations.add("m" + community.getID()); + } + + return locations; + } + @Override public String createLocationQueryForAdministrableItems(Context context) throws SQLException { @@ -807,9 +917,12 @@ public class SolrServiceImpl implements SearchService, IndexingService { */ protected void buildDocument(Context context, Community community) throws SQLException, IOException { + + List locations = getCommunityLocations(community); + // Create Document SolrInputDocument doc = buildDocument(Constants.COMMUNITY, community.getID(), - community.getHandle(), null); + community.getHandle(), locations); DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration(community); DiscoveryHitHighlightingConfiguration highlightingConfiguration = discoveryConfiguration @@ -963,20 +1076,55 @@ public class SolrServiceImpl implements SearchService, IndexingService { doc.addField("discoverable", item.isDiscoverable()); doc.addField("lastModified", item.getLastModified()); + if (item.getSubmitter() != null) { + doc.addField("submitter", item.getSubmitter().getID()); + } + + List discoveryConfigurations = SearchUtils.getAllDiscoveryConfigurations(item); + addDiscoveryFields(doc, context, item, discoveryConfigurations); + + //mandatory facet to show status on mydspace + final String typeText = StringUtils.deleteWhitespace(item.getTypeText().toLowerCase()); + String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService().getProperty( + "discovery.facet.namedtype." + typeText, + typeText + SolrServiceImpl.AUTHORITY_SEPARATOR + typeText); + if (StringUtils.isNotBlank(acvalue)) { + String fvalue = acvalue; + addNamedResourceTypeIndex(doc, acvalue, fvalue); + } + + // write the index and close the inputstreamreaders + try { + writeDocument(doc, new FullTextContentStreams(context, item)); + log.info("Wrote Item: " + handle + " to Index"); + } catch (RuntimeException e) { + log.error("Error while writing item to discovery index: " + handle + " message:" + e.getMessage(), e); + } + } + + protected void addDiscoveryFields(SolrInputDocument doc, Context context, Item item, + List discoveryConfigurations) + throws SQLException, IOException { //Keep a list of our sort values which we added, sort values can only be added once List sortFieldsAdded = new ArrayList(); + Map> searchFilters = null; Set hitHighlightingFields = new HashSet(); try { - List discoveryConfigurations = SearchUtils.getAllDiscoveryConfigurations(item); - //A map used to save each sidebarFacet config by the metadata fields - Map> searchFilters = new HashMap>(); + searchFilters = new HashMap>(); Map sortFields = new HashMap(); Map recentSubmissionsConfigurationMap = new HashMap(); Set moreLikeThisFields = new HashSet(); + // some configuration are returned multiple times, skip them to save CPU cycles + Set appliedConf = new HashSet(); for (DiscoveryConfiguration discoveryConfiguration : discoveryConfigurations) { + if (appliedConf.contains(discoveryConfiguration.getId())) { + continue; + } else { + appliedConf.add(discoveryConfiguration.getId()); + } for (int i = 0; i < discoveryConfiguration.getSearchFilters().size(); i++) { List metadataValueList = new LinkedList<>(); @@ -1289,7 +1437,6 @@ public class SolrServiceImpl implements SearchService, IndexingService { doc.addField(indexField + "_sort", yearUTC); } } - } else if (searchFilter.getType() .equals(DiscoveryConfigurationParameters.TYPE_HIERARCHICAL)) { HierarchicalSidebarFacetConfiguration hierarchicalSidebarFacetConfiguration = @@ -1350,7 +1497,11 @@ public class SolrServiceImpl implements SearchService, IndexingService { if (hitHighlightingFields.contains(field) || hitHighlightingFields .contains("*") || hitHighlightingFields.contains(unqualifiedField + "." + Item.ANY)) { - doc.addField(field + "_hl", value); + if (authority != null) { + doc.addField(field + "_hl", value + "###" + authority); + } else { + doc.addField(field + "_hl", value); + } } if (moreLikeThisFields.contains(field) || moreLikeThisFields @@ -1359,6 +1510,9 @@ public class SolrServiceImpl implements SearchService, IndexingService { } doc.addField(field, value); + if (authority != null) { + doc.addField(field + "_authority", authority); + } if (toProjectionFields.contains(field) || toProjectionFields .contains(unqualifiedField + "." + Item.ANY)) { StringBuffer variantsToStore = new StringBuffer(); @@ -1422,13 +1576,150 @@ public class SolrServiceImpl implements SearchService, IndexingService { for (SolrServiceIndexPlugin solrServiceIndexPlugin : solrServiceIndexPlugins) { solrServiceIndexPlugin.additionalIndex(context, item, doc); } + } - // write the index and close the inputstreamreaders - try { - writeDocument(doc, new FullTextContentStreams(context, item)); - log.info("Wrote Item: " + handle + " to Index"); - } catch (RuntimeException e) { - log.error("Error while writing item to discovery index: " + handle + " message:" + e.getMessage(), e); + private void deleteInProgressSubmissionByItemID(String uniqueID) throws SolrServerException, IOException { + String query = "inprogress.item:\"" + uniqueID + "\""; + log.debug("Try to delete all in progress submission [DELETEBYQUERY]:" + query); + getSolr().deleteByQuery(query); + } + + private void addFacetIndex(SolrInputDocument document, String field, String authority, String fvalue) { + + String acvalue = fvalue + SolrServiceImpl.AUTHORITY_SEPARATOR + authority; + document.addField(field + "_filter", acvalue); + document.addField(field + "_authority", authority); + document.addField(field + "_ac", fvalue); + } + + private void indexInProgressSubmissionItem(Context context, Item item) + throws SQLException, IOException, SolrServerException, WorkflowConfigurationException { + XmlWorkflowItem workflowItem = workflowItemService.findByItem(context, item); + if (workflowItem == null) { + WorkspaceItem workspaceItem = workspaceItemService.findByItem(context, item); + if (workspaceItem == null) { + // mmm... it could be a template item, skip it + return; + } + // workspaceitem + List locations = getCollectionLocations(context, workspaceItem.getCollection()); + SolrInputDocument doc = new SolrInputDocument(); + + doc.addField("lastModified", item.getLastModified()); + if (workspaceItem.getSubmitter() != null) { + doc.addField("read", "ws" + workspaceItem.getSubmitter().getID()); + } + + List discoveryConfigurations = SearchUtils + .getAllDiscoveryConfigurations(workspaceItem); + addDiscoveryFields(doc, context, item, discoveryConfigurations); + addBasicInfoToDocument(doc, Constants.WORKSPACEITEM, workspaceItem.getID(), null, locations); + + String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService() + .getProperty("discovery.facet.namedtype.workspace"); + if (StringUtils.isBlank(acvalue)) { + acvalue = workspaceItem.getTypeText(); + } + String fvalue = acvalue; + addNamedResourceTypeIndex(doc, acvalue, fvalue); + doc.addField("inprogress.item", item.getUniqueIndexID()); + + getSolr().add(doc); + } else { + // so it is an item in the workflow + // get the location string (for searching by collection & community) + List locations = getCollectionLocations(context, workflowItem.getCollection()); + SolrInputDocument doc = new SolrInputDocument(); + + doc.addField("inprogress.item", item.getUniqueIndexID()); + doc.addField("lastModified", item.getLastModified()); + if (workflowItem.getSubmitter() != null) { + addFacetIndex(doc, "submitter", workflowItem.getSubmitter().getID().toString(), + workflowItem.getSubmitter().getFullName()); + } + + List discoveryConfigurations = SearchUtils + .getAllDiscoveryConfigurations(workflowItem); + addDiscoveryFields(doc, context, item, discoveryConfigurations); + + List claimedTasks = claimedTaskService.find(context, workflowItem); + List pools = poolTaskService.find(context, workflowItem); + + List docs = new ArrayList(); + + if (claimedTasks != null) { + for (ClaimedTask claimedTask : claimedTasks) { + SolrInputDocument claimDoc = doc.deepCopy(); + addBasicInfoToDocument(claimDoc, Constants.WORKFLOW_CLAIMED, claimedTask.getID(), null, locations); + claimDoc.addField("workflow.action", claimedTask.getActionID()); + claimDoc.addField("workflow.step", claimedTask.getStepID()); + claimDoc.addField("workflow.owner", claimedTask.getOwner().getID()); + claimDoc.addField("read", "we" + claimedTask.getOwner().getID().toString()); + + addFacetIndex(claimDoc, "action", claimedTask.getActionID(), claimedTask.getActionID()); + addFacetIndex(claimDoc, "task", claimedTask.getStepID(), claimedTask.getStepID()); + + String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService() + .getProperty("discovery.facet.namedtype.workflow.claimed"); + if (StringUtils.isBlank(acvalue)) { + acvalue = claimedTask.getTypeText(); + } + String fvalue = acvalue; + addNamedResourceTypeIndex(claimDoc, acvalue, fvalue); + + docs.add(claimDoc); + } + } + + if (pools != null) { + for (PoolTask poolTask : pools) { + SolrInputDocument claimDoc = doc.deepCopy(); + addBasicInfoToDocument(claimDoc, Constants.WORKFLOW_POOL, poolTask.getID(), null, locations); + claimDoc.addField("workflow.action", poolTask.getActionID()); + claimDoc.addField("workflow.step", poolTask.getStepID()); + addFacetIndex(claimDoc, "action", poolTask.getActionID(), poolTask.getActionID()); + addFacetIndex(claimDoc, "task", poolTask.getStepID(), poolTask.getStepID()); + + if (poolTask.getEperson() != null) { + claimDoc.addField("workflow.owner", poolTask.getEperson().getID()); + claimDoc.addField("read", "we" + poolTask.getEperson().getID().toString()); + } + if (poolTask.getGroup() != null) { + claimDoc.addField("workflow.group", poolTask.getGroup().getID()); + claimDoc.addField("read", "wg" + poolTask.getGroup().getID().toString()); + } + + String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService() + .getProperty("discovery.facet.namedtype.workflow.pooled"); + if (StringUtils.isBlank(acvalue)) { + acvalue = poolTask.getTypeText(); + } + String fvalue = acvalue; + addNamedResourceTypeIndex(claimDoc, acvalue, fvalue); + docs.add(claimDoc); + } + } + + String acvalue = DSpaceServicesFactory.getInstance().getConfigurationService() + .getProperty("discovery.facet.namedtype.workflow.item"); + if (StringUtils.isBlank(acvalue)) { + acvalue = workflowItem.getTypeText(); + } + String fvalue = acvalue; + addNamedResourceTypeIndex(doc, acvalue, fvalue); + + addBasicInfoToDocument(doc, Constants.WORKFLOWITEM, workflowItem.getID(), null, locations); + if (workflowItem.getSubmitter() != null) { + doc.addField("read", "ws" + workflowItem.getSubmitter().getID()); + } + docs.add(doc); + + if (docs.size() > 0) { + getSolr().add(docs); + } else { + // no tasks found?!? + log.error("No tasks found for workflowitem " + workflowItem.getID()); + } } } @@ -1444,14 +1735,19 @@ public class SolrServiceImpl implements SearchService, IndexingService { protected SolrInputDocument buildDocument(int type, UUID id, String handle, List locations) { SolrInputDocument doc = new SolrInputDocument(); + addBasicInfoToDocument(doc, type, id, handle, locations); + return doc; + } + private void addBasicInfoToDocument(SolrInputDocument doc, int type, Serializable id, String handle, + List locations) { // want to be able to check when last updated // (not tokenized, but it is indexed) doc.addField(LAST_INDEXED_FIELD, new Date()); // New fields to weaken the dependence on handles, and allow for faster // list display - doc.addField("search.uniqueid", type + "-" + id); + doc.addField(RESOURCE_UNIQUE_ID, type + "-" + id); doc.addField(RESOURCE_TYPE_FIELD, Integer.toString(type)); doc.addField(RESOURCE_ID_FIELD, id.toString()); @@ -1473,8 +1769,6 @@ public class SolrServiceImpl implements SearchService, IndexingService { } } } - - return doc; } /** @@ -1566,14 +1860,14 @@ public class SolrServiceImpl implements SearchService, IndexingService { } @Override - public DiscoverResult search(Context context, DSpaceObject dso, + public DiscoverResult search(Context context, BrowsableDSpaceObject dso, DiscoverQuery query) throws SearchServiceException { return search(context, dso, query, false); } @Override - public DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery discoveryQuery, + public DiscoverResult search(Context context, BrowsableDSpaceObject dso, DiscoverQuery discoveryQuery, boolean includeUnDiscoverable) throws SearchServiceException { if (dso != null) { if (dso instanceof Community) { @@ -1739,68 +2033,6 @@ public class SolrServiceImpl implements SearchService, IndexingService { return solrQuery; } - @Override - public InputStream searchJSON(Context context, DiscoverQuery query, DSpaceObject dso, String jsonIdentifier) - throws SearchServiceException { - if (dso != null) { - if (dso instanceof Community) { - query.addFilterQueries("location:m" + dso.getID()); - } else if (dso instanceof Collection) { - query.addFilterQueries("location:l" + dso.getID()); - } else if (dso instanceof Item) { - query.addFilterQueries(HANDLE_FIELD + ":" + dso.getHandle()); - } - } - return searchJSON(context, query, jsonIdentifier); - } - - - @Override - public InputStream searchJSON(Context context, DiscoverQuery discoveryQuery, String jsonIdentifier) - throws SearchServiceException { - if (getSolr() == null || !(getSolr() instanceof HttpSolrServer)) { - return null; - } - - SolrQuery solrQuery = resolveToSolrQuery(context, discoveryQuery, false); - //We use json as out output type - solrQuery.setParam("json.nl", "map"); - solrQuery.setParam("json.wrf", jsonIdentifier); - solrQuery.setParam(CommonParams.WT, "json"); - - StringBuilder urlBuilder = new StringBuilder(); - //urlBuilder.append(getSolr().getBaseURL()).append("/select?"); - //urlBuilder.append(solrQuery.toString()); - // New url without any query params appended - urlBuilder.append(((HttpSolrServer)getSolr()).getBaseURL()).append("/select"); - // Post setup - NamedList solrParameters = solrQuery.toNamedList(); - List postParameters = new ArrayList<>(); - for (Map.Entry solrParameter : solrParameters) { - if (solrParameter.getValue() instanceof String[]) { - // Multi-valued solr parameter - for (String val : (String[])solrParameter.getValue()) { - postParameters.add(new BasicNameValuePair(solrParameter.getKey(), val)); - } - } else if (solrParameter.getValue() instanceof String) { - postParameters.add(new BasicNameValuePair(solrParameter.getKey(), solrParameter.getValue().toString())); - } else { - log.warn("Search parameters contain non-string value: " + solrParameter.getValue().toString()); - } - } - - try { - HttpPost post = new HttpPost(urlBuilder.toString()); - post.setEntity(new UrlEncodedFormEntity(postParameters)); - HttpResponse response = new DefaultHttpClient().execute(post); - return response.getEntity().getContent(); - - } catch (Exception e) { - log.error("Error while getting json solr result for discovery search recommendation", e); - } - return null; - } - protected DiscoverResult retrieveResult(Context context, DiscoverQuery query, QueryResponse solrQueryResponse) throws SQLException { DiscoverResult result = new DiscoverResult(); @@ -1813,7 +2045,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { List searchFields = query.getSearchFields(); for (SolrDocument doc : solrQueryResponse.getResults()) { - DSpaceObject dso = findDSpaceObject(context, doc); + BrowsableDSpaceObject dso = findDSpaceObject(context, doc); if (dso != null) { result.addDSpaceObject(dso); @@ -1840,12 +2072,22 @@ public class SolrServiceImpl implements SearchService, IndexingService { if (MapUtils.isNotEmpty(highlightedFields)) { //We need to remove all the "_hl" appendix strings from our keys Map> resultMap = new HashMap>(); + Map> resultMapWithAuthority = new HashMap>(); for (String key : highlightedFields.keySet()) { + List highlightOriginalValue = highlightedFields.get(key); + List resultHighlightOriginalValue = new ArrayList(); + for (String highlightValue : highlightOriginalValue) { + String[] splitted = highlightValue.split("###"); + resultHighlightOriginalValue.add(splitted); + + } resultMap.put(key.substring(0, key.lastIndexOf("_hl")), highlightedFields.get(key)); + resultMapWithAuthority + .put(key.substring(0, key.lastIndexOf("_hl")), resultHighlightOriginalValue); } - result - .addHighlightedResult(dso, new DiscoverResult.DSpaceObjectHighlightResult(dso, resultMap)); + result.addHighlightedResult(dso, + new DiscoverResult.DSpaceObjectHighlightResult(dso, resultMap, resultMapWithAuthority)); } } } @@ -1931,6 +2173,20 @@ public class SolrServiceImpl implements SearchService, IndexingService { return result; } + public DiscoverResult.FacetResult getDiscoveryFacet(Context context, FacetField facetField, + FacetField.Count facetValue, String facetType) throws SQLException { + String displayedValue = transformDisplayedValue(context, facetField.getName(), facetValue.getName()); + String authorityValue = transformAuthorityValue(context, facetField.getName(), facetValue.getName()); + String sortValue = transformSortValue(context, facetField.getName(), facetValue.getName()); + String filterValue = displayedValue; + if (StringUtils.isNotBlank(authorityValue)) { + filterValue = authorityValue; + } + DiscoverResult.FacetResult facetResult = new DiscoverResult.FacetResult(filterValue, displayedValue, + authorityValue, sortValue, facetValue.getCount(), facetType); + return facetResult; + } + /** * Find DSpace object by type and UUID or by handle from given Solr document * @@ -1939,28 +2195,49 @@ public class SolrServiceImpl implements SearchService, IndexingService { * @return DSpace object * @throws SQLException An exception that provides information on a database access error or other errors. */ - protected DSpaceObject findDSpaceObject(Context context, SolrDocument doc) throws SQLException { - + protected BrowsableDSpaceObject findDSpaceObject(Context context, SolrDocument doc) throws SQLException { Integer type = (Integer) doc.getFirstValue(RESOURCE_TYPE_FIELD); - UUID id = UUID.fromString((String) doc.getFirstValue(RESOURCE_ID_FIELD)); + Object id = doc.getFirstValue(RESOURCE_ID_FIELD); String handle = (String) doc.getFirstValue(HANDLE_FIELD); - + BrowsableDSpaceObject o = null; + Serializable uid = null; if (type != null && id != null) { - return contentServiceFactory.getDSpaceObjectService(type).find(context, id); - } else if (handle != null) { - return handleService.resolveToObject(context, handle); + switch (type) { + case Constants.WORKSPACEITEM: + case Constants.WORKFLOWITEM: + case Constants.WORKFLOW_POOL: + case Constants.WORKFLOW_CLAIMED: + uid = Integer.parseInt((String) id); + break; + default: + uid = UUID.fromString((String) id); + break; + } } - return null; + if (uid != null) { + o = (BrowsableDSpaceObject) contentServiceFactory.getBrowsableDSpaceObjectService(type).find(context, uid); + } + + if (o != null) { + for (String f : doc.getFieldNames()) { + o.getExtraInfo().put(f, doc.getFirstValue(f)); + } + } else { + log.warn("Not able to retrieve object RESOURCE_ID:" + id + " - RESOURCE_TYPE_ID:" + type + " - HANDLE:" + + handle); + } + return o; } - public List search(Context context, String query, int offset, int max, String... filterquery) { + public List search(Context context, String query, int offset, int max, + String... filterquery) { return search(context, query, null, true, offset, max, filterquery); } @Override - public List search(Context context, String query, String orderfield, boolean ascending, int offset, - int max, String... filterquery) { + public List search(Context context, String query, String orderfield, boolean ascending, + int offset, int max, String... filterquery) { try { if (getSolr() == null) { @@ -1983,12 +2260,12 @@ public class SolrServiceImpl implements SearchService, IndexingService { SolrDocumentList docs = rsp.getResults(); Iterator iter = docs.iterator(); - List result = new ArrayList(); + List result = new ArrayList(); while (iter.hasNext()) { SolrDocument doc = (SolrDocument) iter.next(); - DSpaceObject o = contentServiceFactory - .getDSpaceObjectService((Integer) doc.getFirstValue(RESOURCE_TYPE_FIELD)) + BrowsableDSpaceObject o = (BrowsableDSpaceObject)contentServiceFactory + .getBrowsableDSpaceObjectService((Integer) doc.getFirstValue(RESOURCE_TYPE_FIELD)) .find(context, UUID.fromString((String) doc.getFirstValue(RESOURCE_ID_FIELD))); if (o != null) { @@ -1999,8 +2276,8 @@ public class SolrServiceImpl implements SearchService, IndexingService { } catch (Exception e) { // Any acception that we get ignore it. // We do NOT want any crashed to shown by the user - log.error(LogManager.getHeader(context, "Error while quering solr", "Queyr: " + query), e); - return new ArrayList(0); + log.error(LogManager.getHeader(context, "Error while quering solr", "Query: " + query), e); + return new ArrayList(0); } } @@ -2093,7 +2370,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { SolrDocumentList relatedDocs = (SolrDocumentList) mltResults.get(item.getType() + "-" + item.getID()); for (Object relatedDoc : relatedDocs) { SolrDocument relatedDocument = (SolrDocument) relatedDoc; - DSpaceObject relatedItem = findDSpaceObject(context, relatedDocument); + BrowsableDSpaceObject relatedItem = findDSpaceObject(context, relatedDocument); if (relatedItem.getType() == Constants.ITEM) { results.add((Item) relatedItem); } @@ -2160,6 +2437,9 @@ public class SolrServiceImpl implements SearchService, IndexingService { } protected String transformDisplayedValue(Context context, String field, String value) throws SQLException { + if (value == null) { + return null; + } if (field.equals("location.comm") || field.equals("location.coll")) { value = locationToName(context, field, value); } else if (field.endsWith("_filter") || field.endsWith("_ac") @@ -2188,6 +2468,9 @@ public class SolrServiceImpl implements SearchService, IndexingService { } protected String transformAuthorityValue(Context context, String field, String value) throws SQLException { + if (value == null) { + return null; + } if (field.equals("location.comm") || field.equals("location.coll")) { return value; } @@ -2218,6 +2501,9 @@ public class SolrServiceImpl implements SearchService, IndexingService { } protected String transformSortValue(Context context, String field, String value) throws SQLException { + if (value == null) { + return null; + } if (field.equals("location.comm") || field.equals("location.coll")) { value = locationToName(context, field, value); } else if (field.endsWith("_filter") || field.endsWith("_ac") @@ -2245,7 +2531,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { } @Override - public void indexContent(Context context, DSpaceObject dso, boolean force, + public void indexContent(Context context, BrowsableDSpaceObject dso, boolean force, boolean commit) throws SearchServiceException, SQLException { indexContent(context, dso, force); if (commit) { @@ -2274,10 +2560,11 @@ public class SolrServiceImpl implements SearchService, IndexingService { } @Override - public FacetYearRange getFacetYearRange(Context context, DSpaceObject scope, DiscoverySearchFilterFacet facet, - List filterQueries) throws SearchServiceException { + public FacetYearRange getFacetYearRange(Context context, BrowsableDSpaceObject scope, + DiscoverySearchFilterFacet facet, List filterQueries, + DiscoverQuery parentQuery) throws SearchServiceException { FacetYearRange result = new FacetYearRange(facet); - result.calculateRange(context, filterQueries, scope, this); + result.calculateRange(context, filterQueries, scope, this, parentQuery); return result; } @@ -2305,4 +2592,64 @@ public class SolrServiceImpl implements SearchService, IndexingService { } return null; } + + private void addNamedResourceTypeIndex(SolrInputDocument document, String acvalue, String fvalue) { + + document.addField("namedresourcetype_filter", acvalue); + + String[] avalues = acvalue.split(SolrServiceImpl.AUTHORITY_SEPARATOR); + acvalue = avalues[0]; + + String avalue = avalues[1]; + document.addField("namedresourcetype_authority", avalue); + document.addField("namedresourcetype_group", avalue); + document.addField("namedresourcetype_ac", acvalue); + + Pattern pattern = Pattern.compile(REGEX); + Matcher matcher = pattern.matcher(acvalue); + if (matcher.matches()) { + fvalue = matcher.group(1); + } + + document.addField("namedresourcetype_keyword", fvalue); + } + + class IndexerThread extends Thread { + private boolean force; + private List itemids; + + public IndexerThread(List itemids, boolean force) { + this.force = force; + this.itemids = itemids; + } + + @Override + public void run() { + Context context = null; + try { + context = new Context(); + context.turnOffAuthorisationSystem(); + int idx = 1; + final String head = this.getName() + "#" + this.getId(); + final int size = itemids.size(); + for (UUID id : itemids) { + try { + Item item = itemService.find(context, id); + indexContent(context, item, force); + context.uncacheEntity(item); + } catch (Exception ex) { + log.error("ERROR: identifier item:" + id + " identifier thread:" + head); + } + System.out.println(head + ":" + (idx++) + " / " + size); + } + } catch (Exception e) { + e.printStackTrace(); + log.error(e.getMessage(), e); + } finally { + if (context != null) { + context.abort(); + } + } + } + } } diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexOutputPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexOutputPlugin.java index 58c0f92c8f..7dde0135ec 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexOutputPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexOutputPlugin.java @@ -8,7 +8,7 @@ package org.dspace.discovery; import org.apache.solr.common.SolrInputDocument; -import org.dspace.content.DSpaceObject; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.core.Context; @@ -20,7 +20,7 @@ import org.dspace.core.Context; public class SolrServiceIndexOutputPlugin implements SolrServiceIndexPlugin { @Override - public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument document) { - System.out.println("Currently indexing: " + dso.getHandle()); + public void additionalIndex(Context context, BrowsableDSpaceObject dso, SolrInputDocument document) { + System.out.println("Currently indexing: " + dso.getUniqueIndexID()); } } diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexPlugin.java index 2038e9ad06..ae8c7fab27 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceIndexPlugin.java @@ -8,7 +8,7 @@ package org.dspace.discovery; import org.apache.solr.common.SolrInputDocument; -import org.dspace.content.DSpaceObject; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.core.Context; /** @@ -20,5 +20,5 @@ import org.dspace.core.Context; */ public interface SolrServiceIndexPlugin { - public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument document); + public void additionalIndex(Context context, BrowsableDSpaceObject dso, SolrInputDocument document); } diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceMetadataBrowseIndexingPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceMetadataBrowseIndexingPlugin.java index 5e78173d93..1a4285b87f 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceMetadataBrowseIndexingPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceMetadataBrowseIndexingPlugin.java @@ -15,9 +15,9 @@ import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.solr.common.SolrInputDocument; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.browse.BrowseException; import org.dspace.browse.BrowseIndex; -import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataValue; import org.dspace.content.authority.service.ChoiceAuthorityService; @@ -57,7 +57,7 @@ public class SolrServiceMetadataBrowseIndexingPlugin implements SolrServiceIndex protected ChoiceAuthorityService choiceAuthorityService; @Override - public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument document) { + public void additionalIndex(Context context, BrowsableDSpaceObject dso, SolrInputDocument document) { // Only works for Items if (!(dso instanceof Item)) { return; diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceResourceRestrictionPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceResourceRestrictionPlugin.java index 4fcc8c38ca..62bb19abee 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceResourceRestrictionPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceResourceRestrictionPlugin.java @@ -11,12 +11,14 @@ import java.sql.SQLException; import java.util.List; import java.util.Set; +import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.common.SolrInputDocument; import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.service.AuthorizeService; import org.dspace.authorize.service.ResourcePolicyService; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.content.DSpaceObject; import org.dspace.content.service.CollectionService; import org.dspace.content.service.CommunityService; @@ -54,9 +56,14 @@ public class SolrServiceResourceRestrictionPlugin implements SolrServiceIndexPlu protected ResourcePolicyService resourcePolicyService; @Override - public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument document) { + public void additionalIndex(Context context, BrowsableDSpaceObject bdso, SolrInputDocument document) { + if (!(bdso instanceof DSpaceObject)) { + return; + } + DSpaceObject dso = (DSpaceObject) bdso; try { - List policies = authorizeService.getPoliciesActionFilter(context, dso, Constants.READ); + List policies = authorizeService + .getPoliciesActionFilterExceptRpType(context, dso, Constants.READ, ResourcePolicy.TYPE_WORKFLOW); for (ResourcePolicy resourcePolicy : policies) { String fieldValue; if (resourcePolicy.getGroup() != null) { @@ -82,39 +89,67 @@ public class SolrServiceResourceRestrictionPlugin implements SolrServiceIndexPlu @Override public void additionalSearchParameters(Context context, DiscoverQuery discoveryQuery, SolrQuery solrQuery) { try { - if (!authorizeService.isAdmin(context)) { - StringBuilder resourceQuery = new StringBuilder(); - //Always add the anonymous group id to the query - Group anonymousGroup = groupService.findByName(context, Group.ANONYMOUS); - String anonGroupId = ""; - if (anonymousGroup != null) { - anonGroupId = anonymousGroup.getID().toString(); - } - resourceQuery.append("read:(g" + anonGroupId); + if (context != null && !authorizeService.isAdmin(context)) { + + boolean isInProgessSubmission = false; EPerson currentUser = context.getCurrentUser(); - if (currentUser != null) { - resourceQuery.append(" OR e").append(currentUser.getID()); - } - - //Retrieve all the groups the current user is a member of ! + // Retrieve all the groups the current user is a member of ! Set groups = groupService.allMemberGroupsSet(context, currentUser); - for (Group group : groups) { - resourceQuery.append(" OR g").append(group.getID()); + + if (currentUser != null) { + if (StringUtils.isNotBlank(discoveryQuery.getDiscoveryConfigurationName())) { + if (discoveryQuery.getDiscoveryConfigurationName().startsWith("workspace")) { + // insert filter by submitter + solrQuery + .addFilterQuery("read:(e" + currentUser.getID() + " OR ws" + currentUser.getID() + ")"); + isInProgessSubmission = true; + } else if (discoveryQuery.getDiscoveryConfigurationName().startsWith("workflow")) { + // insert filter by controllers + StringBuilder controllerQuery = new StringBuilder(); + controllerQuery.append("read:(we" + currentUser.getID()); + for (Group group : groups) { + controllerQuery.append(" OR wg").append(group.getID()); + } + controllerQuery.append(")"); + solrQuery.addFilterQuery(controllerQuery.toString()); + isInProgessSubmission = true; + } + } } - resourceQuery.append(")"); + if (!isInProgessSubmission) { + StringBuilder resourceQuery = new StringBuilder(); + //Always add the anonymous group id to the query + Group anonymousGroup = groupService.findByName(context, Group.ANONYMOUS); + String anonGroupId = ""; + if (anonymousGroup != null) { + anonGroupId = anonymousGroup.getID().toString(); + } + resourceQuery.append("read:(g" + anonGroupId); - if (authorizeService.isCommunityAdmin(context) - || authorizeService.isCollectionAdmin(context)) { - resourceQuery.append(" OR "); - resourceQuery.append(DSpaceServicesFactory.getInstance() - .getServiceManager() - .getServiceByName(SearchService.class.getName(), - SearchService.class) - .createLocationQueryForAdministrableItems(context)); + if (currentUser != null) { + resourceQuery.append(" OR e").append(currentUser.getID()); + } + + //Retrieve all the groups the current user is a member of ! + for (Group group : groups) { + resourceQuery.append(" OR g").append(group.getID()); + } + + resourceQuery.append(")"); + + if (authorizeService.isCommunityAdmin(context) + || authorizeService.isCollectionAdmin(context)) { + resourceQuery.append(" OR "); + resourceQuery.append(DSpaceServicesFactory.getInstance() + .getServiceManager() + .getServiceByName(SearchService.class.getName(), + SearchService.class) + .createLocationQueryForAdministrableItems(context)); + } + + solrQuery.addFilterQuery(resourceQuery.toString()); } - - solrQuery.addFilterQuery(resourceQuery.toString()); } } catch (SQLException e) { log.error(LogManager.getHeader(context, "Error while adding resource policy information to query", ""), e); diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceSpellIndexingPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceSpellIndexingPlugin.java index c6a4b602ca..2ae8d44e0e 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceSpellIndexingPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceSpellIndexingPlugin.java @@ -10,7 +10,7 @@ package org.dspace.discovery; import java.util.List; import org.apache.solr.common.SolrInputDocument; -import org.dspace.content.DSpaceObject; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataValue; import org.dspace.content.service.ItemService; @@ -30,7 +30,7 @@ public class SolrServiceSpellIndexingPlugin implements SolrServiceIndexPlugin { protected ItemService itemService; @Override - public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument document) { + public void additionalIndex(Context context, BrowsableDSpaceObject dso, SolrInputDocument document) { if (dso instanceof Item) { Item item = (Item) dso; List dcValues = itemService.getMetadata(item, Item.ANY, Item.ANY, Item.ANY, Item.ANY); diff --git a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java index 69f992a29b..33b1827327 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java +++ b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfigurationService.java @@ -12,7 +12,7 @@ import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; -import org.dspace.content.DSpaceObject; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.services.factory.DSpaceServicesFactory; /** @@ -20,9 +20,18 @@ import org.dspace.services.factory.DSpaceServicesFactory; */ public class DiscoveryConfigurationService { + private Map> extraConfigurationMapping = new HashMap>(); private Map map; private Map> toIgnoreMetadataFields = new HashMap<>(); + public void setExtraConfigurationMapping(Map> extraConfigurationMapping) { + this.extraConfigurationMapping = extraConfigurationMapping; + } + + public Map> getExtraConfigurationMapping() { + return extraConfigurationMapping; + } + public Map getMap() { return map; } @@ -39,7 +48,7 @@ public class DiscoveryConfigurationService { this.toIgnoreMetadataFields = toIgnoreMetadataFields; } - public DiscoveryConfiguration getDiscoveryConfiguration(DSpaceObject dso) { + public DiscoveryConfiguration getDiscoveryConfiguration(BrowsableDSpaceObject dso) { String name; if (dso == null) { name = "site"; @@ -64,7 +73,7 @@ public class DiscoveryConfigurationService { } public DiscoveryConfiguration getDiscoveryConfigurationByNameOrDso(final String configurationName, - final DSpaceObject dso) { + final BrowsableDSpaceObject dso) { if (StringUtils.isNotBlank(configurationName) && getMap().containsKey(configurationName)) { return getMap().get(configurationName); } else { diff --git a/dspace-api/src/main/java/org/dspace/search/Harvest.java b/dspace-api/src/main/java/org/dspace/search/Harvest.java index 677a760452..1e97dbc6d9 100644 --- a/dspace-api/src/main/java/org/dspace/search/Harvest.java +++ b/dspace-api/src/main/java/org/dspace/search/Harvest.java @@ -17,6 +17,7 @@ import java.util.List; import org.apache.logging.log4j.Logger; import org.dspace.authorize.factory.AuthorizeServiceFactory; import org.dspace.authorize.service.AuthorizeService; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.DCDate; @@ -139,9 +140,10 @@ public class Harvest { DiscoverResult discoverResult = SearchUtils.getSearchService().search(context, discoverQuery); // Process results of query into HarvestedItemInfo objects - Iterator dsoIterator = discoverResult.getDspaceObjects().iterator(); + Iterator dsoIterator = discoverResult.getDspaceObjects().iterator(); while (dsoIterator.hasNext() && ((limit == 0) || (itemCounter < limit))) { - DSpaceObject dso = dsoIterator.next(); + // the query is limited to ITEM + DSpaceObject dso = (DSpaceObject) dsoIterator.next(); HarvestedItemInfo itemInfo = new HarvestedItemInfo(); itemInfo.context = context; itemInfo.handle = dso.getHandle(); diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/DiscoveryRestController.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/DiscoveryRestController.java index 4afde3df07..0d29a85054 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/DiscoveryRestController.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/DiscoveryRestController.java @@ -70,7 +70,7 @@ public class DiscoveryRestController implements InitializingBean { @RequestMapping(method = RequestMethod.GET) public SearchSupportResource getSearchSupport(@RequestParam(name = "scope", required = false) String dsoScope, @RequestParam(name = "configuration", required = false) String - configurationName) + configuration) throws Exception { SearchSupportRest searchSupportRest = discoveryRestRepository.getSearchSupport(); @@ -82,14 +82,14 @@ public class DiscoveryRestController implements InitializingBean { @RequestMapping(method = RequestMethod.GET, value = "/search") public SearchConfigurationResource getSearchConfiguration( @RequestParam(name = "scope", required = false) String dsoScope, - @RequestParam(name = "configuration", required = false) String configurationName) throws Exception { + @RequestParam(name = "configuration", required = false) String configuration) throws Exception { if (log.isTraceEnabled()) { log.trace("Retrieving search configuration for scope " + StringUtils.trimToEmpty(dsoScope) - + " and configuration name " + StringUtils.trimToEmpty(configurationName)); + + " and configuration name " + StringUtils.trimToEmpty(configuration)); } SearchConfigurationRest searchConfigurationRest = discoveryRestRepository - .getSearchConfiguration(dsoScope, configurationName); + .getSearchConfiguration(dsoScope, configuration); SearchConfigurationResource searchConfigurationResource = new SearchConfigurationResource( searchConfigurationRest); @@ -176,6 +176,8 @@ public class DiscoveryRestController implements InitializingBean { @RequestParam(name = "query", required = false) String query, @RequestParam(name = "dsoType", required = false) String dsoType, @RequestParam(name = "scope", required = false) String dsoScope, + @RequestParam(name = "configuration", required = false) String + configurationName, List searchFilters, Pageable page) throws Exception { if (log.isTraceEnabled()) { @@ -188,7 +190,7 @@ public class DiscoveryRestController implements InitializingBean { } FacetResultsRest facetResultsRest = discoveryRestRepository - .getFacetObjects(facetName, prefix, query, dsoType, dsoScope, searchFilters, page); + .getFacetObjects(facetName, prefix, query, dsoType, dsoScope, configurationName, searchFilters, page); FacetResultsResource facetResultsResource = new FacetResultsResource(facetResultsRest); diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/OpenSearchController.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/OpenSearchController.java index 37664d0f51..004e67950b 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/OpenSearchController.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/OpenSearchController.java @@ -30,6 +30,7 @@ import org.dspace.app.util.factory.UtilServiceFactory; import org.dspace.app.util.service.OpenSearchService; import org.dspace.authorize.factory.AuthorizeServiceFactory; import org.dspace.authorize.service.AuthorizeService; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.content.DSpaceObject; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.CollectionService; @@ -140,7 +141,7 @@ public class OpenSearchController { // format and return results Map labelMap = getLabels(request); - List dsoResults = qResults.getDspaceObjects(); + List dsoResults = qResults.getDspaceObjects(); Document resultsDoc = openSearchService.getResultsDoc(context, format, query, (int) qResults.getTotalSearchResults(), qResults.getStart(), qResults.getMaxResults(), container, dsoResults, labelMap); diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/RestResourceController.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/RestResourceController.java index ae01fcc54d..536379c696 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/RestResourceController.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/RestResourceController.java @@ -431,47 +431,6 @@ public class RestResourceController implements InitializingBean { return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result); } - /** - * Called in POST, with a x-www-form-urlencoded, execute an action on a resource - * - * Note that the regular expression in the request mapping accept a number as identifier; - * - * @param request - * @param apiCategory - * @param model - * @param id - * @return - * @throws HttpRequestMethodNotSupportedException - */ - @RequestMapping(method = RequestMethod.POST, value = REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT, headers = - "content-type=application/x-www-form-urlencoded") - public ResponseEntity action(HttpServletRequest request, @PathVariable String apiCategory, - @PathVariable String model, @PathVariable Integer id) - throws HttpRequestMethodNotSupportedException { - checkModelPluralForm(apiCategory, model); - DSpaceRestRepository repository = - utils.getResourceRepository(apiCategory, model); - - RestAddressableModel modelObject = null; - try { - modelObject = repository.action(request, id); - } catch (UnprocessableEntityException e) { - log.error(e.getMessage(), e); - return ControllerUtils.toEmptyResponse(HttpStatus.UNPROCESSABLE_ENTITY); - } catch (Exception e) { - log.error(e.getMessage(), e); - return ControllerUtils.toEmptyResponse(HttpStatus.INTERNAL_SERVER_ERROR); - } - - if (modelObject != null) { - DSpaceResource result = repository.wrapResource(modelObject); - linkService.addLinks(result); - return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, result); - } else { - return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT); - } - } - /** * Called in POST, multipart, upload to a specific rest resource the file passed as "file" request parameter * diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/DiscoverFacetsConverter.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/DiscoverFacetsConverter.java index 79e3234855..7cade7b386 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/DiscoverFacetsConverter.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/DiscoverFacetsConverter.java @@ -50,28 +50,28 @@ public class DiscoverFacetsConverter { return searchResultsRest; } - - private void addFacetValues(Context context, final DiscoverResult searchResult, - final SearchResultsRest searchResultsRest, - final DiscoveryConfiguration configuration) { + public void addFacetValues(Context context, final DiscoverResult searchResult, final SearchResultsRest resultsRest, + final DiscoveryConfiguration configuration) { List facets = configuration.getSidebarFacets(); for (DiscoverySearchFilterFacet field : CollectionUtils.emptyIfNull(facets)) { - List facetValues = searchResult.getFacetResult(field); SearchFacetEntryRest facetEntry = new SearchFacetEntryRest(field.getIndexFieldName()); int valueCount = 0; + facetEntry.setHasMore(false); facetEntry.setFacetLimit(field.getFacetLimit()); - facetEntry.setExposeMinMax(field.exposeMinAndMaxValue()); if (field.exposeMinAndMaxValue()) { - handleExposeMinMaxValues(context,field,facetEntry); + handleExposeMinMaxValues(context, field, facetEntry); } + facetEntry.setExposeMinMax(field.exposeMinAndMaxValue()); for (DiscoverResult.FacetResult value : CollectionUtils.emptyIfNull(facetValues)) { - //The discover results contains max facetLimit + 1 values. If we reach the "+1", indicate that there are - //more results available. + // The discover results contains max facetLimit + 1 values. If we reach the "+1", indicate that there + // are + // more results available. if (valueCount < field.getFacetLimit()) { SearchFacetValueRest valueRest = facetValueConverter.convert(value); + facetEntry.addValue(valueRest); } else { facetEntry.setHasMore(true); @@ -84,27 +84,27 @@ public class DiscoverFacetsConverter { valueCount++; } - searchResultsRest.addFacetEntry(facetEntry); + resultsRest.addFacetEntry(facetEntry); } } /** - * This method will fill the facetEntry with the appropriate min and max values if they're not empty - * @param context The relevant DSpace context - * @param field The DiscoverySearchFilterFacet field to search for this value in solr - * @param facetEntry The SearchFacetEntryRest facetEntry for which this needs to be filled in - */ - private void handleExposeMinMaxValues(Context context,DiscoverySearchFilterFacet field, - SearchFacetEntryRest facetEntry) { + * This method will fill the facetEntry with the appropriate min and max values if they're not empty + * + * @param context + * The relevant DSpace context + * @param field + * The DiscoverySearchFilterFacet field to search for this value in solr + * @param facetEntry + * The SearchFacetEntryRest facetEntry for which this needs to be filled in + */ + private void handleExposeMinMaxValues(Context context, DiscoverySearchFilterFacet field, + SearchFacetEntryRest facetEntry) { try { - String minValue = searchService.calculateExtremeValue(context, - field.getIndexFieldName() + "_min", - field.getIndexFieldName() + "_min_sort", - DiscoverQuery.SORT_ORDER.asc); - String maxValue = searchService.calculateExtremeValue(context, - field.getIndexFieldName() + "_max", - field.getIndexFieldName() + "_max_sort", - DiscoverQuery.SORT_ORDER.desc); + String minValue = searchService.calculateExtremeValue(context, field.getIndexFieldName() + "_min", + field.getIndexFieldName() + "_min_sort", DiscoverQuery.SORT_ORDER.asc); + String maxValue = searchService.calculateExtremeValue(context, field.getIndexFieldName() + "_max", + field.getIndexFieldName() + "_max_sort", DiscoverQuery.SORT_ORDER.desc); if (StringUtils.isNotBlank(minValue) && StringUtils.isNotBlank(maxValue)) { facetEntry.setMinValue(minValue); @@ -115,7 +115,6 @@ public class DiscoverFacetsConverter { } } - private void setRequestInformation(final Context context, final String query, final String dsoType, final String configurationName, final String scope, final List searchFilters, final Pageable page, diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/DiscoverResultConverter.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/DiscoverResultConverter.java index 45470c3e8e..580175d755 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/DiscoverResultConverter.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/DiscoverResultConverter.java @@ -12,23 +12,16 @@ import java.util.Map; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; -import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.dspace.app.rest.converter.query.SearchQueryConverter; -import org.dspace.app.rest.model.DSpaceObjectRest; -import org.dspace.app.rest.model.SearchFacetEntryRest; -import org.dspace.app.rest.model.SearchFacetValueRest; +import org.dspace.app.rest.model.RestAddressableModel; import org.dspace.app.rest.model.SearchResultEntryRest; import org.dspace.app.rest.model.SearchResultsRest; import org.dspace.app.rest.parameter.SearchFilter; -import org.dspace.content.DSpaceObject; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.core.Context; -import org.dspace.discovery.DiscoverQuery; import org.dspace.discovery.DiscoverResult; -import org.dspace.discovery.SearchService; -import org.dspace.discovery.SearchServiceException; import org.dspace.discovery.configuration.DiscoveryConfiguration; -import org.dspace.discovery.configuration.DiscoverySearchFilterFacet; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; @@ -43,12 +36,11 @@ public class DiscoverResultConverter { private static final Logger log = Logger.getLogger(DiscoverResultConverter.class); @Autowired - private List converters; - + private List converters; @Autowired - private SearchService searchService; - - private DiscoverFacetValueConverter facetValueConverter = new DiscoverFacetValueConverter(); + private DiscoverFacetsConverter facetConverter; + @Autowired + private SearchFilterToAppliedFilterConverter searchFilterToAppliedFilterConverter; public SearchResultsRest convert(final Context context, final String query, final String dsoType, final String configurationName, final String scope, @@ -69,74 +61,16 @@ public class DiscoverResultConverter { } private void addFacetValues(Context context, final DiscoverResult searchResult, final SearchResultsRest resultsRest, - final DiscoveryConfiguration configuration) { - - List facets = configuration.getSidebarFacets(); - for (DiscoverySearchFilterFacet field : CollectionUtils.emptyIfNull(facets)) { - List facetValues = searchResult.getFacetResult(field); - - SearchFacetEntryRest facetEntry = new SearchFacetEntryRest(field.getIndexFieldName()); - int valueCount = 0; - facetEntry.setHasMore(false); - facetEntry.setFacetLimit(field.getFacetLimit()); - if (field.exposeMinAndMaxValue()) { - handleExposeMinMaxValues(context,field,facetEntry); - } - facetEntry.setExposeMinMax(field.exposeMinAndMaxValue()); - for (DiscoverResult.FacetResult value : CollectionUtils.emptyIfNull(facetValues)) { - //The discover results contains max facetLimit + 1 values. If we reach the "+1", indicate that there are - //more results available. - if (valueCount < field.getFacetLimit()) { - SearchFacetValueRest valueRest = facetValueConverter.convert(value); - - facetEntry.addValue(valueRest); - } else { - facetEntry.setHasMore(true); - } - - if (StringUtils.isBlank(facetEntry.getFacetType())) { - facetEntry.setFacetType(value.getFieldType()); - } - - valueCount++; - } - - resultsRest.addFacetEntry(facetEntry); - } + final DiscoveryConfiguration configuration) { + facetConverter.addFacetValues(context, searchResult, resultsRest, configuration); } - /** - * This method will fill the facetEntry with the appropriate min and max values if they're not empty - * @param context The relevant DSpace context - * @param field The DiscoverySearchFilterFacet field to search for this value in solr - * @param facetEntry The SearchFacetEntryRest facetEntry for which this needs to be filled in - */ - private void handleExposeMinMaxValues(Context context,DiscoverySearchFilterFacet field, - SearchFacetEntryRest facetEntry) { - try { - String minValue = searchService.calculateExtremeValue(context, - field.getIndexFieldName() + "_min", - field.getIndexFieldName() + "_min_sort", - DiscoverQuery.SORT_ORDER.asc); - String maxValue = searchService.calculateExtremeValue(context, - field.getIndexFieldName() + "_max", - field.getIndexFieldName() + "_max_sort", - DiscoverQuery.SORT_ORDER.desc); - - if (StringUtils.isNotBlank(minValue) && StringUtils.isNotBlank(maxValue)) { - facetEntry.setMinValue(minValue); - facetEntry.setMaxValue(maxValue); - } - } catch (SearchServiceException e) { - log.error(e.getMessage(), e); - } - } private void addSearchResults(final DiscoverResult searchResult, final SearchResultsRest resultsRest) { - for (DSpaceObject dspaceObject : CollectionUtils.emptyIfNull(searchResult.getDspaceObjects())) { + for (BrowsableDSpaceObject dspaceObject : CollectionUtils.emptyIfNull(searchResult.getDspaceObjects())) { SearchResultEntryRest resultEntry = new SearchResultEntryRest(); //Convert the DSpace Object to its REST model - resultEntry.setDspaceObject(convertDSpaceObject(dspaceObject)); + resultEntry.setRObject(convertDSpaceObject(dspaceObject)); //Add hit highlighting for this DSO if present DiscoverResult.DSpaceObjectHighlightResult highlightedResults = searchResult @@ -152,10 +86,10 @@ public class DiscoverResultConverter { } } - private DSpaceObjectRest convertDSpaceObject(final DSpaceObject dspaceObject) { - for (DSpaceObjectConverter converter : converters) { + private RestAddressableModel convertDSpaceObject(final BrowsableDSpaceObject dspaceObject) { + for (BrowsableDSpaceObjectConverter converter : converters) { if (converter.supportsModel(dspaceObject)) { - return converter.fromModel(dspaceObject); + return converter.convert(dspaceObject); } } return null; @@ -179,11 +113,10 @@ public class DiscoverResultConverter { List transformedFilters = searchQueryConverter.convert(searchFilters); SearchFilterToAppliedFilterConverter searchFilterToAppliedFilterConverter = - new SearchFilterToAppliedFilterConverter(); + new SearchFilterToAppliedFilterConverter(); for (SearchFilter searchFilter : CollectionUtils.emptyIfNull(transformedFilters)) { - resultsRest - .addAppliedFilter(searchFilterToAppliedFilterConverter.convertSearchFilter(context, searchFilter)); + .addAppliedFilter(searchFilterToAppliedFilterConverter.convertSearchFilter(context, searchFilter)); } } } diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/SearchFilterToAppliedFilterConverter.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/SearchFilterToAppliedFilterConverter.java index 4f85bd9835..4ab372f419 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/SearchFilterToAppliedFilterConverter.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/converter/SearchFilterToAppliedFilterConverter.java @@ -13,10 +13,12 @@ import org.dspace.authority.AuthorityValue; import org.dspace.authority.service.AuthorityValueService; import org.dspace.core.Context; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; /** * This class' purpose is to convert the SearchFilter object into a SearchResultsRest.AppliedFilter object */ +@Component public class SearchFilterToAppliedFilterConverter { @Autowired diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/DiscoveryRestHalLinkFactory.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/DiscoveryRestHalLinkFactory.java index 26d8b4c20d..c0c0af91cc 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/DiscoveryRestHalLinkFactory.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/DiscoveryRestHalLinkFactory.java @@ -39,13 +39,11 @@ public abstract class DiscoveryRestHalLinkFactory extends HalLinkFactory extends HalLinkFactory extends HalLinkFactory { private SearchResultsRest.Sorting sort; @JsonIgnore private String dsoType; + @JsonIgnore + private List searchFilters; + private String configurationName; public String getCategory() { return CATEGORY; @@ -98,12 +102,10 @@ public abstract class DiscoveryResultsRest extends BaseObjectRest { return configurationName; } - public void setConfigurationName(final String configurationName) { - this.configurationName = configurationName; + public void setConfigurationName(final String configuration) { + this.configurationName = configuration; } - private String configurationName; - public void setSearchFilters(final List searchFilters) { this.searchFilters = searchFilters; } @@ -112,6 +114,5 @@ public abstract class DiscoveryResultsRest extends BaseObjectRest { return searchFilters; } - @JsonIgnore - private List searchFilters; + } diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/ErrorRest.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/ErrorRest.java index 59bf9176dd..172dbf1cf0 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/ErrorRest.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/ErrorRest.java @@ -7,7 +7,7 @@ */ package org.dspace.app.rest.model; -import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; /** @@ -43,7 +43,7 @@ public class ErrorRest { */ public List getPaths() { if (this.paths == null) { - this.paths = new ArrayList(); + this.paths = new LinkedList(); } return paths; } diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/SearchResultEntryRest.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/SearchResultEntryRest.java index 87e47f1bb2..282d230a60 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/SearchResultEntryRest.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/SearchResultEntryRest.java @@ -12,6 +12,7 @@ import java.util.List; import java.util.Map; import com.fasterxml.jackson.annotation.JsonIgnore; + import org.dspace.app.rest.DiscoveryRestController; /** @@ -24,10 +25,9 @@ public class SearchResultEntryRest implements RestAddressableModel { private Map> hitHighlights; + private RestAddressableModel rObject; + @JsonIgnore - private DSpaceObjectRest dspaceObject; - - public String getCategory() { return CATEGORY; } @@ -36,6 +36,7 @@ public class SearchResultEntryRest implements RestAddressableModel { return NAME; } + @JsonIgnore public Class getController() { return DiscoveryRestController.class; } @@ -55,11 +56,12 @@ public class SearchResultEntryRest implements RestAddressableModel { this.hitHighlights = hitHighlights; } - public DSpaceObjectRest getDspaceObject() { - return dspaceObject; + @JsonIgnore + public RestAddressableModel getRObject() { + return rObject; } - public void setDspaceObject(final DSpaceObjectRest dspaceObject) { - this.dspaceObject = dspaceObject; + public void setRObject(final RestAddressableModel dspaceObject) { + this.rObject = dspaceObject; } } diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/SearchResultsRest.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/SearchResultsRest.java index c838451336..3c0b852656 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/SearchResultsRest.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/SearchResultsRest.java @@ -11,6 +11,7 @@ import java.util.LinkedList; import java.util.List; import com.fasterxml.jackson.annotation.JsonIgnore; + import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/SearchResultEntryResource.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/SearchResultEntryResource.java index d59227b7a0..ab94198fe4 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/SearchResultEntryResource.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/SearchResultEntryResource.java @@ -7,7 +7,7 @@ */ package org.dspace.app.rest.model.hateoas; -import org.dspace.app.rest.model.DSpaceObjectRest; +import org.dspace.app.rest.model.RestAddressableModel; import org.dspace.app.rest.model.SearchResultEntryRest; import org.dspace.app.rest.repository.DSpaceRestRepository; import org.dspace.app.rest.utils.Utils; @@ -17,7 +17,7 @@ import org.dspace.app.rest.utils.Utils; */ public class SearchResultEntryResource extends HALResource { - public static final String DSPACE_OBJECT_LINK = "dspaceObject"; + public static final String R_OBJECT_LINK = "rObject"; public SearchResultEntryResource(final SearchResultEntryRest data, final Utils utils) { super(data); @@ -27,12 +27,12 @@ public class SearchResultEntryResource extends HALResource page = new PageImpl(binfo.getBrowseItemResults(), pageResultInfo, binfo.getTotal()) - .map(converter); + Pageable pageResultInfo = + new PageRequest((binfo.getStart() - 1) / binfo.getResultsPerPage(), binfo.getResultsPerPage()); + List tmpResult = new ArrayList(); + for (BrowsableDSpaceObject bb : binfo.getBrowseItemResults()) { + tmpResult.add((Item) bb); + } + Page page = new PageImpl(tmpResult, pageResultInfo, binfo.getTotal()).map(converter); return page; } diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/ClaimedTaskRestRepository.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/ClaimedTaskRestRepository.java index f173169423..6e5bc2579c 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/ClaimedTaskRestRepository.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/ClaimedTaskRestRepository.java @@ -16,7 +16,6 @@ import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; -import org.dspace.app.rest.Parameter; import org.dspace.app.rest.SearchRestMethod; import org.dspace.app.rest.converter.ClaimedTaskConverter; import org.dspace.app.rest.exception.RESTAuthorizationException; @@ -47,6 +46,7 @@ import org.dspace.xmlworkflow.storedcomponents.service.ClaimedTaskService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Component; /** @@ -93,7 +93,7 @@ public class ClaimedTaskRestRepository extends DSpaceRestRepository findByUser(@Parameter(value = "uuid") UUID userID, Pageable pageable) { + public Page findByUser(@Param(value = "uuid") UUID userID, Pageable pageable) { List tasks = null; try { Context context = obtainContext(); diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/DiscoveryRestRepository.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/DiscoveryRestRepository.java index ec73a24e2c..66af3984c9 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/DiscoveryRestRepository.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/DiscoveryRestRepository.java @@ -9,8 +9,6 @@ package org.dspace.app.rest.repository; import java.util.List; -import javax.ws.rs.BadRequestException; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.converter.DiscoverConfigurationConverter; @@ -28,7 +26,7 @@ import org.dspace.app.rest.model.SearchSupportRest; import org.dspace.app.rest.parameter.SearchFilter; import org.dspace.app.rest.utils.DiscoverQueryBuilder; import org.dspace.app.rest.utils.ScopeResolver; -import org.dspace.content.DSpaceObject; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.core.Context; import org.dspace.discovery.DiscoverQuery; import org.dspace.discovery.DiscoverResult; @@ -81,32 +79,32 @@ public class DiscoveryRestRepository extends AbstractDSpaceRestRepository { @Autowired private DiscoverFacetsConverter discoverFacetsConverter; - public SearchConfigurationRest getSearchConfiguration(final String dsoScope, final String configurationName) { + public SearchConfigurationRest getSearchConfiguration(final String dsoScope, final String configuration) { Context context = obtainContext(); - DSpaceObject scopeObject = scopeResolver.resolveScope(context, dsoScope); - DiscoveryConfiguration configuration = searchConfigurationService - .getDiscoveryConfigurationByNameOrDso(configurationName, scopeObject); + BrowsableDSpaceObject scopeObject = scopeResolver.resolveScope(context, dsoScope); + DiscoveryConfiguration discoveryConfiguration = searchConfigurationService + .getDiscoveryConfigurationByNameOrDso(configuration, scopeObject); - return discoverConfigurationConverter.convert(configuration); + return discoverConfigurationConverter.convert(discoveryConfiguration); } public SearchResultsRest getSearchObjects(final String query, final String dsoType, final String dsoScope, - final String configurationName, + final String configuration, final List searchFilters, final Pageable page) - throws InvalidRequestException, BadRequestException { + throws InvalidRequestException { Context context = obtainContext(); - DSpaceObject scopeObject = scopeResolver.resolveScope(context, dsoScope); - DiscoveryConfiguration configuration = searchConfigurationService - .getDiscoveryConfigurationByNameOrDso(configurationName, scopeObject); + BrowsableDSpaceObject scopeObject = scopeResolver.resolveScope(context, dsoScope); + DiscoveryConfiguration discoveryConfiguration = searchConfigurationService + .getDiscoveryConfigurationByNameOrDso(configuration, scopeObject); DiscoverResult searchResult = null; DiscoverQuery discoverQuery = null; try { discoverQuery = queryBuilder - .buildQuery(context, scopeObject, configuration, query, searchFilters, dsoType, page); + .buildQuery(context, scopeObject, discoveryConfiguration, query, searchFilters, dsoType, page); searchResult = searchService.search(context, scopeObject, discoverQuery); } catch (SearchServiceException e) { @@ -115,18 +113,18 @@ public class DiscoveryRestRepository extends AbstractDSpaceRestRepository { } return discoverResultConverter - .convert(context, query, dsoType, configurationName, dsoScope, searchFilters, page, searchResult, - configuration); + .convert(context, query, dsoType, configuration, dsoScope, searchFilters, page, searchResult, + discoveryConfiguration); } - public FacetConfigurationRest getFacetsConfiguration(final String dsoScope, final String configurationName) { + public FacetConfigurationRest getFacetsConfiguration(final String dsoScope, final String configuration) { Context context = obtainContext(); - DSpaceObject scopeObject = scopeResolver.resolveScope(context, dsoScope); - DiscoveryConfiguration configuration = searchConfigurationService - .getDiscoveryConfigurationByNameOrDso(configurationName, scopeObject); + BrowsableDSpaceObject scopeObject = scopeResolver.resolveScope(context, dsoScope); + DiscoveryConfiguration discoveryConfiguration = searchConfigurationService + .getDiscoveryConfigurationByNameOrDso(configuration, scopeObject); - return discoverFacetConfigurationConverter.convert(configurationName, dsoScope, configuration); + return discoverFacetConfigurationConverter.convert(configuration, dsoScope, discoveryConfiguration); } public SearchSupportRest getSearchSupport() { @@ -134,21 +132,20 @@ public class DiscoveryRestRepository extends AbstractDSpaceRestRepository { } public FacetResultsRest getFacetObjects(String facetName, String prefix, String query, String dsoType, - String dsoScope, List searchFilters, Pageable page) + String dsoScope, final String configuration, List searchFilters, Pageable page) throws InvalidRequestException { Context context = obtainContext(); - DSpaceObject scopeObject = scopeResolver.resolveScope(context, dsoScope); - DiscoveryConfiguration configuration = searchConfigurationService - .getDiscoveryConfigurationByNameOrDso(facetName, scopeObject); + BrowsableDSpaceObject scopeObject = scopeResolver.resolveScope(context, dsoScope); + DiscoveryConfiguration discoveryConfiguration = searchConfigurationService + .getDiscoveryConfigurationByNameOrDso(configuration, scopeObject); DiscoverResult searchResult = null; DiscoverQuery discoverQuery = null; try { - discoverQuery = queryBuilder - .buildFacetQuery(context, scopeObject, configuration, prefix, query, - searchFilters, dsoType, page, facetName); + discoverQuery = queryBuilder.buildFacetQuery(context, scopeObject, discoveryConfiguration, prefix, query, + searchFilters, dsoType, page, facetName); searchResult = searchService.search(context, scopeObject, discoverQuery); } catch (SearchServiceException e) { @@ -156,36 +153,34 @@ public class DiscoveryRestRepository extends AbstractDSpaceRestRepository { //TODO TOM handle search exception } - FacetResultsRest facetResultsRest = discoverFacetResultsConverter - .convert(context, facetName, prefix, query, dsoType, dsoScope, searchFilters, - searchResult, configuration, page); + FacetResultsRest facetResultsRest = discoverFacetResultsConverter.convert(context, facetName, prefix, query, + dsoType, dsoScope, searchFilters, searchResult, discoveryConfiguration, page); return facetResultsRest; } - public SearchResultsRest getAllFacets(String query, String dsoType, String dsoScope, String configurationName, + public SearchResultsRest getAllFacets(String query, String dsoType, String dsoScope, String configuration, List searchFilters) throws InvalidRequestException { Context context = obtainContext(); Pageable page = new PageRequest(1, 1); - DSpaceObject scopeObject = scopeResolver.resolveScope(context, dsoScope); - DiscoveryConfiguration configuration = searchConfigurationService - .getDiscoveryConfigurationByNameOrDso(configurationName, scopeObject); + BrowsableDSpaceObject scopeObject = scopeResolver.resolveScope(context, dsoScope); + DiscoveryConfiguration discoveryConfiguration = searchConfigurationService + .getDiscoveryConfigurationByNameOrDso(configuration, scopeObject); DiscoverResult searchResult = null; DiscoverQuery discoverQuery = null; try { discoverQuery = queryBuilder - .buildQuery(context, scopeObject, configuration, query, searchFilters, dsoType, page); + .buildQuery(context, scopeObject, discoveryConfiguration, query, searchFilters, dsoType, page); searchResult = searchService.search(context, scopeObject, discoverQuery); } catch (SearchServiceException e) { log.error("Error while searching with Discovery", e); } - SearchResultsRest searchResultsRest = discoverFacetsConverter - .convert(context, query, dsoType, configurationName, dsoScope, searchFilters, page, configuration, - searchResult); + SearchResultsRest searchResultsRest = discoverFacetsConverter.convert(context, query, dsoType, + configuration, dsoScope, searchFilters, page, discoveryConfiguration, searchResult); return searchResultsRest; diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/LinkRestRepository.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/LinkRestRepository.java index c397b9518b..ddd3d3fb32 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/LinkRestRepository.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/LinkRestRepository.java @@ -7,7 +7,8 @@ */ package org.dspace.app.rest.repository; -import org.dspace.app.rest.model.RestModel; +import java.io.Serializable; + import org.dspace.app.rest.model.hateoas.HALResource; /** @@ -15,7 +16,7 @@ import org.dspace.app.rest.model.hateoas.HALResource; * * @author Andrea Bollini (andrea.bollini at 4science.it) */ -public interface LinkRestRepository { +public interface LinkRestRepository { public abstract HALResource wrapResource(L model, String... rels); public default boolean isEmbeddableRelation(Object data, String name) { diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/PoolTaskRestRepository.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/PoolTaskRestRepository.java index 43ac9031c6..b9197c8aab 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/PoolTaskRestRepository.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/PoolTaskRestRepository.java @@ -15,7 +15,6 @@ import javax.mail.MessagingException; import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; -import org.dspace.app.rest.Parameter; import org.dspace.app.rest.SearchRestMethod; import org.dspace.app.rest.converter.PoolTaskConverter; import org.dspace.app.rest.exception.RESTAuthorizationException; @@ -41,6 +40,7 @@ import org.dspace.xmlworkflow.storedcomponents.service.PoolTaskService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Component; /** @@ -87,7 +87,7 @@ public class PoolTaskRestRepository extends DSpaceRestRepository findByUser(@Parameter(value = "uuid") UUID userID, Pageable pageable) { + public Page findByUser(@Param(value = "uuid") UUID userID, Pageable pageable) { List tasks = null; try { Context context = obtainContext(); diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/utils/DiscoverQueryBuilder.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/utils/DiscoverQueryBuilder.java index 70d97906ae..2ecf5cadcd 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/utils/DiscoverQueryBuilder.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/utils/DiscoverQueryBuilder.java @@ -22,7 +22,7 @@ import org.dspace.app.rest.exception.InvalidSearchFacetException; import org.dspace.app.rest.exception.InvalidSearchFilterException; import org.dspace.app.rest.exception.InvalidSortingException; import org.dspace.app.rest.parameter.SearchFilter; -import org.dspace.content.DSpaceObject; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.LogManager; @@ -67,7 +67,7 @@ public class DiscoverQueryBuilder implements InitializingBean { pageSizeLimit = configurationService.getIntProperty("rest.search.max.results", 100); } - public DiscoverQuery buildQuery(Context context, DSpaceObject scope, + public DiscoverQuery buildQuery(Context context, BrowsableDSpaceObject scope, DiscoveryConfiguration discoveryConfiguration, String query, List searchFilters, String dsoType, Pageable page) @@ -100,7 +100,7 @@ public class DiscoverQueryBuilder implements InitializingBean { } } - public DiscoverQuery buildFacetQuery(Context context, DSpaceObject scope, + public DiscoverQuery buildFacetQuery(Context context, BrowsableDSpaceObject scope, DiscoveryConfiguration discoveryConfiguration, String prefix, String query, List searchFilters, String dsoType, Pageable page, String facetName) @@ -127,9 +127,9 @@ public class DiscoverQueryBuilder implements InitializingBean { } } - private DiscoverQuery addFacetingForFacets(Context context, DSpaceObject scope, String prefix, - DiscoverQuery queryArgs, DiscoveryConfiguration discoveryConfiguration, - String facetName, Pageable page) throws InvalidSearchFacetException { + private DiscoverQuery addFacetingForFacets(Context context, BrowsableDSpaceObject scope, String prefix, + DiscoverQuery queryArgs, DiscoveryConfiguration discoveryConfiguration, String facetName, Pageable page) + throws InvalidSearchFacetException { DiscoverySearchFilterFacet facet = discoveryConfiguration.getSidebarFacet(facetName); if (facet != null) { @@ -145,12 +145,12 @@ public class DiscoverQueryBuilder implements InitializingBean { return queryArgs; } - private void fillFacetIntoQueryArgs(Context context, DSpaceObject scope, String prefix, DiscoverQuery queryArgs, - DiscoverySearchFilterFacet facet, final int pageSize) { + private void fillFacetIntoQueryArgs(Context context, BrowsableDSpaceObject scope, String prefix, + DiscoverQuery queryArgs, DiscoverySearchFilterFacet facet, final int pageSize) { if (facet.getType().equals(DiscoveryConfigurationParameters.TYPE_DATE)) { try { - FacetYearRange facetYearRange = searchService - .getFacetYearRange(context, scope, facet, queryArgs.getFilterQueries()); + FacetYearRange facetYearRange = + searchService.getFacetYearRange(context, scope, facet, queryArgs.getFilterQueries(), queryArgs); queryArgs.addYearRangeFacet(facet, facetYearRange); @@ -193,6 +193,7 @@ public class DiscoverQueryBuilder implements InitializingBean { private DiscoverQuery buildBaseQueryForConfiguration(DiscoveryConfiguration discoveryConfiguration) { DiscoverQuery queryArgs = new DiscoverQuery(); + queryArgs.setDiscoveryConfigurationName(discoveryConfiguration.getId()); queryArgs.addFilterQueries(discoveryConfiguration.getDefaultFilterQueries() .toArray( new String[discoveryConfiguration.getDefaultFilterQueries() @@ -309,7 +310,7 @@ public class DiscoverQueryBuilder implements InitializingBean { return filterQueries.toArray(new String[filterQueries.size()]); } - private DiscoverQuery addFaceting(Context context, DSpaceObject scope, DiscoverQuery queryArgs, + private DiscoverQuery addFaceting(Context context, BrowsableDSpaceObject scope, DiscoverQuery queryArgs, DiscoveryConfiguration discoveryConfiguration) { List facets = discoveryConfiguration.getSidebarFacets(); diff --git a/dspace-spring-rest/src/test/java/org/dspace/app/rest/utils/DiscoverQueryBuilderTest.java b/dspace-spring-rest/src/test/java/org/dspace/app/rest/utils/DiscoverQueryBuilderTest.java index 75a22bf141..d39ba43efa 100644 --- a/dspace-spring-rest/src/test/java/org/dspace/app/rest/utils/DiscoverQueryBuilderTest.java +++ b/dspace-spring-rest/src/test/java/org/dspace/app/rest/utils/DiscoverQueryBuilderTest.java @@ -28,7 +28,7 @@ import org.dspace.app.rest.exception.InvalidSearchFacetException; import org.dspace.app.rest.exception.InvalidSearchFilterException; import org.dspace.app.rest.exception.InvalidSortingException; import org.dspace.app.rest.parameter.SearchFilter; -import org.dspace.content.DSpaceObject; +import org.dspace.browse.BrowsableDSpaceObject; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.discovery.DiscoverFacetField; @@ -75,7 +75,7 @@ public class DiscoverQueryBuilderTest { private Context context; @Mock - private DSpaceObject scope; + private BrowsableDSpaceObject scope; private DiscoveryConfiguration discoveryConfiguration; private String query; @@ -92,30 +92,29 @@ public class DiscoverQueryBuilderTest { .then(invocation -> invocation.getArguments()[0] + "_sort"); when(searchService - .getFacetYearRange(eq(context), any(DSpaceObject.class), any(DiscoverySearchFilterFacet.class), any())) - .then(invocation - -> new FacetYearRange((DiscoverySearchFilterFacet) invocation.getArguments()[2])); + .getFacetYearRange(eq(context), any(BrowsableDSpaceObject.class), any(DiscoverySearchFilterFacet.class), + any(), any(DiscoverQuery.class))) + .then(invocation -> new FacetYearRange((DiscoverySearchFilterFacet) invocation.getArguments()[2])); when(searchService.toFilterQuery(any(Context.class), any(String.class), any(String.class), any(String.class))) .then(invocation -> new DiscoverFilterQuery((String) invocation.getArguments()[1], - invocation.getArguments()[1] + ":\"" + invocation - .getArguments()[3] + "\"", - (String) invocation.getArguments()[3])); + invocation.getArguments()[1] + ":\"" + invocation.getArguments()[3] + "\"", + (String) invocation.getArguments()[3])); discoveryConfiguration = new DiscoveryConfiguration(); discoveryConfiguration.setDefaultFilterQueries(Arrays.asList("archived:true")); - DiscoveryHitHighlightingConfiguration discoveryHitHighlightingConfiguration = new - DiscoveryHitHighlightingConfiguration(); + DiscoveryHitHighlightingConfiguration discoveryHitHighlightingConfiguration = + new DiscoveryHitHighlightingConfiguration(); List discoveryHitHighlightFieldConfigurations = new LinkedList<>(); - DiscoveryHitHighlightFieldConfiguration discoveryHitHighlightFieldConfiguration = new - DiscoveryHitHighlightFieldConfiguration(); + DiscoveryHitHighlightFieldConfiguration discoveryHitHighlightFieldConfiguration = + new DiscoveryHitHighlightFieldConfiguration(); discoveryHitHighlightFieldConfiguration.setField("dc.title"); - DiscoveryHitHighlightFieldConfiguration discoveryHitHighlightFieldConfiguration1 = new - DiscoveryHitHighlightFieldConfiguration(); + DiscoveryHitHighlightFieldConfiguration discoveryHitHighlightFieldConfiguration1 = + new DiscoveryHitHighlightFieldConfiguration(); discoveryHitHighlightFieldConfiguration1.setField("fulltext"); discoveryHitHighlightFieldConfigurations.add(discoveryHitHighlightFieldConfiguration1); @@ -164,8 +163,8 @@ public class DiscoverQueryBuilderTest { @Test public void testBuildQuery() throws Exception { - DiscoverQuery discoverQuery = queryBuilder.buildQuery(context, scope, discoveryConfiguration, query, - Arrays.asList(searchFilter), "item", page); + DiscoverQuery discoverQuery = queryBuilder + .buildQuery(context, scope, discoveryConfiguration, query, Arrays.asList(searchFilter), "item", page); assertThat(discoverQuery.getFilterQueries(), containsInAnyOrder("archived:true", "subject:\"Java\"")); assertThat(discoverQuery.getQuery(), is(query)); @@ -177,24 +176,21 @@ public class DiscoverQueryBuilderTest { assertThat(discoverQuery.getFacetMinCount(), is(1)); assertThat(discoverQuery.getFacetOffset(), is(0)); assertThat(discoverQuery.getFacetFields(), hasSize(2)); - assertThat(discoverQuery.getFacetFields(), containsInAnyOrder( - new ReflectionEquals(new DiscoverFacetField("subject", DiscoveryConfigurationParameters.TYPE_TEXT, 6, - DiscoveryConfigurationParameters.SORT.COUNT)), - new ReflectionEquals( - new DiscoverFacetField("hierarchy", DiscoveryConfigurationParameters.TYPE_HIERARCHICAL, 8, - DiscoveryConfigurationParameters.SORT.VALUE)) - )); + assertThat(discoverQuery.getFacetFields(), containsInAnyOrder(new ReflectionEquals( + new DiscoverFacetField("subject", DiscoveryConfigurationParameters.TYPE_TEXT, 6, + DiscoveryConfigurationParameters.SORT.COUNT)), new ReflectionEquals( + new DiscoverFacetField("hierarchy", DiscoveryConfigurationParameters.TYPE_HIERARCHICAL, 8, + DiscoveryConfigurationParameters.SORT.VALUE)))); assertThat(discoverQuery.getHitHighlightingFields(), hasSize(2)); - assertThat(discoverQuery.getHitHighlightingFields(), containsInAnyOrder( - new ReflectionEquals(new DiscoverHitHighlightingField("dc.title", 0, 3)), - new ReflectionEquals(new DiscoverHitHighlightingField("fulltext", 0, 3)) - )); + assertThat(discoverQuery.getHitHighlightingFields(), + containsInAnyOrder(new ReflectionEquals(new DiscoverHitHighlightingField("dc.title", 0, 3)), + new ReflectionEquals(new DiscoverHitHighlightingField("fulltext", 0, 3)))); } @Test public void testBuildQueryDefaults() throws Exception { - DiscoverQuery discoverQuery = queryBuilder.buildQuery(context, null, discoveryConfiguration, null, - null, null, null); + DiscoverQuery discoverQuery = + queryBuilder.buildQuery(context, null, discoveryConfiguration, null, null, null, null); assertThat(discoverQuery.getFilterQueries(), containsInAnyOrder("archived:true")); assertThat(discoverQuery.getQuery(), isEmptyOrNullString()); @@ -208,26 +204,23 @@ public class DiscoverQueryBuilderTest { assertThat(discoverQuery.getFacetMinCount(), is(1)); assertThat(discoverQuery.getFacetOffset(), is(0)); assertThat(discoverQuery.getFacetFields(), hasSize(2)); - assertThat(discoverQuery.getFacetFields(), containsInAnyOrder( - new ReflectionEquals(new DiscoverFacetField("subject", DiscoveryConfigurationParameters.TYPE_TEXT, 6, - DiscoveryConfigurationParameters.SORT.COUNT)), - new ReflectionEquals( - new DiscoverFacetField("hierarchy", DiscoveryConfigurationParameters.TYPE_HIERARCHICAL, 8, - DiscoveryConfigurationParameters.SORT.VALUE)) - )); + assertThat(discoverQuery.getFacetFields(), containsInAnyOrder(new ReflectionEquals( + new DiscoverFacetField("subject", DiscoveryConfigurationParameters.TYPE_TEXT, 6, + DiscoveryConfigurationParameters.SORT.COUNT)), new ReflectionEquals( + new DiscoverFacetField("hierarchy", DiscoveryConfigurationParameters.TYPE_HIERARCHICAL, 8, + DiscoveryConfigurationParameters.SORT.VALUE)))); assertThat(discoverQuery.getHitHighlightingFields(), hasSize(2)); - assertThat(discoverQuery.getHitHighlightingFields(), containsInAnyOrder( - new ReflectionEquals(new DiscoverHitHighlightingField("dc.title", 0, 3)), - new ReflectionEquals(new DiscoverHitHighlightingField("fulltext", 0, 3)) - )); + assertThat(discoverQuery.getHitHighlightingFields(), + containsInAnyOrder(new ReflectionEquals(new DiscoverHitHighlightingField("dc.title", 0, 3)), + new ReflectionEquals(new DiscoverHitHighlightingField("fulltext", 0, 3)))); } @Test public void testSortByScore() throws Exception { page = new PageRequest(2, 10, Sort.Direction.ASC, "SCORE"); - DiscoverQuery discoverQuery = queryBuilder.buildQuery(context, null, discoveryConfiguration, null, - null, null, page); + DiscoverQuery discoverQuery = + queryBuilder.buildQuery(context, null, discoveryConfiguration, null, null, null, page); assertThat(discoverQuery.getFilterQueries(), containsInAnyOrder("archived:true")); assertThat(discoverQuery.getQuery(), isEmptyOrNullString()); @@ -241,39 +234,36 @@ public class DiscoverQueryBuilderTest { assertThat(discoverQuery.getFacetMinCount(), is(1)); assertThat(discoverQuery.getFacetOffset(), is(0)); assertThat(discoverQuery.getFacetFields(), hasSize(2)); - assertThat(discoverQuery.getFacetFields(), containsInAnyOrder( - new ReflectionEquals(new DiscoverFacetField("subject", DiscoveryConfigurationParameters.TYPE_TEXT, 6, - DiscoveryConfigurationParameters.SORT.COUNT)), - new ReflectionEquals( - new DiscoverFacetField("hierarchy", DiscoveryConfigurationParameters.TYPE_HIERARCHICAL, 8, - DiscoveryConfigurationParameters.SORT.VALUE)) - )); + assertThat(discoverQuery.getFacetFields(), containsInAnyOrder(new ReflectionEquals( + new DiscoverFacetField("subject", DiscoveryConfigurationParameters.TYPE_TEXT, 6, + DiscoveryConfigurationParameters.SORT.COUNT)), new ReflectionEquals( + new DiscoverFacetField("hierarchy", DiscoveryConfigurationParameters.TYPE_HIERARCHICAL, 8, + DiscoveryConfigurationParameters.SORT.VALUE)))); assertThat(discoverQuery.getHitHighlightingFields(), hasSize(2)); - assertThat(discoverQuery.getHitHighlightingFields(), containsInAnyOrder( - new ReflectionEquals(new DiscoverHitHighlightingField("dc.title", 0, 3)), - new ReflectionEquals(new DiscoverHitHighlightingField("fulltext", 0, 3)) - )); + assertThat(discoverQuery.getHitHighlightingFields(), + containsInAnyOrder(new ReflectionEquals(new DiscoverHitHighlightingField("dc.title", 0, 3)), + new ReflectionEquals(new DiscoverHitHighlightingField("fulltext", 0, 3)))); } @Test(expected = InvalidDSpaceObjectTypeException.class) public void testInvalidDSOType() throws Exception { - queryBuilder.buildQuery(context, scope, discoveryConfiguration, query, - Arrays.asList(searchFilter), "TEST", page); + queryBuilder + .buildQuery(context, scope, discoveryConfiguration, query, Arrays.asList(searchFilter), "TEST", page); } @Test(expected = InvalidSortingException.class) public void testInvalidSortField() throws Exception { page = new PageRequest(2, 10, Sort.Direction.ASC, "test"); - queryBuilder.buildQuery(context, scope, discoveryConfiguration, query, - Arrays.asList(searchFilter), "ITEM", page); + queryBuilder + .buildQuery(context, scope, discoveryConfiguration, query, Arrays.asList(searchFilter), "ITEM", page); } @Test(expected = InvalidSearchFilterException.class) public void testInvalidSearchFilter1() throws Exception { searchFilter = new SearchFilter("test", "equals", "Smith, Donald"); - queryBuilder.buildQuery(context, scope, discoveryConfiguration, query, - Arrays.asList(searchFilter), "ITEM", page); + queryBuilder + .buildQuery(context, scope, discoveryConfiguration, query, Arrays.asList(searchFilter), "ITEM", page); } @Test(expected = InvalidSearchFilterException.class) @@ -281,8 +271,8 @@ public class DiscoverQueryBuilderTest { when(searchService.toFilterQuery(any(Context.class), any(String.class), any(String.class), any(String.class))) .thenThrow(SQLException.class); - queryBuilder.buildQuery(context, scope, discoveryConfiguration, query, - Arrays.asList(searchFilter), "ITEM", page); + queryBuilder + .buildQuery(context, scope, discoveryConfiguration, query, Arrays.asList(searchFilter), "ITEM", page); } @Test @@ -310,7 +300,7 @@ public class DiscoverQueryBuilderTest { @Test(expected = InvalidSearchFacetException.class) public void testInvalidSearchFacet() throws Exception { queryBuilder.buildFacetQuery(context, scope, discoveryConfiguration, null, query, - Arrays.asList(searchFilter), "item", page, "test"); + Arrays.asList(searchFilter), "item", page, "test"); } } \ No newline at end of file diff --git a/dspace/config/modules/discovery.cfg b/dspace/config/modules/discovery.cfg index b9d35a65df..f45780edb3 100644 --- a/dspace/config/modules/discovery.cfg +++ b/dspace/config/modules/discovery.cfg @@ -7,6 +7,11 @@ ##### Search Indexing ##### discovery.search.server = ${solr.server}/search +### See SolrServiceImpl, default number of threads is 5; +### WARNING: before changing this value please check the configuration of the connection pool to the Database. +#discovery.indexer.items.threads = 9 +discovery.indexer.items.threads = 5 + #Enable the url validation of the search.server setting above. #Defaults to true: validation is enabled #discovery.solr.url.validation.enabled = true @@ -14,11 +19,12 @@ discovery.search.server = ${solr.server}/search #Char used to ensure that the sidebar facets are case insensitive #discovery.solr.facets.split.char=\n|||\n -# index.ignore-variants = false -# index.ignore-authority = false +# discovery.index.ignore-variants = false +# discovery.index.ignore-authority = false discovery.index.projection=dc.title,dc.contributor.*,dc.date.issued -# ONLY-FOR-JSPUI: -# 1) you need to set the DiscoverySearchRequestProcessor in the dspace.cfg -# 2) to show facet on Site/Community/etc. you need to add a Site/Community/Collection -# Processors plugin in the dspace.cfg +discovery.facet.namedtype.item = 000item\n|||\nArchived###item +discovery.facet.namedtype.workspace = 001workspace\n|||\nWorkspace###workspace +discovery.facet.namedtype.workflow.item = 002workflow\n|||\nWorkflow###workflow +discovery.facet.namedtype.workflow.claimed = 003workflow\n|||\nValidation###validation +discovery.facet.namedtype.workflow.pooled = 004workflow\n|||\nWaiting for Controller###waitingforcontroller diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index ba57e659ea..ff0b0a78c5 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -50,6 +50,9 @@ + + + @@ -134,13 +137,14 @@ - - - - - - - + + + + + search.resourcetype:2 + + @@ -247,6 +251,14 @@ + + + + + search.resourcetype:2 + + @@ -289,6 +301,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:2 OR search.resourcetype:[8 TO 9] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dc.title + dc.contributor.author + dc.creator + dc.subject + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + search.resourcetype:[10 TO 11] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dc.title + dc.contributor.author + dc.creator + dc.subject + + + + + + + + + + + + + + @@ -468,6 +693,46 @@ + + + + + dc.type + + + + + + + + + placeholder.placeholder.placeholder + + + + + + + + + placeholder.placeholder.placeholder + + + + + + + + + + placeholder.placeholder.placeholder + + + +