/*
* Submissions.java
*
* Version: $Revision: 3705 $
*
* Date: $Date: 2009-04-11 18:02:24 +0100 (Sat, 11 Apr 2009) $
*
* Copyright (c) 2002, Hewlett-Packard Company and Massachusetts
* Institute of Technology. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Hewlett-Packard Company nor the name of the
* Massachusetts Institute of Technology nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package org.dspace.app.xmlui.aspect.submission;
import java.io.IOException;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
import org.dspace.app.xmlui.utils.UIException;
import org.dspace.app.xmlui.wing.Message;
import org.dspace.app.xmlui.wing.WingException;
import org.dspace.app.xmlui.wing.element.Body;
import org.dspace.app.xmlui.wing.element.Cell;
import org.dspace.app.xmlui.wing.element.CheckBox;
import org.dspace.app.xmlui.wing.element.Division;
import org.dspace.app.xmlui.wing.element.PageMeta;
import org.dspace.app.xmlui.wing.element.Para;
import org.dspace.app.xmlui.wing.element.Row;
import org.dspace.app.xmlui.wing.element.Table;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection;
import org.dspace.content.DCValue;
import org.dspace.content.Item;
import org.dspace.content.ItemIterator;
import org.dspace.content.SupervisedItem;
import org.dspace.content.WorkspaceItem;
import org.dspace.core.Constants;
import org.dspace.eperson.EPerson;
import org.dspace.workflow.WorkflowItem;
import org.dspace.workflow.WorkflowManager;
import org.xml.sax.SAXException;
/**
* @author Scott Phillips
*/
public class Submissions extends AbstractDSpaceTransformer
{
/** General Language Strings */
protected static final Message T_title =
message("xmlui.Submission.Submissions.title");
protected static final Message T_dspace_home =
message("xmlui.general.dspace_home");
protected static final Message T_trail =
message("xmlui.Submission.Submissions.trail");
protected static final Message T_head =
message("xmlui.Submission.Submissions.head");
protected static final Message T_untitled =
message("xmlui.Submission.Submissions.untitled");
protected static final Message T_email =
message("xmlui.Submission.Submissions.email");
// used by the workflow section
protected static final Message T_w_head1 =
message("xmlui.Submission.Submissions.workflow_head1");
protected static final Message T_w_info1 =
message("xmlui.Submission.Submissions.workflow_info1");
protected static final Message T_w_head2 =
message("xmlui.Submission.Submissions.workflow_head2");
protected static final Message T_w_column1 =
message("xmlui.Submission.Submissions.workflow_column1");
protected static final Message T_w_column2 =
message("xmlui.Submission.Submissions.workflow_column2");
protected static final Message T_w_column3 =
message("xmlui.Submission.Submissions.workflow_column3");
protected static final Message T_w_column4 =
message("xmlui.Submission.Submissions.workflow_column4");
protected static final Message T_w_column5 =
message("xmlui.Submission.Submissions.workflow_column5");
protected static final Message T_w_submit_return =
message("xmlui.Submission.Submissions.workflow_submit_return");
protected static final Message T_w_info2 =
message("xmlui.Submission.Submissions.workflow_info2");
protected static final Message T_w_head3 =
message("xmlui.Submission.Submissions.workflow_head3");
protected static final Message T_w_submit_take =
message("xmlui.Submission.Submissions.workflow_submit_take");
protected static final Message T_w_info3 =
message("xmlui.Submission.Submissions.workflow_info3");
// used by the unfinished submissions section
protected static final Message T_s_head1 =
message("xmlui.Submission.Submissions.submit_head1");
protected static final Message T_s_info1a =
message("xmlui.Submission.Submissions.submit_info1a");
protected static final Message T_s_info1b =
message("xmlui.Submission.Submissions.submit_info1b");
protected static final Message T_s_info1c =
message("xmlui.Submission.Submissions.submit_info1c");
protected static final Message T_s_head2 =
message("xmlui.Submission.Submissions.submit_head2");
protected static final Message T_s_info2a =
message("xmlui.Submission.Submissions.submit_info2a");
protected static final Message T_s_info2b =
message("xmlui.Submission.Submissions.submit_info2b");
protected static final Message T_s_info2c =
message("xmlui.Submission.Submissions.submit_info2c");
protected static final Message T_s_column1 =
message("xmlui.Submission.Submissions.submit_column1");
protected static final Message T_s_column2 =
message("xmlui.Submission.Submissions.submit_column2");
protected static final Message T_s_column3 =
message("xmlui.Submission.Submissions.submit_column3");
protected static final Message T_s_column4 =
message("xmlui.Submission.Submissions.submit_column4");
protected static final Message T_s_head3 =
message("xmlui.Submission.Submissions.submit_head3");
protected static final Message T_s_info3 =
message("xmlui.Submission.Submissions.submit_info3");
protected static final Message T_s_head4 =
message("xmlui.Submission.Submissions.submit_head4");
protected static final Message T_s_submit_remove =
message("xmlui.Submission.Submissions.submit_submit_remove");
// Used in the in progress section
protected static final Message T_p_head1 =
message("xmlui.Submission.Submissions.progress_head1");
protected static final Message T_p_info1 =
message("xmlui.Submission.Submissions.progress_info1");
protected static final Message T_p_column1 =
message("xmlui.Submission.Submissions.progress_column1");
protected static final Message T_p_column2 =
message("xmlui.Submission.Submissions.progress_column2");
protected static final Message T_p_column3 =
message("xmlui.Submission.Submissions.progress_column3");
// Used in the completed section
protected static final Message T_c_head1 =
message("xmlui.Submission.Submissions.complete_head1");
protected static final Message T_c_info1 =
message("xmlui.Submission.Submissions.complete_info1");
protected static final Message T_c_column1 =
message("xmlui.Submission.Submissions.complete_column1");
protected static final Message T_c_column2 =
message("xmlui.Submission.Submissions.complete_column2");
// The workflow status messages
protected static final Message T_status_0 =
message("xmlui.Submission.Submissions.status_0");
protected static final Message T_status_1 =
message("xmlui.Submission.Submissions.status_1");
protected static final Message T_status_2 =
message("xmlui.Submission.Submissions.status_2");
protected static final Message T_status_3 =
message("xmlui.Submission.Submissions.status_3");
protected static final Message T_status_4 =
message("xmlui.Submission.Submissions.status_4");
protected static final Message T_status_5 =
message("xmlui.Submission.Submissions.status_5");
protected static final Message T_status_6 =
message("xmlui.Submission.Submissions.status_6");
protected static final Message T_status_7 =
message("xmlui.Submission.Submissions.status_7");
protected static final Message T_status_unknown =
message("xmlui.Submission.Submissions.status_unknown");
public void addPageMeta(PageMeta pageMeta) throws SAXException,
WingException, UIException, SQLException, IOException,
AuthorizeException
{
pageMeta.addMetadata("title").addContent(T_title);
pageMeta.addTrailLink(contextPath + "/",T_dspace_home);
pageMeta.addTrailLink(contextPath + "/submissions",T_trail);
}
public void addBody(Body body) throws SAXException, WingException,
UIException, SQLException, IOException, AuthorizeException
{
Division div = body.addInteractiveDivision("submissions", contextPath+"/submissions", Division.METHOD_POST,"primary");
div.setHead(T_head);
this.addWorkflowTasks(div);
this.addUnfinishedSubmissions(div);
this.addSubmissionsInWorkflow(div);
this.addCompleteSubmissions(div);
}
/**
* If the user has any workflow tasks, either assigned to them or in an
* available pool of tasks, then build two tables listing each of these queues.
*
* If the user dosn't have any workflows then don't do anything.
*
* @param division The division to add the two queues too.
*/
private void addWorkflowTasks(Division division) throws SQLException, WingException
{
@SuppressWarnings("unchecked") // This cast is correct
java.util.List<WorkflowItem> ownedItems = WorkflowManager.getOwnedTasks(context, context
.getCurrentUser());
@SuppressWarnings("unchecked") // This cast is correct.
java.util.List<WorkflowItem> pooledItems = WorkflowManager.getPooledTasks(context, context
.getCurrentUser());
if (!(ownedItems.size() > 0 || pooledItems.size() > 0))
// No tasks, so don't show the table.
return;
Division workflow = division.addDivision("workflow-tasks");
workflow.setHead(T_w_head1);
workflow.addPara(T_w_info1);
// Tasks you own
Table table = workflow.addTable("workflow-tasks",ownedItems.size() + 2,5);
table.setHead(T_w_head2);
Row header = table.addRow(Row.ROLE_HEADER);
header.addCellContent(T_w_column1);
header.addCellContent(T_w_column2);
header.addCellContent(T_w_column3);
header.addCellContent(T_w_column4);
header.addCellContent(T_w_column5);
if (ownedItems.size() > 0)
{
for (WorkflowItem owned : ownedItems)
{
int workflowItemID = owned.getID();
String url = contextPath+"/handle/"+owned.getCollection().getHandle()+"/workflow?workflowID="+workflowItemID;
DCValue[] titles = owned.getItem().getDC("title", null, Item.ANY);
String collectionName = owned.getCollection().getMetadata("name");
EPerson submitter = owned.getSubmitter();
String submitterName = submitter.getFullName();
String submitterEmail = submitter.getEmail();
Message state = getWorkflowStateMessage(owned);
Row row = table.addRow();
CheckBox remove = row.addCell().addCheckBox("workflowID");
remove.setLabel("selected");
remove.addOption(workflowItemID);
// The task description
row.addCell().addXref(url,state);
// The item description
if (titles != null && titles.length > 0)
{
String displayTitle = titles[0].value;
if (displayTitle.length() > 50)
displayTitle = displayTitle.substring(0,50)+ " ...";
row.addCell().addXref(url,displayTitle);
}
else
row.addCell().addXref(url,T_untitled);
// Submitted too
row.addCell().addXref(url,collectionName);
// Submitted by
Cell cell = row.addCell();
cell.addContent(T_email);
cell.addXref("mailto:"+submitterEmail,submitterName);
}
Row row = table.addRow();
row.addCell(0,5).addButton("submit_return_tasks").setValue(T_w_submit_return);
}
else
{
Row row = table.addRow();
row.addCell(0,5).addHighlight("italic").addContent(T_w_info2);
}
// Tasks in the pool
table = workflow.addTable("workflow-tasks",pooledItems.size()+2,5);
table.setHead(T_w_head3);
header = table.addRow(Row.ROLE_HEADER);
header.addCellContent(T_w_column1);
header.addCellContent(T_w_column2);
header.addCellContent(T_w_column3);
header.addCellContent(T_w_column4);
header.addCellContent(T_w_column5);
if (pooledItems.size() > 0)
{
for (WorkflowItem pooled : pooledItems)
{
int workflowItemID = pooled.getID();
String url = contextPath+"/handle/"+pooled.getCollection().getHandle()+"/workflow?workflowID="+workflowItemID;
DCValue[] titles = pooled.getItem().getDC("title", null, Item.ANY);
String collectionName = pooled.getCollection().getMetadata("name");
EPerson submitter = pooled.getSubmitter();
String submitterName = submitter.getFullName();
String submitterEmail = submitter.getEmail();
Message state = getWorkflowStateMessage(pooled);
Row row = table.addRow();
CheckBox remove = row.addCell().addCheckBox("workflowID");
remove.setLabel("selected");
remove.addOption(workflowItemID);
// The task description
row.addCell().addXref(url,state);
// The item description
if (titles != null && titles.length > 0)
{
String displayTitle = titles[0].value;
if (displayTitle.length() > 50)
displayTitle = displayTitle.substring(0,50)+ " ...";
row.addCell().addXref(url,displayTitle);
}
else
row.addCell().addXref(url,T_untitled);
// Submitted too
row.addCell().addXref(url,collectionName);
// Submitted by
Cell cell = row.addCell();
cell.addContent(T_email);
cell.addXref("mailto:"+submitterEmail,submitterName);
}
Row row = table.addRow();
row.addCell(0,5).addButton("submit_take_tasks").setValue(T_w_submit_take);
}
else
{
Row row = table.addRow();
row.addCell(0,5).addHighlight("italic").addContent(T_w_info3);
}
}
/**
* There are two options, the user has some unfinished submissions
* or the user does not.
*
* If the user does not, then we just display a simple paragraph
* explaining that the user may submit new items to dspace.
*
* If the user does have unfinisshed submissions then a table is
* presented listing all the unfinished submissions that this user has.
*
*/
private void addUnfinishedSubmissions(Division division) throws SQLException, WingException
{
// User's WorkflowItems
WorkspaceItem[] unfinishedItems = WorkspaceItem.findByEPerson(context,context.getCurrentUser());
SupervisedItem[] supervisedItems = SupervisedItem.findbyEPerson(context, context.getCurrentUser());
if (unfinishedItems.length <= 0 && supervisedItems.length <= 0)
{
Collection[] collections = Collection.findAuthorized(context, null, Constants.ADD);
if (collections.length > 0)
{
Division start = division.addDivision("start-submision");
start.setHead(T_s_head1);
Para p = start.addPara();
p.addContent(T_s_info1a);
p.addXref(contextPath+"/submit",T_s_info1b);
p.addContent(T_s_info1c);
return;
}
}
Division unfinished = division.addInteractiveDivision("unfinished-submisions", contextPath+"/submit", Division.METHOD_POST);
unfinished.setHead(T_s_head2);
Para p = unfinished.addPara();
p.addContent(T_s_info2a);
p.addHighlight("bold").addXref(contextPath+"/submit",T_s_info2b);
p.addContent(T_s_info2c);
// Calculate the number of rows.
// Each list pluss the top header and bottom row for the button.
int rows = unfinishedItems.length + supervisedItems.length + 2;
if (supervisedItems.length > 0 && unfinishedItems.length > 0)
rows++; // Authoring heading row
if (supervisedItems.length > 0)
rows++; // Supervising heading row
Table table = unfinished.addTable("unfinished-submissions",rows,5);
Row header = table.addRow(Row.ROLE_HEADER);
header.addCellContent(T_s_column1);
header.addCellContent(T_s_column2);
header.addCellContent(T_s_column3);
header.addCellContent(T_s_column4);
if (supervisedItems.length > 0 && unfinishedItems.length > 0)
{
header = table.addRow();
header.addCell(null,Cell.ROLE_HEADER,0,5,null).addContent(T_s_head3);
}
if (unfinishedItems.length > 0)
{
for (WorkspaceItem workspaceItem : unfinishedItems)
{
DCValue[] titles = workspaceItem.getItem().getDC("title", null, Item.ANY);
EPerson submitterEPerson = workspaceItem.getItem().getSubmitter();
int workspaceItemID = workspaceItem.getID();
String url = contextPath+"/submit?workspaceID="+workspaceItemID;
String submitterName = submitterEPerson.getFullName();
String submitterEmail = submitterEPerson.getEmail();
String collectionName = workspaceItem.getCollection().getMetadata("name");
Row row = table.addRow(Row.ROLE_DATA);
CheckBox remove = row.addCell().addCheckBox("workspaceID");
remove.setLabel("remove");
remove.addOption(workspaceItemID);
if (titles.length > 0)
{
String displayTitle = titles[0].value;
if (displayTitle.length() > 50)
displayTitle = displayTitle.substring(0,50)+ " ...";
row.addCell().addXref(url,displayTitle);
}
else
row.addCell().addXref(url,T_untitled);
row.addCell().addXref(url,collectionName);
Cell cell = row.addCell();
cell.addContent(T_email);
cell.addXref("mailto:"+submitterEmail,submitterName);
}
}
else
{
header = table.addRow();
header.addCell(0,5).addHighlight("italic").addContent(T_s_info3);
}
if (supervisedItems.length > 0)
{
header = table.addRow();
header.addCell(null,Cell.ROLE_HEADER,0,5,null).addContent(T_s_head4);
}
for (WorkspaceItem workspaceItem : supervisedItems)
{
DCValue[] titles = workspaceItem.getItem().getDC("title", null, Item.ANY);
EPerson submitterEPerson = workspaceItem.getItem().getSubmitter();
int workspaceItemID = workspaceItem.getID();
String url = contextPath+"/submit?workspaceID="+workspaceItemID;
String submitterName = submitterEPerson.getFullName();
String submitterEmail = submitterEPerson.getEmail();
String collectionName = workspaceItem.getCollection().getMetadata("name");
Row row = table.addRow(Row.ROLE_DATA);
CheckBox selected = row.addCell().addCheckBox("workspaceID");
selected.setLabel("select");
selected.addOption(workspaceItemID);
if (titles.length > 0)
{
String displayTitle = titles[0].value;
if (displayTitle.length() > 50)
displayTitle = displayTitle.substring(0,50)+ " ...";
row.addCell().addXref(url,displayTitle);
}
else
row.addCell().addXref(url,T_untitled);
row.addCell().addXref(url,collectionName);
Cell cell = row.addCell();
cell.addContent(T_email);
cell.addXref("mailto:"+submitterEmail,submitterName);
}
header = table.addRow();
Cell lastCell = header.addCell(0,5);
if (unfinishedItems.length > 0 || supervisedItems.length > 0)
lastCell.addButton("submit_submissions_remove").setValue(T_s_submit_remove);
}
/**
* This section lists all the submissions that this user has submitted which are currently under review.
*
* If the user has none, this nothing is displayed.
*/
private void addSubmissionsInWorkflow(Division division) throws SQLException, WingException
{
WorkflowItem[] inprogressItems = WorkflowItem.findByEPerson(context,context.getCurrentUser());
// If there is nothing in progress then don't add anything.
if (!(inprogressItems.length > 0))
return;
Division inprogress = division.addDivision("submissions-inprogress");
inprogress.setHead(T_p_head1);
inprogress.addPara(T_p_info1);
Table table = inprogress.addTable("submissions-inprogress",inprogressItems.length+1,3);
Row header = table.addRow(Row.ROLE_HEADER);
header.addCellContent(T_p_column1);
header.addCellContent(T_p_column2);
header.addCellContent(T_p_column3);
for (WorkflowItem workflowItem : inprogressItems)
{
DCValue[] titles = workflowItem.getItem().getDC("title", null, Item.ANY);
String collectionName = workflowItem.getCollection().getMetadata("name");
Message state = getWorkflowStateMessage(workflowItem);
Row row = table.addRow();
// Add the title column
if (titles.length > 0)
{
String displayTitle = titles[0].value;
if (displayTitle.length() > 50)
displayTitle = displayTitle.substring(0,50)+ " ...";
row.addCellContent(displayTitle);
}
else
row.addCellContent(T_untitled);
// Collection name column
row.addCellContent(collectionName);
// Status column
row.addCellContent(state);
}
}
/**
* Added by IF 01/10/2009
*
* This section lists all the submissions that this user has submitted which have been
* successfully completed.
*
* If the user has none, then nothing is displayed.
*/
private void addCompleteSubmissions(Division division) throws SQLException, WingException
{
ItemIterator completedItems = Item.findBySubmitter(context, context.getCurrentUser());
List<Item> itemList = new LinkedList<Item>();
try
{
while (completedItems.hasNext())
{
itemList.add(completedItems.next());
}
}
finally
{
if (completedItems != null)
{
completedItems.close();
}
}
// If there are no complete items then don't add anything.
if (!(itemList.size() > 0))
return;
Division completed = division.addDivision("submissions-complete");
completed.setHead(T_c_head1);
completed.addPara(T_c_info1);
Table table = completed.addTable("submissions-complete-table",itemList.size()+1,2);
Row header = table.addRow(Row.ROLE_HEADER);
header.addCellContent(T_c_column1);
header.addCellContent(T_c_column2);
for (Item item : itemList)
{
DCValue[] titles = item.getDC("title", null, Item.ANY);
String collectionName = item.getOwningCollection().getMetadata("name");
String url = contextPath+"/handle/"+item.getHandle();
Row row = table.addRow();
// Add the title column
if (titles.length > 0)
{
String displayTitle = titles[0].value;
if (displayTitle.length() > 50)
displayTitle = displayTitle.substring(0,50)+ " ...";
row.addCell().addXref(url,displayTitle);
}
else
row.addCell().addXref(url,T_untitled);
// Collection name column
row.addCellContent(collectionName);
}
}
/**
* Determine the correct message that describes this workflow item's state.
*
* FIXME: change to return type of message;
*/
private Message getWorkflowStateMessage(WorkflowItem workflowItem)
{
switch (workflowItem.getState())
{
case WorkflowManager.WFSTATE_SUBMIT:
return T_status_0;
case WorkflowManager.WFSTATE_STEP1POOL:
return T_status_1;
case WorkflowManager.WFSTATE_STEP1:
return T_status_2;
case WorkflowManager.WFSTATE_STEP2POOL:
return T_status_3;
case WorkflowManager.WFSTATE_STEP2:
return T_status_4;
case WorkflowManager.WFSTATE_STEP3POOL:
return T_status_5;
case WorkflowManager.WFSTATE_STEP3:
return T_status_6;
case WorkflowManager.WFSTATE_ARCHIVE:
return T_status_7;
default:
return T_status_unknown;
}
}
}