/* * BrowseItem.java * * 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.browse; import org.apache.log4j.Logger; import org.dspace.authorize.AuthorizeManager; import org.dspace.content.*; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.handle.HandleManager; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; /** * Entity class to represent an item that is being used to generate Browse * results. This behaves in many was similar to the Item object, but its * metadata handling has been further optimised for performance in both * reading and writing, and it does not deal with other objects related to * items * * FIXME: this class violates some of the encapsulation of the Item, but there is * unfortunately no way around this until DAOs and an interface are provided * for the Item class. * * @author Richard Jones * */ public class BrowseItem extends DSpaceObject { /** Logger */ private static Logger log = Logger.getLogger(BrowseItem.class); /** DSpace context */ private Context context; /** a List of all the metadata */ private List metadata = new ArrayList(); /** database id of the item */ private int id = -1; /** is the item in the archive */ private boolean in_archive = true; /** is the item withdrawn */ private boolean withdrawn = false; /** item handle */ private String handle = null; /** inner item, if we really absolutely have to instantiate it */ private Item item; /** * Construct a new browse item with the given context and the database id * * @param context the DSpace context * @param id the database id of the item * @param in_archive * @param withdrawn */ public BrowseItem(Context context, int id, boolean in_archive, boolean withdrawn) { this.context = context; this.id = id; this.in_archive = in_archive; this.withdrawn = withdrawn; } /** * Get String array of metadata values matching the given parameters * * @param schema metadata schema * @param element metadata element * @param qualifier metadata qualifier * @param lang metadata language * @return array of matching values * @throws SQLException */ public DCValue[] getMetadata(String schema, String element, String qualifier, String lang) throws SQLException { try { BrowseItemDAO dao = BrowseDAOFactory.getItemInstance(context); // if the qualifier is a wildcard, we have to get it out of the // database if (Item.ANY.equals(qualifier)) { return dao.queryMetadata(id, schema, element, qualifier, lang); } if (!metadata.isEmpty()) { List values = new ArrayList(); Iterator i = metadata.iterator(); while (i.hasNext()) { DCValue dcv = (DCValue) i.next(); if (match(schema, element, qualifier, lang, dcv)) { values.add(dcv); } } if (values.isEmpty()) { DCValue[] dcvs = dao.queryMetadata(id, schema, element, qualifier, lang); if (dcvs != null) { Collections.addAll(metadata, dcvs); } return dcvs; } // else, Create an array of matching values DCValue[] valueArray = new DCValue[values.size()]; valueArray = (DCValue[]) values.toArray(valueArray); return valueArray; } else { DCValue[] dcvs = dao.queryMetadata(id, schema, element, qualifier, lang); if (dcvs != null) { Collections.addAll(metadata, dcvs); } return dcvs; } } catch (BrowseException be) { log.error("caught exception: ", be); return null; } } /** * Get the type of object. This object masquerates as an Item, so this * returns the value of Constants.ITEM * *@return Constants.ITEM */ public int getType() { return Constants.ITEM; } /** * @deprecated * @param real * @return */ public int getType(boolean real) { if (!real) { return Constants.ITEM; } else { return getType(); } } /** * get the database id of the item * * @return database id of item */ public int getID() { return id; } /** * Set the database id of the item * * @param id the database id of the item */ public void setID(int id) { this.id = id; } /** * Utility method for pattern-matching metadata elements. This * method will return <code>true</code> if the given schema, * element, qualifier and language match the schema, element, * qualifier and language of the <code>DCValue</code> object passed * in. Any or all of the elemenent, qualifier and language passed * in can be the <code>Item.ANY</code> wildcard. * * @param schema * the schema for the metadata field. <em>Must</em> match * the <code>name</code> of an existing metadata schema. * @param element * the element to match, or <code>Item.ANY</code> * @param qualifier * the qualifier to match, or <code>Item.ANY</code> * @param language * the language to match, or <code>Item.ANY</code> * @param dcv * the Dublin Core value * @return <code>true</code> 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; } /* (non-Javadoc) * @see org.dspace.content.DSpaceObject#getHandle() */ public String getHandle() { // Get our Handle if any if (this.handle == null) { try { this.handle = HandleManager.findHandle(context, this); } catch (SQLException e) { log.error("caught exception: ", e); } } return this.handle; } /** * Get a thumbnail object out of the item. * * Warning: using this method actually instantiates an Item, which has a * corresponding performance hit on the database during browse listing * rendering. That's your own fault for wanting to put images on your * browse page! * * @return * @throws SQLException */ public Thumbnail getThumbnail() throws SQLException { // instantiate an item for this one. Not nice. item = Item.find(context, id); if (item == null) { return null; } // now go sort out the thumbnail // if there's no original, there is no thumbnail Bundle[] original = item.getBundles("ORIGINAL"); if (original.length == 0) { return null; } // if multiple bitstreams, check if the primary one is HTML boolean html = false; if (original[0].getBitstreams().length > 1) { Bitstream[] bitstreams = original[0].getBitstreams(); for (int i = 0; (i < bitstreams.length) && !html; i++) { if (bitstreams[i].getID() == original[0].getPrimaryBitstreamID()) { html = bitstreams[i].getFormat().getMIMEType().equals("text/html"); } } } // now actually pull out the thumbnail (ouch!) Bundle[] thumbs = item.getBundles("THUMBNAIL"); // if there are thumbs and we're not dealing with an HTML item // then show the thumbnail if ((thumbs.length > 0) && !html) { Bitstream thumbnailBitstream; Bitstream originalBitstream; if ((original[0].getBitstreams().length > 1) && (original[0].getPrimaryBitstreamID() > -1)) { originalBitstream = Bitstream.find(context, original[0].getPrimaryBitstreamID()); thumbnailBitstream = thumbs[0].getBitstreamByName(originalBitstream.getName() + ".jpg"); } else { originalBitstream = original[0].getBitstreams()[0]; thumbnailBitstream = thumbs[0].getBitstreams()[0]; } if ((thumbnailBitstream != null) && (AuthorizeManager.authorizeActionBoolean(context, thumbnailBitstream, Constants.READ))) { Thumbnail thumbnail = new Thumbnail(thumbnailBitstream, originalBitstream); return thumbnail; } } return null; } public String getName() { // FIXME: there is an exception handling problem here try { DCValue t[] = getMetadata("dc", "title", null, Item.ANY); return (t.length >= 1) ? t[0].value : null; } catch (SQLException sqle) { log.error("caught exception: ", sqle); return null; } } public boolean isArchived() { return in_archive; } public boolean isWithdrawn() { return withdrawn; } }