/*
* WorkspaceItem.java
*
* Version: $Revision: 3705 $
*
* Date: $Date: 2009-04-11 18:02:24 +0100 (Sat, 11 Apr 2009) $
*
* Copyright (c) 2002-2005, 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.content;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.storage.rdbms.DatabaseManager;
import org.dspace.storage.rdbms.TableRow;
import org.dspace.storage.rdbms.TableRowIterator;
import uk.ac.jorum.utils.ExceptionLogger;
/**
* Class representing an item in the process of being submitted by a user
*
* @author Robert Tansley
* @version $Revision: 3705 $
*/
public class WorkspaceItem implements InProgressSubmission
{
/** log4j logger */
private static Logger log = Logger.getLogger(WorkspaceItem.class);
/** The item this workspace object pertains to */
private Item item;
/** Our context */
private Context ourContext;
/** The table row corresponding to this workspace item */
private TableRow wiRow;
/** The collection the item is being submitted to */
private Collection collection;
/**
* Construct a workspace item corresponding to the given database row
*
* @param context
* the context this object exists in
* @param row
* the database row
*/
WorkspaceItem(Context context, TableRow row) throws SQLException
{
ourContext = context;
wiRow = row;
item = Item.find(context, wiRow.getIntColumn("item_id"));
collection = Collection.find(context, wiRow
.getIntColumn("collection_id"));
// Cache ourselves
context.cache(this, row.getIntColumn("workspace_item_id"));
}
/**
* Get a workspace item from the database. The item, collection and
* submitter are loaded into memory.
*
* @param context
* DSpace context object
* @param id
* ID of the workspace item
*
* @return the workspace item, or null if the ID is invalid.
*/
public static WorkspaceItem find(Context context, int id)
throws SQLException
{
// First check the cache
WorkspaceItem fromCache = (WorkspaceItem) context.fromCache(
WorkspaceItem.class, id);
if (fromCache != null)
{
return fromCache;
}
TableRow row = DatabaseManager.find(context, "workspaceitem", id);
if (row == null)
{
if (log.isDebugEnabled())
{
log.debug(LogManager.getHeader(context, "find_workspace_item",
"not_found,workspace_item_id=" + id));
}
return null;
}
else
{
if (log.isDebugEnabled())
{
log.debug(LogManager.getHeader(context, "find_workspace_item",
"workspace_item_id=" + id));
}
return new WorkspaceItem(context, row);
}
}
/**
* Create a new workspace item, with a new ID. An Item is also created. The
* submitter is the current user in the context.
*
* @param c
* DSpace context object
* @param coll
* Collection being submitted to
* @param template
* if <code>true</code>, the workspace item starts as a copy
* of the collection's template item
*
* @return the newly created workspace item
*/
public static WorkspaceItem create(Context c, Collection coll,
boolean template) throws AuthorizeException, SQLException,
IOException
{
// Check the user has permission to ADD to the collection
AuthorizeManager.authorizeAction(c, coll, Constants.ADD);
// Create an item
Item i = Item.create(c);
i.setSubmitter(c.getCurrentUser());
// Now create the policies for the submitter and workflow
// users to modify item and contents
// contents = bitstreams, bundles
// FIXME: icky hardcoded workflow steps
Group step1group = coll.getWorkflowGroup(1);
Group step2group = coll.getWorkflowGroup(2);
Group step3group = coll.getWorkflowGroup(3);
EPerson e = c.getCurrentUser();
// read permission
AuthorizeManager.addPolicy(c, i, Constants.READ, e);
if (step1group != null)
{
AuthorizeManager.addPolicy(c, i, Constants.READ, step1group);
}
if (step2group != null)
{
AuthorizeManager.addPolicy(c, i, Constants.READ, step2group);
}
if (step3group != null)
{
AuthorizeManager.addPolicy(c, i, Constants.READ, step3group);
}
// write permission
AuthorizeManager.addPolicy(c, i, Constants.WRITE, e);
if (step1group != null)
{
AuthorizeManager.addPolicy(c, i, Constants.WRITE, step1group);
}
if (step2group != null)
{
AuthorizeManager.addPolicy(c, i, Constants.WRITE, step2group);
}
if (step3group != null)
{
AuthorizeManager.addPolicy(c, i, Constants.WRITE, step3group);
}
// add permission
AuthorizeManager.addPolicy(c, i, Constants.ADD, e);
if (step1group != null)
{
AuthorizeManager.addPolicy(c, i, Constants.ADD, step1group);
}
if (step2group != null)
{
AuthorizeManager.addPolicy(c, i, Constants.ADD, step2group);
}
if (step3group != null)
{
AuthorizeManager.addPolicy(c, i, Constants.ADD, step3group);
}
// remove contents permission
AuthorizeManager.addPolicy(c, i, Constants.REMOVE, e);
if (step1group != null)
{
AuthorizeManager.addPolicy(c, i, Constants.REMOVE, step1group);
}
if (step2group != null)
{
AuthorizeManager.addPolicy(c, i, Constants.REMOVE, step2group);
}
if (step3group != null)
{
AuthorizeManager.addPolicy(c, i, Constants.REMOVE, step3group);
}
// Copy template if appropriate
Item templateItem = coll.getTemplateItem();
if (template && (templateItem != null))
{
DCValue[] md = templateItem.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY);
for (int n = 0; n < md.length; n++)
{
i.addMetadata(md[n].schema, md[n].element, md[n].qualifier, md[n].language,
md[n].value);
}
}
i.update();
// Create the workspace item row
TableRow row = DatabaseManager.create(c, "workspaceitem");
row.setColumn("item_id", i.getID());
row.setColumn("collection_id", coll.getID());
log.info(LogManager.getHeader(c, "create_workspace_item",
"workspace_item_id=" + row.getIntColumn("workspace_item_id")
+ "item_id=" + i.getID() + "collection_id="
+ coll.getID()));
DatabaseManager.update(c, row);
WorkspaceItem wi = new WorkspaceItem(c, row);
return wi;
}
/**
* Get all workspace items for a particular e-person. These are ordered by
* workspace item ID, since this should likely keep them in the order in
* which they were created.
*
* @param context
* the context object
* @param ep
* the eperson
*
* @return the corresponding workspace items
*/
public static WorkspaceItem[] findByEPerson(Context context, EPerson ep)
throws SQLException
{
List wsItems = new ArrayList();
TableRowIterator tri = DatabaseManager.queryTable(context, "workspaceitem",
"SELECT workspaceitem.* FROM workspaceitem, item WHERE " +
"workspaceitem.item_id=item.item_id AND " +
"item.submitter_id= ? " +
"ORDER BY workspaceitem.workspace_item_id",
ep.getID());
try
{
while (tri.hasNext())
{
TableRow row = tri.next();
// Check the cache
WorkspaceItem wi = (WorkspaceItem) context.fromCache(
WorkspaceItem.class, row.getIntColumn("workspace_item_id"));
if (wi == null)
{
wi = new WorkspaceItem(context, row);
}
wsItems.add(wi);
}
}
finally
{
// close the TableRowIterator to free up resources
if (tri != null)
tri.close();
}
WorkspaceItem[] wsArray = new WorkspaceItem[wsItems.size()];
wsArray = (WorkspaceItem[]) wsItems.toArray(wsArray);
return wsArray;
}
/**
* Get all workspace items for a particular collection.
*
* @param context
* the context object
* @param c
* the collection
*
* @return the corresponding workspace items
*/
public static WorkspaceItem[] findByCollection(Context context, Collection c)
throws SQLException
{
List wsItems = new ArrayList();
TableRowIterator tri = DatabaseManager.queryTable(context, "workspaceitem",
"SELECT workspaceitem.* FROM workspaceitem WHERE " +
"workspaceitem.collection_id= ? ",
c.getID());
try
{
while (tri.hasNext())
{
TableRow row = tri.next();
// Check the cache
WorkspaceItem wi = (WorkspaceItem) context.fromCache(
WorkspaceItem.class, row.getIntColumn("workspace_item_id"));
// not in cache? turn row into workspaceitem
if (wi == null)
{
wi = new WorkspaceItem(context, row);
}
wsItems.add(wi);
}
}
finally
{
// close the TableRowIterator to free up resources
if (tri != null)
tri.close();
}
WorkspaceItem[] wsArray = new WorkspaceItem[wsItems.size()];
wsArray = (WorkspaceItem[]) wsItems.toArray(wsArray);
return wsArray;
}
/**
* Get all workspace items in the whole system
*
* @param context the context object
*
* @return all workspace items
*/
public static WorkspaceItem[] findAll(Context context)
throws SQLException
{
List wsItems = new ArrayList();
String query = "SELECT * FROM workspaceitem ORDER BY item_id";
TableRowIterator tri = DatabaseManager.queryTable(context,
"workspaceitem",
query);
try
{
while (tri.hasNext())
{
TableRow row = tri.next();
// Check the cache
WorkspaceItem wi = (WorkspaceItem) context.fromCache(
WorkspaceItem.class, row.getIntColumn("workspace_item_id"));
// not in cache? turn row into workspaceitem
if (wi == null)
{
wi = new WorkspaceItem(context, row);
}
wsItems.add(wi);
}
}
finally
{
// close the TableRowIterator to free up resources
if (tri != null)
tri.close();
}
WorkspaceItem[] wsArray = new WorkspaceItem[wsItems.size()];
wsArray = (WorkspaceItem[]) wsItems.toArray(wsArray);
return wsArray;
}
/**
* Get the internal ID of this workspace item
*
* @return the internal identifier
*/
public int getID()
{
return wiRow.getIntColumn("workspace_item_id");
}
/**
* Get the value of the stage reached column
*
* @return the value of the stage reached column
*/
public int getStageReached()
{
return wiRow.getIntColumn("stage_reached");
}
/**
* Set the value of the stage reached column
*
* @param v
* the value of the stage reached column
*/
public void setStageReached(int v)
{
wiRow.setColumn("stage_reached", v);
}
/**
* Get the value of the page reached column (which represents the page
* reached within a stage/step)
*
* @return the value of the page reached column
*/
public int getPageReached()
{
return wiRow.getIntColumn("page_reached");
}
/**
* Set the value of the page reached column (which represents the page
* reached within a stage/step)
*
* @param v
* the value of the page reached column
*/
public void setPageReached(int v)
{
wiRow.setColumn("page_reached", v);
}
/**
* Update the workspace item, including the unarchived item.
*/
public void update() throws SQLException, AuthorizeException, IOException
{
// Authorisation is checked by the item.update() method below
log.info(LogManager.getHeader(ourContext, "update_workspace_item",
"workspace_item_id=" + getID()));
// Update the item
item.update();
// Update ourselves
DatabaseManager.update(ourContext, wiRow);
}
/**
* Delete the workspace item. The entry in workspaceitem, the unarchived
* item and its contents are all removed (multiple inclusion
* notwithstanding.)
*/
public void deleteAll() throws SQLException, AuthorizeException,
IOException
{
/*
* Authorisation is a special case. The submitter won't have REMOVE
* permission on the collection, so our policy is this: Only the
* original submitter or an administrator can delete a workspace item.
*/
if (!AuthorizeManager.isAdmin(ourContext)
&& ((ourContext.getCurrentUser() == null) || (ourContext
.getCurrentUser().getID() != item.getSubmitter()
.getID())))
{
// Not an admit, not the submitter
throw new AuthorizeException("Must be an administrator or the "
+ "original submitter to delete a workspace item");
}
log.info(LogManager.getHeader(ourContext, "delete_workspace_item",
"workspace_item_id=" + getID() + "item_id=" + item.getID()
+ "collection_id=" + collection.getID()));
//deleteSubmitPermissions();
// Remove from cache
ourContext.removeCached(this, getID());
// Need to delete the epersongroup2workspaceitem row first since it refers
// to workspaceitem ID
deleteEpersonGroup2WorkspaceItem();
// Need to delete the workspaceitem row first since it refers
// to item ID
DatabaseManager.delete(ourContext, wiRow);
// Delete item
item.delete();
}
private void deleteEpersonGroup2WorkspaceItem() throws SQLException
{
String removeSQL="DELETE FROM epersongroup2workspaceitem WHERE workspace_item_id = ?";
DatabaseManager.updateQuery(ourContext, removeSQL,getID());
}
public void deleteWrapper() throws SQLException, AuthorizeException,
IOException
{
// Check authorisation. We check permissions on the enclosed item.
AuthorizeManager.authorizeAction(ourContext, item, Constants.WRITE);
log.info(LogManager.getHeader(ourContext, "delete_workspace_item",
"workspace_item_id=" + getID() + "item_id=" + item.getID()
+ "collection_id=" + collection.getID()));
// deleteSubmitPermissions();
// Remove from cache
ourContext.removeCached(this, getID());
// Need to delete the workspaceitem row first since it refers
// to item ID
DatabaseManager.delete(ourContext, wiRow);
}
// InProgressSubmission methods
public Item getItem()
{
return item;
}
public Collection getCollection()
{
return collection;
}
public EPerson getSubmitter() throws SQLException
{
return item.getSubmitter();
}
public boolean hasMultipleFiles()
{
return wiRow.getBooleanColumn("multiple_files");
}
public void setMultipleFiles(boolean b)
{
wiRow.setColumn("multiple_files", b);
}
public boolean hasMultipleTitles()
{
return wiRow.getBooleanColumn("multiple_titles");
}
public void setMultipleTitles(boolean b)
{
wiRow.setColumn("multiple_titles", b);
}
public boolean isPublishedBefore()
{
return wiRow.getBooleanColumn("published_before");
}
public void setPublishedBefore(boolean b)
{
wiRow.setColumn("published_before", b);
}
// GWaller 30/11/09 Method to reset collection
public void setCollection(Collection c) throws SQLException, AuthorizeException, IOException{
log.debug("Resetting collection in WorkspaceItem. New Collection: " + c.getName() + " (id=" + c.getID() + ")" );
int origCol = wiRow.getIntColumn("collection_id");
try{
wiRow.setColumn("collection_id", c.getID());
this.update();
// Must of course set the instance pointer to the new collection!
this.collection = c;
} catch (Exception e){
ExceptionLogger.logException(log, e);
// reset the row back to the orig
wiRow.setColumn("collection_id", origCol);
}
}
}