/**
* 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.submit.step;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.dspace.app.util.SubmissionInfo;
import org.dspace.app.util.Util;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.*;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.WorkspaceItemService;
import org.dspace.core.Context;
import org.dspace.submit.AbstractProcessingStep;
/**
* Initial Submission servlet for DSpace. Handles the initial questions which
* are asked to users to gather information regarding what metadata needs to be
* gathered.
* <P>
* This class performs all the behind-the-scenes processing that
* this particular step requires. This class's methods are utilized
* by both the JSP-UI and the Manakin XML-UI
* <P>
*
* @see org.dspace.app.util.SubmissionConfig
* @see org.dspace.app.util.SubmissionStepConfig
* @see org.dspace.submit.AbstractProcessingStep
*
* @author Tim Donohue
* @version $Revision$
*/
public class InitialQuestionsStep extends AbstractProcessingStep
{
/***************************************************************************
* STATUS / ERROR FLAGS (returned by doProcessing() if an error occurs or
* additional user interaction may be required)
*
* (Do NOT use status of 0, since it corresponds to STATUS_COMPLETE flag
* defined in the JSPStepManager class)
**************************************************************************/
// pruning of metadata needs to take place
public static final int STATUS_VERIFY_PRUNE = 1;
// pruning was cancelled by user
public static final int STATUS_CANCEL_PRUNE = 2;
// user attempted to upload a thesis, when theses are not accepted
public static final int STATUS_THESIS_REJECTED = 3;
/**
* Global flags to determine if we need to prune anything
*/
protected boolean willRemoveTitles = false;
protected boolean willRemoveDate = false;
protected boolean willRemoveFiles = false;
protected WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService();
/**
* Do any processing of the information input by the user, and/or perform
* step processing (if no user interaction required)
* <P>
* It is this method's job to save any data to the underlying database, as
* necessary, and return error messages (if any) which can then be processed
* by the appropriate user interface (JSP-UI or XML-UI)
* <P>
* NOTE: If this step is a non-interactive step (i.e. requires no UI), then
* it should perform *all* of its processing in this method!
*
* @param context
* current DSpace context
* @param request
* current servlet request object
* @param response
* current servlet response object
* @param subInfo
* submission info object
* @return Status or error flag which will be processed by
* doPostProcessing() below! (if STATUS_COMPLETE or 0 is returned,
* no errors occurred!)
* @throws ServletException
* A general exception a servlet can throw when it encounters difficulty.
* @throws IOException
* A general class of exceptions produced by failed or interrupted I/O operations.
* @throws SQLException
* An exception that provides information on a database access error or other errors.
* @throws AuthorizeException
* Exception indicating the current user of the context does not have permission
* to perform a particular action.
*/
@Override
public int doProcessing(Context context, HttpServletRequest request,
HttpServletResponse response, SubmissionInfo subInfo)
throws ServletException, IOException, SQLException,
AuthorizeException
{
// Get the values from the initial questions form
boolean multipleTitles = Util.getBoolParameter(request,
"multiple_titles");
boolean publishedBefore = Util.getBoolParameter(request,
"published_before");
boolean multipleFiles = Util.getBoolParameter(request,
"multiple_files");
boolean isThesis = configurationService.getBooleanProperty("webui.submit.blocktheses")
&& Util.getBoolParameter(request, "is_thesis");
if (subInfo.isInWorkflow())
{
// Thesis question does not appear in workflow mode..
isThesis = false;
// Pretend "multiple files" is true in workflow mode
// (There will always be the license file)
multipleFiles = true;
}
// First and foremost - if it's a thesis, reject the submission
if (isThesis)
{
WorkspaceItem wi = (WorkspaceItem) subInfo.getSubmissionItem();
workspaceItemService.deleteAll(context, wi);
subInfo.setSubmissionItem(null);
// Remember that we've removed a thesis in the session
request.getSession().setAttribute("removed_thesis",
Boolean.TRUE);
return STATUS_THESIS_REJECTED; // since theses are disabled, throw
// an error!
}
// Next, check if we are pruning some existing metadata
Item item = subInfo.getSubmissionItem().getItem();
if (request.getParameter("do_not_prune") != null)
{
return STATUS_CANCEL_PRUNE; // cancelled pruning!
}
else if (request.getParameter("prune") != null)
{
processVerifyPrune(context, request, response, subInfo,
multipleTitles, publishedBefore, multipleFiles);
}
else
// otherwise, check if pruning is necessary
{
// Now check to see if the changes will remove any values
// (i.e. multiple files, titles or an issue date.)
if (subInfo.getSubmissionItem() != null)
{
// shouldn't need to check if submission is null, but just in case!
if (!multipleTitles)
{
List<MetadataValue> altTitles = itemService
.getMetadata(item, MetadataSchema.DC_SCHEMA, "title", "alternative", Item.ANY);
willRemoveTitles = altTitles.size() > 0;
}
if (!publishedBefore)
{
List<MetadataValue> dateIssued = itemService
.getMetadata(item, MetadataSchema.DC_SCHEMA, "date", "issued", Item.ANY);
List<MetadataValue> citation = itemService
.getMetadata(item, MetadataSchema.DC_SCHEMA, "identifier", "citation", Item.ANY);
List<MetadataValue> publisher = itemService
.getMetadata(item, MetadataSchema.DC_SCHEMA, "publisher", null, Item.ANY);
willRemoveDate = (dateIssued.size() > 0)
|| (citation.size() > 0) || (publisher.size() > 0);
}
if (!multipleFiles)
{
// see if number of bitstreams in "ORIGINAL" bundle > 1
// FIXME: Assumes multiple bundles, clean up someday...
List<Bundle> bundles = itemService
.getBundles(item, "ORIGINAL");
if (bundles.size() > 0)
{
List<Bitstream> bitstreams = bundles.get(0).getBitstreams();
willRemoveFiles = bitstreams.size() > 1;
}
}
}
// If anything is going to be removed from the item as a result
// of changing the answer to one of the questions, we need
// to inform the user and make sure that's OK, before saving!
if (willRemoveTitles || willRemoveDate || willRemoveFiles)
{
//save what we will need to prune to request (for UI to process)
request.setAttribute("will.remove.titles", Boolean.valueOf(willRemoveTitles));
request.setAttribute("will.remove.date", Boolean.valueOf(willRemoveDate));
request.setAttribute("will.remove.files", Boolean.valueOf(willRemoveFiles));
return STATUS_VERIFY_PRUNE; // we will need to do pruning!
}
}
// If step is complete, save the changes
subInfo.getSubmissionItem().setMultipleTitles(multipleTitles);
subInfo.getSubmissionItem().setPublishedBefore(publishedBefore);
// "Multiple files" irrelevant in workflow mode
if (!subInfo.isInWorkflow())
{
subInfo.getSubmissionItem().setMultipleFiles(multipleFiles);
}
// If this work has not been published before & no issued date is set,
// then the assumption is that TODAY is the issued date.
// (This logic is necessary since the date field is hidden on DescribeStep when publishedBefore==false)
if(!publishedBefore)
{
List<MetadataValue> dateIssued = itemService
.getMetadata(item, MetadataSchema.DC_SCHEMA, "date", "issued", Item.ANY);
if(dateIssued.size()==0)
{
//Set issued date to "today" (NOTE: InstallItem will determine the actual date for us)
itemService.addMetadata(context, item, MetadataSchema.DC_SCHEMA, "date", "issued", null, "today");
}
}
// commit all changes to DB
ContentServiceFactory.getInstance().getInProgressSubmissionService(subInfo.getSubmissionItem()).update(context, subInfo.getSubmissionItem());
context.dispatchEvents();
return STATUS_COMPLETE; // no errors!
}
/**
* Retrieves the number of pages that this "step" extends over. This method
* is used to build the progress bar.
* <P>
* This method may just return 1 for most steps (since most steps consist of
* a single page). But, it should return a number greater than 1 for any
* "step" which spans across a number of HTML pages. For example, the
* configurable "Describe" step (configured using input-forms.xml) overrides
* this method to return the number of pages that are defined by its
* configuration file.
* <P>
* Steps which are non-interactive (i.e. they do not display an interface to
* the user) should return a value of 1, so that they are only processed
* once!
*
* @param request
* The HTTP Request
* @param subInfo
* The current submission information object
*
* @return the number of pages in this step
*/
@Override
public int getNumberOfPages(HttpServletRequest request,
SubmissionInfo subInfo) throws ServletException
{
// always just one page of initial questions
return 1;
}
/**
* Process input from "verify prune" page
*
* @param context
* current DSpace context
* @param request
* current servlet request object
* @param response
* current servlet response object
* @param subInfo
* submission info object
* @param multipleTitles
* if there is multiple titles
* @param publishedBefore
* if published before
* @param multipleFiles
* if there will be multiple files
* @throws ServletException
* A general exception a servlet can throw when it encounters difficulty.
* @throws IOException
* A general class of exceptions produced by failed or interrupted I/O operations.
* @throws SQLException
* An exception that provides information on a database access error or other errors.
* @throws AuthorizeException
* Exception indicating the current user of the context does not have permission
* to perform a particular action.
*/
protected void processVerifyPrune(Context context,
HttpServletRequest request, HttpServletResponse response,
SubmissionInfo subInfo, boolean multipleTitles,
boolean publishedBefore, boolean multipleFiles)
throws ServletException, IOException, SQLException,
AuthorizeException
{
// get the item to prune
Item item = subInfo.getSubmissionItem().getItem();
if (!multipleTitles && subInfo.getSubmissionItem().hasMultipleTitles())
{
itemService.clearMetadata(context, item, MetadataSchema.DC_SCHEMA, "title", "alternative", Item.ANY);
}
if (!publishedBefore && subInfo.getSubmissionItem().isPublishedBefore())
{
itemService.clearMetadata(context, item, MetadataSchema.DC_SCHEMA, "date", "issued", Item.ANY);
itemService.clearMetadata(context, item, MetadataSchema.DC_SCHEMA, "identifier", "citation", Item.ANY);
itemService.clearMetadata(context, item, MetadataSchema.DC_SCHEMA, "publisher", null, Item.ANY);
}
if (!multipleFiles && subInfo.getSubmissionItem().hasMultipleFiles())
{
// remove all but first bitstream from bundle[0]
// FIXME: Assumes multiple bundles, clean up someday...
// (only messes with the first bundle.)
List<Bundle> bundles = itemService.getBundles(item, "ORIGINAL");
if (bundles.size() > 0)
{
Iterator<Bitstream> bitstreams = bundles.get(0).getBitstreams().iterator();
//Do NOT remove the first one
if(bitstreams.hasNext())
{
bitstreams.next();
}
while (bitstreams.hasNext())
{
//TODO: HIBERNATE, write unit test for this
Bitstream bitstream = bitstreams.next();
bundleService.removeBitstream(context, bundles.get(0), bitstream);
}
}
}
}
}