KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > dspace > content > Bundle


1 /*
2  * Bundle.java
3  *
4  * Version: $Revision: 1.26 $
5  *
6  * Date: $Date: 2006/09/05 12:09:32 $
7  *
8  * Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
9  * Institute of Technology. All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions are
13  * met:
14  *
15  * - Redistributions of source code must retain the above copyright
16  * notice, this list of conditions and the following disclaimer.
17  *
18  * - Redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution.
21  *
22  * - Neither the name of the Hewlett-Packard Company nor the name of the
23  * Massachusetts Institute of Technology nor the names of their
24  * contributors may be used to endorse or promote products derived from
25  * this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
33  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
34  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
36  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
37  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38  * DAMAGE.
39  */

40 package org.dspace.content;
41
42 import java.io.IOException JavaDoc;
43 import java.io.InputStream JavaDoc;
44 import java.sql.SQLException JavaDoc;
45 import java.util.ArrayList JavaDoc;
46 import java.util.Iterator JavaDoc;
47 import java.util.List JavaDoc;
48 import java.util.ListIterator JavaDoc;
49
50 import org.apache.log4j.Logger;
51 import org.dspace.authorize.AuthorizeException;
52 import org.dspace.authorize.AuthorizeManager;
53 import org.dspace.core.Constants;
54 import org.dspace.core.Context;
55 import org.dspace.core.LogManager;
56 import org.dspace.storage.rdbms.DatabaseManager;
57 import org.dspace.storage.rdbms.TableRow;
58 import org.dspace.storage.rdbms.TableRowIterator;
59
60 /**
61  * Class representing bundles of bitstreams stored in the DSpace system
62  * <P>
63  * The corresponding Bitstream objects are loaded into memory. At present, there
64  * is no metadata associated with bundles - they are simple containers. Thus,
65  * the <code>update</code> method doesn't do much yet. Creating, adding or
66  * removing bitstreams has instant effect in the database.
67  *
68  * @author Robert Tansley
69  * @version $Revision: 1.26 $
70  */

71 public class Bundle extends DSpaceObject
72 {
73     /** log4j logger */
74     private static Logger log = Logger.getLogger(Bundle.class);
75
76     /** Our context */
77     private Context ourContext;
78
79     /** The table row corresponding to this bundle */
80     private TableRow bundleRow;
81
82     /** The bitstreams in this bundle */
83     private List JavaDoc bitstreams;
84
85     /**
86      * Construct a bundle object with the given table row
87      *
88      * @param context
89      * the context this object exists in
90      * @param row
91      * the corresponding row in the table
92      */

93     Bundle(Context context, TableRow row) throws SQLException JavaDoc
94     {
95         ourContext = context;
96         bundleRow = row;
97         bitstreams = new ArrayList JavaDoc();
98
99         // Get bitstreams
100
TableRowIterator tri = DatabaseManager.queryTable(
101                 ourContext, "bitstream",
102                 "SELECT bitstream.* FROM bitstream, bundle2bitstream WHERE "
103                         + "bundle2bitstream.bitstream_id=bitstream.bitstream_id AND "
104                         + "bundle2bitstream.bundle_id= ? ",
105                 bundleRow.getIntColumn("bundle_id"));
106         
107         while (tri.hasNext())
108         {
109             TableRow r = (TableRow) tri.next();
110
111             // First check the cache
112
Bitstream fromCache = (Bitstream) context.fromCache(
113                     Bitstream.class, r.getIntColumn("bitstream_id"));
114
115             if (fromCache != null)
116             {
117                 bitstreams.add(fromCache);
118             }
119             else
120             {
121                 bitstreams.add(new Bitstream(ourContext, r));
122             }
123         }
124         // close the TableRowIterator to free up resources
125
tri.close();
126
127         // Cache ourselves
128
context.cache(this, row.getIntColumn("bundle_id"));
129     }
130
131     /**
132      * Get a bundle from the database. The bundle and bitstream metadata are all
133      * loaded into memory.
134      *
135      * @param context
136      * DSpace context object
137      * @param id
138      * ID of the bundle
139      *
140      * @return the bundle, or null if the ID is invalid.
141      */

142     public static Bundle find(Context context, int id) throws SQLException JavaDoc
143     {
144         // First check the cache
145
Bundle fromCache = (Bundle) context.fromCache(Bundle.class, id);
146
147         if (fromCache != null)
148         {
149             return fromCache;
150         }
151
152         TableRow row = DatabaseManager.find(context, "bundle", id);
153
154         if (row == null)
155         {
156             if (log.isDebugEnabled())
157             {
158                 log.debug(LogManager.getHeader(context, "find_bundle",
159                         "not_found,bundle_id=" + id));
160             }
161
162             return null;
163         }
164         else
165         {
166             if (log.isDebugEnabled())
167             {
168                 log.debug(LogManager.getHeader(context, "find_bundle",
169                         "bundle_id=" + id));
170             }
171
172             return new Bundle(context, row);
173         }
174     }
175
176     /**
177      * Create a new bundle, with a new ID. This method is not public, since
178      * bundles need to be created within the context of an item. For this
179      * reason, authorisation is also not checked; that is the responsibility of
180      * the caller.
181      *
182      * @param context
183      * DSpace context object
184      *
185      * @return the newly created bundle
186      */

187     static Bundle create(Context context) throws SQLException JavaDoc
188     {
189         // Create a table row
190
TableRow row = DatabaseManager.create(context, "bundle");
191
192         log.info(LogManager.getHeader(context, "create_bundle", "bundle_id="
193                 + row.getIntColumn("bundle_id")));
194
195         return new Bundle(context, row);
196     }
197
198     /**
199      * Get the internal identifier of this bundle
200      *
201      * @return the internal identifier
202      */

203     public int getID()
204     {
205         return bundleRow.getIntColumn("bundle_id");
206     }
207
208     /**
209      * Get the name of the bundle
210      *
211      * @return name of the bundle (ORIGINAL, TEXT, THUMBNAIL) or NULL if not set
212      */

213     public String JavaDoc getName()
214     {
215         return bundleRow.getStringColumn("name");
216     }
217
218     /**
219      * Set the name of the bundle
220      *
221      * @param name
222      * string name of the bundle (ORIGINAL, TEXT, THUMBNAIL) are the
223      * values currently used
224      */

225     public void setName(String JavaDoc name)
226     {
227         bundleRow.setColumn("name", name);
228     }
229
230     /**
231      * Get the primary bitstream ID of the bundle
232      *
233      * @return primary bitstream ID or -1 if not set
234      */

235     public int getPrimaryBitstreamID()
236     {
237         return bundleRow.getIntColumn("primary_bitstream_id");
238     }
239
240     /**
241      * Set the primary bitstream ID of the bundle
242      *
243      * @param bitstreamID
244      * int ID of primary bitstream (e.g. index html file)
245      */

246     public void setPrimaryBitstreamID(int bitstreamID)
247     {
248         bundleRow.setColumn("primary_bitstream_id", bitstreamID);
249     }
250
251     /**
252      * Unset the primary bitstream ID of the bundle
253      */

254     public void unsetPrimaryBitstreamID()
255     {
256         bundleRow.setColumnNull("primary_bitstream_id");
257     }
258     
259     public String JavaDoc getHandle()
260     {
261         // No Handles for bundles
262
return null;
263     }
264
265     /**
266      * @param name
267      * name of the bitstream you're looking for
268      *
269      * @return the bitstream or null if not found
270      */

271     public Bitstream getBitstreamByName(String JavaDoc name)
272     {
273         Bitstream target = null;
274
275         Iterator JavaDoc i = bitstreams.iterator();
276
277         while (i.hasNext())
278         {
279             Bitstream b = (Bitstream) i.next();
280
281             if (name.equals(b.getName()))
282             {
283                 target = b;
284
285                 break;
286             }
287         }
288
289         return target;
290     }
291
292     /**
293      * Get the bitstreams in this bundle
294      *
295      * @return the bitstreams
296      */

297     public Bitstream[] getBitstreams()
298     {
299         Bitstream[] bitstreamArray = new Bitstream[bitstreams.size()];
300         bitstreamArray = (Bitstream[]) bitstreams.toArray(bitstreamArray);
301
302         return bitstreamArray;
303     }
304
305     /**
306      * Get the items this bundle appears in
307      *
308      * @return array of <code>Item</code> s this bundle appears in
309      */

310     public Item[] getItems() throws SQLException JavaDoc
311     {
312         List JavaDoc items = new ArrayList JavaDoc();
313
314         // Get items
315
TableRowIterator tri = DatabaseManager.queryTable(
316                 ourContext, "item",
317                 "SELECT item.* FROM item, item2bundle WHERE " +
318                 "item2bundle.item_id=item.item_id AND " +
319                 "item2bundle.bundle_id= ? ",
320                 bundleRow.getIntColumn("bundle_id"));
321         
322         while (tri.hasNext())
323         {
324             TableRow r = (TableRow) tri.next();
325
326             // Used cached copy if there is one
327
Item fromCache = (Item) ourContext.fromCache(Item.class, r
328                     .getIntColumn("item_id"));
329
330             if (fromCache != null)
331             {
332                 items.add(fromCache);
333             }
334             else
335             {
336                 items.add(new Item(ourContext, r));
337             }
338         }
339         // close the TableRowIterator to free up resources
340
tri.close();
341
342         Item[] itemArray = new Item[items.size()];
343         itemArray = (Item[]) items.toArray(itemArray);
344
345         return itemArray;
346     }
347
348     /**
349      * Create a new bitstream in this bundle.
350      *
351      * @param is
352      * the stream to read the new bitstream from
353      *
354      * @return the newly created bitstream
355      */

356     public Bitstream createBitstream(InputStream JavaDoc is) throws AuthorizeException,
357             IOException JavaDoc, SQLException JavaDoc
358     {
359         // Check authorisation
360
AuthorizeManager.authorizeAction(ourContext, this, Constants.ADD);
361
362         Bitstream b = Bitstream.create(ourContext, is);
363
364         // FIXME: Set permissions for bitstream
365
addBitstream(b);
366
367         return b;
368     }
369
370     /**
371      * Create a new bitstream in this bundle. This method is for registering
372      * bitstreams.
373      *
374      * @param assetstore corresponds to an assetstore in dspace.cfg
375      * @param bitstreamPath the path and filename relative to the assetstore
376      * @return the newly created bitstream
377      * @throws IOException
378      * @throws SQLException
379      */

380     public Bitstream registerBitstream(int assetstore, String JavaDoc bitstreamPath)
381         throws AuthorizeException, IOException JavaDoc, SQLException JavaDoc
382     {
383         // check authorisation
384
AuthorizeManager.authorizeAction(ourContext, this, Constants.ADD);
385
386         Bitstream b = Bitstream.register(ourContext, assetstore, bitstreamPath);
387
388         // FIXME: Set permissions for bitstream
389

390         addBitstream(b);
391         return b;
392     }
393
394     /**
395      * Add an existing bitstream to this bundle
396      *
397      * @param b
398      * the bitstream to add
399      */

400     public void addBitstream(Bitstream b) throws SQLException JavaDoc,
401             AuthorizeException
402     {
403         // Check authorisation
404
AuthorizeManager.authorizeAction(ourContext, this, Constants.ADD);
405
406         log.info(LogManager.getHeader(ourContext, "add_bitstream", "bundle_id="
407                 + getID() + ",bitstream_id=" + b.getID()));
408
409         // First check that the bitstream isn't already in the list
410
for (int i = 0; i < bitstreams.size(); i++)
411         {
412             Bitstream existing = (Bitstream) bitstreams.get(i);
413
414             if (b.getID() == existing.getID())
415             {
416                 // Bitstream is already there; no change
417
return;
418             }
419         }
420
421         // Add the bitstream object
422
bitstreams.add(b);
423
424         // copy authorization policies from bundle to bitstream
425
// FIXME: multiple inclusion is affected by this...
426
AuthorizeManager.inheritPolicies(ourContext, this, b);
427
428         // Add the mapping row to the database
429
TableRow mappingRow = DatabaseManager.create(ourContext,
430                 "bundle2bitstream");
431         mappingRow.setColumn("bundle_id", getID());
432         mappingRow.setColumn("bitstream_id", b.getID());
433         DatabaseManager.update(ourContext, mappingRow);
434     }
435
436     /**
437      * Remove a bitstream from this bundle - the bitstream is only deleted if
438      * this was the last reference to it
439      * <p>
440      * If the bitstream in question is the primary bitstream recorded for the
441      * bundle the primary bitstream field is unset in order to free the
442      * bitstream from the foreign key constraint so that the
443      * <code>cleanup</code> process can run normally.
444      *
445      * @param b
446      * the bitstream to remove
447      */

448     public void removeBitstream(Bitstream b) throws AuthorizeException,
449             SQLException JavaDoc, IOException JavaDoc
450     {
451         // Check authorisation
452
AuthorizeManager.authorizeAction(ourContext, this, Constants.REMOVE);
453
454         log.info(LogManager.getHeader(ourContext, "remove_bitstream",
455                 "bundle_id=" + getID() + ",bitstream_id=" + b.getID()));
456
457         // Remove from internal list of bitstreams
458
ListIterator JavaDoc li = bitstreams.listIterator();
459
460         while (li.hasNext())
461         {
462             Bitstream existing = (Bitstream) li.next();
463
464             if (b.getID() == existing.getID())
465             {
466                 // We've found the bitstream to remove
467
li.remove();
468                 
469                 // In the event that the bitstream to remove is actually
470
// the primary bitstream, be sure to unset the primary
471
// bitstream.
472
if (b.getID() == getPrimaryBitstreamID()) {
473                     unsetPrimaryBitstreamID();
474                 }
475             }
476         }
477
478         // Delete the mapping row
479
DatabaseManager.updateQuery(ourContext,
480                 "DELETE FROM bundle2bitstream WHERE bundle_id= ? "+
481                 "AND bitstream_id= ? ",
482                 getID(), b.getID());
483
484         // If the bitstream is orphaned, it's removed
485
TableRowIterator tri = DatabaseManager.query(ourContext,
486                 "SELECT * FROM bundle2bitstream WHERE bitstream_id= ? ",
487                 b.getID());
488
489         if (!tri.hasNext())
490         {
491             // The bitstream is an orphan, delete it
492
b.delete();
493         }
494         // close the TableRowIterator to free up resources
495
tri.close();
496     }
497
498     /**
499      * Update the bundle metadata
500      */

501     public void update() throws SQLException JavaDoc, AuthorizeException
502     {
503         // Check authorisation
504
//AuthorizeManager.authorizeAction(ourContext, this, Constants.WRITE);
505
log.info(LogManager.getHeader(ourContext, "update_bundle", "bundle_id="
506                 + getID()));
507
508         DatabaseManager.update(ourContext, bundleRow);
509     }
510
511     /**
512      * Delete the bundle. Bitstreams contained by the bundle are removed first;
513      * this may result in their deletion, if deleting this bundle leaves them as
514      * orphans.
515      */

516     void delete() throws SQLException JavaDoc, AuthorizeException, IOException JavaDoc
517     {
518         log.info(LogManager.getHeader(ourContext, "delete_bundle", "bundle_id="
519                 + getID()));
520
521         // Remove from cache
522
ourContext.removeCached(this, getID());
523
524         // Remove bitstreams
525
Bitstream[] bs = getBitstreams();
526
527         for (int i = 0; i < bs.length; i++)
528         {
529             removeBitstream(bs[i]);
530         }
531
532         // remove our authorization policies
533
AuthorizeManager.removeAllPolicies(ourContext, this);
534
535         // Remove ourself
536
DatabaseManager.delete(ourContext, bundleRow);
537     }
538
539     /**
540      * return type found in Constants
541      */

542     public int getType()
543     {
544         return Constants.BUNDLE;
545     }
546 }
547
Popular Tags