mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-17 06:53:09 +00:00
[DS-1144] Maven Project Consolidation : Discovery
This commit is contained in:
@@ -0,0 +1,533 @@
|
||||
/**
|
||||
* 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.browse;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
import org.dspace.content.DCValue;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.authority.ChoiceAuthorityManager;
|
||||
import org.dspace.content.authority.MetadataAuthorityManager;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.discovery.SolrServiceImpl;
|
||||
import org.dspace.discovery.SolrServiceIndexPlugin;
|
||||
import org.dspace.sort.OrderFormat;
|
||||
import org.dspace.sort.SortException;
|
||||
import org.dspace.sort.SortOption;
|
||||
import org.dspace.utils.DSpace;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Andrea Bollini (CILEA)
|
||||
*
|
||||
*/
|
||||
public class SolrBrowseCreateDAO implements BrowseCreateDAO,
|
||||
SolrServiceIndexPlugin
|
||||
{
|
||||
private static final String INFO_NOSQL_TO_RUN = "No SQL to run: data are stored in the SOLR Search Core. PLEASE NOTE THAT YOU MUST UPDATE THE DISCOVERY INDEX AFTER ANY CHANGES TO THE BROWSE CONFIGURATION";
|
||||
|
||||
// reference to a DBMS BrowseCreateDAO needed to remove old tables when
|
||||
// switching from DBMS to SOLR
|
||||
private BrowseCreateDAO dbCreateDAO;
|
||||
|
||||
private static final Logger log = Logger
|
||||
.getLogger(SolrBrowseCreateDAO.class);
|
||||
|
||||
private BrowseIndex[] bis;
|
||||
|
||||
public SolrBrowseCreateDAO()
|
||||
{
|
||||
try
|
||||
{
|
||||
bis = BrowseIndex.getBrowseIndices();
|
||||
}
|
||||
catch (BrowseException e)
|
||||
{
|
||||
log.error(e.getMessage(), e);
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
for (BrowseIndex bi : bis)
|
||||
bi.generateMdBits();
|
||||
}
|
||||
|
||||
public SolrBrowseCreateDAO(Context context) throws BrowseException
|
||||
{
|
||||
// For compatibility with previous versions
|
||||
String db = ConfigurationManager.getProperty("db.name");
|
||||
if ("postgres".equals(db))
|
||||
{
|
||||
dbCreateDAO = new BrowseCreateDAOPostgres(context);
|
||||
}
|
||||
else if ("oracle".equals(db))
|
||||
{
|
||||
dbCreateDAO = new BrowseCreateDAOOracle(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new BrowseException(
|
||||
"The configuration for db.name is either invalid, or contains an unrecognised database");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
bis = BrowseIndex.getBrowseIndices();
|
||||
}
|
||||
catch (BrowseException e)
|
||||
{
|
||||
log.error(e.getMessage(), e);
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
for (BrowseIndex bi : bis)
|
||||
bi.generateMdBits();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument doc)
|
||||
{
|
||||
if (!(dso instanceof Item))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Item item = (Item) dso;
|
||||
|
||||
// faceting for metadata browsing. It is different than search facet
|
||||
// because if there are authority with variants support we wan't all the
|
||||
// variants to go in the facet... they are sorted by count so just the
|
||||
// prefered label is relevant
|
||||
for (BrowseIndex bi : bis)
|
||||
{
|
||||
log.debug("Indexing for item " + item.getID() + ", for index: "
|
||||
+ bi.getTableName());
|
||||
|
||||
if (bi.isMetadataIndex())
|
||||
{
|
||||
// values to show in the browse list
|
||||
Set<String> distFValues = new HashSet<String>();
|
||||
// value for lookup without authority
|
||||
Set<String> distFVal = new HashSet<String>();
|
||||
// value for lookup with authority
|
||||
Set<String> distFAuths = new HashSet<String>();
|
||||
// value for lookup when partial search (the item mapper tool use it)
|
||||
Set<String> distValuesForAC = new HashSet<String>();
|
||||
|
||||
// now index the new details - but only if it's archived and not
|
||||
// withdrawn
|
||||
if (item.isArchived() || item.isWithdrawn())
|
||||
{
|
||||
// get the metadata from the item
|
||||
for (int mdIdx = 0; mdIdx < bi.getMetadataCount(); mdIdx++)
|
||||
{
|
||||
String[] md = bi.getMdBits(mdIdx);
|
||||
DCValue[] values = item.getMetadata(md[0], md[1],
|
||||
md[2], Item.ANY);
|
||||
|
||||
// if we have values to index on, then do so
|
||||
if (values != null && values.length > 0)
|
||||
{
|
||||
int minConfidence = MetadataAuthorityManager
|
||||
.getManager().getMinConfidence(
|
||||
values[0].schema,
|
||||
values[0].element,
|
||||
values[0].qualifier);
|
||||
|
||||
boolean ignoreAuthority = new DSpace()
|
||||
.getConfigurationService()
|
||||
.getPropertyAsType(
|
||||
"discovery.browse.authority.ignore."
|
||||
+ bi.getName(),
|
||||
new DSpace()
|
||||
.getConfigurationService()
|
||||
.getPropertyAsType(
|
||||
"discovery.browse.authority.ignore",
|
||||
new Boolean(false)),
|
||||
true);
|
||||
for (int x = 0; x < values.length; x++)
|
||||
{
|
||||
// Ensure that there is a value to index before
|
||||
// inserting it
|
||||
if (StringUtils.isEmpty(values[x].value))
|
||||
{
|
||||
log.error("Null metadata value for item "
|
||||
+ item.getID()
|
||||
+ ", field: "
|
||||
+ values[x].schema
|
||||
+ "."
|
||||
+ values[x].element
|
||||
+ (values[x].qualifier == null ? ""
|
||||
: "." + values[x].qualifier));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bi.isAuthorityIndex()
|
||||
&& (values[x].authority == null || values[x].confidence < minConfidence))
|
||||
{
|
||||
// if we have an authority index only
|
||||
// authored metadata will go here!
|
||||
log.debug("Skipping item="
|
||||
+ item.getID() + ", field="
|
||||
+ values[x].schema + "."
|
||||
+ values[x].element + "."
|
||||
+ values[x].qualifier
|
||||
+ ", value=" + values[x].value
|
||||
+ ", authority="
|
||||
+ values[x].authority
|
||||
+ ", confidence="
|
||||
+ values[x].confidence
|
||||
+ " (BAD AUTHORITY)");
|
||||
continue;
|
||||
}
|
||||
|
||||
// is there any valid (with appropriate
|
||||
// confidence) authority key?
|
||||
if ((ignoreAuthority && !bi.isAuthorityIndex())
|
||||
|| (values[x].authority != null && values[x].confidence >= minConfidence))
|
||||
{
|
||||
distFAuths.add(values[x].authority);
|
||||
distValuesForAC.add(values[x].value);
|
||||
|
||||
String preferedLabel = null;
|
||||
boolean ignorePrefered = new DSpace()
|
||||
.getConfigurationService()
|
||||
.getPropertyAsType(
|
||||
"discovery.browse.authority.ignore-prefered."
|
||||
+ bi.getName(),
|
||||
new DSpace()
|
||||
.getConfigurationService()
|
||||
.getPropertyAsType(
|
||||
"discovery.browse.authority.ignore-prefered",
|
||||
new Boolean(
|
||||
false)),
|
||||
true);
|
||||
if (!ignorePrefered)
|
||||
{
|
||||
preferedLabel = ChoiceAuthorityManager
|
||||
.getManager()
|
||||
.getLabel(
|
||||
values[x].schema,
|
||||
values[x].element,
|
||||
values[x].qualifier,
|
||||
values[x].authority,
|
||||
values[x].language);
|
||||
}
|
||||
List<String> variants = null;
|
||||
|
||||
boolean ignoreVariants = new DSpace()
|
||||
.getConfigurationService()
|
||||
.getPropertyAsType(
|
||||
"discovery.browse.authority.ignore-variants."
|
||||
+ bi.getName(),
|
||||
new DSpace()
|
||||
.getConfigurationService()
|
||||
.getPropertyAsType(
|
||||
"discovery.browse.authority.ignore-variants",
|
||||
new Boolean(
|
||||
false)),
|
||||
true);
|
||||
if (!ignoreVariants)
|
||||
{
|
||||
variants = ChoiceAuthorityManager
|
||||
.getManager()
|
||||
.getVariants(
|
||||
values[x].schema,
|
||||
values[x].element,
|
||||
values[x].qualifier,
|
||||
values[x].authority,
|
||||
values[x].language);
|
||||
}
|
||||
|
||||
if (StringUtils
|
||||
.isNotBlank(preferedLabel))
|
||||
{
|
||||
String nLabel = OrderFormat
|
||||
.makeSortString(
|
||||
preferedLabel,
|
||||
values[x].language,
|
||||
bi.getDataType());
|
||||
distFValues
|
||||
.add(nLabel
|
||||
+ SolrServiceImpl.FILTER_SEPARATOR
|
||||
+ preferedLabel
|
||||
+ SolrServiceImpl.AUTHORITY_SEPARATOR
|
||||
+ values[x].authority);
|
||||
distValuesForAC.add(preferedLabel);
|
||||
}
|
||||
|
||||
if (variants != null)
|
||||
{
|
||||
for (String var : variants)
|
||||
{
|
||||
String nVal = OrderFormat
|
||||
.makeSortString(
|
||||
var,
|
||||
values[x].language,
|
||||
bi.getDataType());
|
||||
distFValues
|
||||
.add(nVal
|
||||
+ SolrServiceImpl.FILTER_SEPARATOR
|
||||
+ var
|
||||
+ SolrServiceImpl.AUTHORITY_SEPARATOR
|
||||
+ values[x].authority);
|
||||
distValuesForAC.add(var);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
// put it in the browse index as if it
|
||||
// hasn't have an authority key
|
||||
{
|
||||
// get the normalised version of the
|
||||
// value
|
||||
String nVal = OrderFormat
|
||||
.makeSortString(
|
||||
values[x].value,
|
||||
values[x].language,
|
||||
bi.getDataType());
|
||||
distFValues
|
||||
.add(nVal
|
||||
+ SolrServiceImpl.FILTER_SEPARATOR
|
||||
+ values[x].value);
|
||||
distFVal.add(values[x].value);
|
||||
distValuesForAC.add(values[x].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String facet : distFValues)
|
||||
{
|
||||
doc.addField(bi.getDistinctTableName() + "_filter", facet);
|
||||
}
|
||||
for (String facet : distFAuths)
|
||||
{
|
||||
doc.addField(bi.getDistinctTableName()
|
||||
+ "_authority_filter", facet);
|
||||
}
|
||||
for (String facet : distValuesForAC)
|
||||
{
|
||||
doc.addField(bi.getDistinctTableName() + "_partial", facet);
|
||||
}
|
||||
for (String facet : distFVal)
|
||||
{
|
||||
doc.addField(bi.getDistinctTableName()+"_value_filter", facet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add sorting options as configurated for the browse system
|
||||
try
|
||||
{
|
||||
for (SortOption so : SortOption.getSortOptions())
|
||||
{
|
||||
DCValue[] dcvalue = item.getMetadata(so.getMetadata());
|
||||
if (dcvalue != null && dcvalue.length > 0)
|
||||
{
|
||||
String nValue = OrderFormat
|
||||
.makeSortString(dcvalue[0].value,
|
||||
dcvalue[0].language, so.getType());
|
||||
doc.addField("bi_sort_" + so.getNumber() + "_sort", nValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SortException e)
|
||||
{
|
||||
// we can't solve it so rethrow as runtime exception
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteByItemID(String table, int itemID) throws BrowseException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteCommunityMappings(int itemID) throws BrowseException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCommunityMappings(int itemID) throws BrowseException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertIndex(String table, int itemID, Map sortCols)
|
||||
throws BrowseException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateIndex(String table, int itemID, Map sortCols)
|
||||
throws BrowseException
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDistinctID(String table, String value, String authority,
|
||||
String sortValue) throws BrowseException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertDistinctRecord(String table, String value,
|
||||
String authority, String sortValue) throws BrowseException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dropIndexAndRelated(String table, boolean execute)
|
||||
throws BrowseException
|
||||
{
|
||||
return dbCreateDAO.dropIndexAndRelated(table, execute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dropSequence(String sequence, boolean execute)
|
||||
throws BrowseException
|
||||
{
|
||||
return dbCreateDAO.dropSequence(sequence, execute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dropView(String view, boolean execute) throws BrowseException
|
||||
{
|
||||
return dbCreateDAO.dropView(view, execute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createSequence(String sequence, boolean execute)
|
||||
throws BrowseException
|
||||
{
|
||||
return INFO_NOSQL_TO_RUN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createPrimaryTable(String table, List sortCols,
|
||||
boolean execute) throws BrowseException
|
||||
{
|
||||
return INFO_NOSQL_TO_RUN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] createDatabaseIndices(String table, List<Integer> sortCols,
|
||||
boolean value, boolean execute) throws BrowseException
|
||||
{
|
||||
return new String[] { INFO_NOSQL_TO_RUN };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] createMapIndices(String disTable, String mapTable,
|
||||
boolean execute) throws BrowseException
|
||||
{
|
||||
return new String[] { INFO_NOSQL_TO_RUN };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createCollectionView(String table, String view,
|
||||
boolean execute) throws BrowseException
|
||||
{
|
||||
return INFO_NOSQL_TO_RUN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createCommunityView(String table, String view, boolean execute)
|
||||
throws BrowseException
|
||||
{
|
||||
return INFO_NOSQL_TO_RUN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createDistinctTable(String table, boolean execute)
|
||||
throws BrowseException
|
||||
{
|
||||
return INFO_NOSQL_TO_RUN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createDistinctMap(String table, String map, boolean execute)
|
||||
throws BrowseException
|
||||
{
|
||||
return INFO_NOSQL_TO_RUN;
|
||||
}
|
||||
|
||||
public MappingResults updateDistinctMappings(String table, int itemID,
|
||||
Set<Integer> distinctIDs) throws BrowseException
|
||||
{
|
||||
return new MappingResults()
|
||||
{
|
||||
|
||||
@Override
|
||||
public List<Integer> getRetainedDistinctIds()
|
||||
{
|
||||
return new ArrayList<Integer>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getRemovedDistinctIds()
|
||||
{
|
||||
return new ArrayList<Integer>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getAddedDistinctIds()
|
||||
{
|
||||
return new ArrayList<Integer>();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testTableExistence(String table) throws BrowseException
|
||||
{
|
||||
return dbCreateDAO.testTableExistence(table);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> deleteMappingsByItemID(String mapTable, int itemID)
|
||||
throws BrowseException
|
||||
{
|
||||
return new ArrayList<Integer>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pruneExcess(String table, boolean withdrawn)
|
||||
throws BrowseException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pruneMapExcess(String map, boolean withdrawn,
|
||||
List<Integer> distinctIds) throws BrowseException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pruneDistinct(String table, String map,
|
||||
List<Integer> distinctIds) throws BrowseException
|
||||
{
|
||||
}
|
||||
|
||||
}
|
759
dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java
Normal file
759
dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java
Normal file
@@ -0,0 +1,759 @@
|
||||
/**
|
||||
* 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.browse;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.discovery.DiscoverFacetField;
|
||||
import org.dspace.discovery.DiscoverQuery;
|
||||
import org.dspace.discovery.DiscoverQuery.SORT_ORDER;
|
||||
import org.dspace.discovery.DiscoverResult;
|
||||
import org.dspace.discovery.DiscoverResult.FacetResult;
|
||||
import org.dspace.discovery.DiscoverResult.SearchDocument;
|
||||
import org.dspace.discovery.SearchService;
|
||||
import org.dspace.discovery.SearchServiceException;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfigurationParameters;
|
||||
import org.dspace.utils.DSpace;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Andrea Bollini (CILEA)
|
||||
*
|
||||
*/
|
||||
public class SolrBrowseDAO implements BrowseDAO
|
||||
{
|
||||
public SolrBrowseDAO(Context context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
static private class FacetValueComparator implements Comparator
|
||||
{
|
||||
@Override
|
||||
public int compare(Object o1, Object o2)
|
||||
{
|
||||
String s1 = "", s2 = "";
|
||||
if (o1 instanceof FacetResult && o2 instanceof String)
|
||||
{
|
||||
FacetResult c = (FacetResult) o1;
|
||||
s1 = c.getSortValue();
|
||||
s2 = (String) o2;
|
||||
}
|
||||
else if (o2 instanceof FacetResult && o1 instanceof String)
|
||||
{
|
||||
FacetResult c = (FacetResult) o2;
|
||||
s1 = (String) o1;
|
||||
s2 = c.getSortValue();
|
||||
}
|
||||
// both object are FacetResult so they are already sorted
|
||||
return s1.compareTo(s2);
|
||||
}
|
||||
}
|
||||
|
||||
/** Log4j log */
|
||||
private static Logger log = Logger.getLogger(SolrBrowseDAO.class);
|
||||
|
||||
/** The DSpace context */
|
||||
private Context context;
|
||||
|
||||
// SQL query related attributes for this class
|
||||
|
||||
/** table(s) to select from */
|
||||
private String table = null;
|
||||
|
||||
/** field to look for focus value in */
|
||||
private String focusField = null;
|
||||
|
||||
/** value to start browse from in focus field */
|
||||
private String focusValue = null;
|
||||
|
||||
/** field to look for value in */
|
||||
private String valueField = null;
|
||||
|
||||
/** value to restrict browse to (e.g. author name) */
|
||||
private String value = null;
|
||||
|
||||
private String authority = null;
|
||||
|
||||
/** exact or partial matching of the value */
|
||||
private boolean valuePartial = false;
|
||||
|
||||
/** the table that defines the mapping for the relevant container */
|
||||
private String containerTable = null;
|
||||
|
||||
/**
|
||||
* the name of the field which contains the container id (e.g.
|
||||
* collection_id)
|
||||
*/
|
||||
private String containerIDField = null;
|
||||
|
||||
/** the database id of the container we are constraining to */
|
||||
private int containerID = -1;
|
||||
|
||||
/** the column that we are sorting results by */
|
||||
private String orderField = null;
|
||||
|
||||
/** whether to sort results ascending or descending */
|
||||
private boolean ascending = true;
|
||||
|
||||
/** the limit of number of results to return */
|
||||
private int limit = -1;
|
||||
|
||||
/** the offset of the start point */
|
||||
private int offset = 0;
|
||||
|
||||
/** whether to use the equals comparator in value comparisons */
|
||||
private boolean equalsComparator = true;
|
||||
|
||||
/** whether this is a distinct browse or not */
|
||||
private boolean distinct = false;
|
||||
|
||||
private String facetField;
|
||||
|
||||
// administrative attributes for this class
|
||||
|
||||
DSpace dspace = new DSpace();
|
||||
|
||||
SearchService searcher = dspace.getServiceManager().getServiceByName(
|
||||
SearchService.class.getName(), SearchService.class);
|
||||
|
||||
private DiscoverResult sResponse = null;
|
||||
|
||||
private boolean itemsWithdrawn = false;
|
||||
private boolean itemsPrivate = false;
|
||||
|
||||
private boolean showFrequencies;
|
||||
|
||||
private DiscoverResult getSolrResponse() throws BrowseException
|
||||
{
|
||||
if (sResponse == null)
|
||||
{
|
||||
DiscoverQuery query = new DiscoverQuery();
|
||||
addLocationScopeFilter(query);
|
||||
addStatusFilter(query);
|
||||
if (distinct)
|
||||
{
|
||||
DiscoverFacetField dff = new DiscoverFacetField(facetField,
|
||||
DiscoveryConfigurationParameters.TYPE_TEXT, -1,
|
||||
DiscoveryConfigurationParameters.SORT.VALUE);
|
||||
query.addFacetField(dff);
|
||||
query.setFacetMinCount(1);
|
||||
query.setMaxResults(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
query.setMaxResults(limit > 0 ? limit : 20);
|
||||
if (offset > 0)
|
||||
{
|
||||
query.setStart(offset);
|
||||
}
|
||||
|
||||
// caution check first authority, value is always present!
|
||||
if (authority != null)
|
||||
{
|
||||
query.addFilterQueries("{!field f="+facetField + "_authority_filter}"
|
||||
+ authority);
|
||||
}
|
||||
else if (value != null && !valuePartial)
|
||||
{
|
||||
query.addFilterQueries("{!field f="+facetField + "_value_filter}" + value);
|
||||
}
|
||||
else if (valuePartial)
|
||||
{
|
||||
query.addFilterQueries("{!field f="+facetField + "_partial}" + value);
|
||||
}
|
||||
// filter on item to be sure to don't include any other object
|
||||
// indexed in the Discovery Search core
|
||||
query.addFilterQueries("search.resourcetype:" + Constants.ITEM);
|
||||
if (orderField != null)
|
||||
{
|
||||
query.setSortField("bi_" + orderField + "_sort",
|
||||
ascending ? SORT_ORDER.asc : SORT_ORDER.desc);
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
sResponse = searcher.search(context, query, itemsWithdrawn);
|
||||
}
|
||||
catch (SearchServiceException e)
|
||||
{
|
||||
throw new BrowseException(e);
|
||||
}
|
||||
}
|
||||
return sResponse;
|
||||
}
|
||||
|
||||
private void addStatusFilter(DiscoverQuery query)
|
||||
{
|
||||
if (itemsWithdrawn)
|
||||
{
|
||||
query.addFilterQueries("withdrawn:true");
|
||||
if (itemsPrivate)
|
||||
{
|
||||
query.addFilterQueries("discoverable:false");
|
||||
}
|
||||
else
|
||||
{
|
||||
query.addFilterQueries("NOT(discoverable:false)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
query.addFilterQueries("NOT(withdrawn:true)");
|
||||
}
|
||||
}
|
||||
|
||||
private void addLocationScopeFilter(DiscoverQuery query)
|
||||
{
|
||||
if (containerID > 0)
|
||||
{
|
||||
if (containerIDField.startsWith("collection"))
|
||||
{
|
||||
query.addFilterQueries("location.coll:" + containerID);
|
||||
}
|
||||
else if (containerIDField.startsWith("community"))
|
||||
{
|
||||
query.addFilterQueries("location.comm:" + containerID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int doCountQuery() throws BrowseException
|
||||
{
|
||||
DiscoverResult resp = getSolrResponse();
|
||||
int count = 0;
|
||||
if (distinct)
|
||||
{
|
||||
List<FacetResult> facetResults = resp.getFacetResult(facetField);
|
||||
count = facetResults.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
// we need to cast to int to respect the BrowseDAO contract...
|
||||
count = (int) resp.getTotalSearchResults();
|
||||
// FIXME null the response cache
|
||||
// the BrowseEngine send fake argument to the BrowseDAO for the
|
||||
// count...
|
||||
sResponse = null;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List doValueQuery() throws BrowseException
|
||||
{
|
||||
DiscoverResult resp = getSolrResponse();
|
||||
List<FacetResult> facet = resp.getFacetResult(facetField);
|
||||
int count = doCountQuery();
|
||||
int start = offset > 0 ? offset : 0;
|
||||
int max = limit > 0 ? limit : 20;
|
||||
List<String[]> result = new ArrayList<String[]>();
|
||||
if (ascending)
|
||||
{
|
||||
for (int i = start; i < (start + max) && i < count; i++)
|
||||
{
|
||||
FacetResult c = facet.get(i);
|
||||
String freq = showFrequencies ? String.valueOf(c.getCount())
|
||||
: "";
|
||||
result.add(new String[] { c.getDisplayedValue(),
|
||||
c.getAuthorityKey(), freq });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = count - start - 1; i >= count - (start + max)
|
||||
&& i >= 0; i--)
|
||||
{
|
||||
FacetResult c = facet.get(i);
|
||||
String freq = showFrequencies ? String.valueOf(c.getCount())
|
||||
: "";
|
||||
result.add(new String[] { c.getDisplayedValue(),
|
||||
c.getAuthorityKey(), freq });
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List doQuery() throws BrowseException
|
||||
{
|
||||
DiscoverResult resp = getSolrResponse();
|
||||
|
||||
List<BrowseItem> bitems = new ArrayList<BrowseItem>();
|
||||
for (DSpaceObject solrDoc : resp.getDspaceObjects())
|
||||
{
|
||||
// FIXME introduce project, don't retrieve Item immediately when
|
||||
// processing the query...
|
||||
Item item = (Item) solrDoc;
|
||||
BrowseItem bitem = new BrowseItem(context, item.getID(),
|
||||
item.isArchived(), item.isWithdrawn());
|
||||
bitems.add(bitem);
|
||||
}
|
||||
return bitems;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String doMaxQuery(String column, String table, int itemID)
|
||||
throws BrowseException
|
||||
{
|
||||
DiscoverQuery query = new DiscoverQuery();
|
||||
query.setQuery("search.resourceid:" + itemID
|
||||
+ " AND search.resourcetype:" + Constants.ITEM);
|
||||
query.setMaxResults(1);
|
||||
DiscoverResult resp = null;
|
||||
try
|
||||
{
|
||||
resp = searcher.search(context, query);
|
||||
}
|
||||
catch (SearchServiceException e)
|
||||
{
|
||||
throw new BrowseException(e);
|
||||
}
|
||||
if (resp.getTotalSearchResults() > 0)
|
||||
{
|
||||
SearchDocument doc = resp.getSearchDocument(
|
||||
resp.getDspaceObjects().get(0)).get(0);
|
||||
return (String) doc.getSearchFieldValues(column).get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int doOffsetQuery(String column, String value, boolean isAscending)
|
||||
throws BrowseException
|
||||
{
|
||||
DiscoverQuery query = new DiscoverQuery();
|
||||
addLocationScopeFilter(query);
|
||||
addStatusFilter(query);
|
||||
query.setMaxResults(0);
|
||||
query.addFilterQueries("search.resourcetype:" + Constants.ITEM);
|
||||
if (isAscending)
|
||||
{
|
||||
query.setQuery("bi_"+column + "_sort" + ": [* TO \"" + value + "\"]");
|
||||
}
|
||||
else
|
||||
{
|
||||
query.setQuery("bi_" + column + "_sort" + ": [\"" + value + "\" TO *]");
|
||||
}
|
||||
DiscoverResult resp = null;
|
||||
try
|
||||
{
|
||||
resp = searcher.search(context, query);
|
||||
}
|
||||
catch (SearchServiceException e)
|
||||
{
|
||||
throw new BrowseException(e);
|
||||
}
|
||||
return (int) resp.getTotalSearchResults();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int doDistinctOffsetQuery(String column, String value,
|
||||
boolean isAscending) throws BrowseException
|
||||
{
|
||||
DiscoverResult resp = getSolrResponse();
|
||||
List<FacetResult> facets = resp.getFacetResult(facetField);
|
||||
Comparator comparator = new SolrBrowseDAO.FacetValueComparator();
|
||||
Collections.sort(facets, comparator);
|
||||
int x = Collections.binarySearch(facets, value, comparator);
|
||||
int ascValue = (x >= 0) ? x : -(x + 1);
|
||||
if (isAscending)
|
||||
{
|
||||
return ascValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return doCountQuery() - ascValue;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnableBrowseFrequencies()
|
||||
{
|
||||
return showFrequencies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnableBrowseFrequencies(boolean enableBrowseFrequencies)
|
||||
{
|
||||
showFrequencies = enableBrowseFrequencies;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#getContainerID()
|
||||
*/
|
||||
public int getContainerID()
|
||||
{
|
||||
return containerID;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#getContainerIDField()
|
||||
*/
|
||||
public String getContainerIDField()
|
||||
{
|
||||
return containerIDField;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#getContainerTable()
|
||||
*/
|
||||
public String getContainerTable()
|
||||
{
|
||||
return containerTable;
|
||||
}
|
||||
|
||||
// FIXME is this in use?
|
||||
public String[] getCountValues()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#getFocusField()
|
||||
*/
|
||||
public String getJumpToField()
|
||||
{
|
||||
return focusField;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#getFocusValue()
|
||||
*/
|
||||
public String getJumpToValue()
|
||||
{
|
||||
return focusValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#getLimit()
|
||||
*/
|
||||
public int getLimit()
|
||||
{
|
||||
return limit;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#getOffset()
|
||||
*/
|
||||
public int getOffset()
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#getOrderField()
|
||||
*/
|
||||
public String getOrderField()
|
||||
{
|
||||
return orderField;
|
||||
}
|
||||
|
||||
// is this in use?
|
||||
public String[] getSelectValues()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#getTable()
|
||||
*/
|
||||
public String getTable()
|
||||
{
|
||||
return table;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#getValue()
|
||||
*/
|
||||
public String getFilterValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#getValueField()
|
||||
*/
|
||||
public String getFilterValueField()
|
||||
{
|
||||
return valueField;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#isAscending()
|
||||
*/
|
||||
public boolean isAscending()
|
||||
{
|
||||
return ascending;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#isDistinct()
|
||||
*/
|
||||
public boolean isDistinct()
|
||||
{
|
||||
return this.distinct;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#setAscending(boolean)
|
||||
*/
|
||||
public void setAscending(boolean ascending)
|
||||
{
|
||||
this.ascending = ascending;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#setContainerID(int)
|
||||
*/
|
||||
public void setContainerID(int containerID)
|
||||
{
|
||||
this.containerID = containerID;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#setContainerIDField(java.lang.String)
|
||||
*/
|
||||
public void setContainerIDField(String containerIDField)
|
||||
{
|
||||
this.containerIDField = containerIDField;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#setContainerTable(java.lang.String)
|
||||
*/
|
||||
public void setContainerTable(String containerTable)
|
||||
{
|
||||
this.containerTable = containerTable;
|
||||
|
||||
}
|
||||
|
||||
// is this in use?
|
||||
public void setCountValues(String[] fields)
|
||||
{
|
||||
// this.countValues = fields;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#setDistinct(boolean)
|
||||
*/
|
||||
public void setDistinct(boolean bool)
|
||||
{
|
||||
this.distinct = bool;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#setEqualsComparator(boolean)
|
||||
*/
|
||||
public void setEqualsComparator(boolean equalsComparator)
|
||||
{
|
||||
this.equalsComparator = equalsComparator;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#setFocusField(java.lang.String)
|
||||
*/
|
||||
public void setJumpToField(String focusField)
|
||||
{
|
||||
this.focusField = focusField;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#setFocusValue(java.lang.String)
|
||||
*/
|
||||
public void setJumpToValue(String focusValue)
|
||||
{
|
||||
this.focusValue = focusValue;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#setLimit(int)
|
||||
*/
|
||||
public void setLimit(int limit)
|
||||
{
|
||||
this.limit = limit;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#setOffset(int)
|
||||
*/
|
||||
public void setOffset(int offset)
|
||||
{
|
||||
this.offset = offset;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#setOrderField(java.lang.String)
|
||||
*/
|
||||
public void setOrderField(String orderField)
|
||||
{
|
||||
this.orderField = orderField;
|
||||
|
||||
}
|
||||
|
||||
// is this in use?
|
||||
public void setSelectValues(String[] selectValues)
|
||||
{
|
||||
// this.selectValues = selectValues;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#setTable(java.lang.String)
|
||||
*/
|
||||
public void setTable(String table)
|
||||
{
|
||||
if (table.equals(BrowseIndex.getWithdrawnBrowseIndex().getTableName()))
|
||||
{
|
||||
itemsWithdrawn = true;
|
||||
itemsPrivate = false;
|
||||
}
|
||||
else if (table.equals(BrowseIndex.getPrivateBrowseIndex().getTableName()))
|
||||
{
|
||||
itemsPrivate = true;
|
||||
// items private are also withdrawn
|
||||
itemsWithdrawn = true;
|
||||
}
|
||||
facetField = table;
|
||||
}
|
||||
|
||||
public void setFilterMappingTables(String tableDis, String tableMap)
|
||||
{
|
||||
if (tableDis != null)
|
||||
{
|
||||
this.facetField = tableDis;
|
||||
}
|
||||
// this.fields = tableDis;
|
||||
// this.tableMap = tableMap;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#setValue(java.lang.String)
|
||||
*/
|
||||
public void setFilterValue(String value)
|
||||
{
|
||||
this.value = value;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#setFilterValuePartial(boolean)
|
||||
*/
|
||||
public void setFilterValuePartial(boolean part)
|
||||
{
|
||||
this.valuePartial = part;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#setValueField(java.lang.String)
|
||||
*/
|
||||
public void setFilterValueField(String valueField)
|
||||
{
|
||||
this.valueField = valueField;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.dspace.browse.BrowseDAO#useEqualsComparator()
|
||||
*/
|
||||
public boolean useEqualsComparator()
|
||||
{
|
||||
return equalsComparator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorityValue()
|
||||
{
|
||||
return authority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthorityValue(String value)
|
||||
{
|
||||
this.authority = value;
|
||||
}
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
import org.dspace.discovery.configuration.DiscoveryConfigurationParameters;
|
||||
|
||||
/**
|
||||
* Class contains facet query information
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
*/
|
||||
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;
|
||||
this.limit = limit;
|
||||
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;
|
||||
this.type = type;
|
||||
this.sortOrder = sortOrder;
|
||||
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;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public int getLimit() {
|
||||
return limit;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public DiscoveryConfigurationParameters.SORT getSortOrder() {
|
||||
return sortOrder;
|
||||
}
|
||||
|
||||
public int getOffset()
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
public void setOffset(int offset)
|
||||
{
|
||||
this.offset = offset;
|
||||
}
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
/**
|
||||
* This class represents a filter query for discovery and can contain the following objects:
|
||||
* The field in which we are searching
|
||||
* The query the query which the filter query is using
|
||||
* The displayed value
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
*
|
||||
*/
|
||||
public class DiscoverFilterQuery {
|
||||
|
||||
private String field;
|
||||
private String filterQuery;
|
||||
private String displayedValue;
|
||||
|
||||
|
||||
public DiscoverFilterQuery() {
|
||||
}
|
||||
|
||||
public DiscoverFilterQuery(String field, String filterQuery, String displayedValue) {
|
||||
this.field = field;
|
||||
this.filterQuery = filterQuery;
|
||||
this.displayedValue = displayedValue;
|
||||
}
|
||||
|
||||
public void setField(String field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public void setFilterQuery(String filterQuery) {
|
||||
this.filterQuery = filterQuery;
|
||||
}
|
||||
|
||||
public void setDisplayedValue(String displayedValue) {
|
||||
this.displayedValue = displayedValue;
|
||||
}
|
||||
|
||||
public String getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public String getFilterQuery() {
|
||||
return filterQuery;
|
||||
}
|
||||
|
||||
public String getDisplayedValue() {
|
||||
return displayedValue;
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
/**
|
||||
* Configuration for one field that is to be highlighted
|
||||
* Giving 0 as max chars ensures that the entire field is returned !
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
*/
|
||||
public class DiscoverHitHighlightingField {
|
||||
|
||||
public static final int UNLIMITED_FRAGMENT_LENGTH = 0;
|
||||
|
||||
private String field;
|
||||
private int maxChars;
|
||||
private int maxSnippets;
|
||||
|
||||
public DiscoverHitHighlightingField(String field, int maxChars, int maxSnippets)
|
||||
{
|
||||
this.field = field;
|
||||
this.maxChars = maxChars;
|
||||
this.maxSnippets = maxSnippets;
|
||||
}
|
||||
|
||||
public String getField()
|
||||
{
|
||||
return field;
|
||||
}
|
||||
|
||||
/**
|
||||
* The max number of characters that should be shown for a
|
||||
* field containing a matching hit. e.g. If maxChars = 200
|
||||
* and a hit is found in the full-text the 200 chars
|
||||
* surrounding the hit will be shown
|
||||
*/
|
||||
public int getMaxChars()
|
||||
{
|
||||
return maxChars;
|
||||
}
|
||||
|
||||
public int getMaxSnippets()
|
||||
{
|
||||
return maxSnippets;
|
||||
}
|
||||
}
|
267
dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java
Normal file
267
dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java
Normal file
@@ -0,0 +1,267 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This class represents a query which the discovery backend can use
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
*
|
||||
*/
|
||||
public class DiscoverQuery {
|
||||
|
||||
/** Main attributes for the discovery query **/
|
||||
private String query;
|
||||
private List<String> filterQueries;
|
||||
private int DSpaceObjectFilter = -1;
|
||||
private List<String> fieldPresentQueries;
|
||||
|
||||
private int start = 0;
|
||||
private int maxResults = -1;
|
||||
|
||||
/** Attributes used for sorting of results **/
|
||||
public enum SORT_ORDER {
|
||||
desc,
|
||||
asc
|
||||
}
|
||||
private String sortField;
|
||||
private SORT_ORDER sortOrder;
|
||||
|
||||
/** Attributes required for the faceting of values **/
|
||||
private List<DiscoverFacetField> facetFields;
|
||||
private List<String> facetQueries;
|
||||
private int facetLimit = -1;
|
||||
private int facetMinCount = -1;
|
||||
private int facetOffset = 0;
|
||||
private Map<String, DiscoverHitHighlightingField> hitHighlighting;
|
||||
|
||||
/** Used when you want to search for a specific field value **/
|
||||
private List<String> searchFields;
|
||||
|
||||
/** Misc attributes can be implementation dependent **/
|
||||
private Map<String, List<String>> properties;
|
||||
|
||||
public DiscoverQuery() {
|
||||
//Initialize all our lists
|
||||
this.filterQueries = new ArrayList<String>();
|
||||
this.fieldPresentQueries = new ArrayList<String>();
|
||||
|
||||
this.facetFields = new ArrayList<DiscoverFacetField>();
|
||||
this.facetQueries = new ArrayList<String>();
|
||||
this.searchFields = new ArrayList<String>();
|
||||
this.hitHighlighting = new HashMap<String, DiscoverHitHighlightingField>();
|
||||
//Use a linked hashmap since sometimes insertion order might matter
|
||||
this.properties = new LinkedHashMap<String, List<String>>();
|
||||
}
|
||||
|
||||
|
||||
public void setQuery(String query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setStart(int start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public void setSortField(String sortField, SORT_ORDER sortOrder){
|
||||
this.sortField = sortField;
|
||||
this.sortOrder = sortOrder;
|
||||
}
|
||||
|
||||
public String getSortField() {
|
||||
return sortField;
|
||||
}
|
||||
|
||||
public SORT_ORDER getSortOrder() {
|
||||
return sortOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the DSpace object filter, must be an DSpace Object type integer
|
||||
* can be used to only return objects from a certain DSpace Object type
|
||||
* @param DSpaceObjectFilter the DSpace object filer
|
||||
*/
|
||||
public void setDSpaceObjectFilter(int DSpaceObjectFilter) {
|
||||
this.DSpaceObjectFilter = DSpaceObjectFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the DSpace object filter
|
||||
* can be used to only return objects from a certain DSpace Object type
|
||||
* @return the DSpace object filer
|
||||
*/
|
||||
public int getDSpaceObjectFilter() {
|
||||
return DSpaceObjectFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum number of results returned by this query
|
||||
* @return the number of results
|
||||
*/
|
||||
public int getMaxResults() {
|
||||
return maxResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum number of results by this query
|
||||
* @param maxResults the number of results
|
||||
*/
|
||||
public void setMaxResults(int maxResults) {
|
||||
this.maxResults = maxResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new filter queries
|
||||
* @param filterQueries the filter queries to be added
|
||||
*/
|
||||
public void addFilterQueries(String ...filterQueries){
|
||||
this.filterQueries.addAll(Arrays.asList(filterQueries));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filter queries
|
||||
* @return the filter queries in a list
|
||||
*/
|
||||
public List<String> getFilterQueries() {
|
||||
return filterQueries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a query that will ensure that a certain field is present in the index
|
||||
* @param fieldPresentQueries the queries to be added
|
||||
*/
|
||||
public void addFieldPresentQueries(String ...fieldPresentQueries){
|
||||
this.fieldPresentQueries.addAll(Arrays.asList(fieldPresentQueries));
|
||||
}
|
||||
|
||||
public List<String> getFieldPresentQueries() {
|
||||
return fieldPresentQueries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new facet query
|
||||
* @param facetQuery the new facet query to be added
|
||||
*/
|
||||
public void addFacetQuery(String facetQuery){
|
||||
this.facetQueries.add(facetQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the facet queries
|
||||
* @return the facet queries for this query
|
||||
*/
|
||||
public List<String> getFacetQueries() {
|
||||
return facetQueries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new facet field
|
||||
* @param facetField the new facet field to be added
|
||||
*/
|
||||
public void addFacetField(DiscoverFacetField facetField){
|
||||
facetFields.add(facetField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the facets fields configured
|
||||
* @return the facet fields for this query
|
||||
*/
|
||||
public List<DiscoverFacetField> getFacetFields() {
|
||||
return facetFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minimum number of values that need to be present before a valid facet value has been found
|
||||
* @return facetMinCount the minimum number of values to be present for a valid facet
|
||||
*/
|
||||
public int getFacetMinCount() {
|
||||
return facetMinCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minimum number of values that need to be present before a valid facet value has been found
|
||||
* @param facetMinCount the minimum number of values to be present for a valid facet
|
||||
*/
|
||||
public void setFacetMinCount(int facetMinCount) {
|
||||
this.facetMinCount = facetMinCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the facet field offset
|
||||
* @return the facet field offset
|
||||
*/
|
||||
public int getFacetOffset() {
|
||||
return facetOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the facet field offset, one facet offset will be used for all the facet fields
|
||||
* @param facetOffset an integer representing the offset
|
||||
*/
|
||||
public void setFacetOffset(int facetOffset) {
|
||||
this.facetOffset = facetOffset;
|
||||
}
|
||||
|
||||
public void addSearchField(String field){
|
||||
this.searchFields.add(field);
|
||||
}
|
||||
|
||||
public List<String> getSearchFields() {
|
||||
return searchFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the misc search properties
|
||||
* @return a map containing the properties
|
||||
*/
|
||||
public Map<String, List<String>> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new search property to the misc search properties
|
||||
* @param property the name of the property
|
||||
* @param value the value of the property
|
||||
*/
|
||||
public void addProperty(String property, String value){
|
||||
List<String> toAddList = properties.get(property);
|
||||
if(toAddList == null)
|
||||
{
|
||||
toAddList = new ArrayList<String>();
|
||||
}
|
||||
|
||||
toAddList.add(value);
|
||||
|
||||
properties.put(property, toAddList);
|
||||
}
|
||||
|
||||
public DiscoverHitHighlightingField getHitHighlightingField(String field)
|
||||
{
|
||||
return hitHighlighting.get(field);
|
||||
}
|
||||
|
||||
public List<DiscoverHitHighlightingField> getHitHighlightingFields()
|
||||
{
|
||||
return new ArrayList<DiscoverHitHighlightingField>(hitHighlighting.values());
|
||||
}
|
||||
|
||||
public void addHitHighlightingField(DiscoverHitHighlightingField hitHighlighting)
|
||||
{
|
||||
this.hitHighlighting.put(hitHighlighting.getField(), hitHighlighting);
|
||||
}
|
||||
}
|
@@ -0,0 +1,234 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
import org.dspace.content.DSpaceObject;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This class represents the result that the discovery search impl returns
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
*/
|
||||
public class DiscoverResult {
|
||||
|
||||
private long totalSearchResults;
|
||||
private int start;
|
||||
private List<DSpaceObject> dspaceObjects;
|
||||
private Map<String, List<FacetResult>> facetResults;
|
||||
/** A map that contains all the documents sougth after, the key is a string representation of the DSpace object */
|
||||
private Map<String, List<SearchDocument>> searchDocuments;
|
||||
private int maxResults = -1;
|
||||
private int searchTime;
|
||||
private Map<String, DSpaceObjectHighlightResult> highlightedResults;
|
||||
|
||||
|
||||
public DiscoverResult() {
|
||||
dspaceObjects = new ArrayList<DSpaceObject>();
|
||||
facetResults = new LinkedHashMap<String, List<FacetResult>>();
|
||||
searchDocuments = new LinkedHashMap<String, List<SearchDocument>>();
|
||||
highlightedResults = new HashMap<String, DSpaceObjectHighlightResult>();
|
||||
}
|
||||
|
||||
|
||||
public void addDSpaceObject(DSpaceObject dso){
|
||||
this.dspaceObjects.add(dso);
|
||||
}
|
||||
|
||||
public List<DSpaceObject> getDspaceObjects() {
|
||||
return dspaceObjects;
|
||||
}
|
||||
|
||||
public long getTotalSearchResults() {
|
||||
return totalSearchResults;
|
||||
}
|
||||
|
||||
public void setTotalSearchResults(long totalSearchResults) {
|
||||
this.totalSearchResults = totalSearchResults;
|
||||
}
|
||||
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setStart(int start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public int getMaxResults() {
|
||||
return maxResults;
|
||||
}
|
||||
|
||||
public void setMaxResults(int maxResults) {
|
||||
this.maxResults = maxResults;
|
||||
}
|
||||
|
||||
public int getSearchTime()
|
||||
{
|
||||
return searchTime;
|
||||
}
|
||||
|
||||
public void setSearchTime(int searchTime)
|
||||
{
|
||||
this.searchTime = searchTime;
|
||||
}
|
||||
|
||||
public void addFacetResult(String facetField, FacetResult ...facetResults){
|
||||
List<FacetResult> facetValues = this.facetResults.get(facetField);
|
||||
if(facetValues == null)
|
||||
{
|
||||
facetValues = new ArrayList<FacetResult>();
|
||||
}
|
||||
facetValues.addAll(Arrays.asList(facetResults));
|
||||
this.facetResults.put(facetField, facetValues);
|
||||
}
|
||||
|
||||
public Map<String, List<FacetResult>> getFacetResults() {
|
||||
return facetResults;
|
||||
}
|
||||
|
||||
public List<FacetResult> getFacetResult(String facet){
|
||||
return facetResults.get(facet) == null ? new ArrayList<FacetResult>() : facetResults.get(facet);
|
||||
}
|
||||
|
||||
public DSpaceObjectHighlightResult getHighlightedResults(DSpaceObject dso)
|
||||
{
|
||||
return highlightedResults.get(dso.getHandle());
|
||||
}
|
||||
|
||||
public void addHighlightedResult(DSpaceObject dso, DSpaceObjectHighlightResult highlightedResult)
|
||||
{
|
||||
this.highlightedResults.put(dso.getHandle(), highlightedResult);
|
||||
}
|
||||
|
||||
public static final class FacetResult{
|
||||
private String asFilterQuery;
|
||||
private String displayedValue;
|
||||
private String authorityKey;
|
||||
private String sortValue;
|
||||
private long count;
|
||||
|
||||
public FacetResult(String asFilterQuery, String displayedValue, String authorityKey, String sortValue, long count) {
|
||||
this.asFilterQuery = asFilterQuery;
|
||||
this.displayedValue = displayedValue;
|
||||
this.authorityKey = authorityKey;
|
||||
this.sortValue = sortValue;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public String getAsFilterQuery() {
|
||||
return asFilterQuery;
|
||||
}
|
||||
|
||||
public String getDisplayedValue() {
|
||||
return displayedValue;
|
||||
}
|
||||
|
||||
public String getSortValue()
|
||||
{
|
||||
return sortValue;
|
||||
}
|
||||
|
||||
public long getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public String getAuthorityKey()
|
||||
{
|
||||
return authorityKey;
|
||||
}
|
||||
|
||||
public String getFilterType()
|
||||
{
|
||||
return authorityKey != null?"authority":"equals";
|
||||
}
|
||||
}
|
||||
|
||||
public static final class DSpaceObjectHighlightResult
|
||||
{
|
||||
private DSpaceObject dso;
|
||||
private Map<String, List<String>> highlightResults;
|
||||
|
||||
public DSpaceObjectHighlightResult(DSpaceObject dso, Map<String, List<String>> highlightResults)
|
||||
{
|
||||
this.dso = dso;
|
||||
this.highlightResults = highlightResults;
|
||||
}
|
||||
|
||||
public DSpaceObject getDso()
|
||||
{
|
||||
return dso;
|
||||
}
|
||||
|
||||
public List<String> getHighlightResults(String metadataKey)
|
||||
{
|
||||
return highlightResults.get(metadataKey);
|
||||
}
|
||||
}
|
||||
|
||||
public void addSearchDocument(DSpaceObject dso, SearchDocument searchDocument){
|
||||
String dsoString = SearchDocument.getDspaceObjectStringRepresentation(dso);
|
||||
List<SearchDocument> docs = searchDocuments.get(dsoString);
|
||||
if(docs == null){
|
||||
docs = new ArrayList<SearchDocument>();
|
||||
}
|
||||
docs.add(searchDocument);
|
||||
searchDocuments.put(dsoString, docs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the sought after search document values
|
||||
* @param dso the dspace object we want our search documents for
|
||||
* @return the search documents list
|
||||
*/
|
||||
public List<SearchDocument> getSearchDocument(DSpaceObject dso){
|
||||
String dsoString = SearchDocument.getDspaceObjectStringRepresentation(dso);
|
||||
List<SearchDocument> result = searchDocuments.get(dsoString);
|
||||
if(result == null){
|
||||
return new ArrayList<SearchDocument>();
|
||||
}else{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class contains values from the fields searched for in DiscoveryQuery.java
|
||||
*/
|
||||
public static final class SearchDocument{
|
||||
private Map<String, List<String>> searchFields;
|
||||
|
||||
public SearchDocument() {
|
||||
this.searchFields = new LinkedHashMap<String, List<String>>();
|
||||
}
|
||||
|
||||
public void addSearchField(String field, String ...values){
|
||||
List<String>searchFieldValues = searchFields.get(field);
|
||||
if(searchFieldValues == null){
|
||||
searchFieldValues = new ArrayList<String>();
|
||||
}
|
||||
searchFieldValues.addAll(Arrays.asList(values));
|
||||
searchFields.put(field, searchFieldValues);
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getSearchFields() {
|
||||
return searchFields;
|
||||
}
|
||||
|
||||
public List<String> getSearchFieldValues(String field){
|
||||
if(searchFields.get(field) == null)
|
||||
return new ArrayList<String>();
|
||||
else
|
||||
return searchFields.get(field);
|
||||
}
|
||||
|
||||
public static String getDspaceObjectStringRepresentation(DSpaceObject dso){
|
||||
return dso.getType() + ":" + dso.getID();
|
||||
}
|
||||
}
|
||||
}
|
125
dspace-api/src/main/java/org/dspace/discovery/IndexClient.java
Normal file
125
dspace-api/src/main/java/org/dspace/discovery/IndexClient.java
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.commons.cli.*;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.utils.DSpace;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Class used to reindex dspace communities/collections/items into discovery
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
*/
|
||||
public class IndexClient {
|
||||
|
||||
|
||||
private static final Logger log = Logger.getLogger(IndexClient.class);
|
||||
|
||||
/**
|
||||
* When invoked as a command-line tool, creates, updates, removes content
|
||||
* from the whole index
|
||||
*
|
||||
* @param args the command-line arguments, none used
|
||||
* @throws java.io.IOException
|
||||
* @throws java.sql.SQLException
|
||||
*
|
||||
*/
|
||||
public static void main(String[] args) throws SQLException, IOException, SearchServiceException {
|
||||
|
||||
Context context = new Context();
|
||||
context.setIgnoreAuthorization(true);
|
||||
|
||||
String usage = "org.dspace.discovery.IndexClient [-cbhf[r <item handle>]] or nothing to update/clean an existing index.";
|
||||
Options options = new Options();
|
||||
HelpFormatter formatter = new HelpFormatter();
|
||||
CommandLine line = null;
|
||||
|
||||
options
|
||||
.addOption(OptionBuilder
|
||||
.withArgName("item handle")
|
||||
.hasArg(true)
|
||||
.withDescription(
|
||||
"remove an Item, Collection or Community from index based on its handle")
|
||||
.create("r"));
|
||||
|
||||
|
||||
options
|
||||
.addOption(OptionBuilder
|
||||
.isRequired(false)
|
||||
.withDescription(
|
||||
"clean existing index removing any documents that no longer exist in the db")
|
||||
.create("c"));
|
||||
|
||||
options.addOption(OptionBuilder.isRequired(false).withDescription(
|
||||
"(re)build index, wiping out current one if it exists").create(
|
||||
"b"));
|
||||
|
||||
options
|
||||
.addOption(OptionBuilder
|
||||
.isRequired(false)
|
||||
.withDescription(
|
||||
"if updating existing index, force each handle to be reindexed even if uptodate")
|
||||
.create("f"));
|
||||
|
||||
options.addOption(OptionBuilder.isRequired(false).withDescription(
|
||||
"print this help message").create("h"));
|
||||
|
||||
options.addOption(OptionBuilder.isRequired(false).withDescription(
|
||||
"optimize search core").create("o"));
|
||||
|
||||
try {
|
||||
line = new PosixParser().parse(options, args);
|
||||
} catch (Exception e) {
|
||||
// automatically generate the help statement
|
||||
formatter.printHelp(usage, e.getMessage(), options, "");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
if (line.hasOption("h")) {
|
||||
// automatically generate the help statement
|
||||
formatter.printHelp(usage, options);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
/** Acquire from dspace-services in future */
|
||||
/**
|
||||
* new DSpace.getServiceManager().getServiceByName("org.dspace.discovery.SolrIndexer");
|
||||
*/
|
||||
|
||||
DSpace dspace = new DSpace();
|
||||
|
||||
IndexingService indexer = dspace.getServiceManager().getServiceByName(IndexingService.class.getName(),IndexingService.class);
|
||||
|
||||
if (line.hasOption("r")) {
|
||||
log.info("Removing " + line.getOptionValue("r") + " from Index");
|
||||
indexer.unIndexContent(context, line.getOptionValue("r"));
|
||||
} else if (line.hasOption("c")) {
|
||||
log.info("Cleaning Index");
|
||||
indexer.cleanIndex(line.hasOption("f"));
|
||||
} else if (line.hasOption("b")) {
|
||||
log.info("(Re)building index from scratch.");
|
||||
indexer.createIndex(context);
|
||||
} else if (line.hasOption("o")) {
|
||||
log.info("Optimizing search core.");
|
||||
indexer.optimize();
|
||||
} else {
|
||||
log.info("Updating and Cleaning Index");
|
||||
indexer.cleanIndex(line.hasOption("f"));
|
||||
indexer.updateIndex(context, line.hasOption("f"));
|
||||
}
|
||||
|
||||
log.info("Done with indexing");
|
||||
}
|
||||
}
|
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.event.Consumer;
|
||||
import org.dspace.event.Event;
|
||||
import org.dspace.utils.DSpace;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Class for updating search indices in discovery from content events.
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
*/
|
||||
public class IndexEventConsumer implements Consumer {
|
||||
/**
|
||||
* log4j logger
|
||||
*/
|
||||
private static Logger log = Logger.getLogger(IndexEventConsumer.class);
|
||||
|
||||
// collect Items, Collections, Communities that need indexing
|
||||
private Set<DSpaceObject> objectsToUpdate = null;
|
||||
|
||||
// handles to delete since IDs are not useful by now.
|
||||
private Set<String> handlesToDelete = null;
|
||||
|
||||
DSpace dspace = new DSpace();
|
||||
|
||||
IndexingService indexer = dspace.getServiceManager().getServiceByName(IndexingService.class.getName(),IndexingService.class);
|
||||
|
||||
public void initialize() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume a content event -- just build the sets of objects to add (new) to
|
||||
* the index, update, and delete.
|
||||
*
|
||||
* @param ctx DSpace context
|
||||
* @param event Content event
|
||||
*/
|
||||
public void consume(Context ctx, Event event) throws Exception {
|
||||
|
||||
if (objectsToUpdate == null) {
|
||||
objectsToUpdate = new HashSet<DSpaceObject>();
|
||||
handlesToDelete = new HashSet<String>();
|
||||
}
|
||||
|
||||
int st = event.getSubjectType();
|
||||
if (!(st == Constants.ITEM || st == Constants.BUNDLE
|
||||
|| st == Constants.COLLECTION || st == Constants.COMMUNITY)) {
|
||||
log
|
||||
.warn("IndexConsumer should not have been given this kind of Subject in an event, skipping: "
|
||||
+ event.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
DSpaceObject subject = event.getSubject(ctx);
|
||||
|
||||
DSpaceObject object = event.getObject(ctx);
|
||||
|
||||
|
||||
// If event subject is a Bundle and event was Add or Remove,
|
||||
// transform the event to be a Modify on the owning Item.
|
||||
// It could be a new bitstream in the TEXT bundle which
|
||||
// would change the index.
|
||||
int et = event.getEventType();
|
||||
if (st == Constants.BUNDLE) {
|
||||
if ((et == Event.ADD || et == Event.REMOVE) && subject != null
|
||||
&& ((Bundle) subject).getName().equals("TEXT")) {
|
||||
st = Constants.ITEM;
|
||||
et = Event.MODIFY;
|
||||
subject = ((Bundle) subject).getItems()[0];
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Transforming Bundle event into MODIFY of Item "
|
||||
+ subject.getHandle());
|
||||
}
|
||||
} else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (et) {
|
||||
case Event.CREATE:
|
||||
case Event.MODIFY:
|
||||
case Event.MODIFY_METADATA:
|
||||
if (subject == null)
|
||||
{
|
||||
log.warn(event.getEventTypeAsString() + " event, could not get object for "
|
||||
+ event.getSubjectTypeAsString() + " id="
|
||||
+ String.valueOf(event.getSubjectID())
|
||||
+ ", perhaps it has been deleted.");
|
||||
}
|
||||
else {
|
||||
log.debug("consume() adding event to update queue: " + event.toString());
|
||||
objectsToUpdate.add(subject);
|
||||
}
|
||||
break;
|
||||
|
||||
case Event.REMOVE:
|
||||
case Event.ADD:
|
||||
if (object == null)
|
||||
{
|
||||
log.warn(event.getEventTypeAsString() + " event, could not get object for "
|
||||
+ event.getObjectTypeAsString() + " id="
|
||||
+ String.valueOf(event.getObjectID())
|
||||
+ ", perhaps it has been deleted.");
|
||||
}
|
||||
else {
|
||||
log.debug("consume() adding event to update queue: " + event.toString());
|
||||
objectsToUpdate.add(object);
|
||||
}
|
||||
break;
|
||||
|
||||
case Event.DELETE:
|
||||
String detail = event.getDetail();
|
||||
if (detail == null)
|
||||
{
|
||||
log.warn("got null detail on DELETE event, skipping it.");
|
||||
}
|
||||
else {
|
||||
log.debug("consume() adding event to delete queue: " + event.toString());
|
||||
handlesToDelete.add(detail);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log
|
||||
.warn("IndexConsumer should not have been given a event of type="
|
||||
+ event.getEventTypeAsString()
|
||||
+ " on subject="
|
||||
+ event.getSubjectTypeAsString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process sets of objects to add, update, and delete in index. Correct for
|
||||
* interactions between the sets -- e.g. objects which were deleted do not
|
||||
* need to be added or updated, new objects don't also need an update, etc.
|
||||
*/
|
||||
public void end(Context ctx) throws Exception {
|
||||
|
||||
if (objectsToUpdate != null && handlesToDelete != null) {
|
||||
|
||||
// update the changed Items not deleted because they were on create list
|
||||
for (DSpaceObject iu : objectsToUpdate) {
|
||||
/* we let all types through here and
|
||||
* allow the search DSIndexer to make
|
||||
* decisions on indexing and/or removal
|
||||
*/
|
||||
String hdl = iu.getHandle();
|
||||
if (hdl != null && !handlesToDelete.contains(hdl)) {
|
||||
try {
|
||||
indexer.indexContent(ctx, iu, true);
|
||||
log.debug("Indexed "
|
||||
+ Constants.typeText[iu.getType()]
|
||||
+ ", id=" + String.valueOf(iu.getID())
|
||||
+ ", handle=" + hdl);
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("Failed while indexing object: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String hdl : handlesToDelete) {
|
||||
try {
|
||||
indexer.unIndexContent(ctx, hdl, true);
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("UN-Indexed Item, handle=" + hdl);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("Failed while UN-indexing object: " + hdl, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// "free" the resources
|
||||
objectsToUpdate = null;
|
||||
handlesToDelete = null;
|
||||
}
|
||||
|
||||
public void finish(Context ctx) throws Exception {
|
||||
// No-op
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Interface used for indexing dspaceobject into discovery
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
*/
|
||||
public interface IndexingService {
|
||||
|
||||
void indexContent(Context context, DSpaceObject dso)
|
||||
throws SQLException;
|
||||
|
||||
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;
|
||||
|
||||
void unIndexContent(Context context, String handle, boolean commit)
|
||||
throws SQLException, IOException;
|
||||
|
||||
void reIndexContent(Context context, DSpaceObject dso)
|
||||
throws SQLException, IOException;
|
||||
|
||||
void createIndex(Context context) throws SQLException, IOException;
|
||||
|
||||
void updateIndex(Context context);
|
||||
|
||||
void updateIndex(Context context, boolean force);
|
||||
|
||||
void cleanIndex(boolean force) throws IOException,
|
||||
SQLException, SearchServiceException;
|
||||
|
||||
void commit() throws SearchServiceException;
|
||||
|
||||
void optimize() throws SearchServiceException;
|
||||
}
|
124
dspace-api/src/main/java/org/dspace/discovery/SearchService.java
Normal file
124
dspace-api/src/main/java/org/dspace/discovery/SearchService.java
Normal file
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.discovery.configuration.DiscoveryMoreLikeThisConfiguration;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Search interface that discovery uses
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
*/
|
||||
public interface SearchService {
|
||||
|
||||
/**
|
||||
* Convenient method to call @see #search(Context, DSpaceObject,
|
||||
* DiscoverQuery) with a null DSpace Object as scope (i.e. all the
|
||||
* repository)
|
||||
*
|
||||
* @param context
|
||||
* DSpace Context object
|
||||
* @param dso
|
||||
* a DSpace Object to use as scope of the search (only results
|
||||
* within this object)
|
||||
* @param query
|
||||
* the discovery query object
|
||||
* @return
|
||||
* @throws SearchServiceException
|
||||
*/
|
||||
DiscoverResult search(Context context, DiscoverQuery query)
|
||||
throws SearchServiceException;
|
||||
|
||||
/**
|
||||
* Convenient method to call @see #search(Context, DSpaceObject,
|
||||
* DiscoverQuery, boolean) with includeWithdrawn=false
|
||||
*
|
||||
* @param context
|
||||
* DSpace Context object
|
||||
* @param dso
|
||||
* a DSpace Object to use as scope of the search (only results
|
||||
* within this object)
|
||||
* @param query
|
||||
* the discovery query object
|
||||
* @return
|
||||
* @throws SearchServiceException
|
||||
*/
|
||||
DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery query)
|
||||
throws SearchServiceException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param context
|
||||
* DSpace Context object
|
||||
* @param dso
|
||||
* a DSpace Object to use as scope of the search (only results
|
||||
* within this object)
|
||||
* @param includeWithdrawn
|
||||
* use <code>true</code> to include in the results also withdrawn
|
||||
* items that match the query
|
||||
* @return
|
||||
* @throws SearchServiceException
|
||||
*/
|
||||
DiscoverResult search(Context context, DiscoverQuery query,
|
||||
boolean includeWithdrawn) throws SearchServiceException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param context
|
||||
* DSpace Context object
|
||||
* @param dso
|
||||
* a DSpace Object to use as scope of the search (only results
|
||||
* within this object)
|
||||
* @param query
|
||||
* the discovery query object
|
||||
* @param includeWithdrawn
|
||||
* use <code>true</code> to include in the results also withdrawn
|
||||
* items that match the query
|
||||
*
|
||||
* @return
|
||||
* @throws SearchServiceException
|
||||
*/
|
||||
DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery query, boolean includeWithdrawn) throws SearchServiceException;
|
||||
|
||||
|
||||
InputStream searchJSON(Context context, DiscoverQuery query, String jsonIdentifier) throws SearchServiceException;
|
||||
|
||||
InputStream searchJSON(Context context, DiscoverQuery query, DSpaceObject dso, String jsonIdentifier) throws SearchServiceException;
|
||||
|
||||
|
||||
List<DSpaceObject> search(Context context, String query, String orderfield, boolean ascending, int offset, int max, String... filterquery);
|
||||
|
||||
|
||||
/**
|
||||
* Transforms the given string field and value into a filter query
|
||||
* @param context the DSpace context
|
||||
* @param field the field of the filter query
|
||||
* @param value the filter query value
|
||||
* @return a filter query
|
||||
* @throws SQLException ...
|
||||
*/
|
||||
DiscoverFilterQuery toFilterQuery(Context context, String field, String operator, String value) throws SQLException;
|
||||
|
||||
List<Item> getRelatedItems(Context context, Item item, DiscoveryMoreLikeThisConfiguration moreLikeThisConfiguration);
|
||||
|
||||
/**
|
||||
* Transforms the metadata field of the given sort configuration into the indexed field which we can then use in our solr queries
|
||||
* @param metadataField the metadata field
|
||||
* @return the indexed field
|
||||
*/
|
||||
String toSortFieldIndex(String metadataField, String type);
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
/**
|
||||
* Exception used by discovery when discovery search exceptions occur
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
*/
|
||||
public class SearchServiceException extends Exception {
|
||||
|
||||
public SearchServiceException() {
|
||||
}
|
||||
|
||||
public SearchServiceException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public SearchServiceException(String s, Throwable throwable) {
|
||||
super(s, throwable);
|
||||
}
|
||||
|
||||
public SearchServiceException(Throwable throwable) {
|
||||
super(throwable);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
import org.dspace.content.*;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfigurationService;
|
||||
import org.dspace.kernel.ServiceManager;
|
||||
import org.dspace.utils.DSpace;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Util methods used by discovery
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
*/
|
||||
public class SearchUtils {
|
||||
/** Cached search service **/
|
||||
private static SearchService searchService;
|
||||
|
||||
|
||||
public static SearchService getSearchService()
|
||||
{
|
||||
if(searchService == null){
|
||||
DSpace dspace = new DSpace();
|
||||
org.dspace.kernel.ServiceManager manager = dspace.getServiceManager() ;
|
||||
searchService = manager.getServiceByName(SearchService.class.getName(),SearchService.class);
|
||||
}
|
||||
return searchService;
|
||||
}
|
||||
|
||||
public static DiscoveryConfiguration getDiscoveryConfiguration(){
|
||||
return getDiscoveryConfiguration(null);
|
||||
}
|
||||
|
||||
public static DiscoveryConfiguration getDiscoveryConfiguration(DSpaceObject dso){
|
||||
DiscoveryConfigurationService configurationService = getConfigurationService();
|
||||
|
||||
DiscoveryConfiguration result = null;
|
||||
if(dso == null){
|
||||
result = configurationService.getMap().get("site");
|
||||
}else{
|
||||
result = configurationService.getMap().get(dso.getHandle());
|
||||
}
|
||||
|
||||
if(result == null){
|
||||
//No specific configuration, get the default one
|
||||
result = configurationService.getMap().get("default");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static DiscoveryConfigurationService getConfigurationService() {
|
||||
DSpace dspace = new DSpace();
|
||||
ServiceManager manager = dspace.getServiceManager();
|
||||
return manager.getServiceByName(DiscoveryConfigurationService.class.getName(), DiscoveryConfigurationService.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that retrieves a list of all the configuration objects from the given item
|
||||
* A configuration object can be returned for each parent community/collection
|
||||
* @param item the DSpace item
|
||||
* @return a list of configuration objects
|
||||
*/
|
||||
public static List<DiscoveryConfiguration> getAllDiscoveryConfigurations(Item item) throws SQLException {
|
||||
Map<String, DiscoveryConfiguration> result = new HashMap<String, DiscoveryConfiguration>();
|
||||
|
||||
Collection[] collections = item.getCollections();
|
||||
for (Collection collection : collections) {
|
||||
DiscoveryConfiguration configuration = getDiscoveryConfiguration(collection);
|
||||
if(!result.containsKey(configuration.getId())){
|
||||
result.put(configuration.getId(), configuration);
|
||||
}
|
||||
}
|
||||
|
||||
//Also add one for the default
|
||||
DiscoveryConfiguration configuration = getDiscoveryConfiguration(null);
|
||||
if(!result.containsKey(configuration.getId())){
|
||||
result.put(configuration.getId(), configuration);
|
||||
}
|
||||
|
||||
return Arrays.asList(result.values().toArray(new DiscoveryConfiguration[result.size()]));
|
||||
}
|
||||
|
||||
}
|
2113
dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java
Normal file
2113
dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
|
||||
/**
|
||||
* Example class that prints out the handle of the DSpace Object currently being indexed
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
*/
|
||||
public class SolrServiceIndexOutputPlugin implements SolrServiceIndexPlugin{
|
||||
|
||||
@Override
|
||||
public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument document) {
|
||||
System.out.println("Currently indexing: " + dso.getHandle());
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Indexing plugin used when indexing the communities/collections/items into DSpace
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
*/
|
||||
public interface SolrServiceIndexPlugin {
|
||||
|
||||
public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument document);
|
||||
}
|
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.solr.client.solrj.SolrQuery;
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
import org.dspace.authorize.AuthorizeManager;
|
||||
import org.dspace.authorize.ResourcePolicy;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.Group;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Restriction plugin that ensures that indexes all the resource policies.
|
||||
* When a search is performed extra filter queries are added to retrieve only results to which the user has READ access
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
*/
|
||||
public class SolrServiceResourceRestrictionPlugin implements SolrServiceIndexPlugin, SolrServiceSearchPlugin{
|
||||
|
||||
private static final Logger log = Logger.getLogger(SolrServiceResourceRestrictionPlugin.class);
|
||||
|
||||
@Override
|
||||
public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument document) {
|
||||
try {
|
||||
List<ResourcePolicy> policies = AuthorizeManager.getPoliciesActionFilter(context, dso, Constants.READ);
|
||||
for (ResourcePolicy resourcePolicy : policies) {
|
||||
String fieldValue;
|
||||
if(resourcePolicy.getGroupID() != -1){
|
||||
//We have a group add it to the value
|
||||
fieldValue = "g" + resourcePolicy.getGroupID();
|
||||
}else{
|
||||
//We have an eperson add it to the value
|
||||
fieldValue = "e" + resourcePolicy.getEPersonID();
|
||||
|
||||
}
|
||||
|
||||
document.addField("read", fieldValue);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error(LogManager.getHeader(context, "Error while indexing resource policies", "DSpace object: (id " + dso.getID() + " type " + dso.getType() + ")"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void additionalSearchParameters(Context context, DiscoverQuery discoveryQuery, SolrQuery solrQuery) {
|
||||
StringBuilder resourceQuery = new StringBuilder();
|
||||
//Always add the anonymous group id to the query
|
||||
resourceQuery.append("read:(g0");
|
||||
EPerson currentUser = context.getCurrentUser();
|
||||
if(currentUser != null){
|
||||
try {
|
||||
resourceQuery.append(" OR e").append(currentUser.getID());
|
||||
//Retrieve all the groups the current user is a member of !
|
||||
Set<Integer> groupIds = Group.allMemberGroupIDs(context, currentUser);
|
||||
for (Integer groupId : groupIds) {
|
||||
resourceQuery.append(" OR g").append(groupId);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error(LogManager.getHeader(context, "Error while adding resource policy information to query", "") ,e);
|
||||
}
|
||||
}
|
||||
resourceQuery.append(")");
|
||||
try {
|
||||
if(AuthorizeManager.isAdmin(context)){
|
||||
//Admins always have read access even if no policies are present !
|
||||
resourceQuery.append(" OR (!read[* TO *])");
|
||||
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error(LogManager.getHeader(context, "Error while verifying if current user is admin !", ""), e);
|
||||
}
|
||||
solrQuery.addFilterQuery(resourceQuery.toString());
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
import org.apache.solr.client.solrj.SolrQuery;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Plugin from which users can add additional search parameters for every search that occurs in discovery
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
*/
|
||||
public interface SolrServiceSearchPlugin {
|
||||
|
||||
public void additionalSearchParameters(Context context, DiscoverQuery discoveryQuery, SolrQuery solrQuery);
|
||||
}
|
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
*/
|
||||
public class DiscoveryConfiguration implements InitializingBean{
|
||||
|
||||
/** The configuration for the sidebar facets **/
|
||||
private List<DiscoverySearchFilterFacet> sidebarFacets = new ArrayList<DiscoverySearchFilterFacet>();
|
||||
|
||||
/** The default filter queries which will be applied to any search & the recent submissions **/
|
||||
private List<String> defaultFilterQueries;
|
||||
|
||||
/** Configuration object for the recent submissions **/
|
||||
private DiscoveryRecentSubmissionsConfiguration recentSubmissionConfiguration;
|
||||
|
||||
/** The search filters which can be selected on the search page**/
|
||||
private List<DiscoverySearchFilter> searchFilters = new ArrayList<DiscoverySearchFilter>();
|
||||
|
||||
private DiscoverySortConfiguration searchSortConfiguration;
|
||||
|
||||
private int defaultRpp = 10;
|
||||
|
||||
private String id;
|
||||
private DiscoveryHitHighlightingConfiguration hitHighlightingConfiguration;
|
||||
private DiscoveryMoreLikeThisConfiguration moreLikeThisConfiguration;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<DiscoverySearchFilterFacet> getSidebarFacets() {
|
||||
return sidebarFacets;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setSidebarFacets(List<DiscoverySearchFilterFacet> sidebarFacets) {
|
||||
this.sidebarFacets = sidebarFacets;
|
||||
}
|
||||
|
||||
public List<String> getDefaultFilterQueries() {
|
||||
//Since default filter queries are not mandatory we will return an empty list
|
||||
if(defaultFilterQueries == null){
|
||||
return new ArrayList<String>();
|
||||
}else{
|
||||
return defaultFilterQueries;
|
||||
}
|
||||
}
|
||||
|
||||
public void setDefaultFilterQueries(List<String> defaultFilterQueries) {
|
||||
this.defaultFilterQueries = defaultFilterQueries;
|
||||
}
|
||||
|
||||
public DiscoveryRecentSubmissionsConfiguration getRecentSubmissionConfiguration() {
|
||||
return recentSubmissionConfiguration;
|
||||
}
|
||||
|
||||
public void setRecentSubmissionConfiguration(DiscoveryRecentSubmissionsConfiguration recentSubmissionConfiguration) {
|
||||
this.recentSubmissionConfiguration = recentSubmissionConfiguration;
|
||||
}
|
||||
|
||||
public List<DiscoverySearchFilter> getSearchFilters() {
|
||||
return searchFilters;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setSearchFilters(List<DiscoverySearchFilter> searchFilters) {
|
||||
this.searchFilters = searchFilters;
|
||||
}
|
||||
|
||||
public DiscoverySortConfiguration getSearchSortConfiguration() {
|
||||
return searchSortConfiguration;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setSearchSortConfiguration(DiscoverySortConfiguration searchSortConfiguration) {
|
||||
this.searchSortConfiguration = searchSortConfiguration;
|
||||
}
|
||||
|
||||
public void setDefaultRpp(int defaultRpp)
|
||||
{
|
||||
this.defaultRpp = defaultRpp;
|
||||
}
|
||||
|
||||
public int getDefaultRpp()
|
||||
{
|
||||
return defaultRpp;
|
||||
}
|
||||
|
||||
public void setHitHighlightingConfiguration(DiscoveryHitHighlightingConfiguration hitHighlightingConfiguration) {
|
||||
this.hitHighlightingConfiguration = hitHighlightingConfiguration;
|
||||
}
|
||||
|
||||
public DiscoveryHitHighlightingConfiguration getHitHighlightingConfiguration() {
|
||||
return hitHighlightingConfiguration;
|
||||
}
|
||||
|
||||
public void setMoreLikeThisConfiguration(DiscoveryMoreLikeThisConfiguration moreLikeThisConfiguration) {
|
||||
this.moreLikeThisConfiguration = moreLikeThisConfiguration;
|
||||
}
|
||||
|
||||
public DiscoveryMoreLikeThisConfiguration getMoreLikeThisConfiguration() {
|
||||
return moreLikeThisConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* After all the properties are set check that the sidebar facets are a subset of our search filters
|
||||
*
|
||||
* @throws Exception throws an exception if this isn't the case
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
Collection missingSearchFilters = CollectionUtils.subtract(getSidebarFacets(), getSearchFilters());
|
||||
if(CollectionUtils.isNotEmpty(missingSearchFilters))
|
||||
{
|
||||
StringBuilder error = new StringBuilder();
|
||||
error.append("The following sidebar facet configurations are not present in the search filters list: ");
|
||||
for (Object missingSearchFilter : missingSearchFilters)
|
||||
{
|
||||
DiscoverySearchFilter searchFilter = (DiscoverySearchFilter) missingSearchFilter;
|
||||
error.append(searchFilter.getIndexFieldName()).append(" ");
|
||||
|
||||
}
|
||||
error.append("all the sidebar facets MUST be a part of the search filters list.");
|
||||
|
||||
throw new DiscoveryConfigurationException(error.toString());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
/**
|
||||
* Exception that can be thrown if there are issues with the discovery configuration
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
*/
|
||||
public class DiscoveryConfigurationException extends Exception{
|
||||
|
||||
public DiscoveryConfigurationException() {
|
||||
}
|
||||
|
||||
public DiscoveryConfigurationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public DiscoveryConfigurationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DiscoveryConfigurationException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
/**
|
||||
* Class contains parameters used for the configuration of discovery
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
*/
|
||||
public class DiscoveryConfigurationParameters {
|
||||
|
||||
public static final String TYPE_TEXT = "text";
|
||||
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}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
import org.dspace.utils.DSpace;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
*/
|
||||
public class DiscoveryConfigurationService {
|
||||
|
||||
private Map<String, DiscoveryConfiguration> map;
|
||||
|
||||
public Map<String, DiscoveryConfiguration> getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public void setMap(Map<String, DiscoveryConfiguration> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
DSpace dspace = new DSpace();
|
||||
System.out.println(dspace.getServiceManager().getServicesNames().size());
|
||||
DiscoveryConfigurationService mainService = dspace.getServiceManager().getServiceByName(DiscoveryConfigurationService.class.getName(), DiscoveryConfigurationService.class);
|
||||
|
||||
for(String key : mainService.getMap().keySet()){
|
||||
System.out.println(key);
|
||||
|
||||
System.out.println("Facets:");
|
||||
DiscoveryConfiguration discoveryConfiguration = mainService.getMap().get(key);
|
||||
for (int i = 0; i < discoveryConfiguration.getSidebarFacets().size(); i++) {
|
||||
DiscoverySearchFilterFacet sidebarFacet = discoveryConfiguration.getSidebarFacets().get(i);
|
||||
System.out.println("\t" + sidebarFacet.getIndexFieldName());
|
||||
for (int j = 0; j < sidebarFacet.getMetadataFields().size(); j++) {
|
||||
String metadataField = sidebarFacet.getMetadataFields().get(j);
|
||||
System.out.println("\t\t" + metadataField);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Search filters");
|
||||
List<DiscoverySearchFilter> searchFilters = discoveryConfiguration.getSearchFilters();
|
||||
for (DiscoverySearchFilter searchFilter : searchFilters) {
|
||||
for (int i = 0; i < searchFilter.getMetadataFields().size(); i++) {
|
||||
String metadataField = searchFilter.getMetadataFields().get(i);
|
||||
System.out.println("\t\t" + metadataField);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
System.out.println("Recent submissions configuration:");
|
||||
DiscoveryRecentSubmissionsConfiguration recentSubmissionConfiguration = discoveryConfiguration.getRecentSubmissionConfiguration();
|
||||
System.out.println("\tMetadata sort field: " + recentSubmissionConfiguration.getMetadataSortField());
|
||||
System.out.println("\tMax recent submissions: " + recentSubmissionConfiguration.getMax());
|
||||
|
||||
List<String> defaultFilterQueries = discoveryConfiguration.getDefaultFilterQueries();
|
||||
if(0 < defaultFilterQueries.size()){
|
||||
System.out.println("Default filter queries");
|
||||
for (String fq : defaultFilterQueries) {
|
||||
System.out.println("\t" + fq);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
/**
|
||||
* Configuration class that holds hit highlighting configuration for a single metadata field
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
*/
|
||||
public class DiscoveryHitHighlightFieldConfiguration
|
||||
{
|
||||
private String field;
|
||||
private int maxSize = 0;
|
||||
private int snippets = 3;
|
||||
|
||||
|
||||
public String getField()
|
||||
{
|
||||
return field;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setField(String field)
|
||||
{
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public int getMaxSize()
|
||||
{
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
public void setMaxSize(int maxSize)
|
||||
{
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of highlighted snippets to generate per field
|
||||
* @param snippets the number of maximum snippets
|
||||
*/
|
||||
public void setSnippets(int snippets)
|
||||
{
|
||||
this.snippets = snippets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum number of highlighted snippets to generate per field
|
||||
*/
|
||||
public int getSnippets()
|
||||
{
|
||||
return snippets;
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class that contains all the configuration concerning the hit highlighting in search resutls
|
||||
* This class can be configured in the [dspace.dir]/config/spring/discovery/spring-dspace-addon-discovery-configuration-services.xml
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
*/
|
||||
public class DiscoveryHitHighlightingConfiguration
|
||||
{
|
||||
|
||||
/* A list of metadata fields for which the hit highlighting is possible */
|
||||
private List<DiscoveryHitHighlightFieldConfiguration> metadataFields;
|
||||
|
||||
|
||||
@Required
|
||||
public void setMetadataFields(List<DiscoveryHitHighlightFieldConfiguration> metadataFields)
|
||||
{
|
||||
this.metadataFields = metadataFields;
|
||||
}
|
||||
|
||||
public List<DiscoveryHitHighlightFieldConfiguration> getMetadataFields()
|
||||
{
|
||||
return metadataFields;
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class that contains the more like this configuration on item pages
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
*/
|
||||
public class DiscoveryMoreLikeThisConfiguration {
|
||||
private List<String> similarityMetadataFields;
|
||||
private int minTermFrequency;
|
||||
private int max;
|
||||
private int minWordLength;
|
||||
|
||||
@Required
|
||||
public void setSimilarityMetadataFields(List<String> similarityMetadataFields)
|
||||
{
|
||||
this.similarityMetadataFields = similarityMetadataFields;
|
||||
}
|
||||
|
||||
public List<String> getSimilarityMetadataFields()
|
||||
{
|
||||
return similarityMetadataFields;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setMinTermFrequency(int minTermFrequency)
|
||||
{
|
||||
this.minTermFrequency = minTermFrequency;
|
||||
}
|
||||
|
||||
public int getMinTermFrequency()
|
||||
{
|
||||
return minTermFrequency;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setMax(int max)
|
||||
{
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public int getMax()
|
||||
{
|
||||
return max;
|
||||
}
|
||||
|
||||
public int getMinWordLength()
|
||||
{
|
||||
return minWordLength;
|
||||
}
|
||||
|
||||
public void setMinWordLength(int minWordLength)
|
||||
{
|
||||
this.minWordLength = minWordLength;
|
||||
}
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
/**
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
*/
|
||||
public class DiscoveryRecentSubmissionsConfiguration {
|
||||
|
||||
private String metadataSortField;
|
||||
private String type;
|
||||
|
||||
private int max = 5;
|
||||
|
||||
public String getMetadataSortField() {
|
||||
return metadataSortField;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setMetadataSortField(String metadataSortField) {
|
||||
this.metadataSortField = metadataSortField;
|
||||
}
|
||||
|
||||
public int getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setMax(int max) {
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
*/
|
||||
public class DiscoverySearchFilter {
|
||||
|
||||
protected String indexFieldName;
|
||||
protected List<String> metadataFields;
|
||||
protected String type = DiscoveryConfigurationParameters.TYPE_TEXT;
|
||||
public static final String FILTER_TYPE_DEFAULT = "default";
|
||||
|
||||
public String getIndexFieldName() {
|
||||
return indexFieldName;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setIndexFieldName(String indexFieldName) {
|
||||
this.indexFieldName = indexFieldName;
|
||||
}
|
||||
|
||||
public List<String> getMetadataFields() {
|
||||
return metadataFields;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setMetadataFields(List<String> metadataFields) {
|
||||
this.metadataFields = metadataFields;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) throws DiscoveryConfigurationException {
|
||||
if(type.equalsIgnoreCase(DiscoveryConfigurationParameters.TYPE_TEXT))
|
||||
{
|
||||
this.type = DiscoveryConfigurationParameters.TYPE_TEXT;
|
||||
} else
|
||||
if(type.equalsIgnoreCase(DiscoveryConfigurationParameters.TYPE_DATE))
|
||||
{
|
||||
this.type = DiscoveryConfigurationParameters.TYPE_DATE;
|
||||
} else
|
||||
if(type.equalsIgnoreCase(DiscoveryConfigurationParameters.TYPE_HIERARCHICAL))
|
||||
{
|
||||
throw new DiscoveryConfigurationException("The " + type + " can't be used with a default side bar facet use the \"HierarchicalSidebarFacetConfiguration\" class instead.");
|
||||
}else{
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
public String getFilterType(){
|
||||
return FILTER_TYPE_DEFAULT;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
/**
|
||||
* An expanded class that allows a search filter to be used as a sidebar facet
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
*/
|
||||
public class DiscoverySearchFilterFacet extends DiscoverySearchFilter {
|
||||
|
||||
private static final int DEFAULT_FACET_LIMIT = 10;
|
||||
private int facetLimit = -1;
|
||||
private DiscoveryConfigurationParameters.SORT sortOrder = DiscoveryConfigurationParameters.SORT.COUNT;
|
||||
public static final String FILTER_TYPE_FACET = "facet";
|
||||
|
||||
|
||||
public int getFacetLimit()
|
||||
{
|
||||
if(facetLimit == -1){
|
||||
return DEFAULT_FACET_LIMIT;
|
||||
}else{
|
||||
return facetLimit;
|
||||
}
|
||||
}
|
||||
|
||||
public void setFacetLimit(int facetLimit)
|
||||
{
|
||||
this.facetLimit = facetLimit;
|
||||
}
|
||||
|
||||
public DiscoveryConfigurationParameters.SORT getSortOrder()
|
||||
{
|
||||
return sortOrder;
|
||||
}
|
||||
|
||||
public void setSortOrder(DiscoveryConfigurationParameters.SORT sortOrder)
|
||||
{
|
||||
this.sortOrder = sortOrder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilterType()
|
||||
{
|
||||
return FILTER_TYPE_FACET;
|
||||
}
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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/
|
||||
*/
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
*/
|
||||
public class DiscoverySortConfiguration {
|
||||
|
||||
/** Attributes used for sorting of results **/
|
||||
public enum SORT_ORDER {
|
||||
desc,
|
||||
asc
|
||||
}
|
||||
|
||||
private DiscoverySortFieldConfiguration defaultSort = null;
|
||||
|
||||
private List<DiscoverySortFieldConfiguration> sortFields = new ArrayList<DiscoverySortFieldConfiguration>();
|
||||
|
||||
private SORT_ORDER defaultSortOrder = SORT_ORDER.desc;
|
||||
|
||||
public DiscoverySortFieldConfiguration getDefaultSort() {
|
||||
return defaultSort;
|
||||
}
|
||||
|
||||
public void setDefaultSort(DiscoverySortFieldConfiguration defaultSort) {
|
||||
this.defaultSort = defaultSort;
|
||||
}
|
||||
|
||||
public List<DiscoverySortFieldConfiguration> getSortFields() {
|
||||
return sortFields;
|
||||
}
|
||||
|
||||
public void setSortFields(List<DiscoverySortFieldConfiguration> sortFields) {
|
||||
this.sortFields = sortFields;
|
||||
}
|
||||
|
||||
public SORT_ORDER getDefaultSortOrder() {
|
||||
return defaultSortOrder;
|
||||
}
|
||||
|
||||
public void setDefaultSortOrder(SORT_ORDER defaultSortOrder) {
|
||||
this.defaultSortOrder = defaultSortOrder;
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: Kevin
|
||||
* Date: 28/08/11
|
||||
* Time: 14:11
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
public class DiscoverySortFieldConfiguration {
|
||||
|
||||
private String metadataField;
|
||||
private String type = DiscoveryConfigurationParameters.TYPE_TEXT;
|
||||
|
||||
public String getMetadataField() {
|
||||
return metadataField;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setMetadataField(String metadataField) {
|
||||
this.metadataField = metadataField;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(obj != null && obj instanceof DiscoverySortFieldConfiguration){
|
||||
DiscoverySortFieldConfiguration compareConfig = (DiscoverySortFieldConfiguration) obj;
|
||||
if(compareConfig.getMetadataField().equals(getMetadataField()) && compareConfig.getType().equals(getType())){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
import org.dspace.kernel.config.SpringLoader;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
/**
|
||||
* User: kevin (kevin at atmire.com)
|
||||
* Date: 3-aug-2011
|
||||
* Time: 11:39:37
|
||||
*/
|
||||
public class DiscoverySpringLoader implements SpringLoader {
|
||||
|
||||
@Override
|
||||
public String[] getResourcePaths(ConfigurationService configurationService) {
|
||||
StringBuffer filePath = new StringBuffer();
|
||||
filePath.append(configurationService.getProperty("dspace.dir"));
|
||||
filePath.append(File.separator);
|
||||
filePath.append("config");
|
||||
filePath.append(File.separator);
|
||||
filePath.append("spring");
|
||||
filePath.append(File.separator);
|
||||
filePath.append("discovery");
|
||||
filePath.append(File.separator);
|
||||
|
||||
try {
|
||||
return new String[]{new File(filePath.toString()).toURI().toURL().toString() + XML_SUFFIX};
|
||||
} catch (MalformedURLException e) {
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
/**
|
||||
* Special sidebar facet configuration used for hierarchical facets
|
||||
*
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Ben Bosman (ben at atmire dot com)
|
||||
* @author Mark Diggory (markd at atmire dot com)
|
||||
*/
|
||||
public class HierarchicalSidebarFacetConfiguration extends DiscoverySearchFilterFacet{
|
||||
|
||||
private String splitter;
|
||||
private boolean skipFirstNodeLevel = true;
|
||||
|
||||
|
||||
public HierarchicalSidebarFacetConfiguration() {
|
||||
//Our default type is the hieracrhical, can be overridden by the configuration
|
||||
this.type = DiscoveryConfigurationParameters.TYPE_HIERARCHICAL;
|
||||
}
|
||||
|
||||
public String getSplitter() {
|
||||
return splitter;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setSplitter(String splitter) {
|
||||
this.splitter = splitter;
|
||||
}
|
||||
|
||||
public boolean isSkipFirstNodeLevel() {
|
||||
return skipFirstNodeLevel;
|
||||
}
|
||||
|
||||
public void setSkipFirstNodeLevel(boolean skipFirstNodeLevel) {
|
||||
this.skipFirstNodeLevel = skipFirstNodeLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setType(String type) throws DiscoveryConfigurationException {
|
||||
if(type.equalsIgnoreCase(DiscoveryConfigurationParameters.TYPE_HIERARCHICAL)){
|
||||
this.type = type;
|
||||
}else{
|
||||
throw new DiscoveryConfigurationException("The " + type + " can't be used with a hierarchical facet side bar facet use the \"DiscoverySearchFilterFacet\" class instead.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.discovery.configuration;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
*/
|
||||
public class SidebarFacetConfiguration {
|
||||
|
||||
//Let the configuration manager retrieve this !
|
||||
private static final int DEFAULT_FACET_LIMIT = 10;
|
||||
private String indexFieldName;
|
||||
private List<String> metadataFields;
|
||||
private int facetLimit = -1;
|
||||
private DiscoveryConfigurationParameters.SORT sortOrder = DiscoveryConfigurationParameters.SORT.COUNT;
|
||||
private String type = DiscoveryConfigurationParameters.TYPE_TEXT;
|
||||
|
||||
public String getIndexFieldName() {
|
||||
return indexFieldName;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setIndexFieldName(String indexFieldName) {
|
||||
this.indexFieldName = indexFieldName;
|
||||
}
|
||||
|
||||
public List<String> getMetadataFields() {
|
||||
return metadataFields;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setMetadataFields(List<String> metadataFields) {
|
||||
this.metadataFields = metadataFields;
|
||||
}
|
||||
|
||||
public int getFacetLimit() {
|
||||
if(facetLimit == -1){
|
||||
return DEFAULT_FACET_LIMIT;
|
||||
}else{
|
||||
return facetLimit;
|
||||
}
|
||||
}
|
||||
|
||||
public void setFacetLimit(int facetLimit) {
|
||||
this.facetLimit = facetLimit;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
if(type.equalsIgnoreCase(DiscoveryConfigurationParameters.TYPE_TEXT)){
|
||||
this.type = DiscoveryConfigurationParameters.TYPE_TEXT;
|
||||
} else
|
||||
if(type.equalsIgnoreCase(DiscoveryConfigurationParameters.TYPE_DATE)){
|
||||
this.type = DiscoveryConfigurationParameters.TYPE_DATE;
|
||||
}else{
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
public DiscoveryConfigurationParameters.SORT getSortOrder() {
|
||||
return sortOrder;
|
||||
}
|
||||
|
||||
public void setSortOrder(DiscoveryConfigurationParameters.SORT sortOrder) {
|
||||
this.sortOrder = sortOrder;
|
||||
}
|
||||
}
|
@@ -0,0 +1,182 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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/
|
||||
|
||||
-->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
|
||||
default-autowire-candidates="*Service,*DAO,javax.sql.DataSource">
|
||||
|
||||
<context:annotation-config /> <!-- allows us to use spring annotations in beans -->
|
||||
|
||||
<!--Bean that is used for mapping communities/collections to certain discovery configurations.-->
|
||||
<bean id="org.dspace.discovery.configuration.DiscoveryConfigurationService" class="org.dspace.discovery.configuration.DiscoveryConfigurationService">
|
||||
<property name="map">
|
||||
<map>
|
||||
<!--The map containing all the settings,
|
||||
the key is used to refer to the page (the "site" or a community/collection handle)
|
||||
the value-ref is a reference to an identifier of the DiscoveryConfiguration format
|
||||
-->
|
||||
<!--The default entry, DO NOT REMOVE the system requires this-->
|
||||
<entry key="default" value-ref="defaultConfiguration" />
|
||||
|
||||
<!--Use site to override the default configuration for the home page & default discovery page-->
|
||||
<!--<entry key="site" value-ref="defaultConfiguration" />-->
|
||||
<!--<entry key="123456789/7621" value-ref="defaultConfiguration"/>-->
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!--The default configuration settings for discovery-->
|
||||
<bean id="defaultConfiguration" class="org.dspace.discovery.configuration.DiscoveryConfiguration" scope="prototype">
|
||||
<!--Which sidebar facets are to be displayed-->
|
||||
<property name="sidebarFacets">
|
||||
<list>
|
||||
<ref bean="sidebarFacetAuthor" />
|
||||
<ref bean="sidebarFacetSubject" />
|
||||
<ref bean="sidebarFacetDateIssued" />
|
||||
</list>
|
||||
</property>
|
||||
<!--The search filters which can be used on the discovery search page-->
|
||||
<property name="searchFilters">
|
||||
<list>
|
||||
<ref bean="searchFilterTitle" />
|
||||
<ref bean="searchFilterAuthor" />
|
||||
<ref bean="searchFilterSubject" />
|
||||
<ref bean="searchFilterIssued" />
|
||||
</list>
|
||||
</property>
|
||||
<!--The sort filters for the discovery search-->
|
||||
<property name="searchSortConfiguration">
|
||||
<bean class="org.dspace.discovery.configuration.DiscoverySortConfiguration">
|
||||
<!--<property name="defaultSort" ref="sortDateIssued"/>-->
|
||||
<!--DefaultSortOrder can either be desc or asc (desc is default)-->
|
||||
<property name="defaultSortOrder" value="desc"/>
|
||||
<property name="sortFields">
|
||||
<list>
|
||||
<ref bean="sortTitle" />
|
||||
<ref bean="sortDateIssued" />
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
<!--Any default filter queries, these filter queries will be used for all queries done by discovery for this configuration-->
|
||||
<!--<property name="defaultFilterQueries">-->
|
||||
<!--<list>-->
|
||||
<!--Only find items-->
|
||||
<!--<value>search.resourcetype:2</value>-->
|
||||
<!--</list>-->
|
||||
<!--</property>-->
|
||||
<!--The configuration for the recent submissions-->
|
||||
<property name="recentSubmissionConfiguration">
|
||||
<bean class="org.dspace.discovery.configuration.DiscoveryRecentSubmissionsConfiguration">
|
||||
<property name="metadataSortField" value="dc.date.accessioned" />
|
||||
<property name="type" value="date"/>
|
||||
<property name="max" value="5"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
|
||||
|
||||
<!--Search filter configuration beans-->
|
||||
<bean id="searchFilterTitle" class="org.dspace.discovery.configuration.DiscoverySearchFilter">
|
||||
<property name="indexFieldName" value="title"/>
|
||||
<property name="metadataFields">
|
||||
<list>
|
||||
<value>dc.title</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="fullAutoComplete" value="false"/>
|
||||
</bean>
|
||||
|
||||
<bean id="searchFilterAuthor" class="org.dspace.discovery.configuration.DiscoverySearchFilter">
|
||||
<property name="indexFieldName" value="author"/>
|
||||
<property name="metadataFields">
|
||||
<list>
|
||||
<value>dc.contributor.author</value>
|
||||
<value>dc.creator</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="fullAutoComplete" value="true"/>
|
||||
</bean>
|
||||
|
||||
<bean id="searchFilterSubject" class="org.dspace.discovery.configuration.DiscoverySearchFilter">
|
||||
<property name="indexFieldName" value="subject"/>
|
||||
<property name="metadataFields">
|
||||
<list>
|
||||
<value>dc.subject.*</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="fullAutoComplete" value="true"/>
|
||||
</bean>
|
||||
|
||||
<bean id="searchFilterIssued" class="org.dspace.discovery.configuration.DiscoverySearchFilter">
|
||||
<property name="indexFieldName" value="dateIssued"/>
|
||||
<property name="metadataFields">
|
||||
<list>
|
||||
<value>dc.date.issued</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="type" value="date"/>
|
||||
<property name="fullAutoComplete" value="false"/>
|
||||
</bean>
|
||||
|
||||
|
||||
|
||||
<!--Sidebar facet configuration beans-->
|
||||
<bean id="sidebarFacetAuthor" class="org.dspace.discovery.configuration.SidebarFacetConfiguration">
|
||||
<property name="indexFieldName" value="author"/>
|
||||
<property name="metadataFields">
|
||||
<list>
|
||||
<value>dc.contributor.author</value>
|
||||
<value>dc.creator</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="facetLimit" value="10"/>
|
||||
<property name="sortOrder" value="COUNT"/>
|
||||
</bean>
|
||||
|
||||
<bean id="sidebarFacetSubject" class="org.dspace.discovery.configuration.SidebarFacetConfiguration">
|
||||
<property name="indexFieldName" value="subject"/>
|
||||
<property name="metadataFields">
|
||||
<list>
|
||||
<value>dc.subject.*</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="facetLimit" value="10"/>
|
||||
<property name="sortOrder" value="COUNT"/>
|
||||
</bean>
|
||||
|
||||
<bean id="sidebarFacetDateIssued" class="org.dspace.discovery.configuration.SidebarFacetConfiguration">
|
||||
<property name="indexFieldName" value="dateIssued"/>
|
||||
<property name="metadataFields">
|
||||
<list>
|
||||
<value>dc.date.issued</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="type" value="date"/>
|
||||
<property name="sortOrder" value="VALUE"/>
|
||||
</bean>
|
||||
|
||||
|
||||
<!--Sort properties-->
|
||||
<bean id="sortTitle" class="org.dspace.discovery.configuration.DiscoverySortFieldConfiguration">
|
||||
<property name="metadataField" value="dc.title"/>
|
||||
</bean>
|
||||
|
||||
<bean id="sortDateIssued" class="org.dspace.discovery.configuration.DiscoverySortFieldConfiguration">
|
||||
<property name="metadataField" value="dc.date.issued"/>
|
||||
<property name="type" value="date"/>
|
||||
</bean>
|
||||
</beans>
|
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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/
|
||||
|
||||
-->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
|
||||
default-autowire-candidates="*Service,*DAO,javax.sql.DataSource">
|
||||
|
||||
<context:annotation-config /> <!-- allows us to use spring annotations in beans -->
|
||||
<!-- NOTE: I am not convinced this is a good idea, it is really slow and I think possibly dangerous -AZ -->
|
||||
<!--
|
||||
<context:component-scan base-package="org.dspace" name-generator="org.dspace.servicemanager.spring.FullPathBeanNameGenerator" />
|
||||
-->
|
||||
|
||||
|
||||
<bean class="org.dspace.discovery.SolrServiceImpl" id="org.dspace.discovery.SearchService"/>
|
||||
|
||||
<alias name="org.dspace.discovery.SearchService" alias="org.dspace.discovery.IndexingService"/>
|
||||
|
||||
<!--<bean class="org.dspace.discovery.SolrServiceIndexOutputPlugin" id="solrServiceIndexOutputPlugin"/>-->
|
||||
</beans>
|
Reference in New Issue
Block a user