[DS-1243] @mire solr statistics contribution

This commit is contained in:
KevinVdV
2012-09-25 15:58:23 +02:00
parent ab37bd4a51
commit 808bc6fc5d
52 changed files with 5796 additions and 2994 deletions

View File

@@ -103,7 +103,8 @@ public class DSIndexer
private static int batchFlushAfterDocuments = ConfigurationManager.getIntProperty("search.batch.documents", 20);
private static boolean batchProcessingMode = false;
static final Version luceneVersion = Version.LUCENE_35;
// Class to hold the index configuration (one instance per config line)
private static class IndexConfig
{
@@ -637,7 +638,7 @@ public class DSIndexer
Class analyzerClass = Class.forName(analyzerClassName);
Constructor constructor = analyzerClass.getDeclaredConstructor(Version.class);
constructor.setAccessible(true);
analyzer = (Analyzer) constructor.newInstance(Version.LUCENE_33);
analyzer = (Analyzer) constructor.newInstance(luceneVersion);
}
catch (Exception e)
{
@@ -914,7 +915,7 @@ public class DSIndexer
throws IOException
{
Directory dir = FSDirectory.open(new File(indexDirectory));
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_33, getAnalyzer());
IndexWriterConfig iwc = new IndexWriterConfig(luceneVersion, getAnalyzer());
if(wipeExisting){
iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE);
}else{

View File

@@ -122,7 +122,7 @@ public class DSQuery
// grab a searcher, and do the search
IndexSearcher searcher = getSearcher(c);
QueryParser qp = new QueryParser(Version.LUCENE_33, "default", DSIndexer.getAnalyzer());
QueryParser qp = new QueryParser(DSIndexer.luceneVersion, "default", DSIndexer.getAnalyzer());
log.debug("Final query string: " + querystring);
if (operator == null || operator.equals("OR"))

View File

@@ -28,7 +28,9 @@ public class LoggerUsageEventListener extends AbstractUsageEventListener{
public void receiveEvent(Event event) {
if(event instanceof UsageEvent)
//Search events are already logged
//UsageSearchEvent is already logged in the search classes, no need to repeat this logging
if(event instanceof UsageEvent && !(event instanceof UsageSearchEvent))
{
UsageEvent ue = (UsageEvent)event;

View File

@@ -30,6 +30,7 @@ public class UsageEvent extends Event {
REMOVE ("remove"),
BROWSE ("browse"),
SEARCH ("search"),
WORKFLOW ("workflow"),
LOGIN ("login"),
SUBSCRIBE ("subscribe"),
UNSUBSCRIBE ("unsubscribe"),
@@ -59,12 +60,13 @@ public class UsageEvent extends Event {
private static String checkParams(Action action, HttpServletRequest request, Context context, DSpaceObject object)
{
StringBuilder eventName = new StringBuilder();
if(action == null)
{
throw new IllegalStateException("action cannot be null");
}
if(request == null)
if(action != Action.WORKFLOW && request == null)
{
throw new IllegalStateException("request cannot be null");
}
@@ -75,21 +77,17 @@ public class UsageEvent extends Event {
throw new IllegalStateException("context cannot be null");
}
if(object == null)
if(action != Action.WORKFLOW && action != Action.SEARCH && object == null)
{
throw new IllegalStateException("object cannot be null");
}else
if(object != null){
String objText = Constants.typeText[object.getType()].toLowerCase();
eventName.append(objText).append(":");
}
try
{
String objText = Constants.typeText[object.getType()].toLowerCase();
return objText + ":" + action.text();
}catch(Exception e)
{
eventName.append(action.text());
}
return "";
return eventName.toString();
}
public UsageEvent(Action action, HttpServletRequest request, Context context, DSpaceObject object)

View File

@@ -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.usage;
import org.dspace.content.DSpaceObject;
import org.dspace.core.Context;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* Extends the standard usage event to contain search information
* search information includes the query(s) used & the scope
*
* @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 UsageSearchEvent extends UsageEvent{
private List<String> queries;
private DSpaceObject scope;
/** Optional search parameters **/
private int rpp;
private String sortBy;
private String sortOrder;
private int page;
public UsageSearchEvent(Action action, HttpServletRequest request, Context context, DSpaceObject object, List<String> queries, DSpaceObject scope) {
super(action, request, context, object);
this.queries = queries;
this.scope = scope;
this.rpp = -1;
this.sortBy = null;
this.sortOrder = null;
this.page = -1;
}
public List<String> getQueries() {
return queries;
}
public DSpaceObject getScope() {
return scope;
}
public int getRpp() {
return rpp;
}
public void setRpp(int rpp) {
this.rpp = rpp;
}
public String getSortBy() {
return sortBy;
}
public void setSortBy(String sortBy) {
this.sortBy = sortBy;
}
public String getSortOrder() {
return sortOrder;
}
public void setSortOrder(String sortOrder) {
this.sortOrder = sortOrder;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
}

View File

@@ -0,0 +1,80 @@
/**
* 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.usage;
import org.dspace.content.Collection;
import org.dspace.content.InProgressSubmission;
import org.dspace.content.Item;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
/**
* Extends the standard usage event to contain workflow information
*
*
* @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 UsageWorkflowEvent extends UsageEvent {
private String workflowStep;
private String oldState;
private EPerson[] epersonOwners;
private Group[] groupOwners;
private Collection scope;
private EPerson actor;
private InProgressSubmission workflowItem;
public UsageWorkflowEvent(Context context, Item item, InProgressSubmission workflowItem, String workflowStep, String oldState, Collection scope, EPerson actor) {
super(Action.WORKFLOW, null, context, item);
this.workflowItem = workflowItem;
this.workflowStep = workflowStep;
this.oldState = oldState;
this.scope = scope;
this.actor = actor;
}
public String getWorkflowStep() {
return workflowStep;
}
public String getOldState() {
return oldState;
}
public Collection getScope() {
return scope;
}
public EPerson[] getEpersonOwners() {
return epersonOwners;
}
public void setEpersonOwners(EPerson... epersonOwners) {
this.epersonOwners = epersonOwners;
}
public Group[] getGroupOwners() {
return groupOwners;
}
public void setGroupOwners(Group... newGroupOwner) {
this.groupOwners = newGroupOwner;
}
public EPerson getActor() {
return actor;
}
public InProgressSubmission getWorkflowItem() {
return workflowItem;
}
}

View File

@@ -41,6 +41,8 @@ import org.dspace.handle.HandleManager;
import org.dspace.storage.rdbms.DatabaseManager;
import org.dspace.storage.rdbms.TableRow;
import org.dspace.storage.rdbms.TableRowIterator;
import org.dspace.usage.UsageWorkflowEvent;
import org.dspace.utils.DSpace;
/**
* Workflow state machine
@@ -518,6 +520,9 @@ public class WorkflowManager
Group mygroup = null;
boolean archived = false;
//Gather our old data for launching the workflow event
int oldState = wi.getState();
wi.setState(newstate);
switch (newstate)
@@ -657,6 +662,8 @@ public class WorkflowManager
break;
}
logWorkflowEvent(c, wi.getItem(), wi, c.getCurrentUser(), newstate, newowner, mycollection, oldState, mygroup);
if (!archived)
{
wi.update();
@@ -665,6 +672,22 @@ public class WorkflowManager
return archived;
}
private static void logWorkflowEvent(Context c, Item item, WorkflowItem workflowItem, EPerson actor, int newstate, EPerson newOwner, Collection mycollection, int oldState, Group newOwnerGroup) {
if(newstate == WFSTATE_ARCHIVE || newstate == WFSTATE_STEP1POOL || newstate == WFSTATE_STEP2POOL || newstate == WFSTATE_STEP3POOL){
//Clear the newowner variable since this one isn't owned anymore !
newOwner = null;
}
UsageWorkflowEvent usageWorkflowEvent = new UsageWorkflowEvent(c, item, workflowItem, workflowText[newstate], workflowText[oldState], mycollection, actor);
if(newOwner != null){
usageWorkflowEvent.setEpersonOwners(newOwner);
}
if(newOwnerGroup != null){
usageWorkflowEvent.setGroupOwners(newOwnerGroup);
}
new DSpace().getEventService().fireEvent(usageWorkflowEvent);
}
/**
* Get the text representing the given workflow state
*
@@ -816,6 +839,8 @@ public class WorkflowManager
String rejection_message) throws SQLException, AuthorizeException,
IOException
{
int oldState = wi.getState();
// authorize a DSpaceActions.REJECT
// stop workflow
deleteTasks(c, wi);
@@ -848,6 +873,8 @@ public class WorkflowManager
+ "collection_id=" + wi.getCollection().getID() + "eperson_id="
+ e.getID()));
logWorkflowEvent(c, wsi.getItem(), wi, e, WFSTATE_SUBMIT, null, wsi.getCollection(), oldState, null);
return wsi;
}

View File

@@ -19,6 +19,8 @@ import org.dspace.eperson.Group;
import org.dspace.handle.HandleManager;
import org.dspace.storage.rdbms.DatabaseManager;
import org.dspace.storage.rdbms.TableRow;
import org.dspace.usage.UsageWorkflowEvent;
import org.dspace.utils.DSpace;
import org.dspace.xmlworkflow.state.Step;
import org.dspace.xmlworkflow.state.Workflow;
import org.dspace.xmlworkflow.state.actions.*;
@@ -144,6 +146,9 @@ public class XmlWorkflowManager {
// record the start of the workflow w/provenance message
recordStart(wfi.getItem(), firstActionConfig.getProcessingAction());
//Fire an event !
logWorkflowEvent(context, firstStep.getWorkflow().getID(), null, null, wfi, null, firstStep, firstActionConfig);
//If we don't have a UI activate it
if(!firstActionConfig.requiresUI()){
ActionResult outcome = firstActionConfig.getProcessingAction().execute(context, wfi, firstStep, null);
@@ -185,55 +190,81 @@ public class XmlWorkflowManager {
return null;
}else
if (currentOutcome.getType() == ActionResult.TYPE.TYPE_OUTCOME) {
//We have completed our action search & retrieve the next action
Step nextStep = null;
WorkflowActionConfig nextActionConfig = null;
if(currentOutcome.getResult() == ActionResult.OUTCOME_COMPLETE){
nextActionConfig = currentStep.getNextAction(currentActionConfig);
}
if (nextActionConfig != null) {
nextActionConfig.getProcessingAction().activate(c, wfi);
if (nextActionConfig.requiresUI() && !enteredNewStep) {
createOwnedTask(c, wfi, currentStep, nextActionConfig, user);
return nextActionConfig;
} else if( nextActionConfig.requiresUI() && enteredNewStep){
//We have entered a new step and have encountered a UI, return null since the current user doesn't have anything to do with this
c.restoreAuthSystemState();
return null;
} else {
ActionResult newOutcome = nextActionConfig.getProcessingAction().execute(c, wfi, currentStep, null);
return processOutcome(c, user, workflow, currentStep, nextActionConfig, newOutcome, wfi, enteredNewStep);
try {
//We have completed our action search & retrieve the next action
if(currentOutcome.getResult() == ActionResult.OUTCOME_COMPLETE){
nextActionConfig = currentStep.getNextAction(currentActionConfig);
}
}else
if(enteredNewStep){
// If the user finished his/her step, we keep processing until there is a UI step action or no step at all
Step nextStep = workflow.getNextStep(c, wfi, currentStep, currentOutcome.getResult());
c.turnOffAuthorisationSystem();
return processNextStep(c, user, workflow, currentOutcome, wfi, nextStep);
} else {
//
ClaimedTask task = ClaimedTask.findByWorkflowIdAndEPerson(c, wfi.getID(), user.getID());
//Check if we have a task for this action (might not be the case with automatic steps)
//First add it to our list of finished users, since no more actions remain
WorkflowRequirementsManager.addFinishedUser(c, wfi, user);
c.turnOffAuthorisationSystem();
//Check if our requirements have been met
if((currentStep.isFinished(c, wfi) && currentOutcome.getResult() == ActionResult.OUTCOME_COMPLETE) || currentOutcome.getResult() != ActionResult.OUTCOME_COMPLETE){
//Delete all the table rows containing the users who performed this task
WorkflowRequirementsManager.clearInProgressUsers(c, wfi);
//Remove all the tasks
XmlWorkflowManager.deleteAllTasks(c, wfi);
if (nextActionConfig != null) {
//We remain in the current step since an action is found
nextStep = currentStep;
nextActionConfig.getProcessingAction().activate(c, wfi);
if (nextActionConfig.requiresUI() && !enteredNewStep) {
createOwnedTask(c, wfi, currentStep, nextActionConfig, user);
return nextActionConfig;
} else if( nextActionConfig.requiresUI() && enteredNewStep){
//We have entered a new step and have encountered a UI, return null since the current user doesn't have anything to do with this
c.restoreAuthSystemState();
return null;
} else {
ActionResult newOutcome = nextActionConfig.getProcessingAction().execute(c, wfi, currentStep, null);
return processOutcome(c, user, workflow, currentStep, nextActionConfig, newOutcome, wfi, enteredNewStep);
}
}else
if(enteredNewStep){
// If the user finished his/her step, we keep processing until there is a UI step action or no step at all
nextStep = workflow.getNextStep(c, wfi, currentStep, currentOutcome.getResult());
c.turnOffAuthorisationSystem();
nextActionConfig = processNextStep(c, user, workflow, currentOutcome, wfi, nextStep);
//If we require a user interface return null so that the user is redirected to the "submissions page"
if(nextActionConfig == null || nextActionConfig.requiresUI()){
return null;
}else{
return nextActionConfig;
}
} else {
ClaimedTask task = ClaimedTask.findByWorkflowIdAndEPerson(c, wfi.getID(), user.getID());
//Check if we have a task for this action (might not be the case with automatic steps)
//First add it to our list of finished users, since no more actions remain
WorkflowRequirementsManager.addFinishedUser(c, wfi, user);
c.turnOffAuthorisationSystem();
//Check if our requirements have been met
if((currentStep.isFinished(c, wfi) && currentOutcome.getResult() == ActionResult.OUTCOME_COMPLETE) || currentOutcome.getResult() != ActionResult.OUTCOME_COMPLETE){
//Delete all the table rows containing the users who performed this task
WorkflowRequirementsManager.clearInProgressUsers(c, wfi);
//Remove all the tasks
XmlWorkflowManager.deleteAllTasks(c, wfi);
Step nextStep = workflow.getNextStep(c, wfi, currentStep, currentOutcome.getResult());
nextStep = workflow.getNextStep(c, wfi, currentStep, currentOutcome.getResult());
return processNextStep(c, user, workflow, currentOutcome, wfi, nextStep);
}else{
//We are done with our actions so go to the submissions page but remove action ClaimedAction first
deleteClaimedTask(c, wfi, task);
c.restoreAuthSystemState();
return null;
nextActionConfig = processNextStep(c, user, workflow, currentOutcome, wfi, nextStep);
//If we require a user interface return null so that the user is redirected to the "submissions page"
if(nextActionConfig == null || nextActionConfig.requiresUI()){
return null;
}else{
return nextActionConfig;
}
}else{
//We are done with our actions so go to the submissions page but remove action ClaimedAction first
deleteClaimedTask(c, wfi, task);
c.restoreAuthSystemState();
nextStep = currentStep;
nextActionConfig = currentActionConfig;
return null;
}
}
}catch (Exception e){
log.error("error while processing workflow outcome", e);
e.printStackTrace();
}
finally {
if((nextStep != null && nextActionConfig != null) || wfi.getItem().isArchived()){
logWorkflowEvent(c, currentStep.getWorkflow().getID(), currentStep.getId(), currentActionConfig.getId(), wfi, user, nextStep, nextActionConfig);
}
}
@@ -243,6 +274,51 @@ public class XmlWorkflowManager {
throw new WorkflowException("Invalid step outcome");
}
protected static void logWorkflowEvent(Context c, String workflowId, String previousStepId, String previousActionConfigId, XmlWorkflowItem wfi, EPerson actor, Step newStep, WorkflowActionConfig newActionConfig) throws SQLException {
try {
//Fire an event so we can log our action !
Item item = wfi.getItem();
Collection myCollection = wfi.getCollection();
String workflowStepString = null;
List<EPerson> currentEpersonOwners = new ArrayList<EPerson>();
List<Group> currentGroupOwners = new ArrayList<Group>();
//These are only null if our item is sent back to the submission
if(newStep != null && newActionConfig != null){
workflowStepString = workflowId + "." + newStep.getId() + "." + newActionConfig.getId();
//Retrieve the current owners of the task
List<ClaimedTask> claimedTasks = ClaimedTask.find(c, wfi.getID(), newStep.getId());
List<PoolTask> pooledTasks = PoolTask.find(c, wfi);
for (PoolTask poolTask : pooledTasks){
if(poolTask.getEpersonID() != -1){
currentEpersonOwners.add(EPerson.find(c, poolTask.getEpersonID()));
}else{
currentGroupOwners.add(Group.find(c, poolTask.getGroupID()));
}
}
for (ClaimedTask claimedTask : claimedTasks) {
currentEpersonOwners.add(EPerson.find(c, claimedTask.getOwnerID()));
}
}
String previousWorkflowStepString = null;
if(previousStepId != null && previousActionConfigId != null){
previousWorkflowStepString = workflowId + "." + previousStepId + "." + previousActionConfigId;
}
//Fire our usage event !
UsageWorkflowEvent usageWorkflowEvent = new UsageWorkflowEvent(c, item, wfi, workflowStepString, previousWorkflowStepString, myCollection, actor);
usageWorkflowEvent.setEpersonOwners(currentEpersonOwners.toArray(new EPerson[currentEpersonOwners.size()]));
usageWorkflowEvent.setGroupOwners(currentGroupOwners.toArray(new Group[currentGroupOwners.size()]));
new DSpace().getEventService().fireEvent(usageWorkflowEvent);
} catch (Exception e) {
//Catch all errors we do not want our workflow to crash because the logging threw an exception
log.error(LogManager.getHeader(c, "Error while logging workflow event", "Workflow Item: " + wfi.getID()), e);
}
}
private static WorkflowActionConfig processNextStep(Context c, EPerson user, Workflow workflow, ActionResult currentOutcome, XmlWorkflowItem wfi, Step nextStep) throws SQLException, IOException, AuthorizeException, WorkflowException, WorkflowConfigurationException {
WorkflowActionConfig nextActionConfig;
if(nextStep!=null){
@@ -253,7 +329,7 @@ public class XmlWorkflowManager {
if (nextActionConfig.requiresUI()) {
//Since a new step has been started, stop executing actions once one with a user interface is present.
c.restoreAuthSystemState();
return null;
return nextActionConfig;
} else {
ActionResult newOutcome = nextActionConfig.getProcessingAction().execute(c, wfi, nextStep, null);
c.restoreAuthSystemState();
@@ -581,6 +657,18 @@ public class XmlWorkflowManager {
String rejection_message) throws SQLException, AuthorizeException,
IOException
{
String workflowID = null;
String currentStepId = null;
String currentActionConfigId = null;
ClaimedTask claimedTask = ClaimedTask.findByWorkflowIdAndEPerson(c, wi.getID(), e.getID());
if(claimedTask != null){
//Log it
workflowID = claimedTask.getWorkflowID();
currentStepId = claimedTask.getStepID();
currentActionConfigId = claimedTask.getActionID();
}
// authorize a DSpaceActions.REJECT
// stop workflow
deleteAllTasks(c, wi);
@@ -627,6 +715,7 @@ public class XmlWorkflowManager {
+ "collection_id=" + wi.getCollection().getID() + "eperson_id="
+ e.getID()));
logWorkflowEvent(c, workflowID, currentStepId, currentActionConfigId, wi, e, null, null);
c.restoreAuthSystemState();
return wsi;