/**
* 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.app.dav;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.InProgressSubmission;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.workflow.WorkflowItem;
import org.dspace.workflow.WorkflowManager;
import org.jdom.Element;
/**
* Reflect the contents of a WorkflowItem object, which is mainly an in-progress
* submission wrapper around an Item. Allow the client to read and set the slots
* in the workflow item and explore its child Item.
* <p>
* WorkflowItem resources are reached through the Workflow resource, typically
* with a path of /workflow_pool/wfi_db_{id}
* <p>
*
* @author Larry Stone
* @see DAVInProgressSubmission
* @see DAVWorkflow
*/
class DAVWorkflowItem extends DAVInProgressSubmission
{
/** log4j category. */
private static Logger log = Logger.getLogger(DAVWorkflowItem.class);
/** The Constant ownerProperty. */
private static final Element ownerProperty = new Element("owner",
DAV.NS_DSPACE);
/** The all props. */
private static List<Element> allProps = new ArrayList<Element>(inProgressProps);
static
{
allProps.add(ownerProperty);
allProps.add(stateProperty);
}
/**
* Instantiates a new DAV workflow item.
*
* @param context the context
* @param request the request
* @param response the response
* @param pathElt the path elt
* @param wi the wi
*/
protected DAVWorkflowItem(Context context, HttpServletRequest request,
HttpServletResponse response, String pathElt[],
InProgressSubmission wi)
{
super(context, request, response, pathElt, wi);
}
/* (non-Javadoc)
* @see org.dspace.app.dav.DAVResource#getAllProperties()
*/
@Override
protected List<Element> getAllProperties()
{
return allProps;
}
/* (non-Javadoc)
* @see org.dspace.app.dav.DAVResource#typeValue()
*/
@Override
protected Element typeValue()
{
return new Element("workflow-item", DAV.NS_DSPACE);
}
// format the final path element for one of these
/**
* Gets the path elt.
*
* @param dbid the dbid
*
* @return the path elt
*/
protected static String getPathElt(int dbid)
{
return "wfi_db_" + String.valueOf(dbid);
}
/**
* Gets the path elt.
*
* @param wfi the wfi
*
* @return the path elt
*/
protected static String getPathElt(WorkflowItem wfi)
{
return getPathElt(wfi.getID());
}
/**
* Match resource URI.
*
* @param context the context
* @param request the request
* @param response the response
* @param pathElt the path elt
*
* @return the DAV resource
*
* @throws DAVStatusException the DAV status exception
* @throws SQLException the SQL exception
*/
protected static DAVResource matchResourceURI(Context context,
HttpServletRequest request, HttpServletResponse response,
String pathElt[]) throws DAVStatusException, SQLException
{
try
{
// Match "/workflow/wfi_db_<id>" URI
if (pathElt.length >= 2 && pathElt[0].startsWith("workflow_")
&& pathElt[1].startsWith("wfi_db_"))
{
// match /workflow/wfi_db_<id>/item_db_<id> ...
// should be an Item (or Bitstream) URI, child of this
// WorkflowItem.
if (pathElt.length >= 3)
{
DAVResource result = DAVItem.matchResourceURI(context,
request, response, pathElt);
if (result == null)
{
throw new DAVStatusException(
HttpServletResponse.SC_NOT_FOUND,
"Invalid resource path.");
}
else
{
return result;
}
}
// get this WFI
int id = Integer.parseInt(pathElt[1].substring(7));
InProgressSubmission ips = WorkflowItem.find(context, id);
if (ips == null)
{
log.warn("invalid WorkflowItem DB ID in DAV URI, " + "id="
+ pathElt[1]);
throw new DAVStatusException(
HttpServletResponse.SC_NOT_FOUND, "Not found: "
+ pathElt[1] + " does not exist.");
}
else
{
return new DAVWorkflowItem(context, request, response,
pathElt, ips);
}
}
return null;
}
catch (NumberFormatException ne)
{
throw new DAVStatusException(HttpServletResponse.SC_BAD_REQUEST,
"Error parsing number in request URI.", ne);
}
}
/* (non-Javadoc)
* @see org.dspace.app.dav.DAVInProgressSubmission#propfindInternal(org.jdom.Element)
*/
@Override
protected Element propfindInternal(Element property) throws SQLException,
AuthorizeException, IOException, DAVStatusException
{
Element result = super.propfindInternal(property);
if (result != null)
{
return result;
}
String value = null;
// displayname - title or handle.
if (elementsEqualIsh(property, displaynameProperty))
{
value = getPathElt(this.inProgressItem.getID());
}
else if (elementsEqualIsh(property, ownerProperty))
{
EPerson ep = ((WorkflowItem) this.inProgressItem).getOwner();
if (ep != null)
{
value = hrefToEPerson(ep);
}
}
else if (elementsEqualIsh(property, stateProperty))
{
value = WorkflowManager.getWorkflowText(((WorkflowItem) this.inProgressItem).getState());
}
else
{
return super.propfindInternal(property);
}
// value was set up by "if" clause:
if (value == null)
{
throw new DAVStatusException(HttpServletResponse.SC_NOT_FOUND,
"Not found.");
}
Element p = new Element(property.getName(), property.getNamespace());
p.setText(filterForXML(value));
return p;
}
/* (non-Javadoc)
* @see org.dspace.app.dav.DAVInProgressSubmission#proppatchInternal(int, org.jdom.Element)
*/
@Override
protected int proppatchInternal(int action, Element prop)
throws SQLException, AuthorizeException, IOException,
DAVStatusException
{
if (super.proppatchInternal(action, prop) == HttpServletResponse.SC_OK)
{
return HttpServletResponse.SC_OK;
}
else if (elementsEqualIsh(prop, stateProperty))
{
if (action == DAV.PROPPATCH_REMOVE)
{
throw new DAVStatusException(DAV.SC_CONFLICT,
"The state property cannot be removed.");
}
String key = prop.getTextTrim();
int newState;
if (key.equalsIgnoreCase("abort"))
{
WorkflowManager.abort(this.context, (WorkflowItem) this.inProgressItem,
this.inProgressItem.getSubmitter());
}
else if (key.equalsIgnoreCase("reject"))
{
EPerson cu = this.context.getCurrentUser();
String who = cu == null ? "nobody" : cu.getFullName();
WorkflowManager.reject(this.context, (WorkflowItem) this.inProgressItem,
this.inProgressItem.getSubmitter(), "Rejected by " + who
+ ", via WebDAV Network Interface");
}
else if (key.equalsIgnoreCase("advance"))
{
WorkflowManager.advance(this.context, (WorkflowItem) this.inProgressItem,
this.context.getCurrentUser());
}
else if (key.equalsIgnoreCase("claim"))
{
WorkflowManager.claim(this.context, (WorkflowItem) this.inProgressItem,
this.context.getCurrentUser());
}
else if (key.equalsIgnoreCase("unclaim"))
{
WorkflowManager.unclaim(this.context, (WorkflowItem) this.inProgressItem,
this.context.getCurrentUser());
}
else
{
newState = WorkflowManager.getWorkflowID(key);
if (newState >= 0)
{
((WorkflowItem) this.inProgressItem).setState(newState);
}
else
{
throw new DAVStatusException(DAV.SC_CONFLICT,
"Unrecognized verb or state-name in value for state property.");
}
}
this.inProgressItem.update();
return HttpServletResponse.SC_OK;
}
throw new DAVStatusException(DAV.SC_CONFLICT, "The " + prop.getName()
+ " property cannot be changed.");
}
}