Merge pull request #334 from helix84/DS-1409-ItemCountDAOSolr

DS-1409 add ItemCountDAOSolr, make it default
This commit is contained in:
Andrea Bollini
2013-10-20 10:43:51 -07:00
9 changed files with 308 additions and 86 deletions

View File

@@ -15,36 +15,46 @@ import org.dspace.core.ConfigurationManager;
* item count information
*
* @author Richard Jones
* @author Ivan Masár
*
*/
public class ItemCountDAOFactory
{
/**
* Get an instance of ItemCountDAO which supports the correct database
* for the specific DSpace instance.
*
* @param context
* @throws ItemCountException
*/
public static ItemCountDAO getInstance(Context context)
throws ItemCountException
{
String db = ConfigurationManager.getProperty("db.name");
ItemCountDAO dao;
if ("postgres".equals(db))
{
dao = new ItemCountDAOPostgres();
}
else if ("oracle".equals(db))
{
dao = new ItemCountDAOOracle();
}
else
{
throw new ItemCountException("Database type: " + db + " is not currently supported");
}
dao.setContext(context);
return dao;
}
/**
* Get an instance of ItemCountDAO which supports the correct storage backend
* for the specific DSpace instance.
*
* @param context
* @throws ItemCountException
*/
public static ItemCountDAO getInstance(Context context)
throws ItemCountException
{
/** Log4j logger */
ItemCountDAO dao = null;
String className = ConfigurationManager.getProperty("ItemCountDAO.class");
// SOLR implementation is the default since DSpace 4.0
if (className == null)
{
dao = new ItemCountDAOSolr();
}
else
{
try
{
dao = (ItemCountDAO) Class
.forName(className.trim()).newInstance();
}
catch (Exception e)
{
throw new ItemCountException("The configuration for ItemCountDAO is invalid: " + className, e);
}
}
dao.setContext(context);
return dao;
}
}

View File

@@ -0,0 +1,189 @@
/**
* 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.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.DSpaceObject;
import org.dspace.core.Context;
import org.dspace.discovery.DiscoverFacetField;
import org.dspace.discovery.DiscoverQuery;
import org.dspace.discovery.DiscoverResult;
import org.dspace.discovery.DiscoverResult.FacetResult;
import org.dspace.discovery.SearchService;
import org.dspace.discovery.SearchServiceException;
import org.dspace.discovery.configuration.DiscoveryConfigurationParameters;
import org.dspace.utils.DSpace;
/**
* Discovery (Solr) driver implementing ItemCountDAO interface to look up item
* count information in communities and collections. Caching operations are
* intentionally not implemented because Solr already is our cache.
*
* @author Ivan Masár, Andrea Bollini
*
*/
public class ItemCountDAOSolr implements ItemCountDAO
{
/** Log4j logger */
private static Logger log = Logger.getLogger(ItemCountDAOSolr.class);
/** DSpace context */
private Context context;
/**
* Hold the communities item count obtained from SOLR after the first query. This only works
* well if the ItemCountDAO lifecycle is bound to the request lifecycle as
* it is now. If we switch to a Spring-based instantiation we should mark
* this bean as prototype
**/
private Map<String, Integer> communitiesCount = null;
/** Hold the collection item count obtained from SOLR after the first query **/
private Map<String, Integer> collectionsCount = null;
/** DSpace helper services access object */
DSpace dspace = new DSpace();
/** Solr search service */
SearchService searcher = dspace.getServiceManager().getServiceByName(SearchService.class.getName(), SearchService.class);
/**
* Throw an ItemCountException as caching is not supported by ItemCountDAOSolr.
*
* @param collection
* @param count
* @throws ItemCountException
*/
public void collectionCount(Collection collection, int count) throws ItemCountException
{
throw new ItemCountException("Caching is not supported by the ItemCountDAOSolr as it is not really needed, Solr is faster!");
}
/**
* Throw an ItemCountException as caching is not supported by ItemCountDAOSolr.
*
* @param community
* @param count
* @throws ItemCountException
*/
public void communityCount(Community community, int count) throws ItemCountException
{
throw new ItemCountException("Caching is not supported by the ItemCountDAOSolr as it is not really needed, Solr is faster!");
}
/**
* Set the dspace context to use
*
* @param context
* @throws ItemCountException
*/
public void setContext(Context context) throws ItemCountException
{
this.context = context;
}
/**
* Get the count of the items in the given container.
*
* @param dso
* @throws ItemCountException
*/
public int getCount(DSpaceObject dso) throws ItemCountException
{
loadCount();
DiscoverQuery query = new DiscoverQuery();
Integer val = null;
if (dso instanceof Collection)
{
val = collectionsCount.get(String.valueOf(((Collection) dso).getID()));
}
else if (dso instanceof Community)
{
val = communitiesCount.get(String.valueOf(((Community) dso).getID()));
}
else
{
throw new ItemCountException("We can only count items in Communities or Collections");
}
if (val != null)
{
return val.intValue();
}
else
{
return 0;
}
}
/**
* remove the cache for the given container (does nothing in the Solr backend)
*
* @param dso
* @throws ItemCountException
*/
public void remove(DSpaceObject dso) throws ItemCountException
{
}
/**
* make sure that the counts are actually fetched from Solr (if haven't been
* cached in a Map yet)
*
* @throws ItemCountException
*/
private void loadCount() throws ItemCountException
{
if (communitiesCount != null || collectionsCount != null)
{
return;
}
communitiesCount = new HashMap<String, Integer>();
collectionsCount = new HashMap<String, Integer>();
DiscoverQuery query = new DiscoverQuery();
query.setFacetMinCount(1);
query.addFacetField(new DiscoverFacetField("location.comm",
DiscoveryConfigurationParameters.TYPE_STANDARD, -1,
DiscoveryConfigurationParameters.SORT.COUNT));
query.addFacetField(new DiscoverFacetField("location.coll",
DiscoveryConfigurationParameters.TYPE_STANDARD, -1,
DiscoveryConfigurationParameters.SORT.COUNT));
query.addFilterQueries("search.resourcetype:2"); // count only items
query.addFilterQueries("NOT(discoverable:false)"); // only discoverable
query.setMaxResults(0);
DiscoverResult sResponse = null;
try
{
sResponse = searcher.search(context, query, false);
List<FacetResult> commCount = sResponse.getFacetResult("location.comm");
List<FacetResult> collCount = sResponse.getFacetResult("location.coll");
for (FacetResult c : commCount)
{
communitiesCount.put(c.getAsFilterQuery(),(int) c.getCount());
}
for (FacetResult c : collCount)
{
collectionsCount.put(c.getAsFilterQuery(),(int) c.getCount());
}
}
catch (SearchServiceException e)
{
log.error("caught exception: ", e);
throw new ItemCountException(e);
}
}
}

View File

@@ -110,7 +110,8 @@ public class ItemCounter
public int getCount(DSpaceObject dso)
throws ItemCountException
{
boolean useCache = ConfigurationManager.getBooleanProperty("webui.strengths.cache");
boolean useCache = ConfigurationManager.getBooleanProperty(
"webui.strengths.cache", true);
if (useCache)
{

View File

@@ -2178,7 +2178,11 @@ public class SolrServiceImpl implements SearchService, IndexingService {
}
protected String transformAuthorityValue(Context context, String field, String value) throws SQLException {
if (field.endsWith("_filter") || field.endsWith("_ac")
if(field.equals("location.comm") || field.equals("location.coll"))
{
return value;
}
if (field.endsWith("_filter") || field.endsWith("_ac")
|| field.endsWith("_acid"))
{
//We have a filter make sure we split !

View File

@@ -50,10 +50,9 @@
%>
<%!
void showCommunity(Community c, JspWriter out, HttpServletRequest request,
void showCommunity(Community c, JspWriter out, HttpServletRequest request, ItemCounter ic,
Map collectionMap, Map subcommunityMap) throws ItemCountException, IOException, SQLException
{
ItemCounter ic = new ItemCounter(UIUtil.obtainContext(request));
out.println( "<li class=\"media well\">" );
Bitstream logo = c.getLogo();
if (logo != null)
@@ -113,7 +112,7 @@
out.println("<ul class=\"media-list\">");
for (int k = 0; k < comms.length; k++)
{
showCommunity(comms[k], out, request, collectionMap, subcommunityMap);
showCommunity(comms[k], out, request, ic, collectionMap, subcommunityMap);
}
out.println("</ul>");
}
@@ -156,7 +155,7 @@
<%
for (int i = 0; i < communities.length; i++)
{
showCommunity(communities[i], out, request, collectionMap, subcommunityMap);
showCommunity(communities[i], out, request, ic, collectionMap, subcommunityMap);
}
%>
</ul>

View File

@@ -139,8 +139,8 @@ public class CommunityBrowser extends AbstractDSpaceTransformer implements Cache
validity.add(node.getDSO());
// If we are configured to use collection strengths (i.e. item counts) then include that number in the validity.
boolean useCache = ConfigurationManager.getBooleanProperty("webui.strengths.cache");
if (useCache)
boolean showCount = ConfigurationManager.getBooleanProperty("webui.strengths.show");
if (showCount)
{
try
{ //try to determine Collection size (i.e. # of items)

View File

@@ -123,9 +123,9 @@ public class CommunityViewer extends AbstractDSpaceTransformer implements Cachea
{
validity.add(subCommunity);
// Include the item count in the validity, only if the value is cached.
boolean useCache = ConfigurationManager.getBooleanProperty("webui.strengths.cache");
if (useCache)
// Include the item count in the validity, only if the value is shown.
boolean showCount = ConfigurationManager.getBooleanProperty("webui.strengths.show");
if (showCount)
{
try {
int size = new ItemCounter(context).getCount(subCommunity);
@@ -138,9 +138,9 @@ public class CommunityViewer extends AbstractDSpaceTransformer implements Cachea
{
validity.add(collection);
// Include the item count in the validity, only if the value is cached.
boolean useCache = ConfigurationManager.getBooleanProperty("webui.strengths.cache");
if (useCache)
// Include the item count in the validity, only if the value is shown.
boolean showCount = ConfigurationManager.getBooleanProperty("webui.strengths.show");
if (showCount)
{
try {
int size = new ItemCounter(context).getCount(collection);

View File

@@ -273,21 +273,20 @@ public class ContainerAdapter extends AbstractAdapter
createField("dc","rights","license",null,rights_license);
createField("dc","title",null,null,title);
boolean useCache = ConfigurationManager.getBooleanProperty("webui.strengths.cache");
boolean showCount = ConfigurationManager.getBooleanProperty("webui.strengths.show");
//To improve scalability, XMLUI only adds item counts if they are cached
if (useCache)
{
try
{ //try to determine Collection size (i.e. # of items)
int size = new ItemCounter(this.dspaceContext).getCount(collection);
createField("dc","format","extent",null, String.valueOf(size));
}
catch(ItemCountException e)
{
throw new IOException("Could not obtain Collection item-count", e);
}
}
if (showCount)
{
try
{ // try to determine Collection size (i.e. # of items)
int size = new ItemCounter(this.dspaceContext).getCount(collection);
createField("dc","format","extent",null, String.valueOf(size));
}
catch (ItemCountException e)
{
throw new IOException("Could not obtain Collection item count", e);
}
}
}
else if (dso.getType() == Constants.COMMUNITY)
{
@@ -307,26 +306,25 @@ public class ContainerAdapter extends AbstractAdapter
createField("dc","rights",null,null,rights);
createField("dc","title",null,null,title);
boolean useCache = ConfigurationManager.getBooleanProperty("webui.strengths.cache");
boolean showCount = ConfigurationManager.getBooleanProperty("webui.strengths.show");
//To improve scalability, XMLUI only adds item counts if they are cached
if (useCache)
{
try
{ //try to determine Community size (i.e. # of items)
int size = new ItemCounter(this.dspaceContext).getCount(community);
createField("dc","format","extent",null, String.valueOf(size));
}
catch(ItemCountException e)
{
throw new IOException("Could not obtain Collection item-count", e);
}
}
if (showCount)
{
try
{ // try to determine Community size (i.e. # of items)
int size = new ItemCounter(this.dspaceContext).getCount(community);
createField("dc","format","extent",null, String.valueOf(size));
}
catch (ItemCountException e)
{
throw new IOException("Could not obtain Collection item count", e);
}
}
}
// ///////////////////////////////
// End the DIM element
endElement(DIM,"dim");
// End the DIM element
endElement(DIM,"dim");
// ////////////////////////////////
// End elements

View File

@@ -928,34 +928,55 @@ webui.preview.brand.fontpoint = 12
#webui.preview.dc = rights
##### Settings for content count/strength information ####
##### Settings for item count (strength) information ####
# whether to display collection and community strengths
# (This configuration is not used by XMLUI. To show strengths in the
# XMLUI, you just need to create a theme which displays them)
# (Since DSpace 4.0, this config option is used by XMLUI, too.
# XMLUI only makes strengths available to themes if this is set to true!
# To show strengths in the XMLUI, you also need to create a theme which displays them)
webui.strengths.show = false
# if showing the strengths, should they be counted in real time or
# fetched from cache? NOTE: To improve scaling/performance,
# the XMLUI only makes strengths available to themes if they are CACHED!
# if showing strengths, should they be counted in real time or
# fetched from cache?
#
# Counts fetched in real time will perform an actual count of the
# database contents every time a page with this feature is requested,
# which will not scale. If the below setting is to use the cache, you
# must run the following command periodically to update the count:
# which will not scale. The default behaviour is to use a cache (see
# ItemCounter configuration)
#
# [dspace]/bin/itemcounter
# The default is to use a cache
#
# The default is to count in real time
# webui.strengths.cache = true
###### ItemCounter Configuration ######
#
webui.strengths.cache = false
# Define the DAO class to use. This must correspond to your choice of
# storage for the browse system (RDBMS: PostgreSQL or Oracle, Solr).
# By default, since DSpace 4.0, the Solr implementation is used.
#
# Only if you use a DBMS implementation and want to use the cache
# (recommended!), you must run the following command periodically
# to update the count:
#
# [dspace]/bin/itemcounter (NOT required if you use the Solr implementation)
#
#
# PostgreSQL:
# ItemCountDAO.class = org.dspace.browse.ItemCountDAOPostgres
#
# Oracle:
# ItemCountDAO.class = org.dspace.browse.ItemCountDAOOracle
#
# Solr:
# ItemCountDAO.class = org.dspace.browse.ItemCountDAOSolr
###### Browse Configuration ######
#
# Define the DAO class to use this must meet your storage choice for
# the browse system (RDBMS: PostgreSQL or Oracle, SOLR).
# By default, since DSpace 4.0, the SOLR implementation is used
# the browse system (RDBMS: PostgreSQL or Oracle, Solr).
# By default, since DSpace 4.0, the Solr implementation is used
#
# PostgreSQL:
# browseDAO.class = org.dspace.browse.BrowseDAOPostgres
@@ -965,7 +986,7 @@ webui.strengths.cache = false
# browseDAO.class = org.dspace.browse.BrowseDAOOracle
# browseCreateDAO.class = org.dspace.browse.BrowseCreateDAOOracle
#
# SOLR:
# Solr:
# browseDAO.class = org.dspace.browse.SolrBrowseDAO
# browseCreateDAO.class = org.dspace.browse.SolrBrowseCreateDAO