/* * Collection.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.io.InputStream; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.MissingResourceException; import org.apache.log4j.Logger; import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeManager; import org.dspace.authorize.ResourcePolicy; import org.dspace.browse.BrowseException; import org.dspace.browse.IndexBrowse; import org.dspace.browse.ItemCounter; import org.dspace.browse.ItemCountException; import org.dspace.core.ConfigurationManager; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.I18nUtil; import org.dspace.core.LogManager; import org.dspace.eperson.Group; import org.dspace.event.Event; import org.dspace.handle.HandleManager; import org.dspace.storage.rdbms.DatabaseManager; import org.dspace.storage.rdbms.TableRow; import org.dspace.storage.rdbms.TableRowIterator; import org.dspace.workflow.WorkflowItem; /** * Class representing a collection. * <P> * The collection's metadata (name, introductory text etc), workflow groups, and * default group of submitters are loaded into memory. Changes to metadata are * not written to the database until <code>update</code> is called. If you * create or remove a workflow group, the change is only reflected in the * database after calling <code>update</code>. The default group of * submitters is slightly different - creating or removing this has instant * effect. * * @author Robert Tansley * @version $Revision: 3705 $ */ public class Collection extends DSpaceObject { /** log4j category */ private static Logger log = Logger.getLogger(Collection.class); /** Our context */ private Context ourContext; /** The table row corresponding to this item */ private TableRow collectionRow; /** The logo bitstream */ private Bitstream logo; /** The item template */ private Item template; /** Our Handle */ private String handle; /** Flag set when data is modified, for events */ private boolean modified; /** Flag set when metadata is modified, for events */ private boolean modifiedMetadata; /** * Groups corresponding to workflow steps - NOTE these start from one, so * workflowGroups[0] corresponds to workflow_step_1. */ private Group[] workflowGroup; /** The default group of submitters */ private Group submitters; /** The default group of administrators */ private Group admins; /** * Construct a collection with the given table row * * @param context * the context this object exists in * @param row * the corresponding row in the table * @throws SQLException */ Collection(Context context, TableRow row) throws SQLException { ourContext = context; collectionRow = row; // Get the logo bitstream if (collectionRow.isColumnNull("logo_bitstream_id")) { logo = null; } else { logo = Bitstream.find(ourContext, collectionRow .getIntColumn("logo_bitstream_id")); } // Get the template item if (collectionRow.isColumnNull("template_item_id")) { template = null; } else { template = Item.find(ourContext, collectionRow .getIntColumn("template_item_id")); } // Get the relevant groups workflowGroup = new Group[3]; workflowGroup[0] = groupFromColumn("workflow_step_1"); workflowGroup[1] = groupFromColumn("workflow_step_2"); workflowGroup[2] = groupFromColumn("workflow_step_3"); submitters = groupFromColumn("submitter"); admins = groupFromColumn("admin"); // Get our Handle if any handle = HandleManager.findHandle(context, this); // Cache ourselves context.cache(this, row.getIntColumn("collection_id")); modified = modifiedMetadata = false; clearDetails(); } /** * Get a collection from the database. Loads in the metadata * * @param context * DSpace context object * @param id * ID of the collection * * @return the collection, or null if the ID is invalid. * @throws SQLException */ public static Collection find(Context context, int id) throws SQLException { // First check the cache Collection fromCache = (Collection) context.fromCache(Collection.class, id); if (fromCache != null) { return fromCache; } TableRow row = DatabaseManager.find(context, "collection", id); if (row == null) { if (log.isDebugEnabled()) { log.debug(LogManager.getHeader(context, "find_collection", "not_found,collection_id=" + id)); } return null; } // not null, return Collection if (log.isDebugEnabled()) { log.debug(LogManager.getHeader(context, "find_collection", "collection_id=" + id)); } return new Collection(context, row); } /** * Create a new collection, with a new ID. This method is not public, and * does not check authorisation. * * @param context * DSpace context object * * @return the newly created collection * @throws SQLException * @throws AuthorizeException */ static Collection create(Context context) throws SQLException, AuthorizeException { TableRow row = DatabaseManager.create(context, "collection"); Collection c = new Collection(context, row); c.handle = HandleManager.createHandle(context, c); // create the default authorization policy for collections // of 'anonymous' READ Group anonymousGroup = Group.find(context, 0); ResourcePolicy myPolicy = ResourcePolicy.create(context); myPolicy.setResource(c); myPolicy.setAction(Constants.READ); myPolicy.setGroup(anonymousGroup); myPolicy.update(); // now create the default policies for submitted items myPolicy = ResourcePolicy.create(context); myPolicy.setResource(c); myPolicy.setAction(Constants.DEFAULT_ITEM_READ); myPolicy.setGroup(anonymousGroup); myPolicy.update(); myPolicy = ResourcePolicy.create(context); myPolicy.setResource(c); myPolicy.setAction(Constants.DEFAULT_BITSTREAM_READ); myPolicy.setGroup(anonymousGroup); myPolicy.update(); context.addEvent(new Event(Event.CREATE, Constants.COLLECTION, c.getID(), c.handle)); log.info(LogManager.getHeader(context, "create_collection", "collection_id=" + row.getIntColumn("collection_id")) + ",handle=" + c.handle); return c; } /** * Get all collections in the system. These are alphabetically sorted by * collection name. * * @param context * DSpace context object * * @return the collections in the system * @throws SQLException */ public static Collection[] findAll(Context context) throws SQLException { TableRowIterator tri = DatabaseManager.queryTable(context, "collection", "SELECT * FROM collection ORDER BY name"); List<Collection> collections = new ArrayList<Collection>(); try { while (tri.hasNext()) { TableRow row = tri.next(); // First check the cache Collection fromCache = (Collection) context.fromCache( Collection.class, row.getIntColumn("collection_id")); if (fromCache != null) { collections.add(fromCache); } else { collections.add(new Collection(context, row)); } } } finally { // close the TableRowIterator to free up resources if (tri != null) tri.close(); } Collection[] collectionArray = new Collection[collections.size()]; collectionArray = (Collection[]) collections.toArray(collectionArray); return collectionArray; } /** * Get the in_archive items in this collection. The order is indeterminate. * * @return an iterator over the items in the collection. * @throws SQLException */ public ItemIterator getItems() throws SQLException { String myQuery = "SELECT item.* FROM item, collection2item WHERE " + "item.item_id=collection2item.item_id AND " + "collection2item.collection_id= ? " + "AND item.in_archive='1'"; TableRowIterator rows = DatabaseManager.queryTable(ourContext, "item", myQuery,getID()); return new ItemIterator(ourContext, rows); } /** * Get all the items in this collection. The order is indeterminate. * * @return an iterator over the items in the collection. * @throws SQLException */ public ItemIterator getAllItems() throws SQLException { String myQuery = "SELECT item.* FROM item, collection2item WHERE " + "item.item_id=collection2item.item_id AND " + "collection2item.collection_id= ? "; TableRowIterator rows = DatabaseManager.queryTable(ourContext, "item", myQuery,getID()); return new ItemIterator(ourContext, rows); } /** * Get the internal ID of this collection * * @return the internal identifier */ public int getID() { return collectionRow.getIntColumn("collection_id"); } /** * @see org.dspace.content.DSpaceObject#getHandle() */ public String getHandle() { if(handle == null) { try { handle = HandleManager.findHandle(this.ourContext, this); } catch (SQLException e) { // TODO Auto-generated catch block //e.printStackTrace(); } } return handle; } /** * Get the value of a metadata field * * @param field * the name of the metadata field to get * * @return the value of the metadata field * * @exception IllegalArgumentException * if the requested metadata field doesn't exist */ public String getMetadata(String field) { String metadata = collectionRow.getStringColumn(field); return (metadata == null) ? "" : metadata; } /** * Set a metadata value * * @param field * the name of the metadata field to get * @param value * value to set the field to * * @exception IllegalArgumentException * if the requested metadata field doesn't exist * @exception MissingResourceException */ public void setMetadata(String field, String value) throws MissingResourceException { if ((field.trim()).equals("name") && (value == null || value.trim().equals(""))) { try { value = I18nUtil.getMessage("org.dspace.workflow.WorkflowManager.untitled"); } catch (MissingResourceException e) { value = "Untitled"; } } /* * Set metadata field to null if null * and trim strings to eliminate excess * whitespace. */ if(value == null) { collectionRow.setColumnNull(field); } else { collectionRow.setColumn(field, value.trim()); } modifiedMetadata = true; addDetails(field); } public String getName() { return getMetadata("name"); } /** * Get the logo for the collection. <code>null</code> is return if the * collection does not have a logo. * * @return the logo of the collection, or <code>null</code> */ public Bitstream getLogo() { return logo; } /** * Give the collection a logo. Passing in <code>null</code> removes any * existing logo. You will need to set the format of the new logo bitstream * before it will work, for example to "JPEG". Note that * <code>update(/code> will need to be called for the change to take * effect. Setting a logo and not calling <code>update</code> later may * result in a previous logo lying around as an "orphaned" bitstream. * * @param is the stream to use as the new logo * * @return the new logo bitstream, or <code>null</code> if there is no * logo (<code>null</code> was passed in) * @throws AuthorizeException * @throws IOException * @throws SQLException */ public Bitstream setLogo(InputStream is) throws AuthorizeException, IOException, SQLException { // Check authorisation // authorized to remove the logo when DELETE rights // authorized when canEdit if (!((is == null) && AuthorizeManager.authorizeActionBoolean( ourContext, this, Constants.DELETE))) { canEdit(); } // First, delete any existing logo if (!collectionRow.isColumnNull("logo_bitstream_id")) { logo.delete(); } if (is == null) { collectionRow.setColumnNull("logo_bitstream_id"); logo = null; log.info(LogManager.getHeader(ourContext, "remove_logo", "collection_id=" + getID())); } else { Bitstream newLogo = Bitstream.create(ourContext, is); collectionRow.setColumn("logo_bitstream_id", newLogo.getID()); logo = newLogo; // now create policy for logo bitstream // to match our READ policy List policies = AuthorizeManager.getPoliciesActionFilter( ourContext, this, Constants.READ); AuthorizeManager.addPolicies(ourContext, policies, newLogo); log.info(LogManager.getHeader(ourContext, "set_logo", "collection_id=" + getID() + "logo_bitstream_id=" + newLogo.getID())); } modified = true; return logo; } /** * Create a workflow group for the given step if one does not already exist. * Returns either the newly created group or the previously existing one. * Note that while the new group is created in the database, the association * between the group and the collection is not written until * <code>update</code> is called. * * @param step * the step (1-3) of the workflow to create or get the group for * * @return the workflow group associated with this collection * @throws SQLException * @throws AuthorizeException */ public Group createWorkflowGroup(int step) throws SQLException, AuthorizeException { // Check authorisation AuthorizeManager.authorizeAction(ourContext, this, Constants.WRITE); if (workflowGroup[step - 1] == null) { Group g = Group.create(ourContext); g.setName("COLLECTION_" + getID() + "_WORKFLOW_STEP_" + step); g.update(); setWorkflowGroup(step, g); AuthorizeManager.addPolicy(ourContext, this, Constants.ADD, g); } return workflowGroup[step - 1]; } /** * Set the workflow group corresponding to a particular workflow step. * <code>null</code> can be passed in if there should be no associated * group for that workflow step; any existing group is NOT deleted. * * @param step * the workflow step (1-3) * @param g * the new workflow group, or <code>null</code> */ public void setWorkflowGroup(int step, Group g) { workflowGroup[step - 1] = g; if (g == null) { collectionRow.setColumnNull("workflow_step_" + step); } else { collectionRow.setColumn("workflow_step_" + step, g.getID()); } modified = true; } /** * Get the the workflow group corresponding to a particular workflow step. * This returns <code>null</code> if there is no group associated with * this collection for the given step. * * @param step * the workflow step (1-3) * * @return the group of reviewers or <code>null</code> */ public Group getWorkflowGroup(int step) { return workflowGroup[step - 1]; } /** * Create a default submitters group if one does not already exist. Returns * either the newly created group or the previously existing one. Note that * other groups may also be allowed to submit to this collection by the * authorization system. * * @return the default group of submitters associated with this collection * @throws SQLException * @throws AuthorizeException */ public Group createSubmitters() throws SQLException, AuthorizeException { // Check authorisation AuthorizeManager.authorizeAction(ourContext, this, Constants.WRITE); if (submitters == null) { submitters = Group.create(ourContext); submitters.setName("COLLECTION_" + getID() + "_SUBMIT"); submitters.update(); } // register this as the submitter group collectionRow.setColumn("submitter", submitters.getID()); AuthorizeManager.addPolicy(ourContext, this, Constants.ADD, submitters); modified = true; return submitters; } /** * Remove the submitters group, if no group has already been created * then return without error. This will merely dereference the current * submitters group from the collection so that it may be deleted * without violating database constraints. */ public void removeSubmitters() throws SQLException, AuthorizeException { // Check authorisation AuthorizeManager.authorizeAction(ourContext, this, Constants.WRITE); // just return if there is no administrative group. if (submitters == null) return; // Remove the link to the collection table. collectionRow.setColumnNull("submitter"); submitters = null; modified = true; } /** * Get the default group of submitters, if there is one. Note that the * authorization system may allow others to submit to the collection, so * this is not necessarily a definitive list of potential submitters. * <P> * The default group of submitters for collection 100 is the one called * <code>collection_100_submit</code>. * * @return the default group of submitters, or <code>null</code> if there * is no default group. */ public Group getSubmitters() { return submitters; } /** * Create a default administrators group if one does not already exist. * Returns either the newly created group or the previously existing one. * Note that other groups may also be administrators. * * @return the default group of editors associated with this collection * @throws SQLException * @throws AuthorizeException */ public Group createAdministrators() throws SQLException, AuthorizeException { // Check authorisation AuthorizeManager.authorizeAction(ourContext, this, Constants.WRITE); if (admins == null) { admins = Group.create(ourContext); admins.setName("COLLECTION_" + getID() + "_ADMIN"); admins.update(); } AuthorizeManager.addPolicy(ourContext, this, Constants.COLLECTION_ADMIN, admins); // register this as the admin group collectionRow.setColumn("admin", admins.getID()); // administrators also get ADD on the submitter group if (submitters != null) { AuthorizeManager.addPolicy(ourContext, submitters, Constants.ADD, admins); } modified = true; return admins; } /** * Remove the administrators group, if no group has already been created * then return without error. This will merely dereference the current * administrators group from the collection so that it may be deleted * without violating database constraints. */ public void removeAdministrators() throws SQLException, AuthorizeException { // Check authorisation AuthorizeManager.authorizeAction(ourContext, this, Constants.WRITE); // just return if there is no administrative group. if (admins == null) return; // Remove the link to the collection table. collectionRow.setColumnNull("admin"); admins = null; modified = true; } /** * Get the default group of administrators, if there is one. Note that the * authorization system may allow others to be administrators for the * collection. * <P> * The default group of administrators for collection 100 is the one called * <code>collection_100_admin</code>. * * @return group of administrators, or <code>null</code> if there is no * default group. */ public Group getAdministrators() { return admins; } /** * Get the license that users must grant before submitting to this * collection. If the collection does not have a specific license, the * site-wide default is returned. * * @return the license for this collection */ public String getLicense() { String license = getMetadata("license"); if (license == null || license.trim().equals("")) { // Fallback to site-wide default license = ConfigurationManager.getDefaultSubmissionLicense(); } return license; } /** * Get the license that users must grant before submitting to this * collection. * * @return the license for this collection */ public String getLicenseCollection() { return getMetadata("license"); } /** * Find out if the collection has a custom license * * @return <code>true</code> if the collection has a custom license */ public boolean hasCustomLicense() { String license = getMetadata("license"); return !( license == null || license.trim().equals("") ); } /** * Set the license for this collection. Passing in <code>null</code> means * that the site-wide default will be used. * * @param license * the license, or <code>null</code> */ public void setLicense(String license) { setMetadata("license",license); } /** * Get the template item for this collection. <code>null</code> is * returned if the collection does not have a template. Submission * mechanisms may copy this template to provide a convenient starting point * for a submission. * * @return the item template, or <code>null</code> */ public Item getTemplateItem() throws SQLException { return template; } /** * Create an empty template item for this collection. If one already exists, * no action is taken. Caution: Make sure you call <code>update</code> on * the collection after doing this, or the item will have been created but * the collection record will not refer to it. * * @throws SQLException * @throws AuthorizeException */ public void createTemplateItem() throws SQLException, AuthorizeException { // Check authorisation canEdit(); if (template == null) { template = Item.create(ourContext); collectionRow.setColumn("template_item_id", template.getID()); log.info(LogManager.getHeader(ourContext, "create_template_item", "collection_id=" + getID() + ",template_item_id=" + template.getID())); } modified = true; } /** * Remove the template item for this collection, if there is one. Note that * since this has to remove the old template item ID from the collection * record in the database, the colletion record will be changed, including * any other changes made; in other words, this method does an * <code>update</code>. * * @throws SQLException * @throws AuthorizeException * @throws IOException */ public void removeTemplateItem() throws SQLException, AuthorizeException, IOException { // Check authorisation canEdit(); collectionRow.setColumnNull("template_item_id"); DatabaseManager.update(ourContext, collectionRow); if (template != null) { log.info(LogManager.getHeader(ourContext, "remove_template_item", "collection_id=" + getID() + ",template_item_id=" + template.getID())); template.delete(); template = null; } ourContext.addEvent(new Event(Event.MODIFY, Constants.COLLECTION, getID(), "remove_template_item")); } /** * Add an item to the collection. This simply adds a relationship between * the item and the collection - it does nothing like set an issue date, * remove a personal workspace item etc. This has instant effect; * <code>update</code> need not be called. * * @param item * item to add * @throws SQLException * @throws AuthorizeException */ public void addItem(Item item) throws SQLException, AuthorizeException { // Check authorisation AuthorizeManager.authorizeAction(ourContext, this, Constants.ADD); log.info(LogManager.getHeader(ourContext, "add_item", "collection_id=" + getID() + ",item_id=" + item.getID())); // Create mapping TableRow row = DatabaseManager.create(ourContext, "collection2item"); row.setColumn("collection_id", getID()); row.setColumn("item_id", item.getID()); DatabaseManager.update(ourContext, row); ourContext.addEvent(new Event(Event.ADD, Constants.COLLECTION, getID(), Constants.ITEM, item.getID(), item.getHandle())); } /** * Remove an item. If the item is then orphaned, it is deleted. * * @param item * item to remove * @throws SQLException * @throws AuthorizeException * @throws IOException */ public void removeItem(Item item) throws SQLException, AuthorizeException, IOException { // Check authorisation if (! item.canEdit()) AuthorizeManager.authorizeAction(ourContext, this, Constants.REMOVE); log.info(LogManager.getHeader(ourContext, "remove_item", "collection_id=" + getID() + ",item_id=" + item.getID())); DatabaseManager.updateQuery(ourContext, "DELETE FROM collection2item WHERE collection_id= ? "+ "AND item_id= ? ", getID(), item.getID()); ourContext.addEvent(new Event(Event.REMOVE, Constants.COLLECTION, getID(), Constants.ITEM, item.getID(), item.getHandle())); // Is the item an orphan? TableRowIterator tri = DatabaseManager.query(ourContext, "SELECT * FROM collection2item WHERE item_id= ? ", item.getID()); try { if (!tri.hasNext()) { //make the right to remove the item explicit because the implicit // relation //has been removed. This only has to concern the currentUser // because //he started the removal process and he will end it too. //also add right to remove from the item to remove it's bundles. AuthorizeManager.addPolicy(ourContext, item, Constants.DELETE, ourContext.getCurrentUser()); AuthorizeManager.addPolicy(ourContext, item, Constants.REMOVE, ourContext.getCurrentUser()); // Orphan; delete it item.delete(); } } finally { // close the TableRowIterator to free up resources if (tri != null) tri.close(); } } /** * Update the collection metadata (including logo, and workflow groups) to * the database. Inserts if this is a new collection. * * @throws SQLException * @throws IOException * @throws AuthorizeException */ public void update() throws SQLException, IOException, AuthorizeException { // Check authorisation canEdit(); log.info(LogManager.getHeader(ourContext, "update_collection", "collection_id=" + getID())); DatabaseManager.update(ourContext, collectionRow); if (modified) { ourContext.addEvent(new Event(Event.MODIFY, Constants.COLLECTION, getID(), null)); modified = false; } if (modifiedMetadata) { ourContext.addEvent(new Event(Event.MODIFY_METADATA, Constants.COLLECTION, getID(), getDetails())); modifiedMetadata = false; clearDetails(); } } public boolean canEditBoolean() throws java.sql.SQLException { try { canEdit(); return true; } catch (AuthorizeException e) { return false; } } public void canEdit() throws AuthorizeException, SQLException { Community[] parents = getCommunities(); for (int i = 0; i < parents.length; i++) { if (AuthorizeManager.authorizeActionBoolean(ourContext, parents[i], Constants.WRITE)) { return; } if (AuthorizeManager.authorizeActionBoolean(ourContext, parents[i], Constants.ADD)) { return; } } AuthorizeManager.authorizeAnyOf(ourContext, this, new int[] { Constants.WRITE, Constants.COLLECTION_ADMIN }); } /** * Delete the collection, including the metadata and logo. Items that are * then orphans are deleted. Groups associated with this collection * (workflow participants and submitters) are NOT deleted. * * @throws SQLException * @throws AuthorizeException * @throws IOException */ void delete() throws SQLException, AuthorizeException, IOException { log.info(LogManager.getHeader(ourContext, "delete_collection", "collection_id=" + getID())); ourContext.addEvent(new Event(Event.DELETE, Constants.COLLECTION, getID(), getHandle())); // Remove from cache ourContext.removeCached(this, getID()); // remove subscriptions - hmm, should this be in Subscription.java? DatabaseManager.updateQuery(ourContext, "DELETE FROM subscription WHERE collection_id= ? ", getID()); // Remove Template Item removeTemplateItem(); // Remove items ItemIterator items = getAllItems(); try { while (items.hasNext()) { Item item = items.next(); IndexBrowse ib = new IndexBrowse(ourContext); if (item.isOwningCollection(this)) { // the collection to be deletd is the owning collection, thus remove // the item from all collections it belongs to Collection[] collections = item.getCollections(); for (int i=0; i< collections.length; i++) { //notify Browse of removing item. ib.itemRemoved(item); // Browse.itemRemoved(ourContext, itemId); collections[i].removeItem(item); } } // the item was only mapped to this collection, so just remove it else { //notify Browse of removing item mapping. ib.indexItem(item); // Browse.itemChanged(ourContext, item); removeItem(item); } } } catch (BrowseException e) { log.error("caught exception: ", e); throw new IOException(e.getMessage()); } finally { if (items != null) items.close(); } // Delete bitstream logo setLogo(null); // Remove all authorization policies AuthorizeManager.removeAllPolicies(ourContext, this); // Remove any WorkflowItems WorkflowItem[] wfarray = WorkflowItem .findByCollection(ourContext, this); for (int x = 0; x < wfarray.length; x++) { // remove the workflowitem first, then the item Item myItem = wfarray[x].getItem(); wfarray[x].deleteWrapper(); myItem.delete(); } // Remove any WorkspaceItems WorkspaceItem[] wsarray = WorkspaceItem.findByCollection(ourContext, this); for (int x = 0; x < wsarray.length; x++) { wsarray[x].deleteAll(); } // get rid of the content count cache if it exists try { ItemCounter ic = new ItemCounter(ourContext); ic.remove(this); } catch (ItemCountException e) { // FIXME: upside down exception handling due to lack of good // exception framework throw new RuntimeException(e.getMessage(), e); } // Delete collection row DatabaseManager.delete(ourContext, collectionRow); // Remove any workflow groups - must happen after deleting collection Group g = null; g = getWorkflowGroup(1); if (g != null) { g.delete(); } g = getWorkflowGroup(2); if (g != null) { g.delete(); } g = getWorkflowGroup(3); if (g != null) { g.delete(); } // Remove default administrators group g = getAdministrators(); if (g != null) { g.delete(); } // Remove default submitters group g = getSubmitters(); if (g != null) { g.delete(); } } /** * Get the communities this collection appears in * * @return array of <code>Community</code> objects * @throws SQLException */ public Community[] getCommunities() throws SQLException { // Get the bundle table rows TableRowIterator tri = DatabaseManager.queryTable(ourContext,"community", "SELECT community.* FROM community, community2collection WHERE " + "community.community_id=community2collection.community_id " + "AND community2collection.collection_id= ? ", getID()); // Build a list of Community objects List<Community> communities = new ArrayList<Community>(); try { while (tri.hasNext()) { TableRow row = tri.next(); // First check the cache Community owner = (Community) ourContext.fromCache(Community.class, row.getIntColumn("community_id")); if (owner == null) { owner = new Community(ourContext, row); } communities.add(owner); // now add any parent communities Community[] parents = owner.getAllParents(); for (int i = 0; i < parents.length; i++) { communities.add(parents[i]); } } } finally { // close the TableRowIterator to free up resources if (tri != null) tri.close(); } Community[] communityArray = new Community[communities.size()]; communityArray = (Community[]) communities.toArray(communityArray); return communityArray; } /** * Return <code>true</code> if <code>other</code> is the same Collection * as this object, <code>false</code> otherwise * * @param other * object to compare to * * @return <code>true</code> if object passed in represents the same * collection as this object */ public boolean equals(Object other) { if (!(other instanceof Collection)) { return false; } return (getID() == ((Collection) other).getID()); } /** * Utility method for reading in a group from a group ID in a column. If the * column is null, null is returned. * * @param col * the column name to read * @return the group referred to by that column, or null * @throws SQLException */ private Group groupFromColumn(String col) throws SQLException { if (collectionRow.isColumnNull(col)) { return null; } return Group.find(ourContext, collectionRow.getIntColumn(col)); } /** * return type found in Constants * * @return int Constants.COLLECTION */ public int getType() { return Constants.COLLECTION; } /** * return an array of collections that user has a given permission on * (useful for trimming 'select to collection' list) or figuring out which * collections a person is an editor for. * * @param context * @param comm * (optional) restrict search to a community, else null * @param actionID * fo the action * * @return Collection [] of collections with matching permissions * @throws SQLException */ public static Collection[] findAuthorized(Context context, Community comm, int actionID) throws java.sql.SQLException { List<Collection> myResults = new ArrayList<Collection>(); Collection[] myCollections = null; if (comm != null) { myCollections = comm.getCollections(); } else { myCollections = Collection.findAll(context); } // now build a list of collections you have authorization for for (int i = 0; i < myCollections.length; i++) { if (AuthorizeManager.authorizeActionBoolean(context, myCollections[i], actionID)) { myResults.add(myCollections[i]); } } myCollections = new Collection[myResults.size()]; myCollections = (Collection[]) myResults.toArray(myCollections); return myCollections; } /** * counts items in this collection * * @return total items */ public int countItems() throws SQLException { int itemcount = 0; PreparedStatement statement = null; ResultSet rs = null; try { String query = "SELECT count(*) FROM collection2item, item WHERE " + "collection2item.collection_id = ? " + "AND collection2item.item_id = item.item_id " + "AND in_archive ='1' AND item.withdrawn='0' "; statement = ourContext.getDBConnection().prepareStatement(query); statement.setInt(1,getID()); rs = statement.executeQuery(); if (rs != null) { rs.next(); itemcount = rs.getInt(1); } } finally { if (rs != null) { try { rs.close(); } catch (SQLException sqle) { } } if (statement != null) { try { statement.close(); } catch (SQLException sqle) { } } } return itemcount; } }