Merge pull request #60 from abollini/DS-1217
DS-1217 Porting Discovery to the JSPUI
@@ -222,6 +222,24 @@ public class Item extends DSpaceObject
|
||||
return new ItemIterator(context, rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all "final" items in the archive, both archived ("in archive" flag) or
|
||||
* withdrawn items are included. The order of the list is indeterminate.
|
||||
*
|
||||
* @param context
|
||||
* DSpace context object
|
||||
* @return an iterator over the items in the archive.
|
||||
* @throws SQLException
|
||||
*/
|
||||
public static ItemIterator findAllUnfiltered(Context context) throws SQLException
|
||||
{
|
||||
String myQuery = "SELECT * FROM item WHERE in_archive='1' or withdrawn='1'";
|
||||
|
||||
TableRowIterator rows = DatabaseManager.queryTable(context, "item", myQuery);
|
||||
|
||||
return new ItemIterator(context, rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all the items in the archive by a given submitter. The order is
|
||||
* indeterminate. Only items with the "in archive" flag set are included.
|
||||
|
@@ -202,7 +202,7 @@ public class PluginManager
|
||||
if (val == null)
|
||||
{
|
||||
log.warn("No Configuration entry found for Sequence Plugin interface="+iname);
|
||||
return new Object[0];
|
||||
return (Object[]) Array.newInstance(intfc, 0);
|
||||
}
|
||||
classname = val.trim().split("\\s*,\\s*");
|
||||
sequenceConfig.put(iname, classname);
|
||||
|
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.plugin;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Interface that must be implemented by any plugin wanting to be called at the
|
||||
* inception of the Item page (in HandleServlet). Classes that
|
||||
* implement the process method and appear in the configuration will be run
|
||||
* before the at the start of preparing the item home page has any chance
|
||||
* to continue its execution. <b>Note that the plugin is executed also before
|
||||
* than the READ permission on the item is checked</b>
|
||||
*
|
||||
* @author Andrea Bollini
|
||||
*
|
||||
*/
|
||||
public interface ItemHomeProcessor
|
||||
{
|
||||
/**
|
||||
* execute the process
|
||||
*
|
||||
* @param context the DSpace context
|
||||
* @param request the HTTP request
|
||||
* @param response the HTTP response
|
||||
* @param item the item object whose home page we are on
|
||||
*
|
||||
* @throws PluginException any particular problem with the plugin execution
|
||||
* @throws AuthorizeException Authorisation errors during plugin execution
|
||||
*/
|
||||
void process(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response, Item item)
|
||||
throws PluginException, AuthorizeException;
|
||||
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.plugin;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Interface that must be implemented by any plugin wanting to be called at the
|
||||
* inception of the Site home page (in index.jsp "welcome servlet"). Classes that
|
||||
* implement the process method and appear in the configuration will be run
|
||||
* before the at the start of preparing the home page has any chance
|
||||
* to continue its execution
|
||||
*
|
||||
* @author Andrea Bollini
|
||||
*
|
||||
*/
|
||||
public interface SiteHomeProcessor
|
||||
{
|
||||
/**
|
||||
* execute the process
|
||||
*
|
||||
* @param context the DSpace context
|
||||
* @param request the HTTP request
|
||||
* @param response the HTTP response
|
||||
*
|
||||
* @throws PluginException any particular problem with the plugin execution
|
||||
* @throws AuthorizeException Authorisation errors during plugin execution
|
||||
*/
|
||||
void process(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response)
|
||||
throws PluginException, AuthorizeException;
|
||||
|
||||
}
|
@@ -10,6 +10,7 @@ package org.dspace.search;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
@@ -115,6 +116,9 @@ public class DSQuery
|
||||
|
||||
try
|
||||
{
|
||||
// calculate execution time
|
||||
Date startTime = new Date();
|
||||
|
||||
// grab a searcher, and do the search
|
||||
IndexSearcher searcher = getSearcher(c);
|
||||
|
||||
@@ -134,6 +138,10 @@ public class DSQuery
|
||||
//Retrieve enough docs to get all the results we need !
|
||||
TopDocs hits = performQuery(args, searcher, myquery, args.getPageSize() * (args.getStart() + 1));
|
||||
|
||||
Date endTime = new Date();
|
||||
|
||||
qr.setQueryTime(endTime.getTime() - startTime.getTime());
|
||||
|
||||
// set total number of hits
|
||||
qr.setHitCount(hits.totalHits);
|
||||
|
||||
|
@@ -18,6 +18,8 @@ import org.dspace.core.ConfigurationManager;
|
||||
*/
|
||||
public class QueryResults
|
||||
{
|
||||
private long queryTime; // time to search (ms)
|
||||
|
||||
private int hitCount; // total hits returned by search engine
|
||||
|
||||
private int start; // offset of query 'page'
|
||||
@@ -34,6 +36,16 @@ public class QueryResults
|
||||
/** number of metadata elements to display before truncating using "et al" */
|
||||
private int etAl = ConfigurationManager.getIntProperty("webui.itemlist.author-limit");
|
||||
|
||||
public long getQueryTime()
|
||||
{
|
||||
return queryTime;
|
||||
}
|
||||
|
||||
public void setQueryTime(long queryTime)
|
||||
{
|
||||
this.queryTime = queryTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of metadata fields at which to truncate with "et al"
|
||||
*/
|
||||
|
@@ -817,16 +817,40 @@ jsp.search.advanced.type.title = Title
|
||||
jsp.search.error.invalid-search-string = Invalid search string
|
||||
jsp.search.error.number-format-exception = Number format exception
|
||||
jsp.search.error.query-too-broad = Your query was too broad. Try a narrower query.
|
||||
jsp.search.general.new-search = Start a new search
|
||||
jsp.search.general.next = next
|
||||
jsp.search.general.noresults = Search produced no results.
|
||||
jsp.search.general.previous = previous
|
||||
jsp.search.results.colhits = Collection hits:
|
||||
jsp.search.results.comhits = Community Hits:
|
||||
jsp.search.results.itemhits = Item hits:
|
||||
jsp.search.results.results = Results {0}-{1} of {2}.
|
||||
jsp.search.results.results = Results {0}-{1} of {2} (Search time: {3} seconds).
|
||||
jsp.search.results.searchfor = for
|
||||
jsp.search.results.searchin = Search:
|
||||
jsp.search.results.title = Search Results
|
||||
jsp.search.title = Search
|
||||
jsp.search.error.discovery = An error has occured. Your query is invalid or the search engine is down.
|
||||
jsp.search.facet.refine = Discover
|
||||
jsp.search.facet.refine.author = Author
|
||||
jsp.search.facet.refine.subject = Subject
|
||||
jsp.search.facet.refine.dateIssued = Date issued
|
||||
jsp.search.facet.refine.previous = < previous
|
||||
jsp.search.facet.refine.next = next >
|
||||
jsp.search.facet.narrow = Filter by {0}
|
||||
jsp.search.filter.heading = Add filters:
|
||||
jsp.search.filter.hint = Use filters to refine the search results.
|
||||
jsp.search.filter.add = Add
|
||||
jsp.search.filter.applied = Current filters:
|
||||
jsp.search.filter.title = Title
|
||||
jsp.search.filter.author = Author
|
||||
jsp.search.filter.subject = Subject
|
||||
jsp.search.filter.dateIssued = Date Issued
|
||||
jsp.search.filter.op.equals = Equals
|
||||
jsp.search.filter.op.notequals = Not Equals
|
||||
jsp.search.filter.op.contains = Contains
|
||||
jsp.search.filter.op.notcontains = Not Contains
|
||||
jsp.search.filter.op.authority = ID
|
||||
jsp.search.filter.op.notauthority = Not ID
|
||||
jsp.statistics.title = Statistics
|
||||
jsp.statistics.heading.visits = Total Visits
|
||||
jsp.statistics.heading.monthlyvisits = Total Visits per Month
|
||||
@@ -1456,6 +1480,10 @@ search.sort-by.relevance
|
||||
search.sort-by.title = Title
|
||||
search.sort-by.dateissued = Issue Date
|
||||
search.sort-by.dateaccessioned = Submit Date
|
||||
# used by discovery (standard sort index <metadata>_sort)
|
||||
search.sort-by.dc.title_sort = Title
|
||||
# used by discovery (date sort index <metadata>_dt)
|
||||
search.sort-by.dc.date.issued_dt = Issue Date
|
||||
search.update = Update
|
||||
|
||||
# authority-control confidence levels, descriptions:
|
||||
|
53
dspace-discovery/dspace-discovery-jspui-api/pom.xml
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
<artifactId>dspace-discovery-jspui-api</artifactId>
|
||||
<name>DSpace Discovery :: Discovery JSPUI API</name>
|
||||
|
||||
<parent>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-discovery</artifactId>
|
||||
<version>3.0-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-jspui-api</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>solr-solrj</artifactId>
|
||||
<groupId>org.apache.solr</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.sf.flexjson</groupId>
|
||||
<artifactId>flexjson</artifactId>
|
||||
<version>2.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- external -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-discovery-provider</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@@ -0,0 +1,793 @@
|
||||
package org.dspace.app.webui.discovery;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.app.webui.util.UIUtil;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.discovery.DiscoverFacetField;
|
||||
import org.dspace.discovery.DiscoverFilterQuery;
|
||||
import org.dspace.discovery.DiscoverQuery;
|
||||
import org.dspace.discovery.DiscoverQuery.SORT_ORDER;
|
||||
import org.dspace.discovery.DiscoverResult;
|
||||
import org.dspace.discovery.SearchServiceException;
|
||||
import org.dspace.discovery.SearchUtils;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfigurationParameters;
|
||||
import org.dspace.discovery.configuration.DiscoverySearchFilterFacet;
|
||||
import org.dspace.discovery.configuration.DiscoverySortConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoverySortFieldConfiguration;
|
||||
import org.dspace.discovery.configuration.SidebarFacetConfiguration;
|
||||
import org.dspace.handle.HandleManager;
|
||||
import org.dspace.search.QueryArgs;
|
||||
import org.dspace.search.QueryResults;
|
||||
|
||||
public class DiscoverUtility
|
||||
{
|
||||
/** log4j category */
|
||||
private static Logger log = Logger.getLogger(DiscoverUtility.class);
|
||||
|
||||
/**
|
||||
* Get the scope of the search using the parameter found in the request
|
||||
*
|
||||
* @param context
|
||||
* @param request
|
||||
* @return
|
||||
* @throws IllegalStateException
|
||||
* @throws SQLException
|
||||
*/
|
||||
public static DSpaceObject getSearchScope(Context context,
|
||||
HttpServletRequest request) throws IllegalStateException,
|
||||
SQLException
|
||||
{
|
||||
// Get the location parameter, if any
|
||||
String location = request.getParameter("location");
|
||||
if (location == null)
|
||||
{
|
||||
if (UIUtil.getCollectionLocation(request) != null)
|
||||
{
|
||||
return UIUtil.getCollectionLocation(request);
|
||||
}
|
||||
if (UIUtil.getCommunityLocation(request) != null)
|
||||
{
|
||||
return UIUtil.getCommunityLocation(request);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
DSpaceObject scope = HandleManager.resolveToObject(context, location);
|
||||
return scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a DiscoverQuery object using the parameter in the request
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
* @throws SearchServiceException
|
||||
*/
|
||||
public static DiscoverQuery getDiscoverQuery(Context context,
|
||||
HttpServletRequest request, DSpaceObject scope, boolean enableFacet)
|
||||
{
|
||||
DiscoverQuery queryArgs = new DiscoverQuery();
|
||||
DiscoveryConfiguration discoveryConfiguration = SearchUtils
|
||||
.getDiscoveryConfiguration(scope);
|
||||
|
||||
List<String> userFilters = setupBasicQuery(context,
|
||||
discoveryConfiguration, request, queryArgs);
|
||||
|
||||
setPagination(request, queryArgs, discoveryConfiguration);
|
||||
|
||||
if (enableFacet
|
||||
&& !"submit_export_metadata".equals(UIUtil.getSubmitButton(
|
||||
request, "submit")))
|
||||
{
|
||||
setFacet(context, request, scope, queryArgs,
|
||||
discoveryConfiguration, userFilters);
|
||||
}
|
||||
|
||||
return queryArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the DiscoverQuery object for an autocomplete search using
|
||||
* parameters in the request
|
||||
*
|
||||
* @param context
|
||||
* @param request
|
||||
* @param scope
|
||||
* @return
|
||||
*/
|
||||
public static DiscoverQuery getDiscoverAutocomplete(Context context,
|
||||
HttpServletRequest request, DSpaceObject scope)
|
||||
{
|
||||
DiscoverQuery queryArgs = new DiscoverQuery();
|
||||
DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration();
|
||||
|
||||
setupBasicQuery(context, discoveryConfiguration, request, queryArgs);
|
||||
String autoIndex = request.getParameter("auto_idx");
|
||||
String autoQuery = request.getParameter("auto_query");
|
||||
String sort = request.getParameter("auto_sort");
|
||||
String autoType = request.getParameter("auto_type");
|
||||
if ("contains".equals(autoType) || "notcontains".equals(autoType))
|
||||
{
|
||||
autoType = DiscoveryConfigurationParameters.TYPE_STANDARD;
|
||||
}
|
||||
else if ("authority".equals(autoType) || "notauthority".equals(autoType))
|
||||
{
|
||||
autoType = DiscoveryConfigurationParameters.TYPE_AUTHORITY;
|
||||
}
|
||||
else
|
||||
{
|
||||
autoType = DiscoveryConfigurationParameters.TYPE_AC;
|
||||
}
|
||||
DiscoveryConfigurationParameters.SORT sortBy = DiscoveryConfigurationParameters.SORT.VALUE;
|
||||
if (StringUtils.isNotBlank(sort))
|
||||
{
|
||||
if ("count".equalsIgnoreCase(sort))
|
||||
{
|
||||
sortBy = DiscoveryConfigurationParameters.SORT.COUNT;
|
||||
}
|
||||
else
|
||||
{
|
||||
sortBy = DiscoveryConfigurationParameters.SORT.VALUE;
|
||||
}
|
||||
}
|
||||
// no user choices... default for autocomplete should be alphabetic
|
||||
// sorting in all cases except empty query where count is preferable
|
||||
else if ("".equals(autoQuery))
|
||||
{
|
||||
sortBy = DiscoveryConfigurationParameters.SORT.COUNT;
|
||||
}
|
||||
if (autoIndex == null)
|
||||
{
|
||||
autoIndex = "all";
|
||||
}
|
||||
if (autoQuery == null)
|
||||
{
|
||||
autoQuery = "";
|
||||
}
|
||||
|
||||
int limit = UIUtil.getIntParameter(request, "autocomplete.limit");
|
||||
if (limit == -1)
|
||||
{
|
||||
limit = 10;
|
||||
}
|
||||
DiscoverFacetField autocompleteField = new DiscoverFacetField(autoIndex,
|
||||
autoType,
|
||||
limit, sortBy, autoQuery.toLowerCase());
|
||||
queryArgs.addFacetField(autocompleteField);
|
||||
queryArgs.setMaxResults(0);
|
||||
queryArgs.setFacetMinCount(1);
|
||||
return queryArgs;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Build the query from the advanced search form
|
||||
// *
|
||||
// * @param request
|
||||
// * @return
|
||||
// */
|
||||
// public static String buildQuery(HttpServletRequest request)
|
||||
// {
|
||||
// int num_field = UIUtil.getIntParameter(request, "num_search_field");
|
||||
// if (num_field <= 0)
|
||||
// {
|
||||
// num_field = 3;
|
||||
// }
|
||||
// StringBuffer query = new StringBuffer();
|
||||
// buildQueryPart(query, request.getParameter("field"),
|
||||
// request.getParameter("query"), null);
|
||||
// for (int i = 1; i < num_field; i++)
|
||||
// {
|
||||
// buildQueryPart(query, request.getParameter("field" + i),
|
||||
// request.getParameter("query" + i),
|
||||
// request.getParameter("conjuction" + i));
|
||||
// }
|
||||
// return query.toString();
|
||||
// }
|
||||
//
|
||||
// private static void buildQueryPart(StringBuffer currQuery, String field,
|
||||
// String queryPart, String conjuction)
|
||||
// {
|
||||
// if (StringUtils.isBlank(queryPart))
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// StringBuffer tmp = new StringBuffer(queryPart);
|
||||
// if (StringUtils.isNotBlank(field))
|
||||
// {
|
||||
// tmp.insert(0, field + ":(").append(")");
|
||||
// }
|
||||
//
|
||||
// if (StringUtils.isNotBlank(conjuction) && currQuery.length() > 0)
|
||||
// {
|
||||
// currQuery.append(conjuction);
|
||||
// }
|
||||
// currQuery.append(tmp);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Return a QueryResults object as needed by the OpenSearch classes
|
||||
*
|
||||
* @param qResults
|
||||
* @return
|
||||
*/
|
||||
public static QueryResults toQueryResults(DiscoverResult qResults)
|
||||
{
|
||||
QueryResults qR = new QueryResults();
|
||||
qR.setHitCount((int) qResults.getTotalSearchResults());
|
||||
qR.setPageSize(qResults.getMaxResults());
|
||||
qR.setStart(qResults.getStart());
|
||||
|
||||
List<String> handles = new ArrayList<String>();
|
||||
List<Integer> types = new ArrayList<Integer>();
|
||||
List<Integer> ids = new ArrayList<Integer>();
|
||||
|
||||
for (DSpaceObject dso : qResults.getDspaceObjects())
|
||||
{
|
||||
handles.add(dso.getHandle());
|
||||
ids.add(dso.getID());
|
||||
types.add(dso.getType());
|
||||
}
|
||||
|
||||
qR.setHitIds(ids);
|
||||
qR.setHitTypes(types);
|
||||
qR.setHitHandles(handles);
|
||||
return qR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the basic query argumnets: the main query and all the filters
|
||||
* (default + user). Return the list of user filter
|
||||
*
|
||||
* @param context
|
||||
* @param request
|
||||
* @param queryArgs
|
||||
* the query object to populate
|
||||
* @return the list of user filer (as filter query)
|
||||
*/
|
||||
private static List<String> setupBasicQuery(Context context,
|
||||
DiscoveryConfiguration discoveryConfiguration,
|
||||
HttpServletRequest request, DiscoverQuery queryArgs)
|
||||
{
|
||||
// Get the query
|
||||
String query = request.getParameter("query");
|
||||
if (StringUtils.isNotBlank(query))
|
||||
{
|
||||
queryArgs.setQuery(query);
|
||||
}
|
||||
|
||||
List<String> defaultFilterQueries = discoveryConfiguration
|
||||
.getDefaultFilterQueries();
|
||||
if (defaultFilterQueries != null)
|
||||
{
|
||||
for (String f : defaultFilterQueries)
|
||||
{
|
||||
queryArgs.addFacetQuery(f);
|
||||
}
|
||||
}
|
||||
List<String[]> filters = getFilters(request);
|
||||
List<String> userFilters = new ArrayList<String>();
|
||||
for (String[] f : filters)
|
||||
{
|
||||
try
|
||||
{
|
||||
String newFilterQuery = SearchUtils.getSearchService()
|
||||
.toFilterQuery(context, f[0], f[1], f[2])
|
||||
.getFilterQuery();
|
||||
if (newFilterQuery != null)
|
||||
{
|
||||
queryArgs.addFilterQueries(newFilterQuery);
|
||||
userFilters.add(newFilterQuery);
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
log.error(LogManager.getHeader(context,
|
||||
"Error in discovery while setting up user facet query",
|
||||
"filter_field: " + f[0] + ",filter_type:"
|
||||
+ f[1] + ",filer_value:"
|
||||
+ f[2]), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return userFilters;
|
||||
|
||||
}
|
||||
|
||||
private static void setPagination(HttpServletRequest request,
|
||||
DiscoverQuery queryArgs,
|
||||
DiscoveryConfiguration discoveryConfiguration)
|
||||
{
|
||||
int start = UIUtil.getIntParameter(request, "start");
|
||||
// can't start earlier than 0 in the results!
|
||||
if (start < 0)
|
||||
{
|
||||
start = 0;
|
||||
}
|
||||
|
||||
String sortBy = request.getParameter("sort_by");
|
||||
String sortOrder = request.getParameter("order");
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sortOrder == null && searchSortConfiguration != null)
|
||||
{
|
||||
sortOrder = searchSortConfiguration.getDefaultSortOrder()
|
||||
.toString();
|
||||
}
|
||||
if (sortBy != null)
|
||||
{
|
||||
if ("asc".equalsIgnoreCase(sortOrder))
|
||||
{
|
||||
queryArgs.setSortField(sortBy, SORT_ORDER.asc);
|
||||
}
|
||||
else
|
||||
{
|
||||
queryArgs.setSortField(sortBy, SORT_ORDER.desc);
|
||||
}
|
||||
}
|
||||
|
||||
int rpp = UIUtil.getIntParameter(request, "rpp");
|
||||
// Override the page setting if exporting metadata
|
||||
if ("submit_export_metadata".equals(UIUtil.getSubmitButton(request,
|
||||
"submit")))
|
||||
{
|
||||
queryArgs.setStart(0);
|
||||
queryArgs.setMaxResults(Integer.MAX_VALUE);
|
||||
// search only for items other objects are not exported
|
||||
queryArgs.addFilterQueries("search.resourcetype:2");
|
||||
}
|
||||
else
|
||||
{
|
||||
// String groupBy = request.getParameter("group_by");
|
||||
//
|
||||
// // Enable groupBy collapsing if designated
|
||||
// if (groupBy != null && !groupBy.equalsIgnoreCase("none")) {
|
||||
// /** Construct a Collapse Field Query */
|
||||
// queryArgs.addProperty("collapse.field", groupBy);
|
||||
// queryArgs.addProperty("collapse.threshold", "1");
|
||||
// queryArgs.addProperty("collapse.includeCollapsedDocs.fl",
|
||||
// "handle");
|
||||
// queryArgs.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 the 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);
|
||||
//
|
||||
// }
|
||||
|
||||
if (rpp > 0)
|
||||
{
|
||||
queryArgs.setMaxResults(rpp);
|
||||
}
|
||||
else
|
||||
{
|
||||
queryArgs.setMaxResults(discoveryConfiguration.getDefaultRpp());
|
||||
}
|
||||
queryArgs.setStart(start);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setFacet(Context context, HttpServletRequest request,
|
||||
DSpaceObject scope, DiscoverQuery queryArgs,
|
||||
DiscoveryConfiguration discoveryConfiguration,
|
||||
List<String> userFilters)
|
||||
{
|
||||
List<DiscoverySearchFilterFacet> facets = discoveryConfiguration
|
||||
.getSidebarFacets();
|
||||
|
||||
log.info("facets for scope, " + scope + ": "
|
||||
+ (facets != null ? facets.size() : null));
|
||||
if (facets != null)
|
||||
{
|
||||
queryArgs.setFacetMinCount(1);
|
||||
}
|
||||
|
||||
/** enable faceting of search results */
|
||||
if (facets != null)
|
||||
{
|
||||
queryArgs.setFacetMinCount(1);
|
||||
for (DiscoverySearchFilterFacet facet : facets)
|
||||
{
|
||||
if (facet.getType().equals(
|
||||
DiscoveryConfigurationParameters.TYPE_DATE))
|
||||
{
|
||||
String dateFacet = facet.getIndexFieldName() + ".year";
|
||||
List<String> filterQueriesList = queryArgs
|
||||
.getFilterQueries();
|
||||
String[] filterQueries = new String[0];
|
||||
if (filterQueriesList != null)
|
||||
{
|
||||
filterQueries = new String[filterQueries.length];
|
||||
filterQueries = filterQueriesList
|
||||
.toArray(filterQueries);
|
||||
}
|
||||
try
|
||||
{
|
||||
// Get a range query so we can create facet
|
||||
// queries
|
||||
// ranging from out first to our last date
|
||||
// Attempt to determine our oldest & newest year
|
||||
// by
|
||||
// checking for previously selected filters
|
||||
int oldestYear = -1;
|
||||
int newestYear = -1;
|
||||
|
||||
for (String filterQuery : filterQueries)
|
||||
{
|
||||
if (filterQuery.startsWith(dateFacet + ":"))
|
||||
{
|
||||
// Check for a range
|
||||
Pattern pattern = Pattern
|
||||
.compile("\\[(.*? TO .*?)\\]");
|
||||
Matcher matcher = pattern.matcher(filterQuery);
|
||||
boolean hasPattern = matcher.find();
|
||||
if (hasPattern)
|
||||
{
|
||||
filterQuery = matcher.group(0);
|
||||
// We have a range
|
||||
// Resolve our range to a first &
|
||||
// endyear
|
||||
int tempOldYear = Integer
|
||||
.parseInt(filterQuery.split(" TO ")[0]
|
||||
.replace("[", "").trim());
|
||||
int tempNewYear = Integer
|
||||
.parseInt(filterQuery.split(" TO ")[1]
|
||||
.replace("]", "").trim());
|
||||
|
||||
// Check if we have a further filter
|
||||
// (or
|
||||
// a first one found)
|
||||
if (tempNewYear < newestYear
|
||||
|| oldestYear < tempOldYear
|
||||
|| newestYear == -1)
|
||||
{
|
||||
oldestYear = tempOldYear;
|
||||
newestYear = tempNewYear;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (filterQuery.indexOf(" OR ") != -1)
|
||||
{
|
||||
// Should always be the case
|
||||
filterQuery = filterQuery.split(" OR ")[0];
|
||||
}
|
||||
// We should have a single date
|
||||
oldestYear = Integer.parseInt(filterQuery
|
||||
.split(":")[1].trim());
|
||||
newestYear = oldestYear;
|
||||
// No need to look further
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if we have found a range, if not then
|
||||
// retrieve our first & last year by using solr
|
||||
if (oldestYear == -1 && newestYear == -1)
|
||||
{
|
||||
|
||||
DiscoverQuery yearRangeQuery = new DiscoverQuery();
|
||||
yearRangeQuery.setFacetMinCount(1);
|
||||
yearRangeQuery.setMaxResults(1);
|
||||
// Set our query to anything that has this
|
||||
// value
|
||||
yearRangeQuery.addFieldPresentQueries(dateFacet);
|
||||
// Set sorting so our last value will appear
|
||||
// on
|
||||
// top
|
||||
yearRangeQuery.setSortField(dateFacet + "_sort",
|
||||
DiscoverQuery.SORT_ORDER.asc);
|
||||
yearRangeQuery.addFilterQueries(filterQueries);
|
||||
yearRangeQuery.addSearchField(dateFacet);
|
||||
DiscoverResult lastYearResult = SearchUtils
|
||||
.getSearchService().search(context, scope,
|
||||
yearRangeQuery);
|
||||
|
||||
if (0 < lastYearResult.getDspaceObjects().size())
|
||||
{
|
||||
java.util.List<DiscoverResult.SearchDocument> searchDocuments = lastYearResult
|
||||
.getSearchDocument(lastYearResult
|
||||
.getDspaceObjects().get(0));
|
||||
if (0 < searchDocuments.size()
|
||||
&& 0 < searchDocuments
|
||||
.get(0)
|
||||
.getSearchFieldValues(dateFacet)
|
||||
.size())
|
||||
{
|
||||
oldestYear = Integer
|
||||
.parseInt(searchDocuments
|
||||
.get(0)
|
||||
.getSearchFieldValues(
|
||||
dateFacet).get(0));
|
||||
}
|
||||
}
|
||||
// Now get the first year
|
||||
yearRangeQuery.setSortField(dateFacet + "_sort",
|
||||
DiscoverQuery.SORT_ORDER.desc);
|
||||
DiscoverResult firstYearResult = SearchUtils
|
||||
.getSearchService().search(context, scope,
|
||||
yearRangeQuery);
|
||||
if (0 < firstYearResult.getDspaceObjects().size())
|
||||
{
|
||||
java.util.List<DiscoverResult.SearchDocument> searchDocuments = firstYearResult
|
||||
.getSearchDocument(firstYearResult
|
||||
.getDspaceObjects().get(0));
|
||||
if (0 < searchDocuments.size()
|
||||
&& 0 < searchDocuments
|
||||
.get(0)
|
||||
.getSearchFieldValues(dateFacet)
|
||||
.size())
|
||||
{
|
||||
newestYear = Integer
|
||||
.parseInt(searchDocuments
|
||||
.get(0)
|
||||
.getSearchFieldValues(
|
||||
dateFacet).get(0));
|
||||
}
|
||||
}
|
||||
// No values found!
|
||||
if (newestYear == -1 || oldestYear == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int gap = 1;
|
||||
// Attempt to retrieve our gap by the algorithm
|
||||
// below
|
||||
int yearDifference = newestYear - oldestYear;
|
||||
if (yearDifference != 0)
|
||||
{
|
||||
while (10 < ((double) yearDifference / gap))
|
||||
{
|
||||
gap *= 10;
|
||||
}
|
||||
}
|
||||
// We need to determine our top year so we can
|
||||
// start
|
||||
// our count from a clean year
|
||||
// Example: 2001 and a gap from 10 we need the
|
||||
// following result: 2010 - 2000 ; 2000 - 1990
|
||||
// hence
|
||||
// the top year
|
||||
int topYear = (int) (Math.ceil((float) (newestYear)
|
||||
/ gap) * gap);
|
||||
|
||||
if (gap == 1)
|
||||
{
|
||||
// We need a list of our years
|
||||
// We have a date range add faceting for our
|
||||
// field
|
||||
// The faceting will automatically be
|
||||
// limited to
|
||||
// the 10 years in our span due to our
|
||||
// filterquery
|
||||
queryArgs.addFacetField(new DiscoverFacetField(
|
||||
facet.getIndexFieldName(), facet.getType(),
|
||||
10, facet.getSortOrder()));
|
||||
}
|
||||
else
|
||||
{
|
||||
java.util.List<String> facetQueries = new ArrayList<String>();
|
||||
// Create facet queries but limit then to 11
|
||||
// (11
|
||||
// == when we need to show a show more url)
|
||||
for (int year = topYear - gap; year > oldestYear
|
||||
&& (facetQueries.size() < 11); year -= gap)
|
||||
{
|
||||
// Add a filter to remove the last year
|
||||
// only
|
||||
// if we aren't the last year
|
||||
int bottomYear = year - gap;
|
||||
// Make sure we don't go below our last
|
||||
// year
|
||||
// found
|
||||
if (bottomYear < oldestYear)
|
||||
{
|
||||
bottomYear = oldestYear;
|
||||
}
|
||||
|
||||
// Also make sure we don't go above our
|
||||
// newest year
|
||||
int currentTop = year;
|
||||
if ((year == topYear))
|
||||
{
|
||||
currentTop = newestYear;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We need to do -1 on this one to
|
||||
// get a
|
||||
// better result
|
||||
currentTop--;
|
||||
}
|
||||
facetQueries.add(dateFacet + ":[" + bottomYear
|
||||
+ " TO " + currentTop + "]");
|
||||
}
|
||||
for (String facetQuery : facetQueries)
|
||||
{
|
||||
queryArgs.addFacetQuery(facetQuery);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error(
|
||||
LogManager
|
||||
.getHeader(
|
||||
context,
|
||||
"Error in discovery while setting up date facet range",
|
||||
"date facet: " + dateFacet), e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int facetLimit = facet.getFacetLimit();
|
||||
|
||||
int facetPage = UIUtil.getIntParameter(request,
|
||||
facet.getIndexFieldName() + "_page");
|
||||
if (facetPage < 0)
|
||||
{
|
||||
facetPage = 0;
|
||||
}
|
||||
// at most all the user filters belong to this facet
|
||||
int alreadySelected = userFilters.size();
|
||||
|
||||
// Add one to our facet limit to make sure that if
|
||||
// we
|
||||
// have more then the shown facets that we show our
|
||||
// show
|
||||
// more url
|
||||
// add the already selected facet so to have a full
|
||||
// top list
|
||||
// if possible
|
||||
queryArgs.addFacetField(new DiscoverFacetField(facet
|
||||
.getIndexFieldName(),
|
||||
DiscoveryConfigurationParameters.TYPE_TEXT,
|
||||
facetLimit + 1 + alreadySelected, facet
|
||||
.getSortOrder(), facetPage * facetLimit));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String[]> getFilters(HttpServletRequest request)
|
||||
{
|
||||
String submit = UIUtil.getSubmitButton(request, "submit");
|
||||
int ignore = -1;
|
||||
if (submit.startsWith("submit_filter_remove_"))
|
||||
{
|
||||
ignore = Integer.parseInt(submit.substring("submit_filter_remove_".length()));
|
||||
}
|
||||
List<String[]> appliedFilters = new ArrayList<String[]>();
|
||||
|
||||
List<String> filterValue = new ArrayList<String>();
|
||||
List<String> filterOp = new ArrayList<String>();
|
||||
List<String> filterField = new ArrayList<String>();
|
||||
for (int idx = 1; ; idx++)
|
||||
{
|
||||
String op = request.getParameter("filter_type_"+idx);
|
||||
if (StringUtils.isBlank(op))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (idx != ignore)
|
||||
{
|
||||
filterOp.add(op);
|
||||
filterField.add(request.getParameter("filter_field_"+idx));
|
||||
filterValue.add(request.getParameter("filter_value_"+idx));
|
||||
}
|
||||
}
|
||||
|
||||
String op = request.getParameter("filtertype");
|
||||
if (StringUtils.isNotBlank(op))
|
||||
{
|
||||
filterOp.add(op);
|
||||
filterField.add(request.getParameter("filtername"));
|
||||
filterValue.add(request.getParameter("filterquery"));
|
||||
}
|
||||
|
||||
for (int idx = 0; idx < filterOp.size(); idx++)
|
||||
{
|
||||
appliedFilters.add(new String[] { filterField.get(idx),
|
||||
filterOp.get(idx), filterValue.get(idx) });
|
||||
}
|
||||
return appliedFilters;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Build the query from the advanced search form
|
||||
// *
|
||||
// * @param request
|
||||
// * @return
|
||||
// */
|
||||
// public static String buildQuery(HttpServletRequest request)
|
||||
// {
|
||||
// int num_field = UIUtil.getIntParameter(request, "num_search_field");
|
||||
// if (num_field <= 0)
|
||||
// {
|
||||
// num_field = 3;
|
||||
// }
|
||||
// StringBuffer query = new StringBuffer();
|
||||
// buildQueryPart(query, request.getParameter("field"),
|
||||
// request.getParameter("query"), null);
|
||||
// for (int i = 1; i < num_field; i++)
|
||||
// {
|
||||
// buildQueryPart(query, request.getParameter("field" + i),
|
||||
// request.getParameter("query" + i),
|
||||
// request.getParameter("conjuction" + i));
|
||||
// }
|
||||
// return query.toString();
|
||||
// }
|
||||
//
|
||||
// private static void buildQueryPart(StringBuffer currQuery, String field,
|
||||
// String queryPart, String conjuction)
|
||||
// {
|
||||
// if (StringUtils.isBlank(queryPart))
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// StringBuffer tmp = new StringBuffer(queryPart);
|
||||
// if (StringUtils.isNotBlank(field))
|
||||
// {
|
||||
// tmp.insert(0, field + ":(").append(")");
|
||||
// }
|
||||
//
|
||||
// if (StringUtils.isNotBlank(conjuction) && currQuery.length() > 0)
|
||||
// {
|
||||
// currQuery.append(conjuction);
|
||||
// }
|
||||
// currQuery.append(tmp);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
package org.dspace.app.webui.discovery;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.dspace.app.webui.json.JSONRequest;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.discovery.DiscoverQuery;
|
||||
import org.dspace.discovery.DiscoverResult;
|
||||
import org.dspace.discovery.DiscoverResult.FacetResult;
|
||||
import org.dspace.discovery.SearchUtils;
|
||||
|
||||
import flexjson.JSONSerializer;
|
||||
|
||||
public class DiscoveryJSONRequest extends JSONRequest
|
||||
{
|
||||
|
||||
public void doJSONRequest(Context context, HttpServletRequest request,
|
||||
HttpServletResponse resp) throws AuthorizeException, IOException
|
||||
{
|
||||
String reqPath = request.getPathInfo();
|
||||
// remove the first slash if present
|
||||
if (reqPath.startsWith("/"))
|
||||
{
|
||||
reqPath = reqPath.substring(1);
|
||||
}
|
||||
|
||||
if (reqPath.equalsIgnoreCase(getSubPath() + "/autocomplete"))
|
||||
{
|
||||
doAutocomplete(context, request, resp);
|
||||
return;
|
||||
}
|
||||
// unkwon action (in future we can implement ajax for pagination, etc.)
|
||||
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
private void doAutocomplete(Context context, HttpServletRequest request,
|
||||
HttpServletResponse resp)
|
||||
{
|
||||
try
|
||||
{
|
||||
DSpaceObject scope = DiscoverUtility.getSearchScope(context,
|
||||
request);
|
||||
DiscoverQuery autocompleteQuery = DiscoverUtility
|
||||
.getDiscoverAutocomplete(context, request, scope);
|
||||
DiscoverResult qResults = SearchUtils.getSearchService().search(
|
||||
context, autocompleteQuery);
|
||||
// extract the only facet present in the result response
|
||||
Set<String> facets = qResults.getFacetResults().keySet();
|
||||
List<FacetResult> fResults = new ArrayList<DiscoverResult.FacetResult>();
|
||||
if (facets != null && facets.size() > 0)
|
||||
{
|
||||
String autocompleteField = (String) facets.toArray()[0];
|
||||
fResults = qResults
|
||||
.getFacetResult(autocompleteField);
|
||||
}
|
||||
JSONSerializer serializer = new JSONSerializer();
|
||||
serializer.rootName("autocomplete");
|
||||
serializer.exclude("class","asFilterQuery");
|
||||
serializer.deepSerialize(fResults, resp.getWriter());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,481 @@
|
||||
package org.dspace.app.webui.discovery;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.app.bulkedit.DSpaceCSV;
|
||||
import org.dspace.app.bulkedit.MetadataExport;
|
||||
import org.dspace.app.util.OpenSearch;
|
||||
import org.dspace.app.util.SyndicationFeed;
|
||||
import org.dspace.app.webui.search.SearchProcessorException;
|
||||
import org.dspace.app.webui.search.SearchRequestProcessor;
|
||||
import org.dspace.app.webui.util.JSPManager;
|
||||
import org.dspace.app.webui.util.UIUtil;
|
||||
import org.dspace.authorize.AuthorizeManager;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.ItemIterator;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.discovery.DiscoverFilterQuery;
|
||||
import org.dspace.discovery.DiscoverQuery;
|
||||
import org.dspace.discovery.DiscoverResult;
|
||||
import org.dspace.discovery.SearchServiceException;
|
||||
import org.dspace.discovery.SearchUtils;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoverySearchFilter;
|
||||
import org.dspace.discovery.configuration.DiscoverySearchFilterFacet;
|
||||
import org.dspace.discovery.configuration.DiscoverySortFieldConfiguration;
|
||||
import org.dspace.discovery.configuration.SidebarFacetConfiguration;
|
||||
import org.dspace.search.QueryResults;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
public class DiscoverySearchRequestProcessor implements SearchRequestProcessor
|
||||
{
|
||||
private static String msgKey = "org.dspace.app.webui.servlet.FeedServlet";
|
||||
|
||||
/** log4j category */
|
||||
private static Logger log = Logger.getLogger(DiscoverySearchRequestProcessor.class);
|
||||
|
||||
// locale-sensitive metadata labels
|
||||
private Map<String, Map<String, String>> localeLabels = null;
|
||||
|
||||
public void init()
|
||||
{
|
||||
localeLabels = new HashMap<String, Map<String, String>>();
|
||||
}
|
||||
|
||||
public void doOpenSearch(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response) throws SearchProcessorException,
|
||||
IOException, ServletException
|
||||
{
|
||||
// dispense with simple service document requests
|
||||
String scope = request.getParameter("scope");
|
||||
if (scope != null && "".equals(scope))
|
||||
{
|
||||
scope = null;
|
||||
}
|
||||
String path = request.getPathInfo();
|
||||
if (path != null && path.endsWith("description.xml"))
|
||||
{
|
||||
String svcDescrip = OpenSearch.getDescription(scope);
|
||||
response.setContentType(OpenSearch
|
||||
.getContentType("opensearchdescription"));
|
||||
response.setContentLength(svcDescrip.length());
|
||||
response.getWriter().write(svcDescrip);
|
||||
return;
|
||||
}
|
||||
|
||||
// get enough request parameters to decide on action to take
|
||||
String format = request.getParameter("format");
|
||||
if (format == null || "".equals(format))
|
||||
{
|
||||
// default to atom
|
||||
format = "atom";
|
||||
}
|
||||
|
||||
// do some sanity checking
|
||||
if (!OpenSearch.getFormats().contains(format))
|
||||
{
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
// then the rest - we are processing the query
|
||||
DSpaceObject container;
|
||||
try
|
||||
{
|
||||
container = DiscoverUtility.getSearchScope(context,
|
||||
request);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new SearchProcessorException(e.getMessage(), e);
|
||||
}
|
||||
DiscoverQuery queryArgs = DiscoverUtility.getDiscoverQuery(context,
|
||||
request, container, false);
|
||||
String query = queryArgs.getQuery();
|
||||
|
||||
// Perform the search
|
||||
DiscoverResult qResults = null;
|
||||
try
|
||||
{
|
||||
qResults = SearchUtils.getSearchService().search(context,
|
||||
container, queryArgs);
|
||||
}
|
||||
catch (SearchServiceException e)
|
||||
{
|
||||
log.error(
|
||||
LogManager.getHeader(context, "opensearch", "query="
|
||||
+ queryArgs.getQuery() + ",scope=" + scope
|
||||
+ ",error=" + e.getMessage()), e);
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
// Log
|
||||
log.info(LogManager.getHeader(context, "opensearch",
|
||||
"scope=" + scope + ",query=\"" + query + "\",results=("
|
||||
+ qResults.getTotalSearchResults() + ")"));
|
||||
|
||||
// format and return results
|
||||
Map<String, String> labelMap = getLabels(request);
|
||||
DSpaceObject[] dsoResults = new DSpaceObject[qResults
|
||||
.getDspaceObjects().size()];
|
||||
qResults.getDspaceObjects().toArray(dsoResults);
|
||||
QueryResults qR = DiscoverUtility.toQueryResults(qResults);
|
||||
Document resultsDoc = OpenSearch.getResultsDoc(format, query, qR,
|
||||
container, dsoResults, labelMap);
|
||||
try
|
||||
{
|
||||
Transformer xf = TransformerFactory.newInstance().newTransformer();
|
||||
response.setContentType(OpenSearch.getContentType(format));
|
||||
xf.transform(new DOMSource(resultsDoc),
|
||||
new StreamResult(response.getWriter()));
|
||||
}
|
||||
catch (TransformerException e)
|
||||
{
|
||||
log.error(e);
|
||||
throw new ServletException(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> getLabels(HttpServletRequest request)
|
||||
{
|
||||
// Get access to the localized resource bundle
|
||||
Locale locale = request.getLocale();
|
||||
Map<String, String> labelMap = localeLabels.get(locale.toString());
|
||||
if (labelMap == null)
|
||||
{
|
||||
labelMap = getLocaleLabels(locale);
|
||||
localeLabels.put(locale.toString(), labelMap);
|
||||
}
|
||||
return labelMap;
|
||||
}
|
||||
|
||||
private Map<String, String> getLocaleLabels(Locale locale)
|
||||
{
|
||||
Map<String, String> labelMap = new HashMap<String, String>();
|
||||
ResourceBundle labels = ResourceBundle.getBundle("Messages", locale);
|
||||
|
||||
labelMap.put(SyndicationFeed.MSG_UNTITLED,
|
||||
labels.getString(msgKey + ".notitle"));
|
||||
labelMap.put(SyndicationFeed.MSG_LOGO_TITLE,
|
||||
labels.getString(msgKey + ".logo.title"));
|
||||
labelMap.put(SyndicationFeed.MSG_FEED_DESCRIPTION,
|
||||
labels.getString(msgKey + ".general-feed.description"));
|
||||
labelMap.put(SyndicationFeed.MSG_UITYPE, SyndicationFeed.UITYPE_JSPUI);
|
||||
for (String selector : SyndicationFeed.getDescriptionSelectors())
|
||||
{
|
||||
labelMap.put("metadata." + selector,
|
||||
labels.getString(SyndicationFeed.MSG_METADATA + selector));
|
||||
}
|
||||
return labelMap;
|
||||
}
|
||||
|
||||
public void doSimpleSearch(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response) throws SearchProcessorException,
|
||||
IOException, ServletException
|
||||
{
|
||||
Item[] resultsItems;
|
||||
Collection[] resultsCollections;
|
||||
Community[] resultsCommunities;
|
||||
DSpaceObject scope;
|
||||
try
|
||||
{
|
||||
scope = DiscoverUtility.getSearchScope(context, request);
|
||||
}
|
||||
catch (IllegalStateException e)
|
||||
{
|
||||
throw new SearchProcessorException(e.getMessage(), e);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new SearchProcessorException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
DiscoveryConfiguration discoveryConfiguration = SearchUtils
|
||||
.getDiscoveryConfiguration(scope);
|
||||
List<DiscoverySortFieldConfiguration> sortFields = discoveryConfiguration
|
||||
.getSearchSortConfiguration().getSortFields();
|
||||
List<String> sortOptions = new ArrayList<String>();
|
||||
for (DiscoverySortFieldConfiguration sortFieldConfiguration : sortFields)
|
||||
{
|
||||
String sortField = SearchUtils.getSearchService().toSortFieldIndex(
|
||||
sortFieldConfiguration.getMetadataField(),
|
||||
sortFieldConfiguration.getType());
|
||||
sortOptions.add(sortField);
|
||||
}
|
||||
request.setAttribute("sortOptions", sortOptions);
|
||||
|
||||
DiscoverQuery queryArgs = DiscoverUtility.getDiscoverQuery(context,
|
||||
request, scope, true);
|
||||
|
||||
List<DiscoverySearchFilterFacet> availableFacet = discoveryConfiguration
|
||||
.getSidebarFacets();
|
||||
|
||||
request.setAttribute("facetsConfig",
|
||||
availableFacet != null ? availableFacet
|
||||
: new ArrayList<DiscoverySearchFilterFacet>());
|
||||
int etal = UIUtil.getIntParameter(request, "etal");
|
||||
if (etal == -1)
|
||||
{
|
||||
etal = ConfigurationManager
|
||||
.getIntProperty("webui.itemlist.author-limit");
|
||||
}
|
||||
|
||||
request.setAttribute("etal", etal);
|
||||
|
||||
String query = queryArgs.getQuery();
|
||||
request.setAttribute("query", query);
|
||||
request.setAttribute("queryArgs", queryArgs);
|
||||
List<DiscoverySearchFilter> availableFilters = discoveryConfiguration
|
||||
.getSearchFilters();
|
||||
request.setAttribute("availableFilters", availableFilters);
|
||||
|
||||
List<String[]> appliedFilters = DiscoverUtility.getFilters(request);
|
||||
request.setAttribute("appliedFilters", appliedFilters);
|
||||
List<String> appliedFilterQueries = new ArrayList<String>();
|
||||
for (String[] filter : appliedFilters)
|
||||
{
|
||||
appliedFilterQueries.add(filter[0] + "::" + filter[1] + "::"
|
||||
+ filter[2]);
|
||||
}
|
||||
request.setAttribute("appliedFilterQueries", appliedFilterQueries);
|
||||
List<DSpaceObject> scopes = new ArrayList<DSpaceObject>();
|
||||
if (scope == null)
|
||||
{
|
||||
Community[] topCommunities;
|
||||
try
|
||||
{
|
||||
topCommunities = Community.findAllTop(context);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new SearchProcessorException(e.getMessage(), e);
|
||||
}
|
||||
for (Community com : topCommunities)
|
||||
{
|
||||
scopes.add(com);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
DSpaceObject pDso = scope.getParentObject();
|
||||
while (pDso != null)
|
||||
{
|
||||
// add to the available scopes in reverse order
|
||||
scopes.add(0, pDso);
|
||||
pDso = pDso.getParentObject();
|
||||
}
|
||||
scopes.add(scope);
|
||||
if (scope instanceof Community)
|
||||
{
|
||||
Community[] comms = ((Community) scope).getSubcommunities();
|
||||
for (Community com : comms)
|
||||
{
|
||||
scopes.add(com);
|
||||
}
|
||||
Collection[] colls = ((Community) scope).getCollections();
|
||||
for (Collection col : colls)
|
||||
{
|
||||
scopes.add(col);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new SearchProcessorException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
request.setAttribute("scope", scope);
|
||||
request.setAttribute("scopes", scopes);
|
||||
|
||||
// Perform the search
|
||||
DiscoverResult qResults = null;
|
||||
try
|
||||
{
|
||||
qResults = SearchUtils.getSearchService().search(context, scope,
|
||||
queryArgs);
|
||||
List<Community> resultsListComm = new ArrayList<Community>();
|
||||
List<Collection> resultsListColl = new ArrayList<Collection>();
|
||||
List<Item> resultsListItem = new ArrayList<Item>();
|
||||
|
||||
for (DSpaceObject dso : qResults.getDspaceObjects())
|
||||
{
|
||||
if (dso instanceof Item)
|
||||
{
|
||||
resultsListItem.add((Item) dso);
|
||||
}
|
||||
else if (dso instanceof Collection)
|
||||
{
|
||||
resultsListColl.add((Collection) dso);
|
||||
|
||||
}
|
||||
else if (dso instanceof Community)
|
||||
{
|
||||
resultsListComm.add((Community) dso);
|
||||
}
|
||||
}
|
||||
|
||||
// Make objects from the handles - make arrays, fill them out
|
||||
resultsCommunities = new Community[resultsListComm.size()];
|
||||
resultsCollections = new Collection[resultsListColl.size()];
|
||||
resultsItems = new Item[resultsListItem.size()];
|
||||
|
||||
resultsCommunities = resultsListComm.toArray(resultsCommunities);
|
||||
resultsCollections = resultsListColl.toArray(resultsCollections);
|
||||
resultsItems = resultsListItem.toArray(resultsItems);
|
||||
|
||||
// Log
|
||||
log.info(LogManager.getHeader(context, "search", "scope=" + scope
|
||||
+ ",query=\"" + query + "\",results=("
|
||||
+ resultsCommunities.length + ","
|
||||
+ resultsCollections.length + "," + resultsItems.length
|
||||
+ ")"));
|
||||
|
||||
// Pass in some page qualities
|
||||
// total number of pages
|
||||
long pageTotal = 1 + ((qResults.getTotalSearchResults() - 1) / qResults
|
||||
.getMaxResults());
|
||||
|
||||
// current page being displayed
|
||||
long pageCurrent = 1 + (qResults.getStart() / qResults
|
||||
.getMaxResults());
|
||||
|
||||
// pageLast = min(pageCurrent+3,pageTotal)
|
||||
long pageLast = ((pageCurrent + 3) > pageTotal) ? pageTotal
|
||||
: (pageCurrent + 3);
|
||||
|
||||
// pageFirst = max(1,pageCurrent-3)
|
||||
long pageFirst = ((pageCurrent - 3) > 1) ? (pageCurrent - 3) : 1;
|
||||
|
||||
// Pass the results to the display JSP
|
||||
request.setAttribute("items", resultsItems);
|
||||
request.setAttribute("communities", resultsCommunities);
|
||||
request.setAttribute("collections", resultsCollections);
|
||||
|
||||
request.setAttribute("pagetotal", new Long(pageTotal));
|
||||
request.setAttribute("pagecurrent", new Long(pageCurrent));
|
||||
request.setAttribute("pagelast", new Long(pageLast));
|
||||
request.setAttribute("pagefirst", new Long(pageFirst));
|
||||
|
||||
request.setAttribute("queryresults", qResults);
|
||||
|
||||
try
|
||||
{
|
||||
if (AuthorizeManager.isAdmin(context))
|
||||
{
|
||||
// Set a variable to create admin buttons
|
||||
request.setAttribute("admin_button", new Boolean(true));
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new SearchProcessorException(e.getMessage(), e); }
|
||||
|
||||
if ("submit_export_metadata".equals(UIUtil.getSubmitButton(request,
|
||||
"submit")))
|
||||
{
|
||||
exportMetadata(context, response, resultsItems);
|
||||
}
|
||||
}
|
||||
catch (SearchServiceException e)
|
||||
{
|
||||
log.error(
|
||||
LogManager.getHeader(context, "search", "query="
|
||||
+ queryArgs.getQuery() + ",scope=" + scope
|
||||
+ ",error=" + e.getMessage()), e);
|
||||
request.setAttribute("search.error", true);
|
||||
request.setAttribute("search.error.message", e.getMessage());
|
||||
}
|
||||
|
||||
JSPManager.showJSP(request, response, "/search/discovery.jsp");
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the search results as a csv file
|
||||
*
|
||||
* @param context
|
||||
* The DSpace context
|
||||
* @param response
|
||||
* The request object
|
||||
* @param items
|
||||
* The result items
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
protected void exportMetadata(Context context,
|
||||
HttpServletResponse response, Item[] items) throws IOException,
|
||||
ServletException
|
||||
{
|
||||
// Log the attempt
|
||||
log.info(LogManager.getHeader(context, "metadataexport",
|
||||
"exporting_search"));
|
||||
|
||||
// Export a search view
|
||||
ArrayList iids = new ArrayList();
|
||||
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();
|
||||
|
||||
// Return the csv file
|
||||
response.setContentType("text/csv; charset=UTF-8");
|
||||
response.setHeader("Content-Disposition",
|
||||
"attachment; filename=search-results.csv");
|
||||
PrintWriter out = response.getWriter();
|
||||
out.write(csv.toString());
|
||||
out.flush();
|
||||
out.close();
|
||||
log.info(LogManager.getHeader(context, "metadataexport",
|
||||
"exported_file:search-results.csv"));
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for constructing the discovery advanced search form
|
||||
*
|
||||
* @author Andrea Bollini
|
||||
*/
|
||||
@Override
|
||||
public void doAdvancedSearch(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response) throws SearchProcessorException,
|
||||
IOException, ServletException
|
||||
{
|
||||
// just redirect to the simple search servlet.
|
||||
// The advanced form is always displayed with Discovery togheter with
|
||||
// the search result
|
||||
// the first access to the advanced form performs a search for
|
||||
// "anythings" (SOLR *:*)
|
||||
response.sendRedirect(request.getContextPath() + "/simple-search");
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,90 @@
|
||||
package org.dspace.app.webui.discovery;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.discovery.DiscoverQuery;
|
||||
import org.dspace.discovery.DiscoverResult;
|
||||
import org.dspace.discovery.SearchServiceException;
|
||||
import org.dspace.discovery.SearchUtils;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoverySearchFilterFacet;
|
||||
import org.dspace.plugin.CollectionHomeProcessor;
|
||||
import org.dspace.plugin.CommunityHomeProcessor;
|
||||
import org.dspace.plugin.PluginException;
|
||||
import org.dspace.plugin.SiteHomeProcessor;
|
||||
|
||||
public class SideBarFacetProcessor implements CollectionHomeProcessor,
|
||||
CommunityHomeProcessor, SiteHomeProcessor
|
||||
{
|
||||
/** log4j category */
|
||||
private static Logger log = Logger.getLogger(SideBarFacetProcessor.class);
|
||||
|
||||
@Override
|
||||
public void process(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response, Community community)
|
||||
throws PluginException, AuthorizeException
|
||||
{
|
||||
process(context, request, response, (DSpaceObject) community);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response, Collection collection)
|
||||
throws PluginException, AuthorizeException
|
||||
{
|
||||
process(context, request, response, (DSpaceObject) collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response) throws PluginException,
|
||||
AuthorizeException
|
||||
{
|
||||
process(context, request, response, (DSpaceObject) null);
|
||||
}
|
||||
|
||||
private void process(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response, DSpaceObject scope)
|
||||
{
|
||||
DiscoverQuery queryArgs = DiscoverUtility.getDiscoverQuery(context,
|
||||
request, scope, true);
|
||||
queryArgs.setMaxResults(0);
|
||||
DiscoverResult qResults;
|
||||
try
|
||||
{
|
||||
qResults = SearchUtils.getSearchService().search(context, scope,
|
||||
queryArgs);
|
||||
request.setAttribute("discovery.fresults",
|
||||
qResults.getFacetResults());
|
||||
DiscoveryConfiguration discoveryConfiguration = SearchUtils
|
||||
.getDiscoveryConfiguration(scope);
|
||||
List<DiscoverySearchFilterFacet> availableFacet = discoveryConfiguration
|
||||
.getSidebarFacets();
|
||||
|
||||
request.setAttribute("facetsConfig",
|
||||
availableFacet != null ? availableFacet
|
||||
: new ArrayList<DiscoverySearchFilterFacet>());
|
||||
if (scope !=null)
|
||||
{
|
||||
request.setAttribute("discovery.searchScope",
|
||||
"/handle/" + scope.getHandle());
|
||||
}
|
||||
}
|
||||
catch (SearchServiceException e)
|
||||
{
|
||||
log.error(LogManager.getHeader(context,
|
||||
"discovery-process-sidebar", "scope=" + scope));
|
||||
}
|
||||
}
|
||||
}
|
102
dspace-discovery/dspace-discovery-jspui-webapp/pom.xml
Normal file
@@ -0,0 +1,102 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>war</packaging>
|
||||
<artifactId>dspace-discovery-jspui-webapp</artifactId>
|
||||
<name>DSpace Discovery :: Discovery JSPUI Webapp</name>
|
||||
|
||||
<parent>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-discovery</artifactId>
|
||||
<version>3.0-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-jspui-api</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>solr-solrj</artifactId>
|
||||
<groupId>org.apache.solr</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-discovery-jspui-api</artifactId>
|
||||
<version>3.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- external -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<configuration>
|
||||
<archiveClasses>false</archiveClasses>
|
||||
<attachClasses>true</attachClasses>
|
||||
<classesClassifier>classes</classesClassifier>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<packagingExcludes>WEB-INF/lib/*.jar</packagingExcludes>
|
||||
<warSourceExcludes>WEB-INF/lib/*.jar</warSourceExcludes>
|
||||
<webResources>
|
||||
<resource>
|
||||
<filtering>true</filtering>
|
||||
<directory>${basedir}/src/main/webapp</directory>
|
||||
<includes>
|
||||
<include>WEB-INF/web.xml</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</webResources>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>prepare-package</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.mycila.maven-license-plugin</groupId>
|
||||
<artifactId>maven-license-plugin</artifactId>
|
||||
<configuration>
|
||||
<!--Exclude license check for Discovery files which don't need it-->
|
||||
<excludes>
|
||||
<exclude>**/*.LICENSE</exclude>
|
||||
<exclude>**/jquery*</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!--
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<index>true</index>
|
||||
<manifestEntries>
|
||||
<Cocoon-Block-Name>discovery-xmlui-block</Cocoon-Block-Name>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
-->
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
@@ -0,0 +1,27 @@
|
||||
h3.facets {margin-left:0px;}
|
||||
div.facetsBox {margin:2px;min-width: 180px;width: 180px;}
|
||||
div.facetsBox ul {list-style: none; list-style-position: inside; padding:0px;}
|
||||
div.facet {margin-left:0px;margin-right:0px;border: 1px solid #CCCCCC; padding: 5px;}
|
||||
li.facet-next, li.facet-previous {margin-bottom:10px; margin-top:10px;font-weight: bold;}
|
||||
li.facet-next {text-align: right;}
|
||||
.facetName {font-weight: bold;}
|
||||
div.discovery-query {border: 1px solid #CCCCCC;background-color: #EEEEEE;padding:10px;white-space: nowrap;}
|
||||
div.discovery-query a {font-size: smaller;display: block;margin:2px;margin-left:5px;}
|
||||
div.discovery-search-appliedFilters {margin-top: 10px; background-color: #FFFFFF; border: 1px solid #CCCCCC;padding:10px;}
|
||||
div.discovery-search-appliedFilters span {font-weight: bold;display:block;margin-bottom:5px;}
|
||||
div.discovery-query label {font-weight: bold;margin:5px;}
|
||||
div.discovery-query select {margin-bottom:5px;}
|
||||
div.discovery-search-filters{border: 1px solid #CCCCCC;padding:10px;}
|
||||
div.discovery-search-filters span {display:block;margin:5px;}
|
||||
div.discovery-search-filters span.discovery-search-filters-heading {font-weight: bold};
|
||||
div.discovery-search-filters select {margin:5px;}
|
||||
div.discovery-pagination-controls {margin-top: 10px; background-color: #EEEEEE; border: 1px solid #CCCCCC;padding:10px;}
|
||||
|
||||
.clearfix:after {clear: both;content: ".";display: block;height: 0;visibility: hidden;}
|
||||
.pagination-masked.top {margin-top: 5px;}
|
||||
div.discovery-result-pagination {margin: 20px;margin-bottom:0px;line-height: 1em;padding: 10px;vertical-align: middle;}
|
||||
div.discovery-result-pagination h2.info, div.discovery-result-pagination p.info {float: left;margin:0px;}
|
||||
div.discovery-result-pagination ul.links {float: right;margin:0px;list-style: none outside none;}
|
||||
div.discovery-result-pagination ul.links li {display: inline; padding-left: 2px; padding-right: 2px;}
|
||||
.current-page-link {color: #CCCCCC;font-weight: bold;}
|
||||
div.discovery-result-results {padding:10px;}
|
@@ -0,0 +1,123 @@
|
||||
<%--
|
||||
|
||||
The contents of this file are subject to the license and copyright
|
||||
detailed in the LICENSE and NOTICE files at the root of the source
|
||||
tree and available online at
|
||||
|
||||
http://www.dspace.org/license/
|
||||
|
||||
--%>
|
||||
<%--
|
||||
- fragment JSP to be included in site, community or collection home to show discovery facets
|
||||
-
|
||||
- Attributes required:
|
||||
- discovery.fresults - the facets result to show
|
||||
- discovery.facetsConf - the facets configuration
|
||||
- discovery.searchScope - the search scope
|
||||
--%>
|
||||
|
||||
<%@page import="org.dspace.discovery.configuration.DiscoverySearchFilterFacet"%>
|
||||
<%@ page import="java.util.HashMap"%>
|
||||
<%@ page import="java.util.Set"%>
|
||||
<%@ page import="java.util.Map"%>
|
||||
<%@ page import="org.dspace.discovery.DiscoverResult.FacetResult"%>
|
||||
<%@ page import="java.util.List"%>
|
||||
<%@ page import="java.net.URLEncoder"%>
|
||||
<%@ page import="org.apache.commons.lang.StringUtils"%>
|
||||
|
||||
<%
|
||||
boolean brefine = false;
|
||||
|
||||
Map<String, List<FacetResult>> mapFacetes = (Map<String, List<FacetResult>>) request.getAttribute("discovery.fresults");
|
||||
List<DiscoverySearchFilterFacet> facetsConf = (List<DiscoverySearchFilterFacet>) request.getAttribute("facetsConfig");
|
||||
String searchScope = (String) request.getAttribute("discovery.searchScope");
|
||||
if (searchScope == null)
|
||||
{
|
||||
searchScope = "";
|
||||
}
|
||||
|
||||
if (mapFacetes != null)
|
||||
{
|
||||
for (DiscoverySearchFilterFacet facetConf : facetsConf)
|
||||
{
|
||||
String f = facetConf.getIndexFieldName();
|
||||
List<FacetResult> facet = mapFacetes.get(f);
|
||||
if (facet != null && facet.size() > 0)
|
||||
{
|
||||
brefine = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
facet = mapFacetes.get(f+".year");
|
||||
if (facet != null && facet.size() > 0)
|
||||
{
|
||||
brefine = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (brefine) {
|
||||
%>
|
||||
<h3 class="facets"><fmt:message key="jsp.search.facet.refine" /></h3>
|
||||
<div id="facets" class="facetsBox">
|
||||
<%
|
||||
for (DiscoverySearchFilterFacet facetConf : facetsConf)
|
||||
{
|
||||
String f = facetConf.getIndexFieldName();
|
||||
List<FacetResult> facet = mapFacetes.get(f);
|
||||
if (facet == null)
|
||||
{
|
||||
facet = mapFacetes.get(f+".year");
|
||||
}
|
||||
if (facet == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String fkey = "jsp.search.facet.refine."+f;
|
||||
int limit = facetConf.getFacetLimit()+1;
|
||||
%><div id="facet_<%= f %>" class="facet">
|
||||
<span class="facetName"><fmt:message key="<%= fkey %>" /></span>
|
||||
<ul><%
|
||||
int idx = 1;
|
||||
int currFp = UIUtil.getIntParameter(request, f+"_page");
|
||||
if (currFp < 0)
|
||||
{
|
||||
currFp = 0;
|
||||
}
|
||||
if (currFp > 0)
|
||||
{
|
||||
%><li class="facet-previous"><a href="<%= request.getContextPath()
|
||||
+ searchScope
|
||||
+ "?"+f+"_page="+(currFp-1) %>"><fmt:message key="jsp.search.facet.refine.previous" /></a></li>
|
||||
<%
|
||||
}
|
||||
if (facet != null)
|
||||
{
|
||||
for (FacetResult fvalue : facet)
|
||||
{
|
||||
if (idx == limit)
|
||||
{
|
||||
%><li class="facet-next"><a href="<%= request.getContextPath()
|
||||
+ searchScope
|
||||
+ "?"+f+"_page="+(currFp+1) %>"><fmt:message key="jsp.search.facet.refine.next" /></a></li>
|
||||
<%
|
||||
}
|
||||
else
|
||||
{
|
||||
%><li><a href="<%= request.getContextPath()
|
||||
+ searchScope
|
||||
+ "/simple-search?filterquery="+URLEncoder.encode(fvalue.getAsFilterQuery(),"UTF-8")
|
||||
+ "&filtername="+URLEncoder.encode(f,"UTF-8")
|
||||
+ "&filtertype="+URLEncoder.encode(fvalue.getFilterType(),"UTF-8") %>"
|
||||
title="<fmt:message key="jsp.search.facet.narrow"><fmt:param><%=fvalue.getDisplayedValue() %></fmt:param></fmt:message>">
|
||||
<%= StringUtils.abbreviate(fvalue.getDisplayedValue(),32) + " (" + fvalue.getCount()+")" %></a></li><%
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
%></ul></div><%
|
||||
}
|
||||
}
|
||||
%>
|
@@ -0,0 +1,715 @@
|
||||
<%--
|
||||
|
||||
The contents of this file are subject to the license and copyright
|
||||
detailed in the LICENSE and NOTICE files at the root of the source
|
||||
tree and available online at
|
||||
|
||||
http://www.dspace.org/license/
|
||||
|
||||
--%>
|
||||
|
||||
<%--
|
||||
- Display the form to refine the simple-search and dispaly the results of the search
|
||||
-
|
||||
- Attributes to pass in:
|
||||
-
|
||||
- scope - pass in if the scope of the search was a community
|
||||
- or a collection
|
||||
- scopes - the list of available scopes where limit the search
|
||||
- sortOptions - the list of available sort options
|
||||
- availableFilters - the list of filters available to the user
|
||||
-
|
||||
- query - The original query
|
||||
- queryArgs - The query configuration parameters (rpp, sort, etc.)
|
||||
- appliedFilters - The list of applied filters (user input or facet)
|
||||
-
|
||||
- search.error - a flag to say that an error has occurred
|
||||
- qResults - the discovery results
|
||||
- items - the results. An array of Items, most relevant first
|
||||
- communities - results, Community[]
|
||||
- collections - results, Collection[]
|
||||
-
|
||||
- admin_button - If the user is an admin
|
||||
--%>
|
||||
|
||||
<%@page import="org.dspace.discovery.configuration.DiscoverySearchFilterFacet"%>
|
||||
<%@page import="org.dspace.app.webui.util.UIUtil"%>
|
||||
<%@page import="java.util.HashMap"%>
|
||||
<%@page import="java.util.ArrayList"%>
|
||||
<%@page import="org.dspace.discovery.DiscoverFacetField"%>
|
||||
<%@page import="org.dspace.discovery.configuration.DiscoverySearchFilter"%>
|
||||
<%@page import="org.dspace.discovery.DiscoverFilterQuery"%>
|
||||
<%@page import="org.dspace.discovery.DiscoverQuery"%>
|
||||
<%@page import="org.apache.commons.lang.StringUtils"%>
|
||||
<%@page import="java.util.Map"%>
|
||||
<%@page import="org.dspace.discovery.DiscoverResult.FacetResult"%>
|
||||
<%@page import="org.dspace.discovery.DiscoverResult"%>
|
||||
<%@page import="org.dspace.content.DSpaceObject"%>
|
||||
<%@page import="java.util.List"%>
|
||||
<%@ page contentType="text/html;charset=UTF-8" %>
|
||||
|
||||
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"
|
||||
prefix="fmt" %>
|
||||
<%@ taglib uri="http://java.sun.com/jsp/jstl/core"
|
||||
prefix="c" %>
|
||||
|
||||
<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %>
|
||||
<%@ page import="org.apache.commons.lang.StringEscapeUtils" %>
|
||||
<%@ page import="java.net.URLEncoder" %>
|
||||
<%@ page import="org.dspace.content.Community" %>
|
||||
<%@ page import="org.dspace.content.Collection" %>
|
||||
<%@ page import="org.dspace.content.Item" %>
|
||||
<%@ page import="org.dspace.search.QueryResults" %>
|
||||
<%@ page import="org.dspace.sort.SortOption" %>
|
||||
<%@ page import="java.util.Enumeration" %>
|
||||
<%@ page import="java.util.Set" %>
|
||||
<%
|
||||
// Get the attributes
|
||||
DSpaceObject scope = (DSpaceObject) request.getAttribute("scope" );
|
||||
String searchScope = scope!=null?scope.getHandle():"";
|
||||
List<DSpaceObject> scopes = (List<DSpaceObject>) request.getAttribute("scopes");
|
||||
List<String> sortOptions = (List<String>) request.getAttribute("sortOptions");
|
||||
|
||||
String query = (String) request.getAttribute("query");
|
||||
if (query == null)
|
||||
{
|
||||
query = "";
|
||||
}
|
||||
Boolean error_b = (Boolean)request.getAttribute("search.error");
|
||||
boolean error = (error_b == null ? false : error_b.booleanValue());
|
||||
|
||||
DiscoverQuery qArgs = (DiscoverQuery) request.getAttribute("queryArgs");
|
||||
String sortedBy = qArgs.getSortField();
|
||||
String order = qArgs.getSortOrder().toString();
|
||||
String ascSelected = (SortOption.ASCENDING.equalsIgnoreCase(order) ? "selected=\"selected\"" : "");
|
||||
String descSelected = (SortOption.DESCENDING.equalsIgnoreCase(order) ? "selected=\"selected\"" : "");
|
||||
String httpFilters ="";
|
||||
|
||||
List<DiscoverySearchFilter> availableFilters = (List<DiscoverySearchFilter>) request.getAttribute("availableFilters");
|
||||
List<String[]> appliedFilters = (List<String[]>) request.getAttribute("appliedFilters");
|
||||
List<String> appliedFilterQueries = (List<String>) request.getAttribute("appliedFilterQueries");
|
||||
if (appliedFilters != null && appliedFilters.size() >0 )
|
||||
{
|
||||
int idx = 1;
|
||||
for (String[] filter : appliedFilters)
|
||||
{
|
||||
httpFilters += "&filter_field_"+idx+"="+URLEncoder.encode(filter[0],"UTF-8");
|
||||
httpFilters += "&filter_type_"+idx+"="+URLEncoder.encode(filter[1],"UTF-8");
|
||||
httpFilters += "&filter_value_"+idx+"="+URLEncoder.encode(filter[2],"UTF-8");
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
int rpp = qArgs.getMaxResults();
|
||||
int etAl = ((Integer) request.getAttribute("etal")).intValue();
|
||||
|
||||
String[] options = new String[]{"equals","contains","authority","notequals","notcontains","notauthority"};
|
||||
|
||||
// Admin user or not
|
||||
Boolean admin_b = (Boolean)request.getAttribute("admin_button");
|
||||
boolean admin_button = (admin_b == null ? false : admin_b.booleanValue());
|
||||
%>
|
||||
|
||||
<c:set var="dspace.layout.head" scope="request">
|
||||
<script type="text/javascript">
|
||||
var jQ = jQuery.noConflict();
|
||||
jQ(document).ready(function() {
|
||||
jQ( "#filterquery" )
|
||||
.autocomplete({
|
||||
source: function( request, response ) {
|
||||
jQ.ajax({
|
||||
url: "<%= request.getContextPath() %>/json/discovery/autocomplete?query=<%= URLEncoder.encode(query,"UTF-8")%><%= httpFilters.replaceAll("&","&") %>",
|
||||
dataType: "json",
|
||||
cache: false,
|
||||
data: {
|
||||
auto_idx: jQ("#filtername").val(),
|
||||
auto_query: request.term,
|
||||
auto_sort: 'count',
|
||||
auto_type: jQ("#filtertype").val(),
|
||||
location: '<%= searchScope %>'
|
||||
},
|
||||
success: function( data ) {
|
||||
response( jQ.map( data.autocomplete, function( item ) {
|
||||
var tmp_val = item.authorityKey;
|
||||
if (tmp_val == null || tmp_val == '')
|
||||
{
|
||||
tmp_val = item.displayedValue;
|
||||
}
|
||||
return {
|
||||
label: item.displayedValue + " (" + item.count + ")",
|
||||
value: tmp_val
|
||||
};
|
||||
}))
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</c:set>
|
||||
|
||||
<dspace:layout titlekey="jsp.search.title">
|
||||
|
||||
<%-- <h1>Search Results</h1> --%>
|
||||
|
||||
<h1><fmt:message key="jsp.search.title"/></h1>
|
||||
|
||||
<div class="discovery-search-form">
|
||||
<%-- Controls for a repeat search --%>
|
||||
<div class="discovery-query">
|
||||
<form action="simple-search" method="get">
|
||||
<label for="tlocation">
|
||||
<fmt:message key="jsp.search.results.searchin"/>
|
||||
</label>
|
||||
<select name="location" id="tlocation">
|
||||
<%
|
||||
if (scope == null)
|
||||
{
|
||||
// Scope of the search was all of DSpace. The scope control will list
|
||||
// "all of DSpace" and the communities.
|
||||
%>
|
||||
<%-- <option selected value="/">All of DSpace</option> --%>
|
||||
<option selected="selected" value="/"><fmt:message key="jsp.general.genericScope"/></option>
|
||||
<% }
|
||||
else
|
||||
{
|
||||
%>
|
||||
<option value="/"><fmt:message key="jsp.general.genericScope"/></option>
|
||||
<% }
|
||||
for (DSpaceObject dso : scopes)
|
||||
{
|
||||
%>
|
||||
<option value="<%= dso.getHandle() %>" <%=dso.getHandle().equals(searchScope)?"selected=\"selected\"":"" %>>
|
||||
<%= dso.getName() %></option>
|
||||
<%
|
||||
}
|
||||
%> </select><br/>
|
||||
<label for="query"><fmt:message key="jsp.search.results.searchfor"/></label>
|
||||
<input type="text" size="50" name="query" value="<%= (query==null ? "" : StringEscapeUtils.escapeHtml(query)) %>"/>
|
||||
<input type="submit" value="<fmt:message key="jsp.general.go"/>" />
|
||||
<input type="hidden" value="<%= rpp %>" name="rpp" />
|
||||
<input type="hidden" value="<%= sortedBy %>" name="sort_by" />
|
||||
<input type="hidden" value="<%= order %>" name="order" />
|
||||
<% if (appliedFilters.size() > 0 ) { %>
|
||||
<div class="discovery-search-appliedFilters">
|
||||
<span><fmt:message key="jsp.search.filter.applied" /></span>
|
||||
<%
|
||||
int idx = 1;
|
||||
for (String[] filter : appliedFilters)
|
||||
{
|
||||
boolean found = false;
|
||||
%>
|
||||
<select id="filter_field_<%=idx %>" name="filter_field_<%=idx %>">
|
||||
<%
|
||||
for (DiscoverySearchFilter searchFilter : availableFilters)
|
||||
{
|
||||
String fkey = "jsp.search.filter."+searchFilter.getIndexFieldName();
|
||||
%><option value="<%= searchFilter.getIndexFieldName() %>"<%
|
||||
if (filter[0].equals(searchFilter.getIndexFieldName()))
|
||||
{
|
||||
%> selected="selected"<%
|
||||
found = true;
|
||||
}
|
||||
%>><fmt:message key="<%= fkey %>"/></option><%
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
String fkey = "jsp.search.filter."+filter[0];
|
||||
%><option value="<%= filter[0] %>" selected="selected"><fmt:message key="<%= fkey %>"/></option><%
|
||||
}
|
||||
%>
|
||||
</select>
|
||||
<select id="filter_type_<%=idx %>" name="filter_type_<%=idx %>">
|
||||
<%
|
||||
for (String opt : options)
|
||||
{
|
||||
String fkey = "jsp.search.filter.op."+opt;
|
||||
%><option value="<%= opt %>"<%= opt.equals(filter[1])?" selected=\"selected\"":"" %>><fmt:message key="<%= fkey %>"/></option><%
|
||||
}
|
||||
%>
|
||||
</select>
|
||||
<input type="text" id="filter_value_<%=idx %>" name="filter_value_<%=idx %>" value="<%= StringEscapeUtils.escapeHtml(filter[2]) %>" size="45"/>
|
||||
<input type="submit" id="submit_filter_remove_<%=idx %>" name="submit_filter_remove_<%=idx %>" value="X" />
|
||||
<br/>
|
||||
<%
|
||||
idx++;
|
||||
}
|
||||
%>
|
||||
</div>
|
||||
<% } %>
|
||||
<a href="<%= request.getContextPath()+"/simple-search" %>"><fmt:message key="jsp.search.general.new-search" /></a>
|
||||
</form>
|
||||
</div>
|
||||
<% if (availableFilters.size() > 0) { %>
|
||||
<div class="discovery-search-filters">
|
||||
<form action="simple-search" method="get">
|
||||
<input type="hidden" value="<%= StringEscapeUtils.escapeHtml(searchScope) %>" name="location" />
|
||||
<input type="hidden" value="<%= StringEscapeUtils.escapeHtml(query) %>" name="query" />
|
||||
<% if (appliedFilterQueries.size() > 0 ) {
|
||||
int idx = 1;
|
||||
for (String[] filter : appliedFilters)
|
||||
{
|
||||
boolean found = false;
|
||||
%>
|
||||
<input type="hidden" id="filter_field_<%=idx %>" name="filter_field_<%=idx %>" value="<%= filter[0] %>" />
|
||||
<input type="hidden" id="filter_type_<%=idx %>" name="filter_type_<%=idx %>" value="<%= filter[1] %>" />
|
||||
<input type="hidden" id="filter_value_<%=idx %>" name="filter_value_<%=idx %>" value="<%= StringEscapeUtils.escapeHtml(filter[2]) %>" />
|
||||
<%
|
||||
idx++;
|
||||
}
|
||||
} %>
|
||||
<span class="discovery-search-filters-heading"><fmt:message key="jsp.search.filter.heading" /></span>
|
||||
<span class="discovery-search-filters-hint"><fmt:message key="jsp.search.filter.hint" /></span>
|
||||
<select id="filtername" name="filtername">
|
||||
<%
|
||||
for (DiscoverySearchFilter searchFilter : availableFilters)
|
||||
{
|
||||
String fkey = "jsp.search.filter."+searchFilter.getIndexFieldName();
|
||||
%><option value="<%= searchFilter.getIndexFieldName() %>"><fmt:message key="<%= fkey %>"/></option><%
|
||||
}
|
||||
%>
|
||||
</select>
|
||||
<select id="filtertype" name="filtertype">
|
||||
<%
|
||||
for (String opt : options)
|
||||
{
|
||||
String fkey = "jsp.search.filter.op."+opt;
|
||||
%><option value="<%= opt %>"><fmt:message key="<%= fkey %>"/></option><%
|
||||
}
|
||||
%>
|
||||
</select>
|
||||
<input type="text" id="filterquery" name="filterquery" size="45"/>
|
||||
<input type="hidden" value="<%= rpp %>" name="rpp" />
|
||||
<input type="hidden" value="<%= sortedBy %>" name="sort_by" />
|
||||
<input type="hidden" value="<%= order %>" name="order" />
|
||||
<input type="submit" value="<fmt:message key="jsp.search.filter.add"/>" />
|
||||
</form>
|
||||
</div>
|
||||
<% } %>
|
||||
<%-- Include a component for modifying sort by, order, results per page, and et-al limit --%>
|
||||
<div class="discovery-pagination-controls">
|
||||
<form action="simple-search" method="get">
|
||||
<input type="hidden" value="<%= StringEscapeUtils.escapeHtml(searchScope) %>" name="location" />
|
||||
<input type="hidden" value="<%= StringEscapeUtils.escapeHtml(query) %>" name="query" />
|
||||
<% if (appliedFilterQueries.size() > 0 ) {
|
||||
int idx = 1;
|
||||
for (String[] filter : appliedFilters)
|
||||
{
|
||||
boolean found = false;
|
||||
%>
|
||||
<input type="hidden" id="filter_field_<%=idx %>" name="filter_field_<%=idx %>" value="<%= filter[0] %>" />
|
||||
<input type="hidden" id="filter_type_<%=idx %>" name="filter_type_<%=idx %>" value="<%= filter[1] %>" />
|
||||
<input type="hidden" id="filter_value_<%=idx %>" name="filter_value_<%=idx %>" value="<%= StringEscapeUtils.escapeHtml(filter[2]) %>" />
|
||||
<%
|
||||
idx++;
|
||||
}
|
||||
} %>
|
||||
<label for="rpp"><fmt:message key="search.results.perpage"/></label>
|
||||
<select name="rpp">
|
||||
<%
|
||||
for (int i = 5; i <= 100 ; i += 5)
|
||||
{
|
||||
String selected = (i == rpp ? "selected=\"selected\"" : "");
|
||||
%>
|
||||
<option value="<%= i %>" <%= selected %>><%= i %></option>
|
||||
<%
|
||||
}
|
||||
%>
|
||||
</select>
|
||||
|
|
||||
<%
|
||||
if (sortOptions.size() > 0)
|
||||
{
|
||||
%>
|
||||
<label for="sort_by"><fmt:message key="search.results.sort-by"/></label>
|
||||
<select name="sort_by">
|
||||
<option value="score"><fmt:message key="search.sort-by.relevance"/></option>
|
||||
<%
|
||||
for (String sortBy : sortOptions)
|
||||
{
|
||||
String selected = (sortBy.equals(sortedBy) ? "selected=\"selected\"" : "");
|
||||
String mKey = "search.sort-by." + sortBy;
|
||||
%> <option value="<%= sortBy %>" <%= selected %>><fmt:message key="<%= mKey %>"/></option><%
|
||||
}
|
||||
%>
|
||||
</select>
|
||||
<%
|
||||
}
|
||||
%>
|
||||
<label for="order"><fmt:message key="search.results.order"/></label>
|
||||
<select name="order">
|
||||
<option value="ASC" <%= ascSelected %>><fmt:message key="search.order.asc" /></option>
|
||||
<option value="DESC" <%= descSelected %>><fmt:message key="search.order.desc" /></option>
|
||||
</select>
|
||||
<label for="etal"><fmt:message key="search.results.etal" /></label>
|
||||
<select name="etal">
|
||||
<%
|
||||
String unlimitedSelect = "";
|
||||
if (etAl < 1)
|
||||
{
|
||||
unlimitedSelect = "selected=\"selected\"";
|
||||
}
|
||||
%>
|
||||
<option value="0" <%= unlimitedSelect %>><fmt:message key="browse.full.etal.unlimited"/></option>
|
||||
<%
|
||||
boolean insertedCurrent = false;
|
||||
for (int i = 0; i <= 50 ; i += 5)
|
||||
{
|
||||
// for the first one, we want 1 author, not 0
|
||||
if (i == 0)
|
||||
{
|
||||
String sel = (i + 1 == etAl ? "selected=\"selected\"" : "");
|
||||
%><option value="1" <%= sel %>>1</option><%
|
||||
}
|
||||
|
||||
// if the current i is greated than that configured by the user,
|
||||
// insert the one specified in the right place in the list
|
||||
if (i > etAl && !insertedCurrent && etAl > 1)
|
||||
{
|
||||
%><option value="<%= etAl %>" selected="selected"><%= etAl %></option><%
|
||||
insertedCurrent = true;
|
||||
}
|
||||
|
||||
// determine if the current not-special case is selected
|
||||
String selected = (i == etAl ? "selected=\"selected\"" : "");
|
||||
|
||||
// do this for all other cases than the first and the current
|
||||
if (i != 0 && i != etAl)
|
||||
{
|
||||
%>
|
||||
<option value="<%= i %>" <%= selected %>><%= i %></option>
|
||||
<%
|
||||
}
|
||||
}
|
||||
%>
|
||||
</select>
|
||||
<input type="submit" name="submit_search" value="<fmt:message key="search.update" />" />
|
||||
|
||||
<%
|
||||
if (admin_button)
|
||||
{
|
||||
%><input type="submit" name="submit_export_metadata" value="<fmt:message key="jsp.general.metadataexport.button"/>" /><%
|
||||
}
|
||||
%>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<%
|
||||
|
||||
DiscoverResult qResults = (DiscoverResult)request.getAttribute("queryresults");
|
||||
Item [] items = (Item[] )request.getAttribute("items");
|
||||
Community [] communities = (Community[] )request.getAttribute("communities");
|
||||
Collection[] collections = (Collection[])request.getAttribute("collections");
|
||||
|
||||
if( error )
|
||||
{
|
||||
%>
|
||||
<p align="center" class="submitFormWarn">
|
||||
<fmt:message key="jsp.search.error.discovery" />
|
||||
</p>
|
||||
<%
|
||||
}
|
||||
else if( qResults != null && qResults.getTotalSearchResults() == 0 )
|
||||
{
|
||||
%>
|
||||
<%-- <p align="center">Search produced no results.</p> --%>
|
||||
<p align="center"><fmt:message key="jsp.search.general.noresults"/></p>
|
||||
<%
|
||||
}
|
||||
else if( qResults != null)
|
||||
{
|
||||
long pageTotal = ((Long)request.getAttribute("pagetotal" )).longValue();
|
||||
long pageCurrent = ((Long)request.getAttribute("pagecurrent")).longValue();
|
||||
long pageLast = ((Long)request.getAttribute("pagelast" )).longValue();
|
||||
long pageFirst = ((Long)request.getAttribute("pagefirst" )).longValue();
|
||||
|
||||
// create the URLs accessing the previous and next search result pages
|
||||
String baseURL = request.getContextPath()
|
||||
+ searchScope
|
||||
+ "/simple-search?query="
|
||||
+ URLEncoder.encode(query,"UTF-8")
|
||||
+ httpFilters
|
||||
+ "&sort_by=" + sortedBy
|
||||
+ "&order=" + order
|
||||
+ "&rpp=" + rpp
|
||||
+ "&etal=" + etAl
|
||||
+ "&start=";
|
||||
|
||||
String nextURL = baseURL;
|
||||
String firstURL = baseURL;
|
||||
String lastURL = baseURL;
|
||||
|
||||
String prevURL = baseURL
|
||||
+ (pageCurrent-2) * qResults.getMaxResults();
|
||||
|
||||
nextURL = nextURL
|
||||
+ (pageCurrent) * qResults.getMaxResults();
|
||||
|
||||
firstURL = firstURL +"0";
|
||||
lastURL = lastURL + (pageTotal-1) * qResults.getMaxResults();
|
||||
|
||||
|
||||
%>
|
||||
<hr/>
|
||||
<div class="discovery-result-pagination">
|
||||
<%
|
||||
long lastHint = qResults.getStart()+qResults.getMaxResults() <= qResults.getTotalSearchResults()?
|
||||
qResults.getStart()+qResults.getMaxResults():qResults.getTotalSearchResults();
|
||||
%>
|
||||
<%-- <p align="center">Results <//%=qResults.getStart()+1%>-<//%=qResults.getStart()+qResults.getHitHandles().size()%> of --%>
|
||||
<h2 class="info"><fmt:message key="jsp.search.results.results">
|
||||
<fmt:param><%=qResults.getStart()+1%></fmt:param>
|
||||
<fmt:param><%=lastHint%></fmt:param>
|
||||
<fmt:param><%=qResults.getTotalSearchResults()%></fmt:param>
|
||||
<fmt:param><%=(float) qResults.getSearchTime() / 1000%></fmt:param>
|
||||
</fmt:message></h2>
|
||||
<ul class="links">
|
||||
<%
|
||||
if (pageFirst != pageCurrent)
|
||||
{
|
||||
%><li><a href="<%= prevURL %>"><fmt:message key="jsp.search.general.previous" /></a></li><%
|
||||
}
|
||||
|
||||
if (pageFirst != 1)
|
||||
{
|
||||
%><li><a href="<%= firstURL %>">1</a></li><li>...</li><%
|
||||
}
|
||||
|
||||
for( long q = pageFirst; q <= pageLast; q++ )
|
||||
{
|
||||
String myLink = "<li><a href=\""
|
||||
+ baseURL;
|
||||
|
||||
|
||||
if( q == pageCurrent )
|
||||
{
|
||||
myLink = "<li class=\"current-page-link\">" + q + "</li>";
|
||||
}
|
||||
else
|
||||
{
|
||||
myLink = myLink
|
||||
+ (q-1) * qResults.getMaxResults()
|
||||
+ "\">"
|
||||
+ q
|
||||
+ "</a></li>";
|
||||
}
|
||||
%>
|
||||
|
||||
<%= myLink %>
|
||||
|
||||
<%
|
||||
}
|
||||
|
||||
if (pageTotal > pageLast)
|
||||
{
|
||||
%><li>...</li><li><a href="<%= lastURL %>"><%= pageTotal %></a></li><%
|
||||
}
|
||||
if (pageTotal > pageCurrent)
|
||||
{
|
||||
%><li><a href="<%= nextURL %>"><fmt:message key="jsp.search.general.next" /></a></li><%
|
||||
}
|
||||
%>
|
||||
</ul>
|
||||
<!-- give a content to the div -->
|
||||
</div>
|
||||
<div class="discovery-result-results">
|
||||
<% if (communities.length > 0 ) { %>
|
||||
<%-- <h3>Community Hits:</h3> --%>
|
||||
<h3><fmt:message key="jsp.search.results.comhits"/></h3>
|
||||
<dspace:communitylist communities="<%= communities %>" />
|
||||
<% } %>
|
||||
|
||||
<% if (collections.length > 0 ) { %>
|
||||
<%-- <h3>Collection hits:</h3> --%>
|
||||
<h3><fmt:message key="jsp.search.results.colhits"/></h3>
|
||||
<dspace:collectionlist collections="<%= collections %>" />
|
||||
<% } %>
|
||||
|
||||
<% if (items.length > 0) { %>
|
||||
<%-- <h3>Item hits:</h3> --%>
|
||||
<h3><fmt:message key="jsp.search.results.itemhits"/></h3>
|
||||
<dspace:itemlist items="<%= items %>" authorLimit="<%= etAl %>" />
|
||||
<% } %>
|
||||
</div>
|
||||
<%-- if the result page is enought long... --%>
|
||||
<% if ((communities.length + collections.length + items.length) > 10) {%>
|
||||
<%-- show again the navigation info/links --%>
|
||||
<div class="discovery-result-pagination">
|
||||
<%-- <p align="center">Results <//%=qResults.getStart()+1%>-<//%=qResults.getStart()+qResults.getHitHandles().size()%> of --%>
|
||||
<p class="info"><fmt:message key="jsp.search.results.results">
|
||||
<fmt:param><%=qResults.getStart()+1%></fmt:param>
|
||||
<fmt:param><%=lastHint%></fmt:param>
|
||||
<fmt:param><%=qResults.getTotalSearchResults()%></fmt:param>
|
||||
<fmt:param><%=(float) qResults.getSearchTime() / 1000 %></fmt:param>
|
||||
</fmt:message></p>
|
||||
<ul class="links">
|
||||
<%
|
||||
if (pageFirst != pageCurrent)
|
||||
{
|
||||
%><li><a href="<%= prevURL %>"><fmt:message key="jsp.search.general.previous" /></a></li><%
|
||||
}
|
||||
|
||||
if (pageFirst != 1)
|
||||
{
|
||||
%><li><a href="<%= firstURL %>">1</a></li><li>...</li><%
|
||||
}
|
||||
|
||||
for( long q = pageFirst; q <= pageLast; q++ )
|
||||
{
|
||||
String myLink = "<li><a href=\""
|
||||
+ baseURL;
|
||||
|
||||
|
||||
if( q == pageCurrent )
|
||||
{
|
||||
myLink = "<li class=\"current-page-link\">" + q + "</li>";
|
||||
}
|
||||
else
|
||||
{
|
||||
myLink = myLink
|
||||
+ (q-1) * qResults.getMaxResults()
|
||||
+ "\">"
|
||||
+ q
|
||||
+ "</a></li>";
|
||||
}
|
||||
%>
|
||||
|
||||
<%= myLink %>
|
||||
|
||||
<%
|
||||
}
|
||||
|
||||
if (pageTotal > pageLast)
|
||||
{
|
||||
%><li>...</li><li><a href="<%= lastURL %>"><%= pageTotal %></a></li><%
|
||||
}
|
||||
if (pageTotal > pageCurrent)
|
||||
{
|
||||
%><li><a href="<%= nextURL %>"><fmt:message key="jsp.search.general.next" /></a></li><%
|
||||
}
|
||||
%>
|
||||
</ul>
|
||||
<!-- give a content to the div -->
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
<% } %>
|
||||
<dspace:sidebar>
|
||||
<%
|
||||
boolean brefine = false;
|
||||
|
||||
List<DiscoverySearchFilterFacet> facetsConf = (List<DiscoverySearchFilterFacet>) request.getAttribute("facetsConfig");
|
||||
Map<String, Boolean> showFacets = new HashMap<String, Boolean>();
|
||||
|
||||
for (DiscoverySearchFilterFacet facetConf : facetsConf)
|
||||
{
|
||||
String f = facetConf.getIndexFieldName();
|
||||
List<FacetResult> facet = qResults.getFacetResult(f);
|
||||
if (facet.size() == 0)
|
||||
{
|
||||
facet = qResults.getFacetResult(f+".year");
|
||||
if (facet.size() == 0)
|
||||
{
|
||||
showFacets.put(f, false);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
boolean showFacet = false;
|
||||
for (FacetResult fvalue : facet)
|
||||
{
|
||||
if(!appliedFilterQueries.contains(f+"::"+fvalue.getFilterType()+"::"+fvalue.getAsFilterQuery()))
|
||||
{
|
||||
showFacet = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
showFacets.put(f, showFacet);
|
||||
brefine = brefine || showFacet;
|
||||
}
|
||||
if (brefine) {
|
||||
%>
|
||||
|
||||
<h3 class="facets"><fmt:message key="jsp.search.facet.refine" /></h3>
|
||||
<div id="facets" class="facetsBox">
|
||||
|
||||
<%
|
||||
for (DiscoverySearchFilterFacet facetConf : facetsConf)
|
||||
{
|
||||
String f = facetConf.getIndexFieldName();
|
||||
if (!showFacets.get(f))
|
||||
continue;
|
||||
List<FacetResult> facet = qResults.getFacetResult(f);
|
||||
if (facet.size() == 0)
|
||||
{
|
||||
facet = qResults.getFacetResult(f+".year");
|
||||
}
|
||||
int limit = facetConf.getFacetLimit()+1;
|
||||
|
||||
String fkey = "jsp.search.facet.refine."+f;
|
||||
%><div id="facet_<%= f %>" class="facet">
|
||||
<span class="facetName"><fmt:message key="<%= fkey %>" /></span>
|
||||
<ul><%
|
||||
int idx = 1;
|
||||
int currFp = UIUtil.getIntParameter(request, f+"_page");
|
||||
if (currFp < 0)
|
||||
{
|
||||
currFp = 0;
|
||||
}
|
||||
if (currFp > 0)
|
||||
{
|
||||
%><li class="facet-previous"><a href="<%= request.getContextPath()
|
||||
+ (searchScope!=""?"/handle/"+searchScope:"")
|
||||
+ "/simple-search?query="
|
||||
+ URLEncoder.encode(query,"UTF-8")
|
||||
+ "&sort_by=" + sortedBy
|
||||
+ "&order=" + order
|
||||
+ "&rpp=" + rpp
|
||||
+ httpFilters
|
||||
+ "&etal=" + etAl
|
||||
+ "&"+f+"_page="+(currFp-1) %>"><fmt:message key="jsp.search.facet.refine.previous" /></a></li>
|
||||
<%
|
||||
}
|
||||
for (FacetResult fvalue : facet)
|
||||
{
|
||||
if (idx == limit)
|
||||
{
|
||||
%><li class="facet-next"><a href="<%= request.getContextPath()
|
||||
+ (searchScope!=""?"/handle/"+searchScope:"")
|
||||
+ "/simple-search?query="
|
||||
+ URLEncoder.encode(query,"UTF-8")
|
||||
+ "&sort_by=" + sortedBy
|
||||
+ "&order=" + order
|
||||
+ "&rpp=" + rpp
|
||||
+ httpFilters
|
||||
+ "&etal=" + etAl
|
||||
+ "&"+f+"_page="+(currFp+1) %>"><fmt:message key="jsp.search.facet.refine.next" /></a></li>
|
||||
<%
|
||||
}
|
||||
else if(!appliedFilterQueries.contains(f+"::"+fvalue.getFilterType()+"::"+fvalue.getAsFilterQuery()))
|
||||
{
|
||||
%><li><a href="<%= request.getContextPath()
|
||||
+ (searchScope!=""?"/handle/"+searchScope:"")
|
||||
+ "/simple-search?query="
|
||||
+ URLEncoder.encode(query,"UTF-8")
|
||||
+ "&sort_by=" + sortedBy
|
||||
+ "&order=" + order
|
||||
+ "&rpp=" + rpp
|
||||
+ httpFilters
|
||||
+ "&etal=" + etAl
|
||||
+ "&filtername="+URLEncoder.encode(f,"UTF-8")
|
||||
+ "&filterquery="+URLEncoder.encode(fvalue.getAsFilterQuery(),"UTF-8")
|
||||
+ "&filtertype="+URLEncoder.encode(fvalue.getFilterType(),"UTF-8") %>"
|
||||
title="<fmt:message key="jsp.search.facet.narrow"><fmt:param><%=fvalue.getDisplayedValue() %></fmt:param></fmt:message>">
|
||||
<%= StringUtils.abbreviate(fvalue.getDisplayedValue(),32) + " (" + fvalue.getCount()+")" %></a></li><%
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
%></ul></div><%
|
||||
}
|
||||
|
||||
%>
|
||||
|
||||
</div>
|
||||
<% } %>
|
||||
</dspace:sidebar>
|
||||
</dspace:layout>
|
||||
|
@@ -17,12 +17,12 @@ import org.dspace.discovery.configuration.DiscoveryConfigurationParameters;
|
||||
public class DiscoverFacetField {
|
||||
private String field;
|
||||
private int limit;
|
||||
private int offset=-1;
|
||||
/* The facet prefix, all facet values will have to start with the given prefix */
|
||||
private String prefix;
|
||||
private String type;
|
||||
private DiscoveryConfigurationParameters.SORT sortOrder;
|
||||
|
||||
|
||||
public DiscoverFacetField(String field, String type, int limit, DiscoveryConfigurationParameters.SORT sortOrder) {
|
||||
this.field = field;
|
||||
this.type = type;
|
||||
@@ -30,6 +30,14 @@ public class DiscoverFacetField {
|
||||
this.sortOrder = sortOrder;
|
||||
}
|
||||
|
||||
public DiscoverFacetField(String field, String type, int limit, DiscoveryConfigurationParameters.SORT sortOrder, int offset) {
|
||||
this.field = field;
|
||||
this.type = type;
|
||||
this.limit = limit;
|
||||
this.sortOrder = sortOrder;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public DiscoverFacetField(String field, String type, int limit, DiscoveryConfigurationParameters.SORT sortOrder, String prefix) {
|
||||
this.prefix = prefix;
|
||||
this.limit = limit;
|
||||
@@ -38,7 +46,14 @@ public class DiscoverFacetField {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
|
||||
public DiscoverFacetField(String field, String type, int limit, DiscoveryConfigurationParameters.SORT sortOrder, String prefix, int offset) {
|
||||
this.prefix = prefix;
|
||||
this.limit = limit;
|
||||
this.type = type;
|
||||
this.sortOrder = sortOrder;
|
||||
this.field = field;
|
||||
this.offset = offset;
|
||||
}
|
||||
public String getField() {
|
||||
return field;
|
||||
}
|
||||
@@ -58,4 +73,14 @@ public class DiscoverFacetField {
|
||||
public DiscoveryConfigurationParameters.SORT getSortOrder() {
|
||||
return sortOrder;
|
||||
}
|
||||
|
||||
public int getOffset()
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
public void setOffset(int offset)
|
||||
{
|
||||
this.offset = offset;
|
||||
}
|
||||
}
|
||||
|
@@ -143,6 +143,11 @@ public class DiscoverResult {
|
||||
{
|
||||
return authorityKey;
|
||||
}
|
||||
|
||||
public String getFilterType()
|
||||
{
|
||||
return authorityKey != null?"authority":"equals";
|
||||
}
|
||||
}
|
||||
|
||||
public static final class DSpaceObjectHighlightResult
|
||||
|
@@ -28,9 +28,15 @@ public interface IndexingService {
|
||||
void indexContent(Context context, DSpaceObject dso,
|
||||
boolean force) throws SQLException;
|
||||
|
||||
void indexContent(Context context, DSpaceObject dso,
|
||||
boolean force, boolean commit) throws SQLException, SearchServiceException;
|
||||
|
||||
void unIndexContent(Context context, DSpaceObject dso)
|
||||
throws SQLException, IOException;
|
||||
|
||||
void unIndexContent(Context context, DSpaceObject dso, boolean commit)
|
||||
throws SQLException, IOException;
|
||||
|
||||
void unIndexContent(Context context, String handle)
|
||||
throws SQLException, IOException;
|
||||
|
||||
@@ -49,5 +55,7 @@ public interface IndexingService {
|
||||
void cleanIndex(boolean force) throws IOException,
|
||||
SQLException, SearchServiceException;
|
||||
|
||||
void optimize();
|
||||
void commit() throws SearchServiceException;
|
||||
|
||||
void optimize() throws SearchServiceException;
|
||||
}
|
||||
|
@@ -34,6 +34,8 @@ public class DiscoveryConfiguration implements InitializingBean{
|
||||
|
||||
private DiscoverySortConfiguration searchSortConfiguration;
|
||||
|
||||
private int defaultRpp = 10;
|
||||
|
||||
private String id;
|
||||
private DiscoveryHitHighlightingConfiguration hitHighlightingConfiguration;
|
||||
private DiscoveryMoreLikeThisConfiguration moreLikeThisConfiguration;
|
||||
@@ -94,6 +96,16 @@ public class DiscoveryConfiguration implements InitializingBean{
|
||||
this.searchSortConfiguration = searchSortConfiguration;
|
||||
}
|
||||
|
||||
public void setDefaultRpp(int defaultRpp)
|
||||
{
|
||||
this.defaultRpp = defaultRpp;
|
||||
}
|
||||
|
||||
public int getDefaultRpp()
|
||||
{
|
||||
return defaultRpp;
|
||||
}
|
||||
|
||||
public void setHitHighlightingConfiguration(DiscoveryHitHighlightingConfiguration hitHighlightingConfiguration) {
|
||||
this.hitHighlightingConfiguration = hitHighlightingConfiguration;
|
||||
}
|
||||
|
@@ -18,6 +18,8 @@ public class DiscoveryConfigurationParameters {
|
||||
public static final String TYPE_DATE = "date";
|
||||
public static final String TYPE_HIERARCHICAL = "hierarchical";
|
||||
public static final String TYPE_AC = "ac";
|
||||
public static final String TYPE_AUTHORITY = "authority";
|
||||
public static final String TYPE_STANDARD = "standard";
|
||||
|
||||
public static enum SORT {VALUE, COUNT}
|
||||
|
||||
|
@@ -77,11 +77,11 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
|
||||
public static final String FILTER_SEPARATOR = "\n|||\n";
|
||||
|
||||
public static final String AUTHORITY_SEPARATOR = "\n§§§\n";
|
||||
public static final String AUTHORITY_SEPARATOR = "###";
|
||||
|
||||
public static final String STORE_SEPARATOR = "\n|||\n";
|
||||
|
||||
public static final String VARIANTS_STORE_SEPARATOR = "\n§§§\n";
|
||||
public static final String VARIANTS_STORE_SEPARATOR = "###";
|
||||
|
||||
/**
|
||||
* Non-Static CommonsHttpSolrServer for processing indexing events.
|
||||
@@ -193,8 +193,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
}
|
||||
|
||||
/**
|
||||
* unIndex removes an Item, Collection, or Community only works if the
|
||||
* DSpaceObject has a handle (uses the handle for its unique ID)
|
||||
* unIndex removes an Item, Collection, or Community
|
||||
*
|
||||
* @param context
|
||||
* @param dso DSpace Object, can be Community, Item, or Collection
|
||||
@@ -203,10 +202,32 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
*/
|
||||
public void unIndexContent(Context context, DSpaceObject dso)
|
||||
throws SQLException, IOException {
|
||||
unIndexContent(context, dso, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* unIndex removes an Item, Collection, or Community
|
||||
*
|
||||
* @param context
|
||||
* @param dso DSpace Object, can be Community, Item, or Collection
|
||||
* @param commit if <code>true</code> force an immediate commit on SOLR
|
||||
* @throws SQLException
|
||||
* @throws IOException
|
||||
*/
|
||||
public void unIndexContent(Context context, DSpaceObject dso, boolean commit)
|
||||
throws SQLException, IOException {
|
||||
try {
|
||||
unIndexContent(context, dso.getHandle());
|
||||
} catch (Exception exception)
|
||||
{
|
||||
if (dso == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
String uniqueID = dso.getType()+"-"+dso.getID();
|
||||
getSolr().deleteById(uniqueID);
|
||||
if(commit)
|
||||
{
|
||||
getSolr().commit();
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
log.error(exception.getMessage(), exception);
|
||||
emailException(exception);
|
||||
}
|
||||
@@ -234,7 +255,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
throws SQLException, IOException {
|
||||
|
||||
try {
|
||||
getSolr().deleteById(handle);
|
||||
getSolr().deleteByQuery("handle:\""+handle+"\"");
|
||||
if(commit)
|
||||
{
|
||||
getSolr().commit();
|
||||
@@ -305,7 +326,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
try {
|
||||
ItemIterator items = null;
|
||||
try {
|
||||
for (items = Item.findAll(context); items.hasNext();)
|
||||
for (items = Item.findAllUnfiltered(context); items.hasNext();)
|
||||
{
|
||||
Item item = items.next();
|
||||
indexContent(context, item, force);
|
||||
@@ -360,10 +381,10 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
{
|
||||
if (force)
|
||||
{
|
||||
getSolr().deleteByQuery("*:*");
|
||||
getSolr().deleteByQuery("search.resourcetype:[2 TO 4]");
|
||||
} else {
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("*:*");
|
||||
query.setQuery("search.resourcetype:[2 TO 4]");
|
||||
QueryResponse rsp = getSolr().query(query);
|
||||
SolrDocumentList docs = rsp.getResults();
|
||||
|
||||
@@ -935,6 +956,11 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
for (DiscoverySearchFilter searchFilter : searchFilterConfigs)
|
||||
{
|
||||
Date date = null;
|
||||
String separator = new DSpace().getConfigurationService().getProperty("discovery.solr.facets.split.char");
|
||||
if(separator == null)
|
||||
{
|
||||
separator = FILTER_SEPARATOR;
|
||||
}
|
||||
if(searchFilter.getType().equals(DiscoveryConfigurationParameters.TYPE_DATE))
|
||||
{
|
||||
//For our search filters that are dates we format them properly
|
||||
@@ -948,29 +974,63 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
doc.addField(searchFilter.getIndexFieldName(), value);
|
||||
doc.addField(searchFilter.getIndexFieldName() + "_keyword", value);
|
||||
|
||||
if (authority != null && preferedLabel == null)
|
||||
{
|
||||
doc.addField(searchFilter.getIndexFieldName()
|
||||
+ "_keyword", value + AUTHORITY_SEPARATOR
|
||||
+ authority);
|
||||
doc.addField(searchFilter.getIndexFieldName()
|
||||
+ "_authority", authority);
|
||||
doc.addField(searchFilter.getIndexFieldName()
|
||||
+ "_acid", value.toLowerCase()
|
||||
+ separator + value
|
||||
+ AUTHORITY_SEPARATOR + authority);
|
||||
}
|
||||
|
||||
if (preferedLabel != null)
|
||||
{
|
||||
doc.addField(searchFilter.getIndexFieldName(), preferedLabel);
|
||||
doc.addField(searchFilter.getIndexFieldName(),
|
||||
preferedLabel);
|
||||
doc.addField(searchFilter.getIndexFieldName()
|
||||
+ "_keyword", preferedLabel);
|
||||
doc.addField(searchFilter.getIndexFieldName()
|
||||
+ "_keyword", preferedLabel
|
||||
+ AUTHORITY_SEPARATOR + authority);
|
||||
doc.addField(searchFilter.getIndexFieldName()
|
||||
+ "_authority", authority);
|
||||
doc.addField(searchFilter.getIndexFieldName()
|
||||
+ "_acid", preferedLabel.toLowerCase()
|
||||
+ separator + preferedLabel
|
||||
+ AUTHORITY_SEPARATOR + authority);
|
||||
}
|
||||
if (variants != null)
|
||||
{
|
||||
for (String var : variants)
|
||||
{
|
||||
doc.addField(searchFilter.getIndexFieldName(), var);
|
||||
doc.addField(searchFilter.getIndexFieldName() + "_keyword", var);
|
||||
doc.addField(searchFilter.getIndexFieldName()
|
||||
+ "_acid", var.toLowerCase()
|
||||
+ separator + var
|
||||
+ AUTHORITY_SEPARATOR + authority);
|
||||
}
|
||||
}
|
||||
|
||||
//Add a dynamic fields for auto complete in search
|
||||
doc.addField(searchFilter.getIndexFieldName() + "_keyword", value);
|
||||
doc.addField(searchFilter.getIndexFieldName() + "_ac",
|
||||
value.toLowerCase() + separator + value);
|
||||
if (preferedLabel != null)
|
||||
{
|
||||
doc.addField(searchFilter.getIndexFieldName() + "_keyword", preferedLabel);
|
||||
doc.addField(searchFilter.getIndexFieldName()
|
||||
+ "_ac", preferedLabel.toLowerCase()
|
||||
+ separator + preferedLabel);
|
||||
}
|
||||
if (variants != null)
|
||||
{
|
||||
for (String var : variants)
|
||||
{
|
||||
doc.addField(searchFilter.getIndexFieldName() + "_ac", var);
|
||||
doc.addField(searchFilter.getIndexFieldName()
|
||||
+ "_ac", var.toLowerCase() + separator
|
||||
+ var);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -981,11 +1041,6 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
//Add a special filter
|
||||
//We use a separator to split up the lowercase and regular case, this is needed to get our filters in regular case
|
||||
//Solr has issues with facet prefix and cases
|
||||
String separator = new DSpace().getConfigurationService().getProperty("discovery.solr.facets.split.char");
|
||||
if(separator == null)
|
||||
{
|
||||
separator = FILTER_SEPARATOR;
|
||||
}
|
||||
if (authority != null)
|
||||
{
|
||||
String facetValue = preferedLabel != null?preferedLabel:value;
|
||||
@@ -1032,12 +1087,6 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
}
|
||||
}
|
||||
|
||||
String separator = new DSpace().getConfigurationService().getProperty("discovery.solr.facets.split.char");
|
||||
if(separator == null)
|
||||
{
|
||||
separator = FILTER_SEPARATOR;
|
||||
}
|
||||
|
||||
String indexValue = valueBuilder.toString().trim();
|
||||
doc.addField(searchFilter.getIndexFieldName() + "_tax_" + i + "_filter", indexValue.toLowerCase() + separator + indexValue);
|
||||
//We add the field x times that it has occurred
|
||||
@@ -1206,6 +1255,16 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
{
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
finally {
|
||||
Iterator<InputStreamReader> itr = readers.iterator();
|
||||
while (itr.hasNext()) {
|
||||
InputStreamReader reader = itr.next();
|
||||
if (reader != null) {
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
log.debug("closed " + readers.size() + " readers");
|
||||
}
|
||||
|
||||
//Do any additional indexing, depends on the plugins
|
||||
List<SolrServiceIndexPlugin> solrServiceIndexPlugins = new DSpace().getServiceManager().getServicesByType(SolrServiceIndexPlugin.class);
|
||||
@@ -1221,17 +1280,6 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
} catch (RuntimeException e)
|
||||
{
|
||||
log.error("Error while writing item to discovery index: " + handle + " message:"+ e.getMessage(), e);
|
||||
} finally {
|
||||
Iterator<InputStreamReader> itr = readers.iterator();
|
||||
while (itr.hasNext())
|
||||
{
|
||||
InputStreamReader reader = itr.next();
|
||||
if (reader != null)
|
||||
{
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
log.debug("closed " + readers.size() + " readers");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1254,6 +1302,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
|
||||
// New fields to weaken the dependence on handles, and allow for faster
|
||||
// list display
|
||||
doc.addField("search.uniqueid", type+"-"+id);
|
||||
doc.addField("search.resourcetype", Integer.toString(type));
|
||||
|
||||
doc.addField("search.resourceid", Integer.toString(id));
|
||||
@@ -1372,7 +1421,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
DiscoverQuery query)
|
||||
throws SearchServiceException
|
||||
{
|
||||
return search(context, dso, query);
|
||||
return search(context, dso, query, false);
|
||||
}
|
||||
|
||||
public DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery discoveryQuery, boolean includeWithdrawn) throws SearchServiceException {
|
||||
@@ -1485,7 +1534,12 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
facetSort = FacetParams.FACET_SORT_INDEX;
|
||||
}
|
||||
solrQuery.add("f." + field + "." + FacetParams.FACET_SORT, facetSort);
|
||||
|
||||
if (facetFieldConfig.getOffset() != -1)
|
||||
{
|
||||
solrQuery.setParam("f." + field + "."
|
||||
+ FacetParams.FACET_OFFSET,
|
||||
String.valueOf(facetFieldConfig.getOffset()));
|
||||
}
|
||||
if(facetFieldConfig.getPrefix() != null)
|
||||
{
|
||||
solrQuery.setFacetPrefix(field, facetFieldConfig.getPrefix());
|
||||
@@ -1646,10 +1700,14 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
String field = transformFacetField(facetFieldConfig, facetField.getName(), true);
|
||||
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;
|
||||
}
|
||||
result.addFacetResult(
|
||||
field,
|
||||
new DiscoverResult.FacetResult(facetValue
|
||||
.getAsFilterQuery(),
|
||||
new DiscoverResult.FacetResult(filterValue,
|
||||
displayedValue, authorityValue,
|
||||
sortValue, facetValue.getCount()));
|
||||
}
|
||||
@@ -1784,6 +1842,17 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
//Query the keyword indexed field !
|
||||
filterQuery.append("_keyword");
|
||||
}
|
||||
else if ("authority".equals(operator))
|
||||
{
|
||||
//Query the authority indexed field !
|
||||
filterQuery.append("_authority");
|
||||
}
|
||||
else if ("notequals".equals(operator)
|
||||
|| "notcontains".equals(operator)
|
||||
|| "notauthority".equals(operator))
|
||||
{
|
||||
filterQuery.insert(0, "-");
|
||||
}
|
||||
filterQuery.append(":");
|
||||
if("equals".equals(operator))
|
||||
{
|
||||
@@ -1794,7 +1863,8 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
|
||||
}
|
||||
filterQuery.append(value);
|
||||
}else{
|
||||
}
|
||||
else{
|
||||
//DO NOT ESCAPE RANGE QUERIES !
|
||||
if(!value.matches("\\[.*TO.*\\]"))
|
||||
{
|
||||
@@ -1910,7 +1980,17 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
//Only display top level filters !
|
||||
return field + "_tax_0_filter";
|
||||
}
|
||||
|
||||
}else if(facetFieldConfig.getType().equals(DiscoveryConfigurationParameters.TYPE_AUTHORITY))
|
||||
{
|
||||
if(removePostfix)
|
||||
{
|
||||
return field.substring(0, field.lastIndexOf("_acid"));
|
||||
}else{
|
||||
return field + "_acid";
|
||||
}
|
||||
}else if(facetFieldConfig.getType().equals(DiscoveryConfigurationParameters.TYPE_STANDARD))
|
||||
{
|
||||
return field;
|
||||
}else{
|
||||
return field;
|
||||
}
|
||||
@@ -1920,8 +2000,9 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
if(field.equals("location.comm") || field.equals("location.coll"))
|
||||
{
|
||||
value = locationToName(context, field, value);
|
||||
}else
|
||||
if(field.endsWith("_filter"))
|
||||
}
|
||||
else if (field.endsWith("_filter") || field.endsWith("_ac")
|
||||
|| field.endsWith("_acid"))
|
||||
{
|
||||
//We have a filter make sure we split !
|
||||
String separator = new DSpace().getConfigurationService().getProperty("discovery.solr.facets.split.char");
|
||||
@@ -1949,7 +2030,8 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
}
|
||||
|
||||
protected String transformAuthorityValue(Context context, String field, String value) throws SQLException {
|
||||
if(field.endsWith("_filter"))
|
||||
if (field.endsWith("_filter") || field.endsWith("_ac")
|
||||
|| field.endsWith("_acid"))
|
||||
{
|
||||
//We have a filter make sure we split !
|
||||
String separator = new DSpace().getConfigurationService().getProperty("discovery.solr.facets.split.char");
|
||||
@@ -1982,8 +2064,9 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
if(field.equals("location.comm") || field.equals("location.coll"))
|
||||
{
|
||||
value = locationToName(context, field, value);
|
||||
}else
|
||||
if(field.endsWith("_filter"))
|
||||
}
|
||||
else if (field.endsWith("_filter") || field.endsWith("_ac")
|
||||
|| field.endsWith("_acid"))
|
||||
{
|
||||
//We have a filter make sure we split !
|
||||
String separator = new DSpace().getConfigurationService().getProperty("discovery.solr.facets.split.char");
|
||||
@@ -2008,4 +2091,23 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void indexContent(Context context, DSpaceObject dso, boolean force,
|
||||
boolean commit) throws SearchServiceException, SQLException {
|
||||
indexContent(context, dso, force);
|
||||
if (commit)
|
||||
{
|
||||
commit();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() throws SearchServiceException {
|
||||
try {
|
||||
getSolr().commit();
|
||||
} catch (Exception e) {
|
||||
throw new SearchServiceException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -399,7 +399,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
|
||||
Cell cell = singleTable.addRow().addCell();
|
||||
|
||||
//No use in selecting the same filter twice
|
||||
if(filterQueries.contains(searchService.toFilterQuery(context, facetField, "equals", displayedValue).getFilterQuery())){
|
||||
if(filterQueries.contains(searchService.toFilterQuery(context, facetField, value.getFilterType(), value.getAsFilterQuery()).getFilterQuery())){
|
||||
cell.addContent(displayedValue + " (" + value.getCount() + ")");
|
||||
} else {
|
||||
//Add the basics
|
||||
@@ -410,7 +410,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
|
||||
url = addFilterQueriesToUrl(url);
|
||||
//Last add the current filter query
|
||||
url += "&filtertype=" + facetField;
|
||||
url += "&filter_relational_operator=equals";
|
||||
url += "&filter_relational_operator="+value.getFilterType();
|
||||
url += "&filter=" + URLEncoder.encode(displayedValue, "UTF-8");
|
||||
cell.addXref(url, displayedValue + " (" + value.getCount() + ")"
|
||||
);
|
||||
|
@@ -231,7 +231,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen
|
||||
if (i < shownFacets - 1) {
|
||||
String displayedValue = value.getDisplayedValue();
|
||||
String filterQuery = value.getAsFilterQuery();
|
||||
|
||||
String filterType = value.getFilterType();
|
||||
if (fqs.contains(getSearchService().toFilterQuery(context, field.getIndexFieldName(), "equals", value.getDisplayedValue()).getFilterQuery())) {
|
||||
filterValsList.addItem(Math.random() + "", "selected").addContent(displayedValue + " (" + value.getCount() + ")");
|
||||
} else {
|
||||
@@ -243,7 +243,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen
|
||||
"/discover?" +
|
||||
paramsQuery +
|
||||
"filtertype=" + field.getIndexFieldName() +
|
||||
"&filter_relational_operator=equals" +
|
||||
"&filter_relational_operator="+ filterType +
|
||||
"&filter=" + encodeForURL(filterQuery),
|
||||
displayedValue + " (" + value.getCount() + ")"
|
||||
);
|
||||
|
@@ -72,6 +72,10 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC
|
||||
private static final Message T_filters_show = message("xmlui.Discovery.AbstractSearch.filters.display");
|
||||
private static final Message T_filter_contain = message("xmlui.Discovery.SimpleSearch.filter.contains");
|
||||
private static final Message T_filter_equals = message("xmlui.Discovery.SimpleSearch.filter.equals");
|
||||
private static final Message T_filter_notcontain = message("xmlui.Discovery.SimpleSearch.filter.notcontains");
|
||||
private static final Message T_filter_notequals = message("xmlui.Discovery.SimpleSearch.filter.notequals");
|
||||
private static final Message T_filter_authority = message("xmlui.Discovery.SimpleSearch.filter.authority");
|
||||
private static final Message T_filter_notauthority = message("xmlui.Discovery.SimpleSearch.filter.notauthority");
|
||||
|
||||
private SearchService searchService = null;
|
||||
|
||||
@@ -228,6 +232,11 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC
|
||||
Select typeSelect = row.addCell("", Cell.ROLE_DATA, "selection").addSelect("filter_relational_operator_" + index);
|
||||
typeSelect.addOption(StringUtils.equals(relationalOperator, "contains"), "contains", T_filter_contain);
|
||||
typeSelect.addOption(StringUtils.equals(relationalOperator, "equals"), "equals", T_filter_equals);
|
||||
typeSelect.addOption(StringUtils.equals(relationalOperator, "authority"), "authority", T_filter_authority);
|
||||
typeSelect.addOption(StringUtils.equals(relationalOperator, "notcontains"), "notcontains", T_filter_notcontain);
|
||||
typeSelect.addOption(StringUtils.equals(relationalOperator, "notequals"), "notequals", T_filter_notequals);
|
||||
typeSelect.addOption(StringUtils.equals(relationalOperator, "notauthority"), "notauthority", T_filter_notauthority);
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -132,6 +132,10 @@
|
||||
|
||||
<message key="xmlui.Discovery.SimpleSearch.filter.contains">Contains</message>
|
||||
<message key="xmlui.Discovery.SimpleSearch.filter.equals">Equals</message>
|
||||
<message key="xmlui.Discovery.SimpleSearch.filter.authority">ID</message>
|
||||
<message key="xmlui.Discovery.SimpleSearch.filter.notcontains">Not Contains</message>
|
||||
<message key="xmlui.Discovery.SimpleSearch.filter.notequals">Not Equals</message>
|
||||
<message key="xmlui.Discovery.SimpleSearch.filter.notauthority">Not ID</message>
|
||||
|
||||
<message key="xmlui.Discovery.RelatedItems.head">Related items</message>
|
||||
<message key="xmlui.Discovery.RelatedItems.help">Showing items related by title, author, creator and subject.</message>
|
||||
|
@@ -20,6 +20,8 @@
|
||||
<module>dspace-discovery-solr</module>
|
||||
<module>dspace-discovery-xmlui-api</module>
|
||||
<module>dspace-discovery-xmlui-webapp</module>
|
||||
<module>dspace-discovery-jspui-api</module>
|
||||
<module>dspace-discovery-jspui-webapp</module>
|
||||
</modules>
|
||||
|
||||
<build>
|
||||
|
@@ -0,0 +1,31 @@
|
||||
package org.dspace.app.webui.json;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
public abstract class JSONRequest
|
||||
{
|
||||
private String subPath;
|
||||
|
||||
public abstract void doJSONRequest(Context context, HttpServletRequest req,
|
||||
HttpServletResponse resp) throws AuthorizeException, IOException;
|
||||
|
||||
public String getSubPath()
|
||||
{
|
||||
return subPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the subPath that this plugin-instance will serve
|
||||
* @param subPath
|
||||
*/
|
||||
public void setSubPath(String subPath)
|
||||
{
|
||||
this.subPath = subPath;
|
||||
}
|
||||
}
|
@@ -0,0 +1,679 @@
|
||||
package org.dspace.app.webui.search;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.URLEncoder;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.app.bulkedit.DSpaceCSV;
|
||||
import org.dspace.app.bulkedit.MetadataExport;
|
||||
import org.dspace.app.util.OpenSearch;
|
||||
import org.dspace.app.util.SyndicationFeed;
|
||||
import org.dspace.app.util.Util;
|
||||
import org.dspace.app.webui.servlet.SimpleSearchServlet;
|
||||
import org.dspace.app.webui.util.JSPManager;
|
||||
import org.dspace.app.webui.util.UIUtil;
|
||||
import org.dspace.authorize.AuthorizeManager;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.ItemIterator;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.handle.HandleManager;
|
||||
import org.dspace.search.DSQuery;
|
||||
import org.dspace.search.QueryArgs;
|
||||
import org.dspace.search.QueryResults;
|
||||
import org.dspace.sort.SortOption;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
public class LuceneSearchProcessor implements SearchRequestProcessor
|
||||
{
|
||||
/** log4j category */
|
||||
private static Logger log = Logger.getLogger(SimpleSearchServlet.class);
|
||||
|
||||
// locale-sensitive metadata labels
|
||||
private Map<String, Map<String, String>> localeLabels = new HashMap<String, Map<String, String>>();
|
||||
|
||||
private static String msgKey = "org.dspace.app.webui.servlet.FeedServlet";
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* All metadata is search for the value contained in the "query" parameter.
|
||||
* If the "location" parameter is present, the user's location is switched
|
||||
* to that location using a redirect. Otherwise, the user's current location
|
||||
* is used to constrain the query; i.e., if the user is "in" a collection,
|
||||
* only results from the collection will be returned.
|
||||
* <p>
|
||||
* The value of the "location" parameter should be ALL (which means no
|
||||
* location), a the ID of a community (e.g. "123"), or a community ID, then
|
||||
* a slash, then a collection ID, e.g. "123/456".
|
||||
*
|
||||
* @author Robert Tansley
|
||||
*/
|
||||
@Override
|
||||
public void doSimpleSearch(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response) throws SearchProcessorException, IOException, ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get the query
|
||||
String query = request.getParameter("query");
|
||||
int start = UIUtil.getIntParameter(request, "start");
|
||||
String advanced = request.getParameter("advanced");
|
||||
String fromAdvanced = request.getParameter("from_advanced");
|
||||
int sortBy = UIUtil.getIntParameter(request, "sort_by");
|
||||
String order = request.getParameter("order");
|
||||
int rpp = UIUtil.getIntParameter(request, "rpp");
|
||||
String advancedQuery = "";
|
||||
|
||||
// can't start earlier than 0 in the results!
|
||||
if (start < 0)
|
||||
{
|
||||
start = 0;
|
||||
}
|
||||
|
||||
int collCount = 0;
|
||||
int commCount = 0;
|
||||
int itemCount = 0;
|
||||
|
||||
Item[] resultsItems;
|
||||
Collection[] resultsCollections;
|
||||
Community[] resultsCommunities;
|
||||
|
||||
QueryResults qResults = null;
|
||||
QueryArgs qArgs = new QueryArgs();
|
||||
SortOption sortOption = null;
|
||||
|
||||
if (request.getParameter("etal") != null)
|
||||
{
|
||||
qArgs.setEtAl(UIUtil.getIntParameter(request, "etal"));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (sortBy > 0)
|
||||
{
|
||||
sortOption = SortOption.getSortOption(sortBy);
|
||||
qArgs.setSortOption(sortOption);
|
||||
}
|
||||
|
||||
if (SortOption.ASCENDING.equalsIgnoreCase(order))
|
||||
{
|
||||
qArgs.setSortOrder(SortOption.ASCENDING);
|
||||
}
|
||||
else
|
||||
{
|
||||
qArgs.setSortOrder(SortOption.DESCENDING);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
|
||||
// Override the page setting if exporting metadata
|
||||
if ("submit_export_metadata".equals(UIUtil.getSubmitButton(request, "submit")))
|
||||
{
|
||||
qArgs.setPageSize(Integer.MAX_VALUE);
|
||||
}
|
||||
else if (rpp > 0)
|
||||
{
|
||||
qArgs.setPageSize(rpp);
|
||||
}
|
||||
|
||||
// if the "advanced" flag is set, build the query string from the
|
||||
// multiple query fields
|
||||
if (advanced != null)
|
||||
{
|
||||
query = qArgs.buildQuery(request);
|
||||
advancedQuery = qArgs.buildHTTPQuery(request);
|
||||
}
|
||||
|
||||
// Ensure the query is non-null
|
||||
if (query == null)
|
||||
{
|
||||
query = "";
|
||||
}
|
||||
|
||||
// Get the location parameter, if any
|
||||
String location = request.getParameter("location");
|
||||
|
||||
// If there is a location parameter, we should redirect to
|
||||
// do the search with the correct location.
|
||||
if ((location != null) && !location.equals(""))
|
||||
{
|
||||
String url = "";
|
||||
|
||||
if (!location.equals("/"))
|
||||
{
|
||||
// Location is a Handle
|
||||
url = "/handle/" + location;
|
||||
}
|
||||
|
||||
// Encode the query
|
||||
query = URLEncoder.encode(query, Constants.DEFAULT_ENCODING);
|
||||
|
||||
if (advancedQuery.length() > 0)
|
||||
{
|
||||
query = query + "&from_advanced=true&" + advancedQuery;
|
||||
}
|
||||
|
||||
// Do the redirect
|
||||
response.sendRedirect(response.encodeRedirectURL(request
|
||||
.getContextPath()
|
||||
+ url + "/simple-search?query=" + query));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Build log information
|
||||
String logInfo = "";
|
||||
|
||||
// Get our location
|
||||
Community community = UIUtil.getCommunityLocation(request);
|
||||
Collection collection = UIUtil.getCollectionLocation(request);
|
||||
|
||||
// get the start of the query results page
|
||||
// List resultObjects = null;
|
||||
qArgs.setQuery(query);
|
||||
qArgs.setStart(start);
|
||||
|
||||
// Perform the search
|
||||
if (collection != null)
|
||||
{
|
||||
logInfo = "collection_id=" + collection.getID() + ",";
|
||||
|
||||
// Values for drop-down box
|
||||
request.setAttribute("community", community);
|
||||
request.setAttribute("collection", collection);
|
||||
|
||||
qResults = DSQuery.doQuery(context, qArgs, collection);
|
||||
}
|
||||
else if (community != null)
|
||||
{
|
||||
logInfo = "community_id=" + community.getID() + ",";
|
||||
|
||||
request.setAttribute("community", community);
|
||||
|
||||
// Get the collections within the community for the dropdown box
|
||||
request
|
||||
.setAttribute("collection.array", community
|
||||
.getCollections());
|
||||
|
||||
qResults = DSQuery.doQuery(context, qArgs, community);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get all communities for dropdown box
|
||||
Community[] communities = Community.findAll(context);
|
||||
request.setAttribute("community.array", communities);
|
||||
|
||||
qResults = DSQuery.doQuery(context, qArgs);
|
||||
}
|
||||
|
||||
// now instantiate the results and put them in their buckets
|
||||
for (int i = 0; i < qResults.getHitTypes().size(); i++)
|
||||
{
|
||||
Integer myType = qResults.getHitTypes().get(i);
|
||||
|
||||
// add the handle to the appropriate lists
|
||||
switch (myType.intValue())
|
||||
{
|
||||
case Constants.ITEM:
|
||||
itemCount++;
|
||||
break;
|
||||
|
||||
case Constants.COLLECTION:
|
||||
collCount++;
|
||||
break;
|
||||
|
||||
case Constants.COMMUNITY:
|
||||
commCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Make objects from the handles - make arrays, fill them out
|
||||
resultsCommunities = new Community[commCount];
|
||||
resultsCollections = new Collection[collCount];
|
||||
resultsItems = new Item[itemCount];
|
||||
|
||||
collCount = 0;
|
||||
commCount = 0;
|
||||
itemCount = 0;
|
||||
|
||||
for (int i = 0; i < qResults.getHitTypes().size(); i++)
|
||||
{
|
||||
Integer myId = qResults.getHitIds().get(i);
|
||||
String myHandle = qResults.getHitHandles().get(i);
|
||||
Integer myType = qResults.getHitTypes().get(i);
|
||||
|
||||
// add the handle to the appropriate lists
|
||||
switch (myType.intValue())
|
||||
{
|
||||
case Constants.ITEM:
|
||||
if (myId != null)
|
||||
{
|
||||
resultsItems[itemCount] = Item.find(context, myId);
|
||||
}
|
||||
else
|
||||
{
|
||||
resultsItems[itemCount] = (Item)HandleManager.resolveToObject(context, myHandle);
|
||||
}
|
||||
|
||||
if (resultsItems[itemCount] == null)
|
||||
{
|
||||
throw new SQLException("Query \"" + query
|
||||
+ "\" returned unresolvable item");
|
||||
}
|
||||
itemCount++;
|
||||
break;
|
||||
|
||||
case Constants.COLLECTION:
|
||||
if (myId != null)
|
||||
{
|
||||
resultsCollections[collCount] = Collection.find(context, myId);
|
||||
}
|
||||
else
|
||||
{
|
||||
resultsCollections[collCount] = (Collection)HandleManager.resolveToObject(context, myHandle);
|
||||
}
|
||||
|
||||
if (resultsCollections[collCount] == null)
|
||||
{
|
||||
throw new SQLException("Query \"" + query
|
||||
+ "\" returned unresolvable collection");
|
||||
}
|
||||
|
||||
collCount++;
|
||||
break;
|
||||
|
||||
case Constants.COMMUNITY:
|
||||
if (myId != null)
|
||||
{
|
||||
resultsCommunities[commCount] = Community.find(context, myId);
|
||||
}
|
||||
else
|
||||
{
|
||||
resultsCommunities[commCount] = (Community)HandleManager.resolveToObject(context, myHandle);
|
||||
}
|
||||
|
||||
if (resultsCommunities[commCount] == null)
|
||||
{
|
||||
throw new SQLException("Query \"" + query
|
||||
+ "\" returned unresolvable community");
|
||||
}
|
||||
|
||||
commCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Log
|
||||
log.info(LogManager.getHeader(context, "search", logInfo + "query=\""
|
||||
+ query + "\",results=(" + resultsCommunities.length + ","
|
||||
+ resultsCollections.length + "," + resultsItems.length + ")"));
|
||||
|
||||
// Pass in some page qualities
|
||||
// total number of pages
|
||||
int pageTotal = 1 + ((qResults.getHitCount() - 1) / qResults
|
||||
.getPageSize());
|
||||
|
||||
// current page being displayed
|
||||
int pageCurrent = 1 + (qResults.getStart() / qResults.getPageSize());
|
||||
|
||||
// pageLast = min(pageCurrent+9,pageTotal)
|
||||
int pageLast = ((pageCurrent + 9) > pageTotal) ? pageTotal
|
||||
: (pageCurrent + 9);
|
||||
|
||||
// pageFirst = max(1,pageCurrent-9)
|
||||
int pageFirst = ((pageCurrent - 9) > 1) ? (pageCurrent - 9) : 1;
|
||||
|
||||
// Pass the results to the display JSP
|
||||
request.setAttribute("items", resultsItems);
|
||||
request.setAttribute("communities", resultsCommunities);
|
||||
request.setAttribute("collections", resultsCollections);
|
||||
|
||||
request.setAttribute("pagetotal", Integer.valueOf(pageTotal));
|
||||
request.setAttribute("pagecurrent", Integer.valueOf(pageCurrent));
|
||||
request.setAttribute("pagelast", Integer.valueOf(pageLast));
|
||||
request.setAttribute("pagefirst", Integer.valueOf(pageFirst));
|
||||
|
||||
request.setAttribute("queryresults", qResults);
|
||||
|
||||
// And the original query string
|
||||
request.setAttribute("query", query);
|
||||
|
||||
request.setAttribute("order", qArgs.getSortOrder());
|
||||
request.setAttribute("sortedBy", sortOption);
|
||||
|
||||
if (AuthorizeManager.isAdmin(context))
|
||||
{
|
||||
// Set a variable to create admin buttons
|
||||
request.setAttribute("admin_button", Boolean.TRUE);
|
||||
}
|
||||
|
||||
if ((fromAdvanced != null) && (qResults.getHitCount() == 0))
|
||||
{
|
||||
// send back to advanced form if no results
|
||||
Community[] communities = Community.findAll(context);
|
||||
request.setAttribute("communities", communities);
|
||||
request.setAttribute("no_results", "yes");
|
||||
|
||||
Map<String, String> queryHash = qArgs.buildQueryMap(request);
|
||||
|
||||
if (queryHash != null)
|
||||
{
|
||||
for (Map.Entry<String, String> entry : queryHash.entrySet())
|
||||
{
|
||||
request.setAttribute(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
JSPManager.showJSP(request, response, "/search/advanced.jsp");
|
||||
}
|
||||
else if ("submit_export_metadata".equals(UIUtil.getSubmitButton(request, "submit")))
|
||||
{
|
||||
exportMetadata(context, response, resultsItems);
|
||||
}
|
||||
else
|
||||
{
|
||||
JSPManager.showJSP(request, response, "/search/results.jsp");
|
||||
}
|
||||
}
|
||||
catch (IllegalStateException e)
|
||||
{
|
||||
throw new SearchProcessorException(e.getMessage(), e);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new SearchProcessorException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for constructing the advanced search form
|
||||
*
|
||||
* @author gam
|
||||
*/
|
||||
@Override
|
||||
public void doAdvancedSearch(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response) throws SearchProcessorException, ServletException, IOException
|
||||
{
|
||||
// just build a list of top-level communities and pass along to the jsp
|
||||
Community[] communities;
|
||||
try
|
||||
{
|
||||
communities = Community.findAllTop(context);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new SearchProcessorException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
request.setAttribute("communities", communities);
|
||||
|
||||
JSPManager.showJSP(request, response, "/search/advanced.jsp");
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for producing OpenSearch-compliant search results, and the
|
||||
* OpenSearch description document.
|
||||
* <p>
|
||||
* The value of the "scope" parameter should be absent (which means no scope
|
||||
* restriction), or the handle of a community or collection, otherwise
|
||||
* parameters exactly match those of the SearchServlet.
|
||||
* </p>
|
||||
*
|
||||
* @author Richard Rodgers
|
||||
*/
|
||||
@Override
|
||||
public void doOpenSearch(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response) throws SearchProcessorException, IOException, ServletException
|
||||
{
|
||||
// dispense with simple service document requests
|
||||
String scope = request.getParameter("scope");
|
||||
if (scope !=null && "".equals(scope))
|
||||
{
|
||||
scope = null;
|
||||
}
|
||||
String path = request.getPathInfo();
|
||||
if (path != null && path.endsWith("description.xml"))
|
||||
{
|
||||
String svcDescrip = OpenSearch.getDescription(scope);
|
||||
response.setContentType(OpenSearch.getContentType("opensearchdescription"));
|
||||
response.setContentLength(svcDescrip.length());
|
||||
response.getWriter().write(svcDescrip);
|
||||
return;
|
||||
}
|
||||
|
||||
// get enough request parameters to decide on action to take
|
||||
String format = request.getParameter("format");
|
||||
if (format == null || "".equals(format))
|
||||
{
|
||||
// default to atom
|
||||
format = "atom";
|
||||
}
|
||||
|
||||
// do some sanity checking
|
||||
if (! OpenSearch.getFormats().contains(format))
|
||||
{
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
// then the rest - we are processing the query
|
||||
String query = request.getParameter("query");
|
||||
int start = Util.getIntParameter(request, "start");
|
||||
int rpp = Util.getIntParameter(request, "rpp");
|
||||
int sort = Util.getIntParameter(request, "sort_by");
|
||||
String order = request.getParameter("order");
|
||||
String sortOrder = (order == null || order.length() == 0 || order.toLowerCase().startsWith("asc")) ?
|
||||
SortOption.ASCENDING : SortOption.DESCENDING;
|
||||
|
||||
QueryArgs qArgs = new QueryArgs();
|
||||
// can't start earlier than 0 in the results!
|
||||
if (start < 0)
|
||||
{
|
||||
start = 0;
|
||||
}
|
||||
qArgs.setStart(start);
|
||||
|
||||
if (rpp > 0)
|
||||
{
|
||||
qArgs.setPageSize(rpp);
|
||||
}
|
||||
qArgs.setSortOrder(sortOrder);
|
||||
|
||||
if (sort > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
qArgs.setSortOption(SortOption.getSortOption(sort));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// invalid sort id - do nothing
|
||||
}
|
||||
}
|
||||
qArgs.setSortOrder(sortOrder);
|
||||
|
||||
// Ensure the query is non-null
|
||||
if (query == null)
|
||||
{
|
||||
query = "";
|
||||
}
|
||||
|
||||
// If there is a scope parameter, attempt to dereference it
|
||||
// failure will only result in its being ignored
|
||||
DSpaceObject container;
|
||||
try
|
||||
{
|
||||
container = (scope != null) ? HandleManager.resolveToObject(context, scope) : null;
|
||||
}
|
||||
catch (IllegalStateException e)
|
||||
{
|
||||
throw new SearchProcessorException(e.getMessage(), e);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new SearchProcessorException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
// Build log information
|
||||
String logInfo = "";
|
||||
|
||||
// get the start of the query results page
|
||||
qArgs.setQuery(query);
|
||||
|
||||
// Perform the search
|
||||
QueryResults qResults = null;
|
||||
if (container == null)
|
||||
{
|
||||
qResults = DSQuery.doQuery(context, qArgs);
|
||||
}
|
||||
else if (container instanceof Collection)
|
||||
{
|
||||
logInfo = "collection_id=" + container.getID() + ",";
|
||||
qResults = DSQuery.doQuery(context, qArgs, (Collection)container);
|
||||
}
|
||||
else if (container instanceof Community)
|
||||
{
|
||||
logInfo = "community_id=" + container.getID() + ",";
|
||||
qResults = DSQuery.doQuery(context, qArgs, (Community)container);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException("Invalid container for search context");
|
||||
}
|
||||
|
||||
// now instantiate the results
|
||||
DSpaceObject[] results = new DSpaceObject[qResults.getHitHandles().size()];
|
||||
for (int i = 0; i < qResults.getHitHandles().size(); i++)
|
||||
{
|
||||
String myHandle = qResults.getHitHandles().get(i);
|
||||
DSpaceObject dso;
|
||||
try
|
||||
{
|
||||
dso = HandleManager.resolveToObject(context, myHandle);
|
||||
}
|
||||
catch (IllegalStateException e)
|
||||
{
|
||||
throw new SearchProcessorException(e.getMessage(), e);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new SearchProcessorException(e.getMessage(), e);
|
||||
}
|
||||
if (dso == null)
|
||||
{
|
||||
throw new SearchProcessorException("Query \"" + query
|
||||
+ "\" returned unresolvable handle: " + myHandle);
|
||||
}
|
||||
results[i] = dso;
|
||||
}
|
||||
|
||||
// Log
|
||||
log.info(LogManager.getHeader(context, "search", logInfo + "query=\"" + query + "\",results=(" + results.length + ")"));
|
||||
|
||||
// format and return results
|
||||
Map<String, String> labelMap = getLabels(request);
|
||||
Document resultsDoc = OpenSearch.getResultsDoc(format, query, qResults, container, results, labelMap);
|
||||
try
|
||||
{
|
||||
Transformer xf = TransformerFactory.newInstance().newTransformer();
|
||||
response.setContentType(OpenSearch.getContentType(format));
|
||||
xf.transform(new DOMSource(resultsDoc), new StreamResult(response.getWriter()));
|
||||
}
|
||||
catch (TransformerException e)
|
||||
{
|
||||
log.error(e);
|
||||
throw new ServletException(e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the search results as a csv file
|
||||
*
|
||||
* @param context The DSpace context
|
||||
* @param response The request object
|
||||
* @param items The result items
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
protected void exportMetadata(Context context, HttpServletResponse response, Item[] items)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
// Log the attempt
|
||||
log.info(LogManager.getHeader(context, "metadataexport", "exporting_search"));
|
||||
|
||||
// Export a search view
|
||||
List<Integer> iids = new ArrayList<Integer>();
|
||||
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();
|
||||
|
||||
// Return the csv file
|
||||
response.setContentType("text/csv; charset=UTF-8");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=search-results.csv");
|
||||
PrintWriter out = response.getWriter();
|
||||
out.write(csv.toString());
|
||||
out.flush();
|
||||
out.close();
|
||||
log.info(LogManager.getHeader(context, "metadataexport", "exported_file:search-results.csv"));
|
||||
return;
|
||||
}
|
||||
|
||||
private Map<String, String> getLabels(HttpServletRequest request)
|
||||
{
|
||||
// Get access to the localized resource bundle
|
||||
Locale locale = request.getLocale();
|
||||
Map<String, String> labelMap = localeLabels.get(locale.toString());
|
||||
if (labelMap == null)
|
||||
{
|
||||
labelMap = getLocaleLabels(locale);
|
||||
localeLabels.put(locale.toString(), labelMap);
|
||||
}
|
||||
return labelMap;
|
||||
}
|
||||
|
||||
private Map<String, String> getLocaleLabels(Locale locale)
|
||||
{
|
||||
Map<String, String> labelMap = new HashMap<String, String>();
|
||||
ResourceBundle labels = ResourceBundle.getBundle("Messages", locale);
|
||||
|
||||
labelMap.put(SyndicationFeed.MSG_UNTITLED, labels.getString(msgKey + ".notitle"));
|
||||
labelMap.put(SyndicationFeed.MSG_LOGO_TITLE, labels.getString(msgKey + ".logo.title"));
|
||||
labelMap.put(SyndicationFeed.MSG_FEED_DESCRIPTION, labels.getString(msgKey + ".general-feed.description"));
|
||||
labelMap.put(SyndicationFeed.MSG_UITYPE, SyndicationFeed.UITYPE_JSPUI);
|
||||
for (String selector : SyndicationFeed.getDescriptionSelectors())
|
||||
{
|
||||
labelMap.put("metadata." + selector, labels.getString(SyndicationFeed.MSG_METADATA + selector));
|
||||
}
|
||||
return labelMap;
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package org.dspace.app.webui.search;
|
||||
|
||||
public class SearchProcessorException extends Exception
|
||||
{
|
||||
|
||||
public SearchProcessorException()
|
||||
{
|
||||
super();
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public SearchProcessorException(String message)
|
||||
{
|
||||
super(message);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public SearchProcessorException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public SearchProcessorException(Throwable cause)
|
||||
{
|
||||
super(cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package org.dspace.app.webui.search;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.dspace.core.Context;
|
||||
|
||||
public interface SearchRequestProcessor
|
||||
{
|
||||
public void doSimpleSearch(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response) throws SearchProcessorException,
|
||||
IOException, ServletException;
|
||||
|
||||
public void doAdvancedSearch(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response) throws SearchProcessorException,
|
||||
IOException, ServletException;
|
||||
|
||||
public void doOpenSearch(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response) throws SearchProcessorException,
|
||||
IOException, ServletException;
|
||||
|
||||
}
|
@@ -14,28 +14,56 @@ import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.dspace.app.webui.util.JSPManager;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.app.webui.search.LuceneSearchProcessor;
|
||||
import org.dspace.app.webui.search.SearchProcessorException;
|
||||
import org.dspace.app.webui.search.SearchRequestProcessor;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.PluginConfigurationError;
|
||||
import org.dspace.core.PluginManager;
|
||||
|
||||
/**
|
||||
* Servlet for constructing the advanced search form
|
||||
* Servlet for constructing/processing an advanced search form
|
||||
*
|
||||
* @author gam
|
||||
* @version $Revision$
|
||||
*/
|
||||
public class AdvancedSearchServlet extends DSpaceServlet
|
||||
{
|
||||
private SearchRequestProcessor internalLogic;
|
||||
|
||||
/** log4j category */
|
||||
private static Logger log = Logger.getLogger(AdvancedSearchServlet.class);
|
||||
|
||||
public void init()
|
||||
{
|
||||
try
|
||||
{
|
||||
internalLogic = (SearchRequestProcessor) PluginManager
|
||||
.getSinglePlugin(SearchRequestProcessor.class);
|
||||
}
|
||||
catch (PluginConfigurationError e)
|
||||
{
|
||||
log.warn(
|
||||
"AdvancedSearchServlet not properly configurated, please configure the SearchRequestProcessor plugin",
|
||||
e);
|
||||
}
|
||||
if (internalLogic == null)
|
||||
{ // backward compatibility
|
||||
internalLogic = new LuceneSearchProcessor();
|
||||
}
|
||||
}
|
||||
|
||||
protected void doDSGet(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response) throws ServletException, IOException,
|
||||
SQLException, AuthorizeException
|
||||
{
|
||||
// just build a list of top-level communities and pass along to the jsp
|
||||
Community[] communities = Community.findAllTop(context);
|
||||
|
||||
request.setAttribute("communities", communities);
|
||||
|
||||
JSPManager.showJSP(request, response, "/search/advanced.jsp");
|
||||
try
|
||||
{
|
||||
internalLogic.doAdvancedSearch(context, request, response);
|
||||
}
|
||||
catch (SearchProcessorException e)
|
||||
{
|
||||
throw new ServletException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -43,6 +43,7 @@ import org.dspace.eperson.Subscribe;
|
||||
import org.dspace.handle.HandleManager;
|
||||
import org.dspace.plugin.CollectionHomeProcessor;
|
||||
import org.dspace.plugin.CommunityHomeProcessor;
|
||||
import org.dspace.plugin.ItemHomeProcessor;
|
||||
import org.dspace.usage.UsageEvent;
|
||||
import org.dspace.utils.DSpace;
|
||||
import org.jdom.Element;
|
||||
@@ -290,6 +291,9 @@ public class HandleServlet extends DSpaceServlet
|
||||
throws ServletException, IOException, SQLException,
|
||||
AuthorizeException
|
||||
{
|
||||
// perform any necessary pre-processing
|
||||
preProcessItemHome(context, request, response, item);
|
||||
|
||||
// Tombstone?
|
||||
if (item.isWithdrawn())
|
||||
{
|
||||
@@ -416,6 +420,25 @@ public class HandleServlet extends DSpaceServlet
|
||||
JSPManager.showJSP(request, response, "/display-item.jsp");
|
||||
}
|
||||
|
||||
private void preProcessItemHome(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response, Item item)
|
||||
throws ServletException, IOException, SQLException
|
||||
{
|
||||
try
|
||||
{
|
||||
ItemHomeProcessor[] chp = (ItemHomeProcessor[]) PluginManager.getPluginSequence(ItemHomeProcessor.class);
|
||||
for (int i = 0; i < chp.length; i++)
|
||||
{
|
||||
chp[i].process(context, request, response, item);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("caught exception: ", e);
|
||||
throw new ServletException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a community home page, or deal with button press on home page
|
||||
*
|
||||
|
@@ -0,0 +1,72 @@
|
||||
package org.dspace.app.webui.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.app.webui.json.JSONRequest;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.core.PluginManager;
|
||||
|
||||
public class JSONServlet extends DSpaceServlet
|
||||
{
|
||||
private static Logger log = Logger.getLogger(JSONServlet.class);
|
||||
|
||||
@Override
|
||||
protected void doDSPost(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response) throws ServletException, IOException,
|
||||
SQLException, AuthorizeException
|
||||
{
|
||||
doDSGet(context, request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doDSGet(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response) throws IOException,
|
||||
AuthorizeException
|
||||
{
|
||||
String pluginName = request.getPathInfo();
|
||||
|
||||
if (pluginName == null)
|
||||
{
|
||||
pluginName = "";
|
||||
}
|
||||
|
||||
if (pluginName.startsWith("/"))
|
||||
{
|
||||
pluginName = pluginName.substring(1);
|
||||
pluginName = pluginName.split("/")[0];
|
||||
}
|
||||
JSONRequest jsonReq = (JSONRequest) PluginManager.getNamedPlugin(JSONRequest.class,
|
||||
pluginName);
|
||||
|
||||
if (jsonReq == null)
|
||||
{
|
||||
log.error(LogManager.getHeader(context, "jsonrequest",
|
||||
"No plugin found for manage the path " + pluginName));
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
jsonReq.setSubPath(pluginName);
|
||||
try
|
||||
{
|
||||
response.setContentType("application/json; charset=UTF-8");
|
||||
jsonReq.doJSONRequest(context, request, response);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// no need to log, logging is already done by the
|
||||
// InternalErrorServlet
|
||||
// log.error(LogManager.getHeader(context, "jsonrequest",
|
||||
// pluginName),
|
||||
// e);
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -9,237 +9,71 @@ package org.dspace.app.webui.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.app.util.OpenSearch;
|
||||
import org.dspace.app.util.SyndicationFeed;
|
||||
import org.dspace.app.util.Util;
|
||||
import org.dspace.app.webui.search.LuceneSearchProcessor;
|
||||
import org.dspace.app.webui.search.SearchProcessorException;
|
||||
import org.dspace.app.webui.search.SearchRequestProcessor;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.handle.HandleManager;
|
||||
import org.dspace.search.DSQuery;
|
||||
import org.dspace.search.QueryArgs;
|
||||
import org.dspace.search.QueryResults;
|
||||
import org.dspace.sort.SortOption;
|
||||
import org.dspace.core.PluginConfigurationError;
|
||||
import org.dspace.core.PluginManager;
|
||||
|
||||
/**
|
||||
* Servlet for producing OpenSearch-compliant search results, and the
|
||||
* OpenSearch description document.
|
||||
* Servlet for producing OpenSearch-compliant search results, and the OpenSearch
|
||||
* description document.
|
||||
* <p>
|
||||
* OpenSearch is a specification for describing and advertising search-engines
|
||||
* and their result formats. Commonly, RSS and Atom formats are used, which
|
||||
* the current implementation supports, as is HTML (used directly in browsers).
|
||||
* NB: this is baseline OpenSearch, no extensions currently supported.
|
||||
* and their result formats. Commonly, RSS and Atom formats are used, which the
|
||||
* current implementation supports, as is HTML (used directly in browsers). NB:
|
||||
* this is baseline OpenSearch, no extensions currently supported.
|
||||
* </p>
|
||||
* <p>
|
||||
* The value of the "scope" parameter should be absent (which means no
|
||||
* scope restriction), or the handle of a community or collection, otherwise
|
||||
* parameters exactly match those of the SearchServlet.
|
||||
* </p>
|
||||
*
|
||||
* @author Richard Rodgers
|
||||
*
|
||||
*/
|
||||
public class OpenSearchServlet extends DSpaceServlet
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static String msgKey = "org.dspace.app.webui.servlet.FeedServlet";
|
||||
/** log4j category */
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private SearchRequestProcessor internalLogic;
|
||||
|
||||
/** log4j category */
|
||||
private static Logger log = Logger.getLogger(OpenSearchServlet.class);
|
||||
// locale-sensitive metadata labels
|
||||
private Map<String, Map<String, String>> localeLabels = null;
|
||||
|
||||
public void init()
|
||||
{
|
||||
localeLabels = new HashMap<String, Map<String, String>>();
|
||||
try
|
||||
{
|
||||
internalLogic = (SearchRequestProcessor) PluginManager
|
||||
.getSinglePlugin(SearchRequestProcessor.class);
|
||||
}
|
||||
catch (PluginConfigurationError e)
|
||||
{
|
||||
log.warn(
|
||||
"OpenSearchServlet not properly configurated, please configure the SearchRequestProcessor plugin",
|
||||
e);
|
||||
}
|
||||
if (internalLogic == null)
|
||||
{ // backward compatibility
|
||||
internalLogic = new LuceneSearchProcessor();
|
||||
}
|
||||
}
|
||||
|
||||
protected void doDSGet(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response) throws ServletException, IOException,
|
||||
SQLException, AuthorizeException
|
||||
{
|
||||
// dispense with simple service document requests
|
||||
String scope = request.getParameter("scope");
|
||||
if (scope !=null && "".equals(scope))
|
||||
{
|
||||
scope = null;
|
||||
}
|
||||
String path = request.getPathInfo();
|
||||
if (path != null && path.endsWith("description.xml"))
|
||||
{
|
||||
String svcDescrip = OpenSearch.getDescription(scope);
|
||||
response.setContentType(OpenSearch.getContentType("opensearchdescription"));
|
||||
response.setContentLength(svcDescrip.length());
|
||||
response.getWriter().write(svcDescrip);
|
||||
return;
|
||||
}
|
||||
|
||||
// get enough request parameters to decide on action to take
|
||||
String format = request.getParameter("format");
|
||||
if (format == null || "".equals(format))
|
||||
{
|
||||
// default to atom
|
||||
format = "atom";
|
||||
}
|
||||
|
||||
// do some sanity checking
|
||||
if (! OpenSearch.getFormats().contains(format))
|
||||
{
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
// then the rest - we are processing the query
|
||||
String query = request.getParameter("query");
|
||||
int start = Util.getIntParameter(request, "start");
|
||||
int rpp = Util.getIntParameter(request, "rpp");
|
||||
int sort = Util.getIntParameter(request, "sort_by");
|
||||
String order = request.getParameter("order");
|
||||
String sortOrder = (order == null || order.length() == 0 || order.toLowerCase().startsWith("asc")) ?
|
||||
SortOption.ASCENDING : SortOption.DESCENDING;
|
||||
|
||||
QueryArgs qArgs = new QueryArgs();
|
||||
// can't start earlier than 0 in the results!
|
||||
if (start < 0)
|
||||
{
|
||||
start = 0;
|
||||
}
|
||||
qArgs.setStart(start);
|
||||
|
||||
if (rpp > 0)
|
||||
{
|
||||
qArgs.setPageSize(rpp);
|
||||
}
|
||||
qArgs.setSortOrder(sortOrder);
|
||||
|
||||
if (sort > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
qArgs.setSortOption(SortOption.getSortOption(sort));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// invalid sort id - do nothing
|
||||
}
|
||||
}
|
||||
qArgs.setSortOrder(sortOrder);
|
||||
|
||||
// Ensure the query is non-null
|
||||
if (query == null)
|
||||
{
|
||||
query = "";
|
||||
}
|
||||
|
||||
// If there is a scope parameter, attempt to dereference it
|
||||
// failure will only result in its being ignored
|
||||
DSpaceObject container = (scope != null) ? HandleManager.resolveToObject(context, scope) : null;
|
||||
|
||||
// Build log information
|
||||
String logInfo = "";
|
||||
|
||||
// get the start of the query results page
|
||||
qArgs.setQuery(query);
|
||||
|
||||
// Perform the search
|
||||
QueryResults qResults = null;
|
||||
if (container == null)
|
||||
{
|
||||
qResults = DSQuery.doQuery(context, qArgs);
|
||||
}
|
||||
else if (container instanceof Collection)
|
||||
{
|
||||
logInfo = "collection_id=" + container.getID() + ",";
|
||||
qResults = DSQuery.doQuery(context, qArgs, (Collection)container);
|
||||
}
|
||||
else if (container instanceof Community)
|
||||
{
|
||||
logInfo = "community_id=" + container.getID() + ",";
|
||||
qResults = DSQuery.doQuery(context, qArgs, (Community)container);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException("Invalid container for search context");
|
||||
}
|
||||
|
||||
// now instantiate the results
|
||||
DSpaceObject[] results = new DSpaceObject[qResults.getHitHandles().size()];
|
||||
for (int i = 0; i < qResults.getHitHandles().size(); i++)
|
||||
{
|
||||
String myHandle = qResults.getHitHandles().get(i);
|
||||
DSpaceObject dso = HandleManager.resolveToObject(context, myHandle);
|
||||
if (dso == null)
|
||||
{
|
||||
throw new SQLException("Query \"" + query
|
||||
+ "\" returned unresolvable handle: " + myHandle);
|
||||
}
|
||||
results[i] = dso;
|
||||
}
|
||||
|
||||
// Log
|
||||
log.info(LogManager.getHeader(context, "search", logInfo + "query=\"" + query + "\",results=(" + results.length + ")"));
|
||||
|
||||
// format and return results
|
||||
Map<String, String> labelMap = getLabels(request);
|
||||
Document resultsDoc = OpenSearch.getResultsDoc(format, query, qResults, container, results, labelMap);
|
||||
try
|
||||
{
|
||||
Transformer xf = TransformerFactory.newInstance().newTransformer();
|
||||
response.setContentType(OpenSearch.getContentType(format));
|
||||
xf.transform(new DOMSource(resultsDoc), new StreamResult(response.getWriter()));
|
||||
internalLogic.doOpenSearch(context, request, response);
|
||||
}
|
||||
catch (TransformerException e)
|
||||
catch (SearchProcessorException e)
|
||||
{
|
||||
log.error(e);
|
||||
throw new ServletException(e.toString(), e);
|
||||
throw new ServletException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> getLabels(HttpServletRequest request)
|
||||
{
|
||||
// Get access to the localized resource bundle
|
||||
Locale locale = request.getLocale();
|
||||
Map<String, String> labelMap = localeLabels.get(locale.toString());
|
||||
if (labelMap == null)
|
||||
{
|
||||
labelMap = getLocaleLabels(locale);
|
||||
localeLabels.put(locale.toString(), labelMap);
|
||||
}
|
||||
return labelMap;
|
||||
}
|
||||
|
||||
private Map<String, String> getLocaleLabels(Locale locale)
|
||||
{
|
||||
Map<String, String> labelMap = new HashMap<String, String>();
|
||||
ResourceBundle labels = ResourceBundle.getBundle("Messages", locale);
|
||||
|
||||
labelMap.put(SyndicationFeed.MSG_UNTITLED, labels.getString(msgKey + ".notitle"));
|
||||
labelMap.put(SyndicationFeed.MSG_LOGO_TITLE, labels.getString(msgKey + ".logo.title"));
|
||||
labelMap.put(SyndicationFeed.MSG_FEED_DESCRIPTION, labels.getString(msgKey + ".general-feed.description"));
|
||||
labelMap.put(SyndicationFeed.MSG_UITYPE, SyndicationFeed.UITYPE_JSPUI);
|
||||
for (String selector : SyndicationFeed.getDescriptionSelectors())
|
||||
{
|
||||
labelMap.put("metadata." + selector, labels.getString(SyndicationFeed.MSG_METADATA + selector));
|
||||
}
|
||||
return labelMap;
|
||||
}
|
||||
}
|
||||
|
@@ -8,423 +8,62 @@
|
||||
package org.dspace.app.webui.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.URLEncoder;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.app.webui.util.JSPManager;
|
||||
import org.dspace.app.webui.util.UIUtil;
|
||||
import org.dspace.app.bulkedit.MetadataExport;
|
||||
import org.dspace.app.bulkedit.DSpaceCSV;
|
||||
import org.dspace.app.webui.search.LuceneSearchProcessor;
|
||||
import org.dspace.app.webui.search.SearchProcessorException;
|
||||
import org.dspace.app.webui.search.SearchRequestProcessor;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.authorize.AuthorizeManager;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.ItemIterator;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.handle.HandleManager;
|
||||
import org.dspace.search.DSQuery;
|
||||
import org.dspace.search.QueryArgs;
|
||||
import org.dspace.search.QueryResults;
|
||||
import org.dspace.sort.SortOption;
|
||||
import org.dspace.core.PluginConfigurationError;
|
||||
import org.dspace.core.PluginManager;
|
||||
|
||||
/**
|
||||
* Servlet for handling a simple search.
|
||||
* <p>
|
||||
* All metadata is search for the value contained in the "query" parameter. If
|
||||
* the "location" parameter is present, the user's location is switched to that
|
||||
* location using a redirect. Otherwise, the user's current location is used to
|
||||
* constrain the query; i.e., if the user is "in" a collection, only results
|
||||
* from the collection will be returned.
|
||||
* <p>
|
||||
* The value of the "location" parameter should be ALL (which means no
|
||||
* location), a the ID of a community (e.g. "123"), or a community ID, then a
|
||||
* slash, then a collection ID, e.g. "123/456".
|
||||
*
|
||||
* @author Robert Tansley
|
||||
* @version $Id: SimpleSearchServlet.java,v 1.17 2004/12/15 15:21:10 jimdowning
|
||||
* Exp $
|
||||
*/
|
||||
public class SimpleSearchServlet extends DSpaceServlet
|
||||
{
|
||||
private SearchRequestProcessor internalLogic;
|
||||
|
||||
/** log4j category */
|
||||
private static Logger log = Logger.getLogger(SimpleSearchServlet.class);
|
||||
|
||||
public void init()
|
||||
{
|
||||
try
|
||||
{
|
||||
internalLogic = (SearchRequestProcessor) PluginManager
|
||||
.getSinglePlugin(SearchRequestProcessor.class);
|
||||
}
|
||||
catch (PluginConfigurationError e)
|
||||
{
|
||||
log.warn(
|
||||
"SimpleSearchServlet not properly configurated, please configure the SearchRequestProcessor plugin",
|
||||
e);
|
||||
}
|
||||
if (internalLogic == null)
|
||||
{ // backward compatibility
|
||||
internalLogic = new LuceneSearchProcessor();
|
||||
}
|
||||
}
|
||||
|
||||
protected void doDSGet(Context context, HttpServletRequest request,
|
||||
HttpServletResponse response) throws ServletException, IOException,
|
||||
SQLException, AuthorizeException
|
||||
{
|
||||
// Get the query
|
||||
String query = request.getParameter("query");
|
||||
int start = UIUtil.getIntParameter(request, "start");
|
||||
String advanced = request.getParameter("advanced");
|
||||
String fromAdvanced = request.getParameter("from_advanced");
|
||||
int sortBy = UIUtil.getIntParameter(request, "sort_by");
|
||||
String order = request.getParameter("order");
|
||||
int rpp = UIUtil.getIntParameter(request, "rpp");
|
||||
String advancedQuery = "";
|
||||
|
||||
// can't start earlier than 0 in the results!
|
||||
if (start < 0)
|
||||
{
|
||||
start = 0;
|
||||
}
|
||||
|
||||
int collCount = 0;
|
||||
int commCount = 0;
|
||||
int itemCount = 0;
|
||||
|
||||
Item[] resultsItems;
|
||||
Collection[] resultsCollections;
|
||||
Community[] resultsCommunities;
|
||||
|
||||
QueryResults qResults = null;
|
||||
QueryArgs qArgs = new QueryArgs();
|
||||
SortOption sortOption = null;
|
||||
|
||||
if (request.getParameter("etal") != null)
|
||||
{
|
||||
qArgs.setEtAl(UIUtil.getIntParameter(request, "etal"));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (sortBy > 0)
|
||||
{
|
||||
sortOption = SortOption.getSortOption(sortBy);
|
||||
qArgs.setSortOption(sortOption);
|
||||
}
|
||||
|
||||
if (SortOption.ASCENDING.equalsIgnoreCase(order))
|
||||
{
|
||||
qArgs.setSortOrder(SortOption.ASCENDING);
|
||||
}
|
||||
else
|
||||
{
|
||||
qArgs.setSortOrder(SortOption.DESCENDING);
|
||||
}
|
||||
internalLogic.doSimpleSearch(context, request, response);
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (SearchProcessorException e)
|
||||
{
|
||||
throw new ServletException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
// Override the page setting if exporting metadata
|
||||
if ("submit_export_metadata".equals(UIUtil.getSubmitButton(request, "submit")))
|
||||
{
|
||||
qArgs.setPageSize(Integer.MAX_VALUE);
|
||||
}
|
||||
else if (rpp > 0)
|
||||
{
|
||||
qArgs.setPageSize(rpp);
|
||||
}
|
||||
|
||||
// if the "advanced" flag is set, build the query string from the
|
||||
// multiple query fields
|
||||
if (advanced != null)
|
||||
{
|
||||
query = qArgs.buildQuery(request);
|
||||
advancedQuery = qArgs.buildHTTPQuery(request);
|
||||
}
|
||||
|
||||
// Ensure the query is non-null
|
||||
if (query == null)
|
||||
{
|
||||
query = "";
|
||||
}
|
||||
|
||||
// Get the location parameter, if any
|
||||
String location = request.getParameter("location");
|
||||
|
||||
// If there is a location parameter, we should redirect to
|
||||
// do the search with the correct location.
|
||||
if ((location != null) && !location.equals(""))
|
||||
{
|
||||
String url = "";
|
||||
|
||||
if (!location.equals("/"))
|
||||
{
|
||||
// Location is a Handle
|
||||
url = "/handle/" + location;
|
||||
}
|
||||
|
||||
// Encode the query
|
||||
query = URLEncoder.encode(query, Constants.DEFAULT_ENCODING);
|
||||
|
||||
if (advancedQuery.length() > 0)
|
||||
{
|
||||
query = query + "&from_advanced=true&" + advancedQuery;
|
||||
}
|
||||
|
||||
// Do the redirect
|
||||
response.sendRedirect(response.encodeRedirectURL(request
|
||||
.getContextPath()
|
||||
+ url + "/simple-search?query=" + query));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Build log information
|
||||
String logInfo = "";
|
||||
|
||||
// Get our location
|
||||
Community community = UIUtil.getCommunityLocation(request);
|
||||
Collection collection = UIUtil.getCollectionLocation(request);
|
||||
|
||||
// get the start of the query results page
|
||||
// List resultObjects = null;
|
||||
qArgs.setQuery(query);
|
||||
qArgs.setStart(start);
|
||||
|
||||
// Perform the search
|
||||
if (collection != null)
|
||||
{
|
||||
logInfo = "collection_id=" + collection.getID() + ",";
|
||||
|
||||
// Values for drop-down box
|
||||
request.setAttribute("community", community);
|
||||
request.setAttribute("collection", collection);
|
||||
|
||||
qResults = DSQuery.doQuery(context, qArgs, collection);
|
||||
}
|
||||
else if (community != null)
|
||||
{
|
||||
logInfo = "community_id=" + community.getID() + ",";
|
||||
|
||||
request.setAttribute("community", community);
|
||||
|
||||
// Get the collections within the community for the dropdown box
|
||||
request
|
||||
.setAttribute("collection.array", community
|
||||
.getCollections());
|
||||
|
||||
qResults = DSQuery.doQuery(context, qArgs, community);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get all communities for dropdown box
|
||||
Community[] communities = Community.findAll(context);
|
||||
request.setAttribute("community.array", communities);
|
||||
|
||||
qResults = DSQuery.doQuery(context, qArgs);
|
||||
}
|
||||
|
||||
// now instantiate the results and put them in their buckets
|
||||
for (int i = 0; i < qResults.getHitTypes().size(); i++)
|
||||
{
|
||||
Integer myType = qResults.getHitTypes().get(i);
|
||||
|
||||
// add the handle to the appropriate lists
|
||||
switch (myType.intValue())
|
||||
{
|
||||
case Constants.ITEM:
|
||||
itemCount++;
|
||||
break;
|
||||
|
||||
case Constants.COLLECTION:
|
||||
collCount++;
|
||||
break;
|
||||
|
||||
case Constants.COMMUNITY:
|
||||
commCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Make objects from the handles - make arrays, fill them out
|
||||
resultsCommunities = new Community[commCount];
|
||||
resultsCollections = new Collection[collCount];
|
||||
resultsItems = new Item[itemCount];
|
||||
|
||||
collCount = 0;
|
||||
commCount = 0;
|
||||
itemCount = 0;
|
||||
|
||||
for (int i = 0; i < qResults.getHitTypes().size(); i++)
|
||||
{
|
||||
Integer myId = qResults.getHitIds().get(i);
|
||||
String myHandle = qResults.getHitHandles().get(i);
|
||||
Integer myType = qResults.getHitTypes().get(i);
|
||||
|
||||
// add the handle to the appropriate lists
|
||||
switch (myType.intValue())
|
||||
{
|
||||
case Constants.ITEM:
|
||||
if (myId != null)
|
||||
{
|
||||
resultsItems[itemCount] = Item.find(context, myId);
|
||||
}
|
||||
else
|
||||
{
|
||||
resultsItems[itemCount] = (Item)HandleManager.resolveToObject(context, myHandle);
|
||||
}
|
||||
|
||||
if (resultsItems[itemCount] == null)
|
||||
{
|
||||
throw new SQLException("Query \"" + query
|
||||
+ "\" returned unresolvable item");
|
||||
}
|
||||
itemCount++;
|
||||
break;
|
||||
|
||||
case Constants.COLLECTION:
|
||||
if (myId != null)
|
||||
{
|
||||
resultsCollections[collCount] = Collection.find(context, myId);
|
||||
}
|
||||
else
|
||||
{
|
||||
resultsCollections[collCount] = (Collection)HandleManager.resolveToObject(context, myHandle);
|
||||
}
|
||||
|
||||
if (resultsCollections[collCount] == null)
|
||||
{
|
||||
throw new SQLException("Query \"" + query
|
||||
+ "\" returned unresolvable collection");
|
||||
}
|
||||
|
||||
collCount++;
|
||||
break;
|
||||
|
||||
case Constants.COMMUNITY:
|
||||
if (myId != null)
|
||||
{
|
||||
resultsCommunities[commCount] = Community.find(context, myId);
|
||||
}
|
||||
else
|
||||
{
|
||||
resultsCommunities[commCount] = (Community)HandleManager.resolveToObject(context, myHandle);
|
||||
}
|
||||
|
||||
if (resultsCommunities[commCount] == null)
|
||||
{
|
||||
throw new SQLException("Query \"" + query
|
||||
+ "\" returned unresolvable community");
|
||||
}
|
||||
|
||||
commCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Log
|
||||
log.info(LogManager.getHeader(context, "search", logInfo + "query=\""
|
||||
+ query + "\",results=(" + resultsCommunities.length + ","
|
||||
+ resultsCollections.length + "," + resultsItems.length + ")"));
|
||||
|
||||
// Pass in some page qualities
|
||||
// total number of pages
|
||||
int pageTotal = 1 + ((qResults.getHitCount() - 1) / qResults
|
||||
.getPageSize());
|
||||
|
||||
// current page being displayed
|
||||
int pageCurrent = 1 + (qResults.getStart() / qResults.getPageSize());
|
||||
|
||||
// pageLast = min(pageCurrent+9,pageTotal)
|
||||
int pageLast = ((pageCurrent + 9) > pageTotal) ? pageTotal
|
||||
: (pageCurrent + 9);
|
||||
|
||||
// pageFirst = max(1,pageCurrent-9)
|
||||
int pageFirst = ((pageCurrent - 9) > 1) ? (pageCurrent - 9) : 1;
|
||||
|
||||
// Pass the results to the display JSP
|
||||
request.setAttribute("items", resultsItems);
|
||||
request.setAttribute("communities", resultsCommunities);
|
||||
request.setAttribute("collections", resultsCollections);
|
||||
|
||||
request.setAttribute("pagetotal", Integer.valueOf(pageTotal));
|
||||
request.setAttribute("pagecurrent", Integer.valueOf(pageCurrent));
|
||||
request.setAttribute("pagelast", Integer.valueOf(pageLast));
|
||||
request.setAttribute("pagefirst", Integer.valueOf(pageFirst));
|
||||
|
||||
request.setAttribute("queryresults", qResults);
|
||||
|
||||
// And the original query string
|
||||
request.setAttribute("query", query);
|
||||
|
||||
request.setAttribute("order", qArgs.getSortOrder());
|
||||
request.setAttribute("sortedBy", sortOption);
|
||||
|
||||
if (AuthorizeManager.isAdmin(context))
|
||||
{
|
||||
// Set a variable to create admin buttons
|
||||
request.setAttribute("admin_button", Boolean.TRUE);
|
||||
}
|
||||
|
||||
if ((fromAdvanced != null) && (qResults.getHitCount() == 0))
|
||||
{
|
||||
// send back to advanced form if no results
|
||||
Community[] communities = Community.findAll(context);
|
||||
request.setAttribute("communities", communities);
|
||||
request.setAttribute("no_results", "yes");
|
||||
|
||||
Map<String, String> queryHash = qArgs.buildQueryMap(request);
|
||||
|
||||
if (queryHash != null)
|
||||
{
|
||||
for (Map.Entry<String, String> entry : queryHash.entrySet())
|
||||
{
|
||||
request.setAttribute(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
JSPManager.showJSP(request, response, "/search/advanced.jsp");
|
||||
}
|
||||
else if ("submit_export_metadata".equals(UIUtil.getSubmitButton(request, "submit")))
|
||||
{
|
||||
exportMetadata(context, response, resultsItems);
|
||||
}
|
||||
else
|
||||
{
|
||||
JSPManager.showJSP(request, response, "/search/results.jsp");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the search results as a csv file
|
||||
*
|
||||
* @param context The DSpace context
|
||||
* @param response The request object
|
||||
* @param items The result items
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
protected void exportMetadata(Context context, HttpServletResponse response, Item[] items)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
// Log the attempt
|
||||
log.info(LogManager.getHeader(context, "metadataexport", "exporting_search"));
|
||||
|
||||
// Export a search view
|
||||
List<Integer> iids = new ArrayList<Integer>();
|
||||
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();
|
||||
|
||||
// Return the csv file
|
||||
response.setContentType("text/csv; charset=UTF-8");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=search-results.csv");
|
||||
PrintWriter out = response.getWriter();
|
||||
out.write(csv.toString());
|
||||
out.flush();
|
||||
out.close();
|
||||
log.info(LogManager.getHeader(context, "metadataexport", "exported_file:search-results.csv"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@@ -434,6 +434,11 @@
|
||||
<servlet-class>org.dspace.app.webui.servlet.ShibbolethServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>json</servlet-name>
|
||||
<servlet-class>org.dspace.app.webui.servlet.JSONServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>shibboleth-login</servlet-name>
|
||||
<url-pattern>/shibboleth-login</url-pattern>
|
||||
@@ -712,6 +717,11 @@
|
||||
<url-pattern>/choices/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>json</servlet-name>
|
||||
<url-pattern>/json/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Icon MIME type -->
|
||||
<mime-mapping>
|
||||
<extension>ico</extension>
|
||||
|
@@ -362,6 +362,8 @@
|
||||
}
|
||||
%>
|
||||
<%= sidebar %>
|
||||
|
||||
<%@ include file="discovery/static-sidebar-facet.jsp" %>
|
||||
</dspace:sidebar>
|
||||
|
||||
</dspace:layout>
|
||||
|
@@ -403,7 +403,7 @@
|
||||
%>
|
||||
|
||||
<%= sidebar %>
|
||||
|
||||
<%@ include file="discovery/static-sidebar-facet.jsp" %>
|
||||
</dspace:sidebar>
|
||||
|
||||
<div align="center">
|
||||
|
@@ -172,5 +172,6 @@ for (int i = supportedLocales.length-1; i >= 0; i--)
|
||||
<%
|
||||
}
|
||||
%>
|
||||
<%@ include file="discovery/static-sidebar-facet.jsp" %>
|
||||
</dspace:sidebar>
|
||||
</dspace:layout>
|
||||
|
@@ -37,6 +37,8 @@
|
||||
<%@ page import="org.dspace.content.Community" %>
|
||||
<%@ page import="org.dspace.core.Context" %>
|
||||
<%@ page import="org.dspace.core.LogManager" %>
|
||||
<%@ page import="org.dspace.core.PluginManager" %>
|
||||
<%@ page import="org.dspace.plugin.SiteHomeProcessor" %>
|
||||
|
||||
<%
|
||||
Context context = null;
|
||||
@@ -49,6 +51,21 @@
|
||||
// Obtain a context so that the location bar can display log in status
|
||||
context = UIUtil.obtainContext(request);
|
||||
|
||||
try
|
||||
{
|
||||
SiteHomeProcessor[] chp = (SiteHomeProcessor[]) PluginManager.getPluginSequence(SiteHomeProcessor.class);
|
||||
for (int i = 0; i < chp.length; i++)
|
||||
{
|
||||
chp[i].process(context, request, response);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger log = Logger.getLogger("org.dspace.jsp");
|
||||
log.error("caught exception: ", e);
|
||||
throw new ServletException(e);
|
||||
}
|
||||
|
||||
// Home page shows community list
|
||||
Community[] communities = Community.findAllTop(context);
|
||||
request.setAttribute("communities", communities);
|
||||
|
@@ -50,6 +50,8 @@
|
||||
<link rel="stylesheet" href="<%= request.getContextPath() %>/styles.css" type="text/css" />
|
||||
<link rel="stylesheet" href="<%= request.getContextPath() %>/print.css" media="print" type="text/css" />
|
||||
<link rel="shortcut icon" href="<%= request.getContextPath() %>/favicon.ico" type="image/x-icon"/>
|
||||
<link rel="stylesheet" href="<%= request.getContextPath() %>/css/discovery.css" type="text/css" />
|
||||
<link rel="stylesheet" href="<%= request.getContextPath() %>/static/css/jquery-ui-1.8.22.custom/redmond/jquery-ui-1.8.22.custom.css" type="text/css" />
|
||||
<%
|
||||
if (!"NONE".equals(feedRef))
|
||||
{
|
||||
@@ -81,7 +83,8 @@
|
||||
<script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/builder.js"> </script>
|
||||
<script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/controls.js"> </script>
|
||||
<script type="text/javascript" src="<%= request.getContextPath() %>/static/js/choice-support.js"> </script>
|
||||
|
||||
<script type='text/javascript' src='<%= request.getContextPath() %>/static/js/jquery/jquery-1.7.2.min.js'></script>
|
||||
<script type='text/javascript' src='<%= request.getContextPath() %>/static/js/jquery/jquery-ui-1.8.22.custom.min.js'></script>
|
||||
<%--Gooogle Analytics recording.--%>
|
||||
<%
|
||||
if (analyticsKey != null && analyticsKey.length() > 0)
|
||||
|
@@ -185,6 +185,7 @@ else
|
||||
<fmt:param><%=qResults.getStart()+1%></fmt:param>
|
||||
<fmt:param><%=qResults.getStart()+qResults.getHitHandles().size()%></fmt:param>
|
||||
<fmt:param><%=qResults.getHitCount()%></fmt:param>
|
||||
<fmt:param><%=(float) qResults.getQueryTime() / 1000 %></fmt:param>
|
||||
</fmt:message></p>
|
||||
|
||||
<% } %>
|
||||
|
After Width: | Height: | Size: 180 B |
After Width: | Height: | Size: 182 B |
After Width: | Height: | Size: 162 B |
After Width: | Height: | Size: 123 B |
After Width: | Height: | Size: 119 B |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 104 B |
After Width: | Height: | Size: 88 B |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 4.3 KiB |
@@ -0,0 +1,563 @@
|
||||
/*!
|
||||
* jQuery UI CSS Framework 1.8.22
|
||||
*
|
||||
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Theming/API
|
||||
*/
|
||||
|
||||
/* Layout helpers
|
||||
----------------------------------*/
|
||||
.ui-helper-hidden { display: none; }
|
||||
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
|
||||
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
|
||||
.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
|
||||
.ui-helper-clearfix:after { clear: both; }
|
||||
.ui-helper-clearfix { zoom: 1; }
|
||||
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
|
||||
|
||||
|
||||
/* Interaction Cues
|
||||
----------------------------------*/
|
||||
.ui-state-disabled { cursor: default !important; }
|
||||
|
||||
|
||||
/* Icons
|
||||
----------------------------------*/
|
||||
|
||||
/* states and images */
|
||||
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
|
||||
|
||||
|
||||
/* Misc visuals
|
||||
----------------------------------*/
|
||||
|
||||
/* Overlays */
|
||||
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
|
||||
|
||||
|
||||
/*!
|
||||
* jQuery UI CSS Framework 1.8.22
|
||||
*
|
||||
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Theming/API
|
||||
*
|
||||
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande,%20Lucida%20Sans,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
|
||||
*/
|
||||
|
||||
|
||||
/* Component containers
|
||||
----------------------------------*/
|
||||
.ui-widget { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1.1em; }
|
||||
.ui-widget .ui-widget { font-size: 1em; }
|
||||
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1em; }
|
||||
.ui-widget-content { border: 1px solid #a6c9e2; background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x; color: #222222; }
|
||||
.ui-widget-content a { color: #222222; }
|
||||
.ui-widget-header { border: 1px solid #4297d7; background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
|
||||
.ui-widget-header a { color: #ffffff; }
|
||||
|
||||
/* Interaction states
|
||||
----------------------------------*/
|
||||
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #c5dbec; background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #2e6e9e; }
|
||||
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #2e6e9e; text-decoration: none; }
|
||||
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #79b7e7; background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1d5987; }
|
||||
.ui-state-hover a, .ui-state-hover a:hover { color: #1d5987; text-decoration: none; }
|
||||
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #79b7e7; background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #e17009; }
|
||||
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #e17009; text-decoration: none; }
|
||||
.ui-widget :active { outline: none; }
|
||||
|
||||
/* Interaction Cues
|
||||
----------------------------------*/
|
||||
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fad42e; background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x; color: #363636; }
|
||||
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
|
||||
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
|
||||
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
|
||||
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
|
||||
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
|
||||
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
|
||||
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
|
||||
|
||||
/* Icons
|
||||
----------------------------------*/
|
||||
|
||||
/* states and images */
|
||||
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_469bdd_256x240.png); }
|
||||
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_469bdd_256x240.png); }
|
||||
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_d8e7f3_256x240.png); }
|
||||
.ui-state-default .ui-icon { background-image: url(images/ui-icons_6da8d5_256x240.png); }
|
||||
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_217bc0_256x240.png); }
|
||||
.ui-state-active .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); }
|
||||
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
|
||||
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
|
||||
|
||||
/* positioning */
|
||||
.ui-icon-carat-1-n { background-position: 0 0; }
|
||||
.ui-icon-carat-1-ne { background-position: -16px 0; }
|
||||
.ui-icon-carat-1-e { background-position: -32px 0; }
|
||||
.ui-icon-carat-1-se { background-position: -48px 0; }
|
||||
.ui-icon-carat-1-s { background-position: -64px 0; }
|
||||
.ui-icon-carat-1-sw { background-position: -80px 0; }
|
||||
.ui-icon-carat-1-w { background-position: -96px 0; }
|
||||
.ui-icon-carat-1-nw { background-position: -112px 0; }
|
||||
.ui-icon-carat-2-n-s { background-position: -128px 0; }
|
||||
.ui-icon-carat-2-e-w { background-position: -144px 0; }
|
||||
.ui-icon-triangle-1-n { background-position: 0 -16px; }
|
||||
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
|
||||
.ui-icon-triangle-1-e { background-position: -32px -16px; }
|
||||
.ui-icon-triangle-1-se { background-position: -48px -16px; }
|
||||
.ui-icon-triangle-1-s { background-position: -64px -16px; }
|
||||
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
|
||||
.ui-icon-triangle-1-w { background-position: -96px -16px; }
|
||||
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
|
||||
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
|
||||
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
|
||||
.ui-icon-arrow-1-n { background-position: 0 -32px; }
|
||||
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
|
||||
.ui-icon-arrow-1-e { background-position: -32px -32px; }
|
||||
.ui-icon-arrow-1-se { background-position: -48px -32px; }
|
||||
.ui-icon-arrow-1-s { background-position: -64px -32px; }
|
||||
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
|
||||
.ui-icon-arrow-1-w { background-position: -96px -32px; }
|
||||
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
|
||||
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
|
||||
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
|
||||
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
|
||||
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
|
||||
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
|
||||
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
|
||||
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
|
||||
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
|
||||
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
|
||||
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
|
||||
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
|
||||
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
|
||||
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
|
||||
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
|
||||
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
|
||||
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
|
||||
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
|
||||
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
|
||||
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
|
||||
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
|
||||
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
|
||||
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
|
||||
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
|
||||
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
|
||||
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
|
||||
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
|
||||
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
|
||||
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
|
||||
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
|
||||
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
|
||||
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
|
||||
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
|
||||
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
|
||||
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
|
||||
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
|
||||
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
|
||||
.ui-icon-arrow-4 { background-position: 0 -80px; }
|
||||
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
|
||||
.ui-icon-extlink { background-position: -32px -80px; }
|
||||
.ui-icon-newwin { background-position: -48px -80px; }
|
||||
.ui-icon-refresh { background-position: -64px -80px; }
|
||||
.ui-icon-shuffle { background-position: -80px -80px; }
|
||||
.ui-icon-transfer-e-w { background-position: -96px -80px; }
|
||||
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
|
||||
.ui-icon-folder-collapsed { background-position: 0 -96px; }
|
||||
.ui-icon-folder-open { background-position: -16px -96px; }
|
||||
.ui-icon-document { background-position: -32px -96px; }
|
||||
.ui-icon-document-b { background-position: -48px -96px; }
|
||||
.ui-icon-note { background-position: -64px -96px; }
|
||||
.ui-icon-mail-closed { background-position: -80px -96px; }
|
||||
.ui-icon-mail-open { background-position: -96px -96px; }
|
||||
.ui-icon-suitcase { background-position: -112px -96px; }
|
||||
.ui-icon-comment { background-position: -128px -96px; }
|
||||
.ui-icon-person { background-position: -144px -96px; }
|
||||
.ui-icon-print { background-position: -160px -96px; }
|
||||
.ui-icon-trash { background-position: -176px -96px; }
|
||||
.ui-icon-locked { background-position: -192px -96px; }
|
||||
.ui-icon-unlocked { background-position: -208px -96px; }
|
||||
.ui-icon-bookmark { background-position: -224px -96px; }
|
||||
.ui-icon-tag { background-position: -240px -96px; }
|
||||
.ui-icon-home { background-position: 0 -112px; }
|
||||
.ui-icon-flag { background-position: -16px -112px; }
|
||||
.ui-icon-calendar { background-position: -32px -112px; }
|
||||
.ui-icon-cart { background-position: -48px -112px; }
|
||||
.ui-icon-pencil { background-position: -64px -112px; }
|
||||
.ui-icon-clock { background-position: -80px -112px; }
|
||||
.ui-icon-disk { background-position: -96px -112px; }
|
||||
.ui-icon-calculator { background-position: -112px -112px; }
|
||||
.ui-icon-zoomin { background-position: -128px -112px; }
|
||||
.ui-icon-zoomout { background-position: -144px -112px; }
|
||||
.ui-icon-search { background-position: -160px -112px; }
|
||||
.ui-icon-wrench { background-position: -176px -112px; }
|
||||
.ui-icon-gear { background-position: -192px -112px; }
|
||||
.ui-icon-heart { background-position: -208px -112px; }
|
||||
.ui-icon-star { background-position: -224px -112px; }
|
||||
.ui-icon-link { background-position: -240px -112px; }
|
||||
.ui-icon-cancel { background-position: 0 -128px; }
|
||||
.ui-icon-plus { background-position: -16px -128px; }
|
||||
.ui-icon-plusthick { background-position: -32px -128px; }
|
||||
.ui-icon-minus { background-position: -48px -128px; }
|
||||
.ui-icon-minusthick { background-position: -64px -128px; }
|
||||
.ui-icon-close { background-position: -80px -128px; }
|
||||
.ui-icon-closethick { background-position: -96px -128px; }
|
||||
.ui-icon-key { background-position: -112px -128px; }
|
||||
.ui-icon-lightbulb { background-position: -128px -128px; }
|
||||
.ui-icon-scissors { background-position: -144px -128px; }
|
||||
.ui-icon-clipboard { background-position: -160px -128px; }
|
||||
.ui-icon-copy { background-position: -176px -128px; }
|
||||
.ui-icon-contact { background-position: -192px -128px; }
|
||||
.ui-icon-image { background-position: -208px -128px; }
|
||||
.ui-icon-video { background-position: -224px -128px; }
|
||||
.ui-icon-script { background-position: -240px -128px; }
|
||||
.ui-icon-alert { background-position: 0 -144px; }
|
||||
.ui-icon-info { background-position: -16px -144px; }
|
||||
.ui-icon-notice { background-position: -32px -144px; }
|
||||
.ui-icon-help { background-position: -48px -144px; }
|
||||
.ui-icon-check { background-position: -64px -144px; }
|
||||
.ui-icon-bullet { background-position: -80px -144px; }
|
||||
.ui-icon-radio-off { background-position: -96px -144px; }
|
||||
.ui-icon-radio-on { background-position: -112px -144px; }
|
||||
.ui-icon-pin-w { background-position: -128px -144px; }
|
||||
.ui-icon-pin-s { background-position: -144px -144px; }
|
||||
.ui-icon-play { background-position: 0 -160px; }
|
||||
.ui-icon-pause { background-position: -16px -160px; }
|
||||
.ui-icon-seek-next { background-position: -32px -160px; }
|
||||
.ui-icon-seek-prev { background-position: -48px -160px; }
|
||||
.ui-icon-seek-end { background-position: -64px -160px; }
|
||||
.ui-icon-seek-start { background-position: -80px -160px; }
|
||||
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
|
||||
.ui-icon-seek-first { background-position: -80px -160px; }
|
||||
.ui-icon-stop { background-position: -96px -160px; }
|
||||
.ui-icon-eject { background-position: -112px -160px; }
|
||||
.ui-icon-volume-off { background-position: -128px -160px; }
|
||||
.ui-icon-volume-on { background-position: -144px -160px; }
|
||||
.ui-icon-power { background-position: 0 -176px; }
|
||||
.ui-icon-signal-diag { background-position: -16px -176px; }
|
||||
.ui-icon-signal { background-position: -32px -176px; }
|
||||
.ui-icon-battery-0 { background-position: -48px -176px; }
|
||||
.ui-icon-battery-1 { background-position: -64px -176px; }
|
||||
.ui-icon-battery-2 { background-position: -80px -176px; }
|
||||
.ui-icon-battery-3 { background-position: -96px -176px; }
|
||||
.ui-icon-circle-plus { background-position: 0 -192px; }
|
||||
.ui-icon-circle-minus { background-position: -16px -192px; }
|
||||
.ui-icon-circle-close { background-position: -32px -192px; }
|
||||
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
|
||||
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
|
||||
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
|
||||
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
|
||||
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
|
||||
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
|
||||
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
|
||||
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
|
||||
.ui-icon-circle-zoomin { background-position: -176px -192px; }
|
||||
.ui-icon-circle-zoomout { background-position: -192px -192px; }
|
||||
.ui-icon-circle-check { background-position: -208px -192px; }
|
||||
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
|
||||
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
|
||||
.ui-icon-circlesmall-close { background-position: -32px -208px; }
|
||||
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
|
||||
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
|
||||
.ui-icon-squaresmall-close { background-position: -80px -208px; }
|
||||
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
|
||||
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
|
||||
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
|
||||
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
|
||||
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
|
||||
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
|
||||
|
||||
|
||||
/* Misc visuals
|
||||
----------------------------------*/
|
||||
|
||||
/* Corner radius */
|
||||
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -khtml-border-top-left-radius: 5px; border-top-left-radius: 5px; }
|
||||
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; -khtml-border-top-right-radius: 5px; border-top-right-radius: 5px; }
|
||||
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; -khtml-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; }
|
||||
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; -khtml-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
|
||||
|
||||
/* Overlays */
|
||||
.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
|
||||
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*!
|
||||
* jQuery UI Resizable 1.8.22
|
||||
*
|
||||
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Resizable#theming
|
||||
*/
|
||||
.ui-resizable { position: relative;}
|
||||
.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
|
||||
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
|
||||
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
|
||||
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
|
||||
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
|
||||
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
|
||||
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
|
||||
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
|
||||
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
|
||||
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*!
|
||||
* jQuery UI Selectable 1.8.22
|
||||
*
|
||||
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Selectable#theming
|
||||
*/
|
||||
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
|
||||
/*!
|
||||
* jQuery UI Accordion 1.8.22
|
||||
*
|
||||
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Accordion#theming
|
||||
*/
|
||||
/* IE/Win - Fix animation bug - #4615 */
|
||||
.ui-accordion { width: 100%; }
|
||||
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
|
||||
.ui-accordion .ui-accordion-li-fix { display: inline; }
|
||||
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
|
||||
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
|
||||
.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
|
||||
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
|
||||
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
|
||||
.ui-accordion .ui-accordion-content-active { display: block; }
|
||||
/*!
|
||||
* jQuery UI Autocomplete 1.8.22
|
||||
*
|
||||
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Autocomplete#theming
|
||||
*/
|
||||
.ui-autocomplete { position: absolute; cursor: default; }
|
||||
|
||||
/* workarounds */
|
||||
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
|
||||
|
||||
/*
|
||||
* jQuery UI Menu 1.8.22
|
||||
*
|
||||
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Menu#theming
|
||||
*/
|
||||
.ui-menu {
|
||||
list-style:none;
|
||||
padding: 2px;
|
||||
margin: 0;
|
||||
display:block;
|
||||
float: left;
|
||||
}
|
||||
.ui-menu .ui-menu {
|
||||
margin-top: -3px;
|
||||
}
|
||||
.ui-menu .ui-menu-item {
|
||||
margin:0;
|
||||
padding: 0;
|
||||
zoom: 1;
|
||||
float: left;
|
||||
clear: left;
|
||||
width: 100%;
|
||||
}
|
||||
.ui-menu .ui-menu-item a {
|
||||
text-decoration:none;
|
||||
display:block;
|
||||
padding:.2em .4em;
|
||||
line-height:1.5;
|
||||
zoom:1;
|
||||
}
|
||||
.ui-menu .ui-menu-item a.ui-state-hover,
|
||||
.ui-menu .ui-menu-item a.ui-state-active {
|
||||
font-weight: normal;
|
||||
margin: -1px;
|
||||
}
|
||||
/*!
|
||||
* jQuery UI Button 1.8.22
|
||||
*
|
||||
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Button#theming
|
||||
*/
|
||||
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
|
||||
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
|
||||
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
|
||||
.ui-button-icons-only { width: 3.4em; }
|
||||
button.ui-button-icons-only { width: 3.7em; }
|
||||
|
||||
/*button text element */
|
||||
.ui-button .ui-button-text { display: block; line-height: 1.4; }
|
||||
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
|
||||
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
|
||||
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
|
||||
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
|
||||
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
|
||||
/* no icon support for input elements, provide padding by default */
|
||||
input.ui-button { padding: .4em 1em; }
|
||||
|
||||
/*button icon element(s) */
|
||||
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
|
||||
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
|
||||
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
|
||||
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
||||
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
||||
|
||||
/*button sets*/
|
||||
.ui-buttonset { margin-right: 7px; }
|
||||
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
|
||||
|
||||
/* workarounds */
|
||||
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
|
||||
/*!
|
||||
* jQuery UI Dialog 1.8.22
|
||||
*
|
||||
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Dialog#theming
|
||||
*/
|
||||
.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
|
||||
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
|
||||
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
|
||||
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
|
||||
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
|
||||
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
|
||||
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
|
||||
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
|
||||
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
|
||||
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
|
||||
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
|
||||
.ui-draggable .ui-dialog-titlebar { cursor: move; }
|
||||
/*!
|
||||
* jQuery UI Slider 1.8.22
|
||||
*
|
||||
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Slider#theming
|
||||
*/
|
||||
.ui-slider { position: relative; text-align: left; }
|
||||
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
|
||||
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
|
||||
|
||||
.ui-slider-horizontal { height: .8em; }
|
||||
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
|
||||
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
|
||||
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
|
||||
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
|
||||
|
||||
.ui-slider-vertical { width: .8em; height: 100px; }
|
||||
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
|
||||
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
|
||||
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
|
||||
.ui-slider-vertical .ui-slider-range-max { top: 0; }/*!
|
||||
* jQuery UI Tabs 1.8.22
|
||||
*
|
||||
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Tabs#theming
|
||||
*/
|
||||
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
|
||||
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
|
||||
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
|
||||
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
|
||||
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
|
||||
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
|
||||
.ui-tabs .ui-tabs-hide { display: none !important; }
|
||||
/*!
|
||||
* jQuery UI Datepicker 1.8.22
|
||||
*
|
||||
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Datepicker#theming
|
||||
*/
|
||||
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
|
||||
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
|
||||
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
|
||||
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
|
||||
.ui-datepicker .ui-datepicker-prev { left:2px; }
|
||||
.ui-datepicker .ui-datepicker-next { right:2px; }
|
||||
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
|
||||
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
|
||||
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
|
||||
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
|
||||
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
|
||||
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
|
||||
.ui-datepicker select.ui-datepicker-month,
|
||||
.ui-datepicker select.ui-datepicker-year { width: 49%;}
|
||||
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
|
||||
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
|
||||
.ui-datepicker td { border: 0; padding: 1px; }
|
||||
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
|
||||
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
|
||||
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
|
||||
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
|
||||
|
||||
/* with multiple calendars */
|
||||
.ui-datepicker.ui-datepicker-multi { width:auto; }
|
||||
.ui-datepicker-multi .ui-datepicker-group { float:left; }
|
||||
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
|
||||
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
|
||||
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
|
||||
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
|
||||
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
|
||||
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
|
||||
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
|
||||
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
|
||||
|
||||
/* RTL support */
|
||||
.ui-datepicker-rtl { direction: rtl; }
|
||||
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
|
||||
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
|
||||
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
||||
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
||||
|
||||
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
|
||||
.ui-datepicker-cover {
|
||||
position: absolute; /*must have*/
|
||||
z-index: -1; /*must have*/
|
||||
filter: mask(); /*must have*/
|
||||
top: -4px; /*must have*/
|
||||
left: -4px; /*must have*/
|
||||
width: 200px; /*must have*/
|
||||
height: 200px; /*must have*/
|
||||
}/*!
|
||||
* jQuery UI Progressbar 1.8.22
|
||||
*
|
||||
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Progressbar#theming
|
||||
*/
|
||||
.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
|
||||
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
|
4
dspace-jspui/dspace-jspui-webapp/src/main/webapp/static/js/jquery/jquery-1.7.2.min.js
vendored
Normal file
125
dspace-jspui/dspace-jspui-webapp/src/main/webapp/static/js/jquery/jquery-ui-1.8.22.custom.min.js
vendored
Normal file
@@ -1078,6 +1078,37 @@ plugin.sequence.org.dspace.plugin.CommunityHomeProcessor = \
|
||||
plugin.sequence.org.dspace.plugin.CollectionHomeProcessor = \
|
||||
org.dspace.app.webui.components.RecentCollectionSubmissions
|
||||
|
||||
#### JSPUI Discovery (extra Discovery setting that apply only to the JSPUI) ####
|
||||
# uncomment the following configuration if you want use Discovery with JSPUI
|
||||
# plugin.single.org.dspace.app.webui.search.SearchRequestProcessor = \
|
||||
# org.dspace.app.webui.discovery.DiscoverySearchRequestProcessor
|
||||
#
|
||||
# default is to use the Legacy Lucene search engine
|
||||
plugin.single.org.dspace.app.webui.search.SearchRequestProcessor = \
|
||||
org.dspace.app.webui.search.LuceneSearchRequestProcessor
|
||||
|
||||
#### Sidebar Facets ####
|
||||
# to show facets on the site home page, community, collection
|
||||
# uncomments the following lines
|
||||
#plugin.sequence.org.dspace.plugin.CommunityHomeProcessor = \
|
||||
# org.dspace.app.webui.components.RecentCommunitySubmissions,\
|
||||
# org.dspace.app.webui.discovery.SideBarFacetProcessor
|
||||
#
|
||||
#plugin.sequence.org.dspace.plugin.CollectionHomeProcessor = \
|
||||
# org.dspace.app.webui.components.RecentCollectionSubmissions,\
|
||||
# org.dspace.app.webui.discovery.SideBarFacetProcessor
|
||||
#
|
||||
#plugin.sequence.org.dspace.plugin.SiteHomeProcessor = \
|
||||
# org.dspace.app.webui.discovery.SideBarFacetProcessor
|
||||
|
||||
#### JSON JSPUI Request Handler ####
|
||||
# define here any json handler
|
||||
#
|
||||
# comment this line if you disable discovery
|
||||
plugin.named.org.dspace.app.webui.json,JSONRequest = \
|
||||
org.dspace.app.webui.discovery.DiscoveryJSONRequest = discovery
|
||||
|
||||
|
||||
#### Submission License substitution variables ####
|
||||
# it is possible include contextual information in the submission license using substitution variables
|
||||
# the text substitution is driven by a plugin implementation
|
||||
|
@@ -16,3 +16,8 @@ index.ignore=dc.description.provenance
|
||||
# index.ignore-variants = false
|
||||
# index.ignore-authority = false
|
||||
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
|
||||
|
@@ -85,6 +85,8 @@
|
||||
<property name="max" value="5"/>
|
||||
</bean>
|
||||
</property>
|
||||
<!--Default result per page -->
|
||||
<property name="defaultRpp" value="10" />
|
||||
<property name="hitHighlightingConfiguration">
|
||||
<bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightingConfiguration">
|
||||
<property name="metadataFields">
|
||||
|
@@ -44,9 +44,7 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
|
||||
<build>
|
||||
<filters>
|
||||
<filter>${basedir}/../../../${filters.file}</filter>
|
||||
@@ -68,6 +66,19 @@
|
||||
</includes>
|
||||
</resource>
|
||||
</webResources>
|
||||
<overlays>
|
||||
<overlay></overlay>
|
||||
<overlay>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-discovery-jspui-webapp</artifactId>
|
||||
<type>war</type>
|
||||
</overlay>
|
||||
<overlay>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-jspui-webapp</artifactId>
|
||||
<type>war</type>
|
||||
</overlay>
|
||||
</overlays>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
@@ -80,10 +91,10 @@
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dspace.modules</groupId>
|
||||
<artifactId>additions</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dspace.modules</groupId>
|
||||
<artifactId>additions</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
@@ -91,6 +102,19 @@
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-discovery-jspui-api</artifactId>
|
||||
<version>3.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-discovery-jspui-webapp</artifactId>
|
||||
<version>3.0-SNAPSHOT</version>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-jspui-api</artifactId>
|
||||
|
@@ -498,8 +498,11 @@
|
||||
<!-- Internal DSpaceObject Type ID -->
|
||||
<field name="search.resourcetype" type="sint" indexed="true" stored="true" required="true" omitNorms="true" />
|
||||
|
||||
<!-- All Items/Communities/Collections placed in Discovery must have a unique handle -->
|
||||
<field name="handle" type="string" indexed="true" stored="true" required="true" omitNorms="true" />
|
||||
<!-- All object placed in Discovery must have an unique id (for standard DSpaceObject it is resourceID-resourceTypeID) -->
|
||||
<field name="search.uniqueid" type="string" indexed="true" stored="true" required="true" omitNorms="true" />
|
||||
|
||||
<!-- All Items/Communities/Collections placed in Discovery should have an handle -->
|
||||
<field name="handle" type="string" indexed="true" stored="true" omitNorms="true" />
|
||||
|
||||
<field name="withdrawn" type="string" indexed="true" stored="true" omitNorms="true" />
|
||||
|
||||
@@ -526,10 +529,12 @@
|
||||
<dynamicField name="*_stored" type="dspaceMetadataProjection" indexed="false" stored="true" multiValued="true"/>
|
||||
|
||||
<!--Dynamic field used for search autocompletion-->
|
||||
<dynamicField name="*_ac" type="dspaceAutoComplete" indexed="true" stored="true" omitNorms="true" multiValued="true"/>
|
||||
<dynamicField name="*_ac" type="keywordFilter" indexed="true" stored="true" omitNorms="true" multiValued="true"/>
|
||||
<dynamicField name="*_acid" type="keywordFilter" indexed="true" stored="true" omitNorms="true" multiValued="true"/>
|
||||
|
||||
<!--Dynamic field used for sidebar filters & SOLR browse by value -->
|
||||
<dynamicField name="*_filter" type="keywordFilter" indexed="true" stored="true" multiValued="true" omitNorms="true" />
|
||||
<dynamicField name="*_authority" type="keywordFilter" indexed="true" stored="true" multiValued="true" omitNorms="true" />
|
||||
<dynamicField name="*_keyword" type="keywordFilter" indexed="true" stored="true" multiValued="true" omitNorms="true" />
|
||||
|
||||
<!--Dynamic field used for SOLR browse by partial value -->
|
||||
@@ -589,7 +594,7 @@
|
||||
<!-- Field to use to determine and enforce document uniqueness.
|
||||
Unless this field is marked with required="false", it will be a required field
|
||||
-->
|
||||
<uniqueKey>handle</uniqueKey>
|
||||
<uniqueKey>search.uniqueid</uniqueKey>
|
||||
|
||||
<!-- field for the QueryParser to use when an explicit fieldname is absent -->
|
||||
<defaultSearchField>text</defaultSearchField>
|
||||
|