/**
* 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.HashSet;
import org.apache.solr.common.SolrInputDocument;
import org.dspace.content.MetadataValue;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.service.ItemService;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.dspace.browse.BrowseException;
import org.dspace.browse.BrowseIndex;
import org.dspace.content.authority.service.ChoiceAuthorityService;
import org.dspace.content.authority.service.MetadataAuthorityService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.sort.OrderFormat;
import org.dspace.sort.SortException;
import org.dspace.sort.SortOption;
/**
* A Solr Indexing plugin for the "metadata" browse index type.
* <p>
* For Example:
* webui.browse.index.2 = author:metadata:dc.contributor.*\,dc.creator:text
* OR
* webui.browse.index.4 = subject:metadata:dc.subject.*:text
* <p>
* This plugin was based heavily on the old (DSpace 5.x or below), SolrBrowseCreateDAO
* class, specifically its "additionalIndex()" method, which used to perform this function.
*
* @author Tim Donohue
*/
public class SolrServiceMetadataBrowseIndexingPlugin implements SolrServiceIndexPlugin {
private static final Logger log = Logger
.getLogger(SolrServiceMetadataBrowseIndexingPlugin.class);
@Autowired(required = true)
protected ItemService itemService;
@Autowired(required = true)
protected MetadataAuthorityService metadataAuthorityService;
@Autowired(required = true)
protected ChoiceAuthorityService choiceAuthorityService;
@Override
public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument document)
{
// Only works for Items
if (!(dso instanceof Item))
{
return;
}
Item item = (Item) dso;
// Get the currently configured browse indexes
BrowseIndex[] bis;
try
{
bis = BrowseIndex.getBrowseIndices();
}
catch (BrowseException e)
{
log.error(e.getMessage(), e);
throw new IllegalStateException(e);
}
// Faceting for metadata browsing. It is different than search facet
// because if there are authority with variants support we want 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());
// ONLY perform indexing for "metadata" type indices
if (bi.isMetadataIndex())
{
// Generate our bits of metadata (so getMdBits() can be used below)
bi.generateMdBits();
// 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 or
// 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);
List<MetadataValue> values = itemService.getMetadata(item, md[0], md[1],
md[2], Item.ANY);
// if we have values to index on, then do so
if (values != null && values.size() > 0)
{
int minConfidence = metadataAuthorityService.getMinConfidence(values.get(0).getMetadataField());
boolean ignoreAuthority = DSpaceServicesFactory.getInstance().getConfigurationService()
.getPropertyAsType(
"discovery.browse.authority.ignore."
+ bi.getName(),
DSpaceServicesFactory.getInstance().getConfigurationService()
.getPropertyAsType(
"discovery.browse.authority.ignore",
new Boolean(false)),
true);
for (int x = 0; x < values.size(); x++)
{
// Ensure that there is a value to index before
// inserting it
if (StringUtils.isEmpty(values.get(x).getValue()))
{
log.error("Null metadata value for item "
+ item.getID()
+ ", field: "
+ values.get(x).getMetadataField().toString()
);
}
else
{
if (bi.isAuthorityIndex()
&& (values.get(x).getAuthority() == null || values.get(x).getConfidence() < minConfidence))
{
// if we have an authority index only
// authored metadata will go here!
log.debug("Skipping item="
+ item.getID() + ", field="
+ values.get(x).getMetadataField().toString()
+ ", value=" + values.get(x).getValue()
+ ", authority="
+ values.get(x).getAuthority()
+ ", confidence="
+ values.get(x).getConfidence()
+ " (BAD AUTHORITY)");
continue;
}
// is there any valid (with appropriate
// confidence) authority key?
if ((ignoreAuthority && !bi.isAuthorityIndex())
|| (values.get(x).getAuthority() != null && values.get(x).getConfidence() >= minConfidence))
{
distFAuths.add(values.get(x).getAuthority());
distValuesForAC.add(values.get(x).getValue());
String preferedLabel = null;
boolean ignorePrefered = DSpaceServicesFactory.getInstance().getConfigurationService()
.getPropertyAsType(
"discovery.browse.authority.ignore-prefered."
+ bi.getName(),
DSpaceServicesFactory.getInstance().getConfigurationService()
.getPropertyAsType(
"discovery.browse.authority.ignore-prefered",
new Boolean(
false)),
true);
if (!ignorePrefered)
{
preferedLabel = choiceAuthorityService
.getLabel(values.get(x), values.get(x).getLanguage());
}
List<String> variants = null;
boolean ignoreVariants = DSpaceServicesFactory.getInstance().getConfigurationService()
.getPropertyAsType(
"discovery.browse.authority.ignore-variants."
+ bi.getName(),
DSpaceServicesFactory.getInstance().getConfigurationService()
.getPropertyAsType(
"discovery.browse.authority.ignore-variants",
new Boolean(
false)),
true);
if (!ignoreVariants)
{
variants = choiceAuthorityService
.getVariants(
values.get(x));
}
if (StringUtils
.isNotBlank(preferedLabel))
{
String nLabel = OrderFormat
.makeSortString(
preferedLabel,
values.get(x).getLanguage(),
bi.getDataType());
distFValues
.add(nLabel
+ SolrServiceImpl.FILTER_SEPARATOR
+ preferedLabel
+ SolrServiceImpl.AUTHORITY_SEPARATOR
+ values.get(x).getAuthority());
distValuesForAC.add(preferedLabel);
}
if (variants != null)
{
for (String var : variants)
{
String nVal = OrderFormat
.makeSortString(
var,
values.get(x).getLanguage(),
bi.getDataType());
distFValues
.add(nVal
+ SolrServiceImpl.FILTER_SEPARATOR
+ var
+ SolrServiceImpl.AUTHORITY_SEPARATOR
+ values.get(x).getAuthority());
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.get(x).getValue(),
values.get(x).getLanguage(),
bi.getDataType());
distFValues
.add(nVal
+ SolrServiceImpl.FILTER_SEPARATOR
+ values.get(x).getValue());
distFVal.add(values.get(x).getValue());
distValuesForAC.add(values.get(x).getValue());
}
}
}
}
}
}
for (String facet : distFValues)
{
document.addField(bi.getDistinctTableName() + "_filter", facet);
}
for (String facet : distFAuths)
{
document.addField(bi.getDistinctTableName()
+ "_authority_filter", facet);
}
for (String facet : distValuesForAC)
{
document.addField(bi.getDistinctTableName() + "_partial", facet);
}
for (String facet : distFVal)
{
document.addField(bi.getDistinctTableName()+"_value_filter", facet);
}
}
}
// Add sorting options as configurated for the browse system
try
{
for (SortOption so : SortOption.getSortOptions())
{
List<MetadataValue> dcvalue = itemService.getMetadataByMetadataString(item, so.getMetadata());
if (dcvalue != null && dcvalue.size() > 0)
{
String nValue = OrderFormat
.makeSortString(dcvalue.get(0).getValue(),
dcvalue.get(0).getLanguage(), so.getType());
document.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);
}
}
}