diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/AbstractSearch.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/AbstractSearch.java index 9ae3851375..e6d67309da 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/AbstractSearch.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/AbstractSearch.java @@ -23,6 +23,7 @@ import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer; import org.dspace.app.xmlui.utils.DSpaceValidity; import org.dspace.app.xmlui.utils.HandleUtil; import org.dspace.app.xmlui.utils.UIException; +import org.dspace.app.xmlui.utils.ContextUtil; import org.dspace.app.xmlui.wing.Message; import org.dspace.app.xmlui.wing.WingException; import org.dspace.app.xmlui.wing.element.*; @@ -91,28 +92,7 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement * Cached query results */ protected DiscoverResult queryResults; - - /** - * Static query results for exporting metadata - */ - private static DiscoverResult staticQueryResults; - - public static boolean isStaticQueryResults = false; - public void setStaticQueryResults(DiscoverResult qResults) { - staticQueryResults = qResults; - isStaticQueryResults = true; - } - - public static DiscoverResult getStaticQueryResults() { - return staticQueryResults; - } - - public static void freeStaticQueryResults() { - staticQueryResults = null; - isStaticQueryResults = false; - } - /** * Cached query arguments */ @@ -736,28 +716,24 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement * * @param scope the dspace object parent */ - public void performSearch(DSpaceObject scope) throws UIException, SearchServiceException { - - if (queryResults != null) - { + public void performSearch(DSpaceObject scope) throws UIException, SearchServiceException + { + if (queryResults != null) { return; } String query = getQuery(); - - //DSpaceObject scope = getScope(); - + int page = getParameterPage(); List filterQueries = new ArrayList(); String[] fqs = getFilterQueries(); - if (fqs != null) - { + if (fqs != null) { filterQueries.addAll(Arrays.asList(fqs)); } - + this.queryArgs = new DiscoverQuery(); queryArgs.setMaxResults(getParameterRpp()); @@ -773,35 +749,32 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement String sortBy = ObjectModelHelper.getRequest(objectModel).getParameter("sort_by"); DiscoverySortConfiguration searchSortConfiguration = discoveryConfiguration.getSearchSortConfiguration(); - if(sortBy == null){ + if(sortBy == null) { //Attempt to find the default one, if none found we use SCORE sortBy = "score"; - if(searchSortConfiguration != null){ + if(searchSortConfiguration != null) { for (DiscoverySortFieldConfiguration sortFieldConfiguration : searchSortConfiguration.getSortFields()) { - if(sortFieldConfiguration.equals(searchSortConfiguration.getDefaultSort())){ + if(sortFieldConfiguration.equals(searchSortConfiguration.getDefaultSort())) { sortBy = SearchUtils.getSearchService().toSortFieldIndex(sortFieldConfiguration.getMetadataField(), sortFieldConfiguration.getType()); } } } } + String sortOrder = ObjectModelHelper.getRequest(objectModel).getParameter("order"); - if(sortOrder == null && searchSortConfiguration != null){ + if(sortOrder == null && searchSortConfiguration != null) { sortOrder = searchSortConfiguration.getDefaultSortOrder().toString(); } - if (sortOrder == null || sortOrder.equalsIgnoreCase("DESC")) - { + if (sortOrder == null || sortOrder.equalsIgnoreCase("DESC")) { queryArgs.setSortField(sortBy, DiscoverQuery.SORT_ORDER.desc); } - else - { + else { queryArgs.setSortField(sortBy, DiscoverQuery.SORT_ORDER.asc); } - String groupBy = ObjectModelHelper.getRequest(objectModel).getParameter("group_by"); - // Enable groupBy collapsing if designated if (groupBy != null && !groupBy.equalsIgnoreCase("none")) { /** Construct a Collapse Field Query */ @@ -816,25 +789,20 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement // TODO: I think that can be more transparently done in the solr solrconfig.xml with DISMAX and boosting /** sort in groups to get publications to top */ queryArgs.setSortField("dc.type", DiscoverQuery.SORT_ORDER.asc); - } queryArgs.setQuery(query != null && !query.trim().equals("") ? query : null); - if (page > 1) - { + if (page > 1) { queryArgs.setStart((page - 1) * queryArgs.getMaxResults()); } - else - { + else { queryArgs.setStart(0); } - if(discoveryConfiguration.getHitHighlightingConfiguration() != null) - { + if(discoveryConfiguration.getHitHighlightingConfiguration() != null) { List metadataFields = discoveryConfiguration.getHitHighlightingConfiguration().getMetadataFields(); - for (DiscoveryHitHighlightFieldConfiguration fieldConfiguration : metadataFields) - { + for (DiscoveryHitHighlightFieldConfiguration fieldConfiguration : metadataFields) { queryArgs.addHitHighlightingField(new DiscoverHitHighlightingField(fieldConfiguration.getField(), fieldConfiguration.getMaxSize(), fieldConfiguration.getSnippets())); } } @@ -842,18 +810,6 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement queryArgs.setSpellCheck(discoveryConfiguration.isSpellCheckEnabled()); this.queryResults = SearchUtils.getSearchService().search(context, scope, queryArgs); - - if(page == 1) { - queryArgs.setMaxResults(safeLongToInt(this.queryResults.getTotalSearchResults())); - setStaticQueryResults(SearchUtils.getSearchService().search(context, scope, queryArgs)); - } - } - - public static int safeLongToInt(long l) { - if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) { - throw new IllegalArgumentException(l + " cannot be cast to int."); - } - return (int) l; } /** @@ -861,35 +817,135 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement * * @throws IOException */ - public static DSpaceCSV exportMetadata(Context context) throws IOException + public DSpaceCSV exportMetadata(Map objectModel, String query, String filters) throws IOException, UIException, SearchServiceException, SQLException { + DiscoverResult qResults = new DiscoverResult(); + DiscoverQuery qArgs = new DiscoverQuery(); + + Context context = ContextUtil.obtainContext(objectModel); + + Request request = ObjectModelHelper.getRequest(objectModel); + + DSpaceObject scope = HandleUtil.obtainHandle(objectModel); + + List filterQueries = new ArrayList(); + + String[] fqs = filters.split(","); + + if (fqs != null) { + filterQueries.addAll(Arrays.asList(fqs)); + } + + qArgs.setMaxResults(getParameterRpp()); + + //Add the configured default filter queries + DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration(scope); + List defaultFilterQueries = discoveryConfiguration.getDefaultFilterQueries(); + qArgs.addFilterQueries(defaultFilterQueries.toArray(new String[defaultFilterQueries.size()])); + + if (filterQueries.size() > 0) { + qArgs.addFilterQueries(filterQueries.toArray(new String[filterQueries.size()])); + } + + String sortBy = ObjectModelHelper.getRequest(objectModel).getParameter("sort_by"); + DiscoverySortConfiguration searchSortConfiguration = discoveryConfiguration.getSearchSortConfiguration(); + if(sortBy == null) { + //Attempt to find the default one, if none found we use SCORE + sortBy = "score"; + if(searchSortConfiguration != null) { + for (DiscoverySortFieldConfiguration sortFieldConfiguration : searchSortConfiguration.getSortFields()) { + if(sortFieldConfiguration.equals(searchSortConfiguration.getDefaultSort())) { + sortBy = SearchUtils.getSearchService().toSortFieldIndex(sortFieldConfiguration.getMetadataField(), sortFieldConfiguration.getType()); + } + } + } + } + + String sortOrder = ObjectModelHelper.getRequest(objectModel).getParameter("order"); + if(sortOrder == null && searchSortConfiguration != null) { + sortOrder = searchSortConfiguration.getDefaultSortOrder().toString(); + } + + if (sortOrder == null || sortOrder.equalsIgnoreCase("DESC")) { + qArgs.setSortField(sortBy, DiscoverQuery.SORT_ORDER.desc); + } + else { + qArgs.setSortField(sortBy, DiscoverQuery.SORT_ORDER.asc); + } + + String groupBy = ObjectModelHelper.getRequest(objectModel).getParameter("group_by"); + + // Enable groupBy collapsing if designated + if (groupBy != null && !groupBy.equalsIgnoreCase("none")) { + /** Construct a Collapse Field Query */ + qArgs.addProperty("collapse.field", groupBy); + qArgs.addProperty("collapse.threshold", "1"); + qArgs.addProperty("collapse.includeCollapsedDocs.fl", "handle"); + qArgs.addProperty("collapse.facet", "before"); + + //queryArgs.a type:Article^2 + + // TODO: This is a hack to get Publications (Articles) to always be at the top of Groups. + // TODO: I think that can be more transparently done in the solr solrconfig.xml with DISMAX and boosting + /** sort in groups to get publications to top */ + qArgs.setSortField("dc.type", DiscoverQuery.SORT_ORDER.asc); + } + + qArgs.setQuery(query != null && !query.trim().equals("") ? query : null); + + qArgs.setStart(0); + + if(discoveryConfiguration.getHitHighlightingConfiguration() != null) { + List metadataFields = discoveryConfiguration.getHitHighlightingConfiguration().getMetadataFields(); + for (DiscoveryHitHighlightFieldConfiguration fieldConfiguration : metadataFields) { + qArgs.addHitHighlightingField(new DiscoverHitHighlightingField(fieldConfiguration.getField(), fieldConfiguration.getMaxSize(), fieldConfiguration.getSnippets())); + } + } + + qArgs.setSpellCheck(discoveryConfiguration.isSpellCheckEnabled()); + + qResults = SearchUtils.getSearchService().search(context, scope, qArgs); + + qArgs.setMaxResults(safeLongToInt(qResults.getTotalSearchResults())); + + qResults = SearchUtils.getSearchService().search(context, scope, qArgs); + Item[] resultsItems; - // Get a list of found items + + // Get a list of found items ArrayList items = new ArrayList(); - for (DSpaceObject resultDSO : getStaticQueryResults().getDspaceObjects()) - { - if (resultDSO instanceof Item) - { + for (DSpaceObject resultDSO : qResults.getDspaceObjects()) { + if (resultDSO instanceof Item) { items.add((Item) resultDSO); } } resultsItems = new Item[items.size()]; resultsItems = items.toArray(resultsItems); + // Log the attempt log.info(LogManager.getHeader(context, "metadataexport", "exporting_search")); + // Export a search view ArrayList iids = new ArrayList(); - for (Item item : items) - { + for (Item item : items) { iids.add(item.getID()); } ItemIterator ii = new ItemIterator(context, iids); MetadataExport exporter = new MetadataExport(context, ii, false); + // Perform the export DSpaceCSV csv = exporter.export(); log.info(LogManager.getHeader(context, "metadataexport", "exported_file:search-results.csv")); + return csv; } + + public static int safeLongToInt(long l) { + if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) { + throw new IllegalArgumentException(l + " cannot be cast to int."); + } + return (int) l; + } /** * Returns a list of the filter queries for use in rendering pages, creating page more urls, .... @@ -1128,5 +1184,4 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement + (queryArgs == null ? "" : queryArgs.getQuery()) + "\",results=(" + countCommunities + "," + countCollections + "," + countItems + ")")); } -} - +} \ No newline at end of file diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/Navigation.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/Navigation.java index b9e4d38d3c..14dfc9e910 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/Navigation.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/Navigation.java @@ -34,6 +34,7 @@ import org.dspace.content.Item; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.DSpaceObject; +import org.dspace.discovery.*; import org.xml.sax.SAXException; import org.apache.log4j.Logger; @@ -57,23 +58,7 @@ public class Navigation extends AbstractDSpaceTransformer implements CacheablePr * This key must be unique inside the space of this component. */ public Serializable getKey() { - try { - Request request = ObjectModelHelper.getRequest(objectModel); - String key = request.getScheme() + request.getServerName() + request.getServerPort() + request.getSitemapURI() + request.getQueryString(); - - DSpaceObject dso = HandleUtil.obtainHandle(objectModel); - if (dso != null) - { - key += "-" + dso.getHandle(); - } - - return HashUtil.hash(key); - } - catch (SQLException sqle) - { - // Ignore all errors and just return that the component is not cachable. - return "0"; - } + return "0"; } /** @@ -143,28 +128,37 @@ public class Navigation extends AbstractDSpaceTransformer implements CacheablePr String search_export_config = ConfigurationManager.getProperty("xmlui.search.metadata_export"); - if(uri.contains("discover")) { + String query = decodeFromURL(request.getParameter("query")); + + String fqps = ""; + String[] fqs = DiscoveryUIUtils.getFilterQueries(ObjectModelHelper.getRequest(objectModel), context); + + if (fqs != null) + { + for(int i = 0; i < fqs.length; i++) { + if(i < fqs.length - 1) + fqps += fqs[i] + ","; + else + fqps += fqs[i]; + } + } + + if(uri.contains("discover")) { if(search_export_config != null) { if(search_export_config.equals("admin")) { if(AuthorizeManager.isAdmin(context)) { List results = options.addList("context"); results.setHead(T_context_head); - results.addItem().addXref(contextPath + "/discover/csv", T_export_metadata); + results.addItem().addXref(contextPath + "/discover/csv/" + query + "/" + fqps, T_export_metadata); } } else if(search_export_config.equals("user") || search_export_config.equals("anonymous")){ List results = options.addList("context"); results.setHead(T_context_head); - results.addItem().addXref(contextPath + "/discover/csv", T_export_metadata); + results.addItem().addXref(contextPath + "/discover/csv/" + query + "/" + fqps, T_export_metadata); } } - } - else { - if(AbstractSearch.isStaticQueryResults) { - AbstractSearch.freeStaticQueryResults(); - } - } - + } } /** @@ -179,7 +173,4 @@ public class Navigation extends AbstractDSpaceTransformer implements CacheablePr pageMeta.addMetadata("search", "advancedURL").addContent(contextPath + "/discover"); pageMeta.addMetadata("search", "queryField").addContent("query"); } - -} - - +} \ No newline at end of file diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/SearchMetadataExportReader.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/SearchMetadataExportReader.java index 2ba0e6ffc9..b6ea9e8f00 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/SearchMetadataExportReader.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/SearchMetadataExportReader.java @@ -35,6 +35,7 @@ import org.dspace.app.xmlui.wing.element.Body; import org.dspace.app.xmlui.utils.UIException; import org.dspace.app.xmlui.utils.AuthenticationUtil; import org.dspace.app.xmlui.utils.ContextUtil; + import org.dspace.app.xmlui.aspect.discovery.AbstractSearch; import org.apache.log4j.Logger; @@ -52,7 +53,6 @@ import org.dspace.content.DSpaceObject; import org.dspace.content.ItemIterator; - /** * * AbstractReader that generates a CSV of search @@ -62,6 +62,8 @@ import org.dspace.content.ItemIterator; public class SearchMetadataExportReader extends AbstractReader implements Recyclable { + private static Logger log = Logger.getLogger(MetadataExportReader.class); + /** * Messages to be sent when the user is not authorized to view * a particular bitstream. They will be redirected to the login @@ -91,8 +93,6 @@ public class SearchMetadataExportReader extends AbstractReader implements Recycl /** The Cocoon request */ protected Request request; - private static Logger log = Logger.getLogger(MetadataExportReader.class); - DSpaceCSV csv = null; String filename = null; @@ -101,24 +101,27 @@ public class SearchMetadataExportReader extends AbstractReader implements Recycl * * See the class description for information on configuration options. */ - public void setup(SourceResolver resolver, Map objectModel, String src, - Parameters par) throws ProcessingException, SAXException, - IOException + public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par) throws ProcessingException, SAXException, IOException { super.setup(resolver, objectModel, src, par); try { - this.request = ObjectModelHelper.getRequest(objectModel); - this.response = ObjectModelHelper.getResponse(objectModel); - + this.request = ObjectModelHelper.getRequest(objectModel); + this.response = ObjectModelHelper.getResponse(objectModel); + + String query = par.getParameter("query"); + String filters = par.getParameter("filters"); + + ExportSearch exportSearch = new ExportSearch(); + Context context = ContextUtil.obtainContext(objectModel); String search_export_config = ConfigurationManager.getProperty("xmlui.search.metadata_export"); if(search_export_config.equals("admin")) { if(AuthorizeManager.isAdmin(context)) { - csv = AbstractSearch.exportMetadata(context); + csv = exportSearch.exportMetadata(objectModel, query, filters); filename = "search-results.csv"; } else { @@ -144,7 +147,7 @@ public class SearchMetadataExportReader extends AbstractReader implements Recycl } else if(search_export_config.equals("user")) { if(AuthenticationUtil.isLoggedIn(request)) { - csv = AbstractSearch.exportMetadata(context); + csv = exportSearch.exportMetadata(objectModel, query, filters); filename = "search-results.csv"; } else { @@ -156,20 +159,17 @@ public class SearchMetadataExportReader extends AbstractReader implements Recycl } } else if(search_export_config.equals("anonymous")) { - csv = AbstractSearch.exportMetadata(context); + csv = exportSearch.exportMetadata(objectModel, query, filters); filename = "search-results.csv"; } } - catch (RuntimeException e) - { + catch (RuntimeException e) { throw e; } - catch (IOException e) - { + catch (IOException e) { throw new ProcessingException("Unable to export metadata.",e); } - catch (Exception e) - { + catch (Exception e) { throw new ProcessingException("Unable to read bitstream.",e); } } @@ -192,5 +192,14 @@ public class SearchMetadataExportReader extends AbstractReader implements Recycl public void recycle() { this.response = null; this.request = null; - } + } +} + +class ExportSearch extends AbstractSearch +{ + public ExportSearch() {} + protected String getQuery() throws UIException { return null; } + protected String getBasicUrl() throws SQLException { return null; } + protected String generateURL(Map parameters) throws UIException { return null; } + public void addBody(Body body) throws SAXException, WingException, UIException, SQLException, IOException, AuthorizeException {} } diff --git a/dspace-xmlui/src/main/webapp/sitemap.xmap b/dspace-xmlui/src/main/webapp/sitemap.xmap index 8ab4614d13..de91c49ee4 100644 --- a/dspace-xmlui/src/main/webapp/sitemap.xmap +++ b/dspace-xmlui/src/main/webapp/sitemap.xmap @@ -391,8 +391,11 @@ - - + + + + +