001: /*
002: * HandleManager.java
003: *
004: * Version: $Revision: 1523 $
005: *
006: * Date: $Date: 2006-05-26 09:23:17 -0500 (Fri, 26 May 2006) $
007: *
008: * Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
009: * Institute of Technology. All rights reserved.
010: *
011: * Redistribution and use in source and binary forms, with or without
012: * modification, are permitted provided that the following conditions are
013: * met:
014: *
015: * - Redistributions of source code must retain the above copyright
016: * notice, this list of conditions and the following disclaimer.
017: *
018: * - Redistributions in binary form must reproduce the above copyright
019: * notice, this list of conditions and the following disclaimer in the
020: * documentation and/or other materials provided with the distribution.
021: *
022: * - Neither the name of the Hewlett-Packard Company nor the name of the
023: * Massachusetts Institute of Technology nor the names of their
024: * contributors may be used to endorse or promote products derived from
025: * this software without specific prior written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
030: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
032: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
033: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
034: * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
035: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
036: * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
037: * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
038: * DAMAGE.
039: */
040: package org.dspace.handle;
041:
042: import java.sql.SQLException;
043: import java.util.ArrayList;
044: import java.util.List;
045:
046: import org.apache.log4j.Logger;
047: import org.dspace.content.Collection;
048: import org.dspace.content.Community;
049: import org.dspace.content.DSpaceObject;
050: import org.dspace.content.Item;
051: import org.dspace.core.ConfigurationManager;
052: import org.dspace.core.Constants;
053: import org.dspace.core.Context;
054: import org.dspace.storage.rdbms.DatabaseManager;
055: import org.dspace.storage.rdbms.TableRow;
056: import org.dspace.storage.rdbms.TableRowIterator;
057:
058: /**
059: * Interface to the <a href="http://www.handle.net" target=_new>CNRI Handle
060: * System </a>.
061: *
062: * <p>
063: * Currently, this class simply maps handles to local facilities; handles which
064: * are owned by other sites (including other DSpaces) are treated as
065: * non-existent.
066: * </p>
067: *
068: * @author Peter Breton
069: * @version $Revision: 1523 $
070: */
071: public class HandleManager {
072: /** log4j category */
073: private static Logger log = Logger.getLogger(HandleManager.class);
074:
075: /** Private Constructor */
076: private HandleManager() {
077: }
078:
079: /**
080: * Return the local URL for handle, or null if handle cannot be found.
081: *
082: * The returned URL is a (non-handle-based) location where a dissemination
083: * of the object referred to by handle can be obtained.
084: *
085: * @param context
086: * DSpace context
087: * @param handle
088: * The handle
089: * @return The local URL
090: * @exception SQLException
091: * If a database error occurs
092: */
093: public static String resolveToURL(Context context, String handle)
094: throws SQLException {
095: TableRow dbhandle = findHandleInternal(context, handle);
096:
097: if (dbhandle == null) {
098: return null;
099: }
100:
101: String url = ConfigurationManager.getProperty("dspace.url")
102: + "/handle/" + handle;
103:
104: if (log.isDebugEnabled()) {
105: log.debug("Resolved " + handle + " to " + url);
106: }
107:
108: return url;
109: }
110:
111: /**
112: * Transforms handle into the canonical form <em>hdl:handle</em>.
113: *
114: * No attempt is made to verify that handle is in fact valid.
115: *
116: * @param handle
117: * The handle
118: * @return The canonical form
119: */
120: public static String getCanonicalForm(String handle) {
121: // return "hdl:" + handle;
122: return "http://hdl.handle.net/" + handle;
123: }
124:
125: /**
126: * Returns displayable string of the handle's 'temporary' URL
127: * <em>http://hdl.handle.net/handle/em>.
128: *
129: * No attempt is made to verify that handle is in fact valid.
130: *
131: * @param handle The handle
132: * @return The canonical form
133: */
134:
135: // public static String getURLForm(String handle)
136: // {
137: // return "http://hdl.handle.net/" + handle;
138: // }
139: /**
140: * Creates a new handle in the database.
141: *
142: * @param context
143: * DSpace context
144: * @param dso
145: * The DSpaceObject to create a handle for
146: * @return The newly created handle
147: * @exception SQLException
148: * If a database error occurs
149: */
150: public static String createHandle(Context context, DSpaceObject dso)
151: throws SQLException {
152: TableRow handle = DatabaseManager.create(context, "Handle");
153: String handleId = createId(handle.getIntColumn("handle_id"));
154:
155: handle.setColumn("handle", handleId);
156: handle.setColumn("resource_type_id", dso.getType());
157: handle.setColumn("resource_id", dso.getID());
158: DatabaseManager.update(context, handle);
159:
160: if (log.isDebugEnabled()) {
161: log.debug("Created new handle for "
162: + Constants.typeText[dso.getType()] + " "
163: + handleId);
164: }
165:
166: return handleId;
167: }
168:
169: /**
170: * Creates a handle entry, but with a handle supplied by the caller (new
171: * Handle not generated)
172: *
173: * @param context
174: * DSpace context
175: * @param dso
176: * DSpaceObject
177: * @param suppliedHandle
178: * existing handle value
179: * @return the Handle
180: */
181: public static String createHandle(Context context,
182: DSpaceObject dso, String suppliedHandle)
183: throws SQLException {
184: TableRow handle = DatabaseManager.create(context, "Handle");
185: String handleId = suppliedHandle;
186:
187: handle.setColumn("handle", handleId);
188: handle.setColumn("resource_type_id", dso.getType());
189: handle.setColumn("resource_id", dso.getID());
190: DatabaseManager.update(context, handle);
191:
192: if (log.isDebugEnabled()) {
193: log.debug("Created new handle for "
194: + Constants.typeText[dso.getType()] + " "
195: + handleId);
196: }
197:
198: return handleId;
199: }
200:
201: /**
202: * Return the object which handle maps to, or null. This is the object
203: * itself, not a URL which points to it.
204: *
205: * @param context
206: * DSpace context
207: * @param handle
208: * The handle to resolve
209: * @return The object which handle maps to, or null if handle is not mapped
210: * to any object.
211: * @exception SQLException
212: * If a database error occurs
213: */
214: public static DSpaceObject resolveToObject(Context context,
215: String handle) throws SQLException {
216: TableRow dbhandle = findHandleInternal(context, handle);
217:
218: if (dbhandle == null) {
219: return null;
220: }
221:
222: if ((dbhandle.isColumnNull("resource_type_id"))
223: || (dbhandle.isColumnNull("resource_id"))) {
224: throw new IllegalStateException(
225: "No associated resource type");
226: }
227:
228: // What are we looking at here?
229: int handletypeid = dbhandle.getIntColumn("resource_type_id");
230: int resourceID = dbhandle.getIntColumn("resource_id");
231:
232: if (handletypeid == Constants.ITEM) {
233: Item item = Item.find(context, resourceID);
234:
235: if (log.isDebugEnabled()) {
236: log.debug("Resolved handle " + handle + " to item "
237: + ((item == null) ? (-1) : item.getID()));
238: }
239:
240: return item;
241: } else if (handletypeid == Constants.COLLECTION) {
242: Collection collection = Collection
243: .find(context, resourceID);
244:
245: if (log.isDebugEnabled()) {
246: log.debug("Resolved handle "
247: + handle
248: + " to collection "
249: + ((collection == null) ? (-1) : collection
250: .getID()));
251: }
252:
253: return collection;
254: } else if (handletypeid == Constants.COMMUNITY) {
255: Community community = Community.find(context, resourceID);
256:
257: if (log.isDebugEnabled()) {
258: log.debug("Resolved handle "
259: + handle
260: + " to community "
261: + ((community == null) ? (-1) : community
262: .getID()));
263: }
264:
265: return community;
266: }
267:
268: throw new IllegalStateException("Unsupported Handle Type "
269: + Constants.typeText[handletypeid]);
270: }
271:
272: /**
273: * Return the handle for an Object, or null if the Object has no handle.
274: *
275: * @param context
276: * DSpace context
277: * @param dso
278: * The object to obtain a handle for
279: * @return The handle for object, or null if the object has no handle.
280: * @exception SQLException
281: * If a database error occurs
282: */
283: public static String findHandle(Context context, DSpaceObject dso)
284: throws SQLException {
285: // if (!(obj instanceof Item))
286: // return null;
287: // Item item = (Item) obj;
288: return getHandleInternal(context, dso.getType(), dso.getID());
289: }
290:
291: /**
292: * Return all the handles which start with prefix.
293: *
294: * @param context
295: * DSpace context
296: * @param prefix
297: * The handle prefix
298: * @return A list of the handles starting with prefix. The list is
299: * guaranteed to be non-null. Each element of the list is a String.
300: * @exception SQLException
301: * If a database error occurs
302: */
303: static List getHandlesForPrefix(Context context, String prefix)
304: throws SQLException {
305: String sql = "SELECT handle FROM handle WHERE handle LIKE ? ";
306: TableRowIterator iterator = DatabaseManager.queryTable(context,
307: null, sql, prefix + "%");
308: List results = new ArrayList();
309:
310: while (iterator.hasNext()) {
311: TableRow row = (TableRow) iterator.next();
312: results.add(row.getStringColumn("handle"));
313: }
314:
315: iterator.close();
316:
317: return results;
318: }
319:
320: ////////////////////////////////////////
321: // Internal methods
322: ////////////////////////////////////////
323:
324: /**
325: * Return the handle for an Object, or null if the Object has no handle.
326: *
327: * @param context
328: * DSpace context
329: * @param type
330: * The type of object
331: * @param id
332: * The id of object
333: * @return The handle for object, or null if the object has no handle.
334: * @exception SQLException
335: * If a database error occurs
336: */
337: private static String getHandleInternal(Context context, int type,
338: int id) throws SQLException {
339: String sql = "SELECT handle FROM Handle WHERE resource_type_id = ? "
340: + "AND resource_id = ?";
341:
342: TableRow row = DatabaseManager.querySingle(context, sql, type,
343: id);
344:
345: return (row == null) ? null : row.getStringColumn("handle");
346: }
347:
348: /**
349: * Find the database row corresponding to handle.
350: *
351: * @param context
352: * DSpace context
353: * @param handle
354: * The handle to resolve
355: * @return The database row corresponding to the handle
356: * @exception SQLException
357: * If a database error occurs
358: */
359: private static TableRow findHandleInternal(Context context,
360: String handle) throws SQLException {
361: if (handle == null) {
362: throw new IllegalArgumentException("Handle is null");
363: }
364:
365: return DatabaseManager.findByUnique(context, "Handle",
366: "handle", handle);
367: }
368:
369: /**
370: * Create a new handle id. The implementation uses the PK of the RDBMS
371: * Handle table.
372: *
373: * @return A new handle id
374: * @exception SQLException
375: * If a database error occurs
376: */
377: private static String createId(int id) throws SQLException {
378: String handlePrefix = ConfigurationManager
379: .getProperty("handle.prefix");
380:
381: return new StringBuffer().append(handlePrefix).append(
382: handlePrefix.endsWith("/") ? "" : "/").append(id)
383: .toString();
384: }
385: }
|