[DS-102] Submission without file possible with the skip upload functionality disabled

[DS-103] Use of the Progress bar button don't save the current page modification
[DS-104] Cancel/save button during edit of a workflow item doesn't work

git-svn-id: http://scm.dspace.org/svn/repo/branches/dspace-1_5_x@3625 9c30dcfa-912a-0410-8fc2-9e0234be79fd
This commit is contained in:
Andrea Bollini
2009-03-23 11:18:53 +00:00
parent e4a8bfff87
commit ef01a162c6
8 changed files with 280 additions and 128 deletions

View File

@@ -2164,6 +2164,35 @@ public class Item extends DSpaceObject
}
}
/**
* Check the bundle ORIGINAL to see if there are any uploaded files
*
* @param item
* @return true if there is a bundle named ORIGINAL with one or more
* bitstreams inside
* @throws SQLException
*/
public boolean hasUploadedFiles() throws SQLException
{
Bundle[] bundles = getBundles("ORIGINAL");
if (bundles.length == 0)
{
// if no ORIGINAL bundle,
// return false that there is no file!
return false;
}
else
{
Bitstream[] bitstreams = bundles[0].getBitstreams();
if (bitstreams.length == 0)
{
// no files in ORIGINAL bundle!
return false;
}
}
return true;
}
/**
* Get the collections this item is not in.
*

View File

@@ -268,10 +268,11 @@ public class DescribeStep extends AbstractProcessingStep
// Step 3:
// Check to see if any fields are missing
// Only check for required fields if user clicked the "next" button
// (or clicked progress bar)
// @TODO: It'd be better if we allowed them to click *backwards* in Progress bar, but not *forwards*
if (buttonPressed.equals(NEXT_BUTTON) || buttonPressed.startsWith(PROGRESS_BAR_PREFIX))
// Only check for required fields if user clicked the "next", the "previous" or the "progress bar" button
if (buttonPressed.equals(NEXT_BUTTON)
|| buttonPressed.startsWith(PROGRESS_BAR_PREFIX)
|| buttonPressed.equals(PREVIOUS_BUTTON)
|| buttonPressed.equals(CANCEL_BUTTON))
{
clearErrorFields(request);
for (int i = 0; i < inputs.length; i++)
@@ -864,5 +865,4 @@ public class DescribeStep extends AbstractProcessingStep
}
}
}

View File

@@ -119,6 +119,8 @@ public class UploadStep extends AbstractProcessingStep
/** log4j logger */
private static Logger log = Logger.getLogger(UploadStep.class);
/** is the upload required? */
private boolean fileRequired = ConfigurationManager.getBooleanProperty("webui.submit.upload.required", true);
/**
* Do any processing of the information input by the user, and/or perform
@@ -154,11 +156,37 @@ public class UploadStep extends AbstractProcessingStep
// get reference to item
Item item = subInfo.getSubmissionItem().getItem();
// -----------------------------------
// Step #0: Upload new files (if any)
// -----------------------------------
String contentType = request.getContentType();
// if multipart form, then we are uploading a file
if ((contentType != null)
&& (contentType.indexOf("multipart/form-data") != -1))
{
// This is a multipart request, so it's a file upload
// (return any status messages or errors reported)
int status = processUploadFile(context, request, response, subInfo);
// if error occurred, return immediately
if (status != STATUS_COMPLETE)
return status;
}
// if user pressed jump-to button in process bar,
// return success (so that jump will occur)
if (buttonPressed.startsWith(PROGRESS_BAR_PREFIX))
{
return STATUS_COMPLETE;
// check if a file is required to be uploaded
if (fileRequired && !item.hasUploadedFiles())
{
return STATUS_NO_FILES_ERROR;
}
else
{
return STATUS_COMPLETE;
}
}
// ---------------------------------------------
@@ -248,30 +276,8 @@ public class UploadStep extends AbstractProcessingStep
subInfo.setBitstream(null);
}
// -----------------------------------
// Step #3: Upload new files (if any)
// -----------------------------------
String contentType = request.getContentType();
if (buttonPressed.equalsIgnoreCase(SUBMIT_UPLOAD_BUTTON) || buttonPressed.equalsIgnoreCase(NEXT_BUTTON))
{
// if multipart form, then we are uploading a file
if ((contentType != null)
&& (contentType.indexOf("multipart/form-data") != -1))
{
// This is a multipart request, so it's a file upload
// (return any status messages or errors reported)
int status = processUploadFile(context, request, response,
subInfo);
// if error occurred, return immediately
if (status != STATUS_COMPLETE)
return status;
}
}
// -------------------------------------------------
// Step #4: Check for a change in file description
// Step #3: Check for a change in file description
// -------------------------------------------------
String fileDescription = request.getParameter("description");
@@ -287,7 +293,7 @@ public class UploadStep extends AbstractProcessingStep
}
// ------------------------------------------
// Step #5: Check for a file format change
// Step #4: Check for a file format change
// (if user had to manually specify format)
// ------------------------------------------
int formatTypeID = Util.getIntParameter(request, "format");
@@ -307,7 +313,7 @@ public class UploadStep extends AbstractProcessingStep
}
// ---------------------------------------------------
// Step #6: Check if primary bitstream has changed
// Step #5: Check if primary bitstream has changed
// -------------------------------------------------
if (request.getParameter("primary_bitstream_id") != null)
{
@@ -318,29 +324,13 @@ public class UploadStep extends AbstractProcessingStep
}
// ---------------------------------------------------
// Step #7: Determine if there is an error because no
// Step #6: Determine if there is an error because no
// files have been uploaded.
// ---------------------------------------------------
//check if a file is required to be uploaded
boolean fileRequired = ConfigurationManager.getBooleanProperty("webui.submit.upload.required", true);
if (fileRequired)
if (fileRequired && !item.hasUploadedFiles())
{
Bundle[] bundles = item.getBundles("ORIGINAL");
if (bundles.length == 0)
{
// if no ORIGINAL bundle,
// throw an error that there is no file!
return STATUS_NO_FILES_ERROR;
}
else
{
Bitstream[] bitstreams = bundles[0].getBitstreams();
if (bitstreams.length == 0)
{
// no files in ORIGINAL bundle!
return STATUS_NO_FILES_ERROR;
}
}
return STATUS_NO_FILES_ERROR;
}
// commit all changes to database

View File

@@ -335,7 +335,7 @@ public class SubmissionController extends DSpaceServlet
AbstractProcessingStep.PROGRESS_BAR_PREFIX))
{
// jumping to a particular step/page
doStepJump(context, request, response, subInfo);
doStepJump(context, request, response, subInfo, currentStepConfig);
}
else
{
@@ -519,6 +519,24 @@ public class SubmissionController extends DSpaceServlet
throws ServletException, IOException, SQLException,
AuthorizeException
{
int result = doSaveCurrentState(context, request, response, subInfo, currentStepConfig);
int currStep=currentStepConfig.getStepNumber();
int currPage=AbstractProcessingStep.getCurrentPage(request);
double currStepAndPage = Float.parseFloat(currStep+"."+currPage);
// default value if we are in workflow
double stepAndPageReached = -1;
if (!subInfo.isInWorkflow())
{
stepAndPageReached = Float.parseFloat(getStepReached(subInfo)+"."+JSPStepManager.getPageReached(subInfo));
}
if (result != AbstractProcessingStep.STATUS_COMPLETE && currStepAndPage != stepAndPageReached)
{
doStep(context, request, response, subInfo, currStep);
}
// find current Step number
int currentStepNum;
if (currentStepConfig == null)
@@ -613,8 +631,8 @@ public class SubmissionController extends DSpaceServlet
* @param subInfo
* SubmissionInfo pertaining to this submission
*/
public void doStepJump(Context context, HttpServletRequest request,
HttpServletResponse response, SubmissionInfo subInfo)
private void doStepJump(Context context, HttpServletRequest request,
HttpServletResponse response, SubmissionInfo subInfo, SubmissionStepConfig currentStepConfig)
throws ServletException, IOException, SQLException,
AuthorizeException
{
@@ -622,15 +640,6 @@ public class SubmissionController extends DSpaceServlet
// "submit_jump_".
String buttonPressed = UIUtil.getSubmitButton(request, "");
// Now, if the request was a multi-part (file upload), we need to
// get the original request back out, as the wrapper causes problems
// further down the line.
if (request instanceof FileUploadRequest)
{
FileUploadRequest fur = (FileUploadRequest) request;
request = fur.getOriginalRequest();
}
int nextStep = -1; // next step to load
int nextPage = -1; // page within the nextStep to load
@@ -681,17 +690,51 @@ public class SubmissionController extends DSpaceServlet
}
else
{
// save page info to request (for the step to access)
AbstractProcessingStep.setCurrentPage(request, nextPage);
int result = doSaveCurrentState(context, request, response,
subInfo, currentStepConfig);
//flag that we are going back to the start of this step (for JSPStepManager class)
setBeginningOfStep(request, true);
// Now, if the request was a multi-part (file upload), we need to
// get the original request back out, as the wrapper causes problems
// further down the line.
if (request instanceof FileUploadRequest)
{
FileUploadRequest fur = (FileUploadRequest) request;
request = fur.getOriginalRequest();
}
log.debug("Jumping to Step " + nextStep + " and Page " + nextPage);
int currStep = currentStepConfig.getStepNumber();
int currPage = AbstractProcessingStep.getCurrentPage(request);
double currStepAndPage = Float
.parseFloat(currStep + "." + currPage);
// default value if we are in workflow
double stepAndPageReached = -1;
// do the step (the step should take care of going to
// the specified page)
doStep(context, request, response, subInfo, nextStep);
if (!subInfo.isInWorkflow())
{
stepAndPageReached = Float.parseFloat(getStepReached(subInfo)+"."+JSPStepManager.getPageReached(subInfo));
}
if (result != AbstractProcessingStep.STATUS_COMPLETE
&& currStepAndPage != stepAndPageReached)
{
doStep(context, request, response, subInfo, currStep);
}
else
{
// save page info to request (for the step to access)
AbstractProcessingStep.setCurrentPage(request, nextPage);
// flag that we are going back to the start of this step (for
// JSPStepManager class)
setBeginningOfStep(request, true);
log.debug("Jumping to Step " + nextStep + " and Page "
+ nextPage);
// do the step (the step should take care of going to
// the specified page)
doStep(context, request, response, subInfo, nextStep);
}
}
}
@@ -715,14 +758,24 @@ public class SubmissionController extends DSpaceServlet
private void doCancelOrSave(Context context, HttpServletRequest request,
HttpServletResponse response, SubmissionInfo subInfo,
SubmissionStepConfig stepConfig) throws ServletException, IOException,
SQLException
SQLException, AuthorizeException
{
// If this is a workflow item, we need to return the
// user to the "perform task" page
if (subInfo.isInWorkflow())
{
request.setAttribute("workflow.item", subInfo.getSubmissionItem());
JSPManager.showJSP(request, response, "/mydspace/perform-task.jsp");
int result = doSaveCurrentState(context, request, response, subInfo, stepConfig);
if (result == AbstractProcessingStep.STATUS_COMPLETE)
{
request.setAttribute("workflow.item", subInfo.getSubmissionItem());
JSPManager.showJSP(request, response, "/mydspace/perform-task.jsp");
}
else
{
int currStep=stepConfig.getStepNumber();
doStep(context, request, response, subInfo, currStep);
}
}
else
{
@@ -736,49 +789,25 @@ public class SubmissionController extends DSpaceServlet
}
else
{
//tell the step class to do its processing (to save any inputs)
//but, send flag that this is a "cancellation"
setCancellationInProgress(request, true);
// As long as we're not uploading a file, go ahead and SAVE
// all of the user's inputs for later
try
{
if (!Class.forName("org.dspace.app.webui.util.FileUploadRequest")
.isInstance(request))
{
// call post-processing on Step (to save any inputs from JSP)
log.debug("Cancel/Save Request: calling processing for Step: '"
+ stepConfig.getProcessingClassName() + "'");
int result = doSaveCurrentState(context, request, response, subInfo,
stepConfig);
try
{
// load the step class (using the current class loader)
ClassLoader loader = this.getClass().getClassLoader();
Class stepClass = loader
.loadClass(stepConfig.getProcessingClassName());
int currStep=stepConfig.getStepNumber();
int currPage=AbstractProcessingStep.getCurrentPage(request);
double currStepAndPage = Float.parseFloat(currStep+"."+currPage);
double stepAndPageReached = Float.parseFloat(getStepReached(subInfo)+"."+JSPStepManager.getPageReached(subInfo));
// load the JSPStepManager object for this step
AbstractProcessingStep step = (AbstractProcessingStep) stepClass
.newInstance();
//tell the step class to do its processing (to save any inputs)
//but, send flag that this is a "cancellation"
setCancellationInProgress(request, true);
step.doProcessing(context, request, response, subInfo);
//commit & close context
context.complete();
}
catch (Exception e)
{
log.error("Error loading step class'" + stepConfig.getProcessingClassName() + "':", e);
JSPManager.showInternalError(request, response);
}
}//end if not file upload request
}
catch(Exception e)
{
throw new ServletException(e);
if (result != AbstractProcessingStep.STATUS_COMPLETE && currStepAndPage < stepAndPageReached){
setReachedStepAndPage(subInfo, currStep, currPage);
}
//commit & close context
context.complete();
// save changes to submission info & step info for JSP
saveSubmissionInfo(request, subInfo);
saveCurrentStepConfig(request, stepConfig);
@@ -790,6 +819,48 @@ public class SubmissionController extends DSpaceServlet
}
}
private int doSaveCurrentState(Context context,
HttpServletRequest request, HttpServletResponse response,
SubmissionInfo subInfo, SubmissionStepConfig stepConfig)
throws ServletException
{
int result = -1;
// As long as we're not uploading a file, go ahead and SAVE
// all of the user's inputs for later
try
{
// call post-processing on Step (to save any inputs from JSP)
log
.debug("Cancel/Save or Jump/Previous Request: calling processing for Step: '"
+ stepConfig.getProcessingClassName() + "'");
try
{
// load the step class (using the current class loader)
ClassLoader loader = this.getClass().getClassLoader();
Class stepClass = loader.loadClass(stepConfig
.getProcessingClassName());
// load the JSPStepManager object for this step
AbstractProcessingStep step = (AbstractProcessingStep) stepClass
.newInstance();
result = step.doProcessing(context, request, response, subInfo);
}
catch (Exception e)
{
log.error("Error loading step class'"
+ stepConfig.getProcessingClassName() + "':", e);
JSPManager.showInternalError(request, response);
}
}
catch(Exception e)
{
throw new ServletException(e);
}
return result;
}
/**
* Process information from "submission cancelled" page.
* This saves the item if the user decided to "cancel & save",
@@ -838,7 +909,7 @@ public class SubmissionController extends DSpaceServlet
}
else
{
doStepJump(context, request, response, subInfo);
doStepJump(context, request, response, subInfo, currentStepConfig);
}
}
@@ -1224,6 +1295,29 @@ public class SubmissionController extends DSpaceServlet
}
}
/**
* Set a specific step and page as reached.
* It will also "set back" where a user has reached.
*
* @param subInfo
* the SubmissionInfo object pertaining to the current submission
* @param step the step to set as reached, can be also a previous reached step
* @param page the page (within the step) to set as reached, can be also a previous reached page
*/
private void setReachedStepAndPage(SubmissionInfo subInfo, int step,
int page) throws SQLException, AuthorizeException, IOException
{
if (!subInfo.isInWorkflow() && subInfo.getSubmissionItem() != null)
{
WorkspaceItem wi = (WorkspaceItem) subInfo.getSubmissionItem();
wi.setStageReached(step);
wi.setPageReached(page);
wi.update();
}
}
/**
* Find out which step a user has reached in the submission process. If the
* submission is in the workflow process, this returns -1.

View File

@@ -77,13 +77,11 @@
titlekey="jsp.submit.choose-file.title"
nocache="true">
<form method="post" action="<%= request.getContextPath() %>/submit" onkeydown="return disableEnterKey(event);">
<form method="post" action="<%= request.getContextPath() %>/submit" enctype="multipart/form-data" onkeydown="return disableEnterKey(event);">
<jsp:include page="/submit/progressbar.jsp"/>
<%-- Hidden fields needed for SubmissionController servlet to know which step is next--%>
<%= SubmissionController.getSubmissionParameters(context, request) %>
</form>
<form method="post" action="<%= request.getContextPath() %>/submit" enctype="multipart/form-data" onkeydown="return disableEnterKey(event);">
<%-- <h1>Submit: Upload a File</h1> --%>
<h1><fmt:message key="jsp.submit.choose-file.heading"/></h1>

View File

@@ -243,6 +243,31 @@ public class FlowUtils {
}
}
/**
* Set a specific step and page as reached.
* It will also "set back" where a user has reached.
*
* @param context The current DSpace content
* @param id The unique ID of the current workflow/workspace
* @param step the step to set as reached, can be also a previous reached step
* @param page the page (within the step) to set as reached, can be also a previous reached page
*/
public static void setBackPageReached(Context context, String id, int step,
int page) throws SQLException, AuthorizeException, IOException
{
InProgressSubmission submission = findSubmission(context, id);
if (submission instanceof WorkspaceItem)
{
WorkspaceItem workspaceItem = (WorkspaceItem) submission;
workspaceItem.setStageReached(step);
workspaceItem.setPageReached(page > 0 ? page : 1);
workspaceItem.update();
context.commit();
}
}
/**
* Find the maximum step the user has reached in the submission processes.
* If this submission is a workflow then return max-int.

View File

@@ -322,6 +322,10 @@ function submissionControl(collectionHandle, workspaceID, initStepAndPage)
//in case an error occurred
response_flag = doNextPage(collectionHandle, workspaceID, stepConfig, state.stepAndPage, response_flag);
var maxStep = FlowUtils.getMaximumStepReached(getDSContext(),workspaceID);
var maxPage = FlowUtils.getMaximumPageReached(getDSContext(),workspaceID);
var maxStepAndPage = parseFloat(maxStep + "." + maxPage);
//----------------------------------------------------------
// #2: Determine which page/step the user should be sent to next
//-----------------------------------------------------------
@@ -355,7 +359,8 @@ function submissionControl(collectionHandle, workspaceID, initStepAndPage)
cocoon.log.debug("Next Step & Page=" + state.stepAndPage);
}
}//User clicked "<- Previous" button
else if (cocoon.request.get(AbstractProcessingStep.PREVIOUS_BUTTON))
else if (cocoon.request.get(AbstractProcessingStep.PREVIOUS_BUTTON) &&
(response_flag==AbstractProcessingStep.STATUS_COMPLETE || state.stepAndPage == maxStepAndPage))
{
var stepBack = true;
@@ -382,21 +387,17 @@ function submissionControl(collectionHandle, workspaceID, initStepAndPage)
// User clicked "Save/Cancel" Button
else if (cocoon.request.get(AbstractProcessingStep.CANCEL_BUTTON))
{
submitStepSaveOrRemove(collectionHandle,workspaceID,step);
submitStepSaveOrRemove(collectionHandle,workspaceID,step,page);
}
//User clicked on Progress Bar:
// only check for a 'step_jump' (i.e. click on progress bar)
// if there are no errors to be resolved
if(response_flag==AbstractProcessingStep.STATUS_COMPLETE)
if(response_flag==AbstractProcessingStep.STATUS_COMPLETE || state.stepAndPage == maxStepAndPage)
{
var names = cocoon.request.getParameterNames();
while(names.hasMoreElements())
{
var maxStep = FlowUtils.getMaximumStepReached(getDSContext(),workspaceID);
var maxPage = FlowUtils.getMaximumPageReached(getDSContext(),workspaceID);
var maxStepAndPage = parseFloat(maxStep + "." + maxPage);
var name = names.nextElement();
if (name.startsWith(AbstractProcessingStep.PROGRESS_BAR_PREFIX))
{
@@ -682,15 +683,27 @@ function stepHasUI(stepConfig)
* This step is used when ever the user clicks save/cancel during the submission
* processes. We ask them if they would like to save the submission or remove it.
*/
function submitStepSaveOrRemove(collectionHandle,workspaceID,step)
function submitStepSaveOrRemove(collectionHandle,workspaceID,step,page)
{
sendPageAndWait("handle/"+collectionHandle+"/submit/saveOrRemoveStep",{"id":workspaceID,"step":String(step)});
sendPageAndWait("handle/"+collectionHandle+"/submit/saveOrRemoveStep",{"id":workspaceID,"step":String(step),"page":String(page)});
FlowUtils.processSaveOrRemove(getDSContext(), workspaceID, cocoon.request);
if (cocoon.request.get("submit_save"))
{
// Allready saved, just take them back to dspace home.
// Allready saved...
// but we need to update the reached step to prevent smart user to skip file upload
// or keep empty required metadata using the resume
var maxStep = FlowUtils.getMaximumStepReached(getDSContext(),workspaceID);
var maxPage = FlowUtils.getMaximumPageReached(getDSContext(),workspaceID);
var maxStepAndPage = parseFloat(maxStep + "." + maxPage);
var currStepAndPage = parseFloat(step + "." + page);
if (maxStepAndPage > currStepAndPage)
{
FlowUtils.setBackPageReached(getDSContext(),workspaceID, step, page);
}
var contextPath = cocoon.request.getContextPath();
cocoon.redirectTo(contextPath+"/submissions",true);
cocoon.exit();

View File

@@ -108,6 +108,9 @@
- [DS-83] Hardcoded behaviour of Initial question step in the submission
- [DS-101] Impossible to complete Registration in JSPUI
- [DS-107] DIDL Crosswalk thrown NPE
- [DS-102] Submission without file possible with the skip upload functionality disabled
- [DS-103] Use of the Progress bar button don't save the current page modification
- [DS-104] Cancel/save button during edit of a workflow item doesn't work
(Paulo Jobim)
- SF Patch [2655052] Authors re-ordered when item edited (xmlui)