/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.xmlui.utils;
import java.sql.SQLException;
import java.util.Map;
import java.util.Stack;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.dspace.app.xmlui.wing.Message;
import org.dspace.app.xmlui.wing.WingException;
import org.dspace.app.xmlui.wing.element.PageMeta;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.handle.HandleManager;
/**
* Simple utility class for extracting handles.
*
* @author Scott Phillips
*/
public class HandleUtil
{
/** The URL prefix of all handles */
protected static final String HANDLE_PREFIX = "handle/";
protected static final String DSPACE_OBJECT = "dspace.object";
/**
* Obtain the current DSpace handle for the specified request.
*
* @param objectModel
* The cocoon model.
* @return A DSpace handle, or null if none found.
*/
public static DSpaceObject obtainHandle(Map objectModel)
throws SQLException
{
Request request = ObjectModelHelper.getRequest(objectModel);
DSpaceObject dso = (DSpaceObject) request.getAttribute(DSPACE_OBJECT);
if (dso == null)
{
String uri = request.getSitemapURI();
if (!uri.startsWith(HANDLE_PREFIX))
{
// Dosn't start with the prefix then no match
return null;
}
String handle = uri.substring(HANDLE_PREFIX.length());
int firstSlash = handle.indexOf('/');
if (firstSlash < 0)
{
// If there is no first slash then no match
return null;
}
int secondSlash = handle.indexOf('/', firstSlash + 1);
if (secondSlash < 0)
{
// A trailing slash is not nesssary if there is nothing after
// the handle.
secondSlash = handle.length();
}
handle = handle.substring(0, secondSlash);
Context context = ContextUtil.obtainContext(objectModel);
dso = HandleManager.resolveToObject(context, handle);
request.setAttribute(DSPACE_OBJECT, dso);
}
return dso;
}
/**
* Determine if the given DSO is an ancestor of the the parent handle.
*
* @param dso
* The child DSO object.
* @param parent
* The Handle to test against.
* @return The matched DSO object or null if none found.
*/
public static boolean inheritsFrom(DSpaceObject dso, String parent)
throws SQLException
{
DSpaceObject current = dso;
while (current != null)
{
// Check if the current object has the handle we are looking for.
if (current.getHandle().equals(parent))
{
return true;
}
if (current.getType() == Constants.ITEM)
{
current = ((Item) current).getOwningCollection();
}
else if (current.getType() == Constants.COLLECTION)
{
current = ((Collection) current).getCommunities()[0];
}
else if (current.getType() == Constants.COMMUNITY)
{
current = ((Community) current).getParentCommunity();
}
}
// If the loop finished then we searched the entire parant-child chain
// and did not find this handle, so the object was not found.
return false;
}
/**
* Build a list of trail metadata starting with the owning collection and
* ending with the root level parent. If the Object is an item, a bundle,
* or a bitstream, then the object is not included, but its collection and
* community parents are. However if the item is a community or collection
* then it is included along with all parents.
*
* <p>
* If the terminal object in the trail is the passed object, do not link to
* it, because that is (presumably) the page at which the user has arrived.
*
* @param dso
* @param pageMeta
*/
public static void buildHandleTrail(DSpaceObject dso, PageMeta pageMeta,
String contextPath) throws SQLException, WingException
{
// Add the trail back to the repository root.
Stack<DSpaceObject> stack = new Stack<DSpaceObject>();
DSpaceObject aDso = dso;
if (aDso instanceof Bitstream)
{
Bitstream bitstream = (Bitstream) aDso;
Bundle[] bundles = bitstream.getBundles();
aDso = bundles[0];
}
if (aDso instanceof Bundle)
{
Bundle bundle = (Bundle) aDso;
Item[] items = bundle.getItems();
aDso = items[0];
}
if (aDso instanceof Item)
{
Item item = (Item) aDso;
Collection collection = item.getOwningCollection();
aDso = collection;
}
if (aDso instanceof Collection)
{
Collection collection = (Collection) aDso;
stack.push(collection);
Community[] communities = collection.getCommunities();
aDso = communities[0];
}
if (aDso instanceof Community)
{
Community community = (Community) aDso;
stack.push(community);
for (Community parent : community.getAllParents())
{
stack.push(parent);
}
}
while (!stack.empty())
{
DSpaceObject pop = stack.pop();
String target;
if (pop == dso)
target = null; // Do not link "back" to the terminal object
else
target = contextPath + "/handle/" + pop.getHandle();
if (pop instanceof Collection)
{
Collection collection = (Collection) pop;
String name = collection.getMetadata("name");
if (name == null || name.length() == 0)
{
pageMeta.addTrailLink(target, new Message("default", "xmlui.general.untitled"));
}
else
{
pageMeta.addTrailLink(target, name);
}
}
else if (pop instanceof Community)
{
Community community = (Community) pop;
String name = community.getMetadata("name");
if (name == null || name.length() == 0)
{
pageMeta.addTrailLink(target, new Message("default", "xmlui.general.untitled"));
}
else
{
pageMeta.addTrailLink(target, name);
}
}
}
}
}