/* * Item.java * * Version: $Revision$ * * Date: $Date$ * * Copyright (c) 2002-2009, The DSpace Foundation. 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 DSpace Foundation nor the names of its * 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.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import org.apache.log4j.Logger; import org.dspace.app.util.AuthorizeUtil; import org.dspace.authorize.AuthorizeConfiguration; 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.core.Constants; import org.dspace.core.Context; import org.dspace.core.LogManager; import org.dspace.content.authority.Choices; import org.dspace.content.authority.ChoiceAuthorityManager; import org.dspace.content.authority.MetadataAuthorityManager; import org.dspace.event.Event; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; import org.dspace.handle.HandleManager; import org.dspace.storage.rdbms.DatabaseManager; import org.dspace.storage.rdbms.TableRow; import org.dspace.storage.rdbms.TableRowIterator; /** * Class representing an item in DSpace. *
* This class holds in memory the item Dublin Core metadata, the bundles in the
* item, and the bitstreams in those bundles. When modifying the item, if you
* modify the Dublin Core or the "in archive" flag, you must call
*
* Examples:
*
* Return values of the unqualified "title" field, in any language.
* Qualified title fields (e.g. "title.uniform") are NOT returned:
*
*
* Return all US English values of the "title" element, with any qualifier
* (including unqualified):
*
*
* The ordering of values of a particular element/qualifier/language
* combination is significant. When retrieving with wildcards, values of a
* particular element/qualifier/language combinations will be adjacent, but
* the overall ordering of the combinations is indeterminate.
*
* @param element
* the Dublin Core element.
* Examples:
*
* Return values of the unqualified "title" field, in any language.
* Qualified title fields (e.g. "title.uniform") are NOT returned:
*
*
* Return all US English values of the "title" element, with any qualifier
* (including unqualified):
*
*
* The ordering of values of a particular element/qualifier/language
* combination is significant. When retrieving with wildcards, values of a
* particular element/qualifier/language combinations will be adjacent, but
* the overall ordering of the combinations is indeterminate.
*
* @param schema
* the schema for the metadata field. Must match
* the
* If metadata authority control is available, try to get authority
* values. The authority confidence depends on whether authority is
* required or not.
* @param schema
* the schema for the metadata field. Must match
* the
* This method is used by the org.dspace.submit.step.LicenseStep class
*
* @throws SQLException
* @throws AuthorizeException
* @throws IOException
*/
public void removeDSpaceLicense() throws SQLException, AuthorizeException,
IOException
{
// get all bundles with name "LICENSE" (these are the DSpace license
// bundles)
Bundle[] bunds = getBundles("LICENSE");
for (int i = 0; i < bunds.length; i++)
{
// FIXME: probably serious troubles with Authorizations
// fix by telling system not to check authorization?
removeBundle(bunds[i]);
}
}
/**
* Remove all licenses from an item - it was rejected
*
* @throws SQLException
* @throws AuthorizeException
* @throws IOException
*/
public void removeLicenses() throws SQLException, AuthorizeException,
IOException
{
// Find the License format
BitstreamFormat bf = BitstreamFormat.findByShortDescription(ourContext,
"License");
int licensetype = bf.getID();
// search through bundles, looking for bitstream type license
Bundle[] bunds = getBundles();
for (int i = 0; i < bunds.length; i++)
{
boolean removethisbundle = false;
Bitstream[] bits = bunds[i].getBitstreams();
for (int j = 0; j < bits.length; j++)
{
BitstreamFormat bft = bits[j].getFormat();
if (bft.getID() == licensetype)
{
removethisbundle = true;
}
}
// probably serious troubles with Authorizations
// fix by telling system not to check authorization?
if (removethisbundle)
{
removeBundle(bunds[i]);
}
}
}
/**
* Update the item "in archive" flag and Dublin Core metadata in the
* database
*
* @throws SQLException
* @throws AuthorizeException
*/
public void update() throws SQLException, AuthorizeException
{
// Check authorisation
// only do write authorization if user is not an editor
if (!canEdit())
{
AuthorizeManager.authorizeAction(ourContext, this, Constants.WRITE);
}
log.info(LogManager.getHeader(ourContext, "update_item", "item_id="
+ getID()));
// Set sequence IDs for bitstreams in item
int sequence = 0;
Bundle[] bunds = getBundles();
// find the highest current sequence number
for (int i = 0; i < bunds.length; i++)
{
Bitstream[] streams = bunds[i].getBitstreams();
for (int k = 0; k < streams.length; k++)
{
if (streams[k].getSequenceID() > sequence)
{
sequence = streams[k].getSequenceID();
}
}
}
// start sequencing bitstreams without sequence IDs
sequence++;
for (int i = 0; i < bunds.length; i++)
{
Bitstream[] streams = bunds[i].getBitstreams();
for (int k = 0; k < streams.length; k++)
{
if (streams[k].getSequenceID() < 0)
{
streams[k].setSequenceID(sequence);
sequence++;
streams[k].update();
modified = true;
}
}
}
// Map counting number of values for each element/qualifier.
// Keys are Strings: "element" or "element.qualifier"
// Values are Integers indicating number of values written for a
// element/qualifier
Mapupdate
for the changes to be written to the database.
* Creating, adding or removing bundles or bitstreams has immediate effect in
* the database.
*
* @author Robert Tansley
* @author Martin Hald
* @version $Revision$
*/
public class Item extends DSpaceObject
{
/**
* Wild card for Dublin Core metadata qualifiers/languages
*/
public final static String ANY = "*";
/** log4j category */
private static Logger log = Logger.getLogger(Item.class);
/** Our context */
private Context ourContext;
/** The table row corresponding to this item */
private TableRow itemRow;
/** The e-person who submitted this item */
private EPerson submitter;
/** The bundles in this item - kept in sync with DB */
private ListWorkflowItem.archive()
should set this.
*
* @param isArchived
* new value for the flag
*/
public void setArchived(boolean isArchived)
{
itemRow.setColumn("in_archive", isArchived);
modified = true;
}
/**
* Set the owning Collection for the item
*
* @param c
* Collection
*/
public void setOwningCollection(Collection c)
{
itemRow.setColumn("owning_collection", c.getID());
modified = true;
}
/**
* Get the owning Collection for the item
*
* @return Collection that is the owner of the item
* @throws SQLException
*/
public Collection getOwningCollection() throws java.sql.SQLException
{
Collection myCollection = null;
// get the collection ID
int cid = itemRow.getIntColumn("owning_collection");
myCollection = Collection.find(ourContext, cid);
return myCollection;
}
// just get the collection ID for internal use
private int getOwningCollectionID()
{
return itemRow.getIntColumn("owning_collection");
}
/**
* Get Dublin Core metadata for the item.
* Passing in a null
value for qualifier
* or lang
only matches Dublin Core fields where that
* qualifier or languages is actually null
.
* Passing in Item.ANY
* retrieves all metadata fields with any value for the qualifier or
* language, including null
* item.getDC( "title", null, Item.ANY );
* item.getDC( "title", Item.ANY, "en_US" );
* Item.ANY
matches any
* element. null
doesn't really make sense as all
* DC must have an element.
* @param qualifier
* the qualifier. null
means unqualified, and
* Item.ANY
means any qualifier (including
* unqualified.)
* @param lang
* the ISO639 language code, optionally followed by an underscore
* and the ISO3166 country code. null
means only
* values with no language are returned, and
* Item.ANY
means values with any country code or
* no country code are returned.
* @return Dublin Core fields that match the parameters
*/
@Deprecated
public DCValue[] getDC(String element, String qualifier, String lang)
{
return getMetadata(MetadataSchema.DC_SCHEMA, element, qualifier, lang);
}
/**
* Get metadata for the item in a chosen schema.
* See MetadataSchema
for more information about schemas.
* Passing in a null
value for qualifier
* or lang
only matches metadata fields where that
* qualifier or languages is actually null
.
* Passing in Item.ANY
* retrieves all metadata fields with any value for the qualifier or
* language, including null
* item.getMetadata("dc", "title", null, Item.ANY );
* item.getMetadata("dc, "title", Item.ANY, "en_US" );
* name
of an existing metadata schema.
* @param element
* the element name. Item.ANY
matches any
* element. null
doesn't really make sense as all
* metadata must have an element.
* @param qualifier
* the qualifier. null
means unqualified, and
* Item.ANY
means any qualifier (including
* unqualified.)
* @param lang
* the ISO639 language code, optionally followed by an underscore
* and the ISO3166 country code. null
means only
* values with no language are returned, and
* Item.ANY
means values with any country code or
* no country code are returned.
* @return metadata fields that match the parameters
*/
public DCValue[] getMetadata(String schema, String element, String qualifier,
String lang)
{
// Build up list of matching values
ListclearDC
to remove values. The ordering of values
* passed in is maintained.
*
* @param element
* the Dublin Core element
* @param qualifier
* the Dublin Core qualifier, or null
for
* unqualified
* @param lang
* the ISO639 language code, optionally followed by an underscore
* and the ISO3166 country code. null
means the
* value has no language (for example, a date).
* @param values
* the values to add.
*/
@Deprecated
public void addDC(String element, String qualifier, String lang,
String[] values)
{
addMetadata(MetadataSchema.DC_SCHEMA, element, qualifier, lang, values);
}
/**
* Add a single Dublin Core metadata field. This is appended to existing
* values. Use clearDC
to remove values.
*
* @param element
* the Dublin Core element
* @param qualifier
* the Dublin Core qualifier, or null
for
* unqualified
* @param lang
* the ISO639 language code, optionally followed by an underscore
* and the ISO3166 country code. null
means the
* value has no language (for example, a date).
* @param value
* the value to add.
*/
@Deprecated
public void addDC(String element, String qualifier, String lang,
String value)
{
addMetadata(MetadataSchema.DC_SCHEMA, element, qualifier, lang, value);
}
/**
* Add metadata fields. These are appended to existing values.
* Use clearDC
to remove values. The ordering of values
* passed in is maintained.
* name
of an existing metadata schema.
* @param element
* the metadata element name
* @param qualifier
* the metadata qualifier name, or null
for
* unqualified
* @param lang
* the ISO639 language code, optionally followed by an underscore
* and the ISO3166 country code. null
means the
* value has no language (for example, a date).
* @param values
* the values to add.
*/
public void addMetadata(String schema, String element, String qualifier, String lang,
String[] values)
{
MetadataAuthorityManager mam = MetadataAuthorityManager.getManager();
String fieldKey = MetadataAuthorityManager.makeFieldKey(schema, element, qualifier);
if (mam.isAuthorityControlled(fieldKey))
{
String authorities[] = new String[values.length];
int confidences[] = new int[values.length];
for (int i = 0; i < values.length; ++i)
{
Choices c = ChoiceAuthorityManager.getManager().getBestMatch(fieldKey, values[i], getOwningCollectionID(), null);
authorities[i] = c.values.length > 0 ? c.values[0].authority : null;
confidences[i] = c.confidence;
}
addMetadata(schema, element, qualifier, lang, values, authorities, confidences);
}
else
addMetadata(schema, element, qualifier, lang, values, null, null);
}
/**
* Add metadata fields. These are appended to existing values.
* Use clearDC
to remove values. The ordering of values
* passed in is maintained.
* @param schema
* the schema for the metadata field. Must match
* the name
of an existing metadata schema.
* @param element
* the metadata element name
* @param qualifier
* the metadata qualifier name, or null
for
* unqualified
* @param lang
* the ISO639 language code, optionally followed by an underscore
* and the ISO3166 country code. null
means the
* value has no language (for example, a date).
* @param values
* the values to add.
* @param authority
* the external authority key for this value (or null)
* @param confidence
* the authority confidence (default 0)
*/
public void addMetadata(String schema, String element, String qualifier, String lang,
String[] values, String authorities[], int confidences[])
{
ListclearDC
to remove values.
*
* @param schema
* the schema for the metadata field. Must match
* the name
of an existing metadata schema.
* @param element
* the metadata element name
* @param qualifier
* the metadata qualifier, or null
for
* unqualified
* @param lang
* the ISO639 language code, optionally followed by an underscore
* and the ISO3166 country code. null
means the
* value has no language (for example, a date).
* @param value
* the value to add.
*/
public void addMetadata(String schema, String element, String qualifier,
String lang, String value)
{
String[] valArray = new String[1];
valArray[0] = value;
addMetadata(schema, element, qualifier, lang, valArray);
}
/**
* Add a single metadata field. This is appended to existing
* values. Use clearDC
to remove values.
*
* @param schema
* the schema for the metadata field. Must match
* the name
of an existing metadata schema.
* @param element
* the metadata element name
* @param qualifier
* the metadata qualifier, or null
for
* unqualified
* @param lang
* the ISO639 language code, optionally followed by an underscore
* and the ISO3166 country code. null
means the
* value has no language (for example, a date).
* @param value
* the value to add.
* @param authority
* the external authority key for this value (or null)
* @param confidence
* the authority confidence (default 0)
*/
public void addMetadata(String schema, String element, String qualifier,
String lang, String value, String authority, int confidence)
{
String[] valArray = new String[1];
String[] authArray = new String[1];
int[] confArray = new int[1];
valArray[0] = value;
authArray[0] = authority;
confArray[0] = confidence;
addMetadata(schema, element, qualifier, lang, valArray, authArray, confArray);
}
/**
* Clear Dublin Core metadata values. As with getDC
above,
* passing in null
only matches fields where the qualifier or
* language is actually null
.Item.ANY
will
* match any element, qualifier or language, including null
.
* Thus, item.clearDC(Item.ANY, Item.ANY, Item.ANY)
will
* remove all Dublin Core metadata associated with an item.
*
* @param element
* the Dublin Core element to remove, or Item.ANY
* @param qualifier
* the qualifier. null
means unqualified, and
* Item.ANY
means any qualifier (including
* unqualified.)
* @param lang
* the ISO639 language code, optionally followed by an underscore
* and the ISO3166 country code. null
means only
* values with no language are removed, and Item.ANY
* means values with any country code or no country code are
* removed.
*/
@Deprecated
public void clearDC(String element, String qualifier, String lang)
{
clearMetadata(MetadataSchema.DC_SCHEMA, element, qualifier, lang);
}
/**
* Clear metadata values. As with getDC
above,
* passing in null
only matches fields where the qualifier or
* language is actually null
.Item.ANY
will
* match any element, qualifier or language, including null
.
* Thus, item.clearDC(Item.ANY, Item.ANY, Item.ANY)
will
* remove all Dublin Core metadata associated with an item.
*
* @param schema
* the schema for the metadata field. Must match
* the name
of an existing metadata schema.
* @param element
* the Dublin Core element to remove, or Item.ANY
* @param qualifier
* the qualifier. null
means unqualified, and
* Item.ANY
means any qualifier (including
* unqualified.)
* @param lang
* the ISO639 language code, optionally followed by an underscore
* and the ISO3166 country code. null
means only
* values with no language are removed, and Item.ANY
* means values with any country code or no country code are
* removed.
*/
public void clearMetadata(String schema, String element, String qualifier,
String lang)
{
// We will build a list of values NOT matching the values to clear
Listtrue
if the given schema,
* element, qualifier and language match the schema, element,
* qualifier and language of the DCValue
object passed
* in. Any or all of the element, qualifier and language passed
* in can be the Item.ANY
wildcard.
*
* @param schema
* the schema for the metadata field. Must match
* the name
of an existing metadata schema.
* @param element
* the element to match, or Item.ANY
* @param qualifier
* the qualifier to match, or Item.ANY
* @param language
* the language to match, or Item.ANY
* @param dcv
* the Dublin Core value
* @return true
if there is a match
*/
private boolean match(String schema, String element, String qualifier,
String language, DCValue dcv)
{
// We will attempt to disprove a match - if we can't we have a match
if (!element.equals(Item.ANY) && !element.equals(dcv.element))
{
// Elements do not match, no wildcard
return false;
}
if (qualifier == null)
{
// Value must be unqualified
if (dcv.qualifier != null)
{
// Value is qualified, so no match
return false;
}
}
else if (!qualifier.equals(Item.ANY))
{
// Not a wildcard, so qualifier must match exactly
if (!qualifier.equals(dcv.qualifier))
{
return false;
}
}
if (language == null)
{
// Value must be null language to match
if (dcv.language != null)
{
// Value is qualified, so no match
return false;
}
}
else if (!language.equals(Item.ANY))
{
// Not a wildcard, so language must match exactly
if (!language.equals(dcv.language))
{
return false;
}
}
else if (!schema.equals(Item.ANY))
{
if (dcv.schema != null && !dcv.schema.equals(schema))
{
// The namespace doesn't match
return false;
}
}
// If we get this far, we have a match
return true;
}
/**
* Get the e-person that originally submitted this item
*
* @return the submitter
*/
public EPerson getSubmitter() throws SQLException
{
if (submitter == null && !itemRow.isColumnNull("submitter_id"))
{
submitter = EPerson.find(ourContext, itemRow
.getIntColumn("submitter_id"));
}
return submitter;
}
/**
* Set the e-person that originally submitted this item. This is a public
* method since it is handled by the WorkspaceItem class in the ingest
* package. update
must be called to write the change to the
* database.
*
* @param sub
* the submitter
*/
public void setSubmitter(EPerson sub)
{
submitter = sub;
if (submitter != null)
{
itemRow.setColumn("submitter_id", submitter.getID());
}
else
{
itemRow.setColumnNull("submitter_id");
}
modified = true;
}
/**
* See whether this Item is contained by a given Collection.
* @param collection
* @return true if {@code collection} contains this Item.
* @throws SQLException
*/
public boolean isIn(Collection collection) throws SQLException
{
TableRow tr = DatabaseManager.querySingle(ourContext,
"SELECT COUNT(*) AS count" +
" FROM collection2item" +
" WHERE collection_id = ? AND item_id = ?",
collection.getID(), itemRow.getIntColumn("item_id"));
return tr.getLongColumn("count") > 0;
}
/**
* Get the collections this item is in. The order is indeterminate.
*
* @return the collections this item is in, if any.
* @throws SQLException
*/
public Collection[] getCollections() throws SQLException
{
Listtrue
if other
is the same Item as
* this object, false
otherwise
*
* @param other
* object to compare to
* @return true
if object passed in represents the same item
* as this object
*/
@Override
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final Item other = (Item) obj;
if (this.getType() != other.getType()) return false;
if (this.getID() != other.getID()) return false;
return true;
}
@Override
public int hashCode()
{
int hash = 5;
hash = 71 * hash + (this.itemRow != null ? this.itemRow.hashCode() : 0);
return hash;
}
/**
* Return true if this Collection 'owns' this item
*
* @param c
* Collection
* @return true if this Collection owns this item
*/
public boolean isOwningCollection(Collection c)
{
int owner_id = itemRow.getIntColumn("owning_collection");
if (c.getID() == owner_id)
{
return true;
}
// not the owner
return false;
}
/**
* Utility method to remove all descriptive metadata associated with the item from
* the database (regardless of in-memory version)
*
* @throws SQLException
*/
private void removeMetadataFromDatabase() throws SQLException
{
DatabaseManager.updateQuery(ourContext,
"DELETE FROM MetadataValue WHERE item_id= ? ",
getID());
}
/**
* return type found in Constants
*
* @return int Constants.ITEM
*/
public int getType()
{
return Constants.ITEM;
}
/**
* remove all of the policies for item and replace them with a new list of
* policies
*
* @param newpolicies -
* this will be all of the new policies for the item and its
* contents
* @throws SQLException
* @throws AuthorizeException
*/
public void replaceAllItemPolicies(List newpolicies) throws SQLException,
AuthorizeException
{
// remove all our policies, add new ones
AuthorizeManager.removeAllPolicies(ourContext, this);
AuthorizeManager.addPolicies(ourContext, newpolicies, this);
}
/**
* remove all of the policies for item's bitstreams and bundles and replace
* them with a new list of policies
*
* @param newpolicies -
* this will be all of the new policies for the bundle and
* bitstream contents
* @throws SQLException
* @throws AuthorizeException
*/
public void replaceAllBitstreamPolicies(List newpolicies)
throws SQLException, AuthorizeException
{
// remove all policies from bundles, add new ones
// Remove bundles
Bundle[] bunds = getBundles();
for (int i = 0; i < bunds.length; i++)
{
Bundle mybundle = bunds[i];
mybundle.replaceAllBitstreamPolicies(newpolicies);
}
}
/**
* remove all of the policies for item's bitstreams and bundles that belong
* to a given Group
*
* @param g
* Group referenced by policies that needs to be removed
* @throws SQLException
*/
public void removeGroupPolicies(Group g) throws SQLException
{
// remove Group's policies from Item
AuthorizeManager.removeGroupPolicies(ourContext, this, g);
// remove all policies from bundles
Bundle[] bunds = getBundles();
for (int i = 0; i < bunds.length; i++)
{
Bundle mybundle = bunds[i];
Bitstream[] bs = mybundle.getBitstreams();
for (int j = 0; j < bs.length; j++)
{
Bitstream mybitstream = bs[j];
// remove bitstream policies
AuthorizeManager.removeGroupPolicies(ourContext, bs[j], g);
}
// change bundle policies
AuthorizeManager.removeGroupPolicies(ourContext, mybundle, g);
}
}
/**
* remove all policies on an item and its contents, and replace them with
* the DEFAULT_ITEM_READ and DEFAULT_BITSTREAM_READ policies belonging to
* the collection.
*
* @param c
* Collection
* @throws java.sql.SQLException
* if an SQL error or if no default policies found. It's a bit
* draconian, but default policies must be enforced.
* @throws AuthorizeException
*/
public void inheritCollectionDefaultPolicies(Collection c)
throws java.sql.SQLException, AuthorizeException
{
// remove the submit authorization policies
// and replace them with the collection's default READ policies
List policies = AuthorizeManager.getPoliciesActionFilter(ourContext, c,
Constants.DEFAULT_ITEM_READ);
// change the action to just READ
// just don't call update on the resourcepolicies!!!
Iterator i = policies.iterator();
// MUST have default policies
if (!i.hasNext())
{
throw new java.sql.SQLException("Collection " + c.getID()
+ " has no default item READ policies");
}
while (i.hasNext())
{
ResourcePolicy rp = (ResourcePolicy) i.next();
rp.setAction(Constants.READ);
}
replaceAllItemPolicies(policies);
policies = AuthorizeManager.getPoliciesActionFilter(ourContext, c,
Constants.DEFAULT_BITSTREAM_READ);
// change the action to just READ
// just don't call update on the resourcepolicies!!!
i = policies.iterator();
if (!i.hasNext())
{
throw new java.sql.SQLException("Collection " + c.getID()
+ " has no default bitstream READ policies");
}
while (i.hasNext())
{
ResourcePolicy rp = (ResourcePolicy) i.next();
rp.setAction(Constants.READ);
}
replaceAllBitstreamPolicies(policies);
}
/**
* Moves the item from one collection to another one
*
* @throws SQLException
* @throws AuthorizeException
* @throws IOException
*/
public void move (Collection from, Collection to) throws SQLException, AuthorizeException, IOException
{
// Check authorisation on the item before that the move occur
// otherwise we will need edit permission on the "target collection" to archive our goal
// only do write authorization if user is not an editor
if (!canEdit())
{
AuthorizeManager.authorizeAction(ourContext, this, Constants.WRITE);
}
// Move the Item from one Collection to the other
to.addItem(this);
from.removeItem(this);
// If we are moving from the owning collection, update that too
if (isOwningCollection(from))
{
setOwningCollection(to);
ourContext.turnOffAuthorisationSystem();
update();
ourContext.restoreAuthSystemState();
}
else
{
// Although we haven't actually updated anything within the item
// we'll tell the event system that it has, so that any consumers that
// care about the structure of the repository can take account of the move
// Note that updating the owning collection above will have the same effect,
// so we only do this here if the owning collection hasn't changed.
ourContext.addEvent(new Event(Event.MODIFY, Constants.ITEM, getID(), null));
}
}
/**
* Check the bundle ORIGINAL to see if there are any uploaded files
*
* @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.
*
* @return the collections this item is not in, if any.
* @throws SQLException
*/
public Collection[] getCollectionsNotLinked() throws SQLException
{
Collection[] allCollections = Collection.findAll(ourContext);
Collection[] linkedCollections = getCollections();
Collection[] notLinkedCollections = new Collection[allCollections.length - linkedCollections.length];
if ((allCollections.length - linkedCollections.length) == 0)
{
return notLinkedCollections;
}
int i = 0;
for (Collection collection : allCollections)
{
boolean alreadyLinked = false;
for (Collection linkedCommunity : linkedCollections)
{
if (collection.getID() == linkedCommunity.getID())
{
alreadyLinked = true;
break;
}
}
if (!alreadyLinked)
{
notLinkedCollections[i++] = collection;
}
}
return notLinkedCollections;
}
/**
* return TRUE if context's user can edit item, false otherwise
*
* @return boolean true = current user can edit item
* @throws SQLException
*/
public boolean canEdit() throws java.sql.SQLException
{
// can this person write to the item?
if (AuthorizeManager.authorizeActionBoolean(ourContext, this,
Constants.WRITE))
{
return true;
}
// is this collection not yet created, and an item template is created
if (getOwningCollection() == null)
{
return true;
}
// is this person an COLLECTION_EDITOR for the owning collection?
if (getOwningCollection().canEditBoolean(false))
{
return true;
}
return false;
}
public String getName()
{
DCValue t[] = getMetadata("dc", "title", null, Item.ANY);
return (t.length >= 1) ? t[0].value : null;
}
/**
* Returns an iterator of Items possessing the passed metadata field, or only
* those matching the passed value, if value is not Item.ANY
*
* @param context DSpace context object
* @param schema metadata field schema
* @param element metadata field element
* @param qualifier metadata field qualifier
* @param value field value or Item.ANY to match any value
* @return an iterator over the items matching that authority value
* @throws SQLException, AuthorizeException, IOException
*
*/
public static ItemIterator findByMetadataField(Context context,
String schema, String element, String qualifier, String value)
throws SQLException, AuthorizeException, IOException
{
MetadataSchema mds = MetadataSchema.find(context, schema);
if (mds == null)
throw new IllegalArgumentException("No such metadata schema: "+schema);
MetadataField mdf = MetadataField.findByElement(context, mds.getSchemaID(), element, qualifier);
if (mdf == null)
throw new IllegalArgumentException(
"No such metadata field: schema="+schema+", element="+element+", qualifier="+qualifier);
String query = "SELECT item.* FROM metadatavalue,item WHERE item.in_archive='1' "+
"AND item.item_id = metadatavalue.item_id AND metadata_field_id = ?";
TableRowIterator rows = null;
if (Item.ANY.equals(value))
{
rows = DatabaseManager.queryTable(context, "item", query, mdf.getFieldID());
}
else
{
query += " AND metadatavalue.text_value = ?";
rows = DatabaseManager.queryTable(context, "item", query, mdf.getFieldID(), value);
}
return new ItemIterator(context, rows);
}
public DSpaceObject getAdminObject(int action) throws SQLException
{
DSpaceObject adminObject = null;
Collection collection = getOwningCollection();
Community community = null;
if (collection != null)
{
Community[] communities = collection.getCommunities();
if (communities != null && communities.length > 0)
{
community = communities[0];
}
}
else
{
// is a template item?
TableRow qResult = DatabaseManager.querySingle(ourContext,
"SELECT collection_id FROM collection " +
"WHERE template_item_id = ?",getID());
if (qResult != null)
{
collection = Collection.find(ourContext, qResult.getIntColumn("collection_id"));
Community[] communities = collection.getCommunities();
if (communities != null && communities.length > 0)
{
community = communities[0];
}
}
}
switch (action)
{
case Constants.ADD:
// ADD a cc license is less general than add a bitstream but we can't/won't
// add complex logic here to know if the ADD action on the item is required by a cc or
// a generic bitstream so simply we ignore it.. UI need to enforce the requirements.
if (AuthorizeConfiguration.canItemAdminPerformBitstreamCreation())
{
adminObject = this;
}
else if (AuthorizeConfiguration.canCollectionAdminPerformBitstreamCreation())
{
adminObject = collection;
}
else if (AuthorizeConfiguration.canCommunityAdminPerformBitstreamCreation())
{
adminObject = community;
}
break;
case Constants.REMOVE:
// see comments on ADD action, same things...
if (AuthorizeConfiguration.canItemAdminPerformBitstreamDeletion())
{
adminObject = this;
}
else if (AuthorizeConfiguration.canCollectionAdminPerformBitstreamDeletion())
{
adminObject = collection;
}
else if (AuthorizeConfiguration.canCommunityAdminPerformBitstreamDeletion())
{
adminObject = community;
}
break;
case Constants.DELETE:
if (getOwningCollection() != null)
{
if (AuthorizeConfiguration.canCollectionAdminPerformItemDeletion())
{
adminObject = collection;
}
else if (AuthorizeConfiguration.canCommunityAdminPerformItemDeletion())
{
adminObject = community;
}
}
else
{
if (AuthorizeConfiguration.canCollectionAdminManageTemplateItem())
{
adminObject = collection;
}
else if (AuthorizeConfiguration.canCommunityAdminManageCollectionTemplateItem())
{
adminObject = community;
}
}
break;
case Constants.WRITE:
// if it is a template item we need to check the
// collection/community admin configuration
if (getOwningCollection() == null)
{
if (AuthorizeConfiguration.canCollectionAdminManageTemplateItem())
{
adminObject = collection;
}
else if (AuthorizeConfiguration.canCommunityAdminManageCollectionTemplateItem())
{
adminObject = community;
}
}
else
{
adminObject = this;
}
break;
default:
adminObject = this;
break;
}
return adminObject;
}
public DSpaceObject getParentObject() throws SQLException
{
Collection ownCollection = getOwningCollection();
if (ownCollection != null)
{
return ownCollection;
}
else
{
// is a template item?
TableRow qResult = DatabaseManager.querySingle(ourContext,
"SELECT collection_id FROM collection " +
"WHERE template_item_id = ?",getID());
if (qResult != null)
{
return Collection.find(ourContext,qResult.getIntColumn("collection_id"));
}
return null;
}
}
/**
* Find all the items in the archive with a given authority key value
* in the indicated metadata field.
*
* @param context DSpace context object
* @param schema metadata field schema
* @param element metadata field element
* @param qualifier metadata field qualifier
* @param value the value of authority key to look for
* @return an iterator over the items matching that authority value
* @throws SQLException, AuthorizeException, IOException
*/
public static ItemIterator findByAuthorityValue(Context context,
String schema, String element, String qualifier, String value)
throws SQLException, AuthorizeException, IOException
{
MetadataSchema mds = MetadataSchema.find(context, schema);
if (mds == null)
throw new IllegalArgumentException("No such metadata schema: "+schema);
MetadataField mdf = MetadataField.findByElement(context, mds.getSchemaID(), element, qualifier);
if (mdf == null)
throw new IllegalArgumentException("No such metadata field: schema="+schema+", element="+element+", qualifier="+qualifier);
TableRowIterator rows = DatabaseManager.queryTable(context, "item",
"SELECT item.* FROM metadatavalue,item WHERE item.in_archive='1' "+
"AND item.item_id = metadatavalue.item_id AND metadata_field_id = ? AND authority = ?",
mdf.getFieldID(), value);
return new ItemIterator(context, rows);
}
private List