KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > dspace > app > itemexport > ItemExport


1 /*
2  * ItemExport.java
3  *
4  * Version: $Revision: 1.14 $
5  *
6  * Date: $Date: 2005/11/16 21:40:52 $
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.app.itemexport;
41
42 import java.io.BufferedOutputStream JavaDoc;
43 import java.io.File JavaDoc;
44 import java.io.FileOutputStream JavaDoc;
45 import java.io.FileWriter JavaDoc;
46 import java.io.InputStream JavaDoc;
47 import java.io.PrintWriter JavaDoc;
48 import java.util.HashMap JavaDoc;
49 import java.util.Iterator JavaDoc;
50
51 import org.apache.commons.cli.CommandLine;
52 import org.apache.commons.cli.CommandLineParser;
53 import org.apache.commons.cli.HelpFormatter;
54 import org.apache.commons.cli.Options;
55 import org.apache.commons.cli.PosixParser;
56 import org.dspace.content.Bitstream;
57 import org.dspace.content.Bundle;
58 import org.dspace.content.Collection;
59 import org.dspace.content.DCValue;
60 import org.dspace.content.Item;
61 import org.dspace.content.ItemIterator;
62 import org.dspace.content.MetadataSchema;
63 import org.dspace.core.Constants;
64 import org.dspace.core.Context;
65 import org.dspace.core.Utils;
66 import org.dspace.handle.HandleManager;
67
68 /**
69  * Item exporter to create simple AIPs for DSpace content. Currently exports
70  * individual items, or entire collections. For instructions on use, see
71  * printUsage() method.
72  * <P>
73  * ItemExport creates the simple AIP package that the importer also uses. It
74  * consists of:
75  * <P>
76  * /exportdir/42/ (one directory per item) / dublin_core.xml - qualified dublin
77  * core in RDF schema / contents - text file, listing one file per line / file1 -
78  * files contained in the item / file2 / ...
79  * <P>
80  * issues -doesn't handle special characters in metadata (needs to turn &'s into
81  * &amp;, etc.)
82  * <P>
83  * Modified by David Little, UCSD Libraries 12/21/04 to
84  * allow the registration of files (bitstreams) into DSpace.
85  */

86 public class ItemExport
87 {
88     /*
89      *
90      */

91     public static void main(String JavaDoc[] argv) throws Exception JavaDoc
92     {
93         // create an options object and populate it
94
CommandLineParser parser = new PosixParser();
95
96         Options options = new Options();
97
98         options.addOption("t", "type", true, "type: COLLECTION or ITEM");
99         options.addOption("i", "id", true, "ID or handle of thing to export");
100         options.addOption("d", "dest", true,
101                 "destination where you want items to go");
102         options.addOption("n", "number", true,
103                 "sequence number to begin exporting items with");
104         options.addOption("h", "help", false, "help");
105
106         CommandLine line = parser.parse(options, argv);
107
108         String JavaDoc typeString = null;
109         String JavaDoc destDirName = null;
110         String JavaDoc myIDString = null;
111         int seqStart = -1;
112         int myType = -1;
113
114         Item myItem = null;
115         Collection mycollection = null;
116
117         if (line.hasOption('h'))
118         {
119             HelpFormatter myhelp = new HelpFormatter();
120             myhelp.printHelp("ItemExport\n", options);
121             System.out
122                     .println("\nfull collection: ItemExport -t COLLECTION -i ID -d dest -n number");
123             System.out
124                     .println("singleitem: ItemExport -t ITEM -i ID -d dest -n number");
125
126             System.exit(0);
127         }
128
129         if (line.hasOption('t')) // type
130
{
131             typeString = line.getOptionValue('t');
132
133             if (typeString.equals("ITEM"))
134             {
135                 myType = Constants.ITEM;
136             }
137             else if (typeString.equals("COLLECTION"))
138             {
139                 myType = Constants.COLLECTION;
140             }
141         }
142
143         if (line.hasOption('i')) // id
144
{
145             myIDString = line.getOptionValue('i');
146         }
147
148         if (line.hasOption('d')) // dest
149
{
150             destDirName = line.getOptionValue('d');
151         }
152
153         if (line.hasOption('n')) // number
154
{
155             seqStart = Integer.parseInt(line.getOptionValue('n'));
156         }
157
158         // now validate the args
159
if (myType == -1)
160         {
161             System.out
162                     .println("type must be either COLLECTION or ITEM (-h for help)");
163             System.exit(1);
164         }
165
166         if (destDirName == null)
167         {
168             System.out
169                     .println("destination directory must be set (-h for help)");
170             System.exit(1);
171         }
172
173         if (seqStart == -1)
174         {
175             System.out
176                     .println("sequence start number must be set (-h for help)");
177             System.exit(1);
178         }
179
180         if (myIDString == null)
181         {
182             System.out
183                     .println("ID must be set to either a database ID or a handle (-h for help)");
184             System.exit(1);
185         }
186
187         Context c = new Context();
188         c.setIgnoreAuthorization(true);
189
190         if (myType == Constants.ITEM)
191         {
192             // first, is myIDString a handle?
193
if (myIDString.indexOf('/') != -1)
194             {
195                 myItem = (Item) HandleManager.resolveToObject(c, myIDString);
196
197                 if ((myItem == null) || (myItem.getType() != Constants.ITEM))
198                 {
199                     myItem = null;
200                 }
201             }
202             else
203             {
204                 myItem = Item.find(c, Integer.parseInt(myIDString));
205             }
206
207             if (myItem == null)
208             {
209                 System.out
210                         .println("Error, item cannot be found: " + myIDString);
211             }
212         }
213         else
214         {
215             if (myIDString.indexOf('/') != -1)
216             {
217                 // has a / must be a handle
218
mycollection = (Collection) HandleManager.resolveToObject(c,
219                         myIDString);
220
221                 // ensure it's a collection
222
if ((mycollection == null)
223                         || (mycollection.getType() != Constants.COLLECTION))
224                 {
225                     mycollection = null;
226                 }
227             }
228             else if (myIDString != null)
229             {
230                 mycollection = Collection.find(c, Integer.parseInt(myIDString));
231             }
232
233             if (mycollection == null)
234             {
235                 System.out.println("Error, collection cannot be found: "
236                         + myIDString);
237                 System.exit(1);
238             }
239         }
240
241         if (myItem != null)
242         {
243             // it's only a single item
244
exportItem(c, myItem, destDirName, seqStart);
245         }
246         else
247         {
248             System.out.println("Exporting from collection: " + myIDString);
249
250             // it's a collection, so do a bunch of items
251
ItemIterator i = mycollection.getItems();
252
253             exportItem(c, i, destDirName, seqStart);
254         }
255
256         c.complete();
257     }
258
259     private static void exportItem(Context c, ItemIterator i,
260             String JavaDoc destDirName, int seqStart) throws Exception JavaDoc
261     {
262         int mySequenceNumber = seqStart;
263
264         System.out.println("Beginning export");
265
266         while (i.hasNext())
267         {
268             System.out.println("Exporting item to " + mySequenceNumber);
269             exportItem(c, i.next(), destDirName, mySequenceNumber);
270             mySequenceNumber++;
271         }
272     }
273
274     private static void exportItem(Context c, Item myItem, String JavaDoc destDirName,
275             int seqStart) throws Exception JavaDoc
276     {
277         File JavaDoc destDir = new File JavaDoc(destDirName);
278
279         if (destDir.exists())
280         {
281             // now create a subdirectory
282
File JavaDoc itemDir = new File JavaDoc(destDir + "/" + seqStart);
283
284             System.out.println("Exporting Item " + myItem.getID() + " to "
285                     + itemDir);
286
287             if (itemDir.exists())
288             {
289                 throw new Exception JavaDoc("Directory " + destDir + "/" + seqStart
290                         + " already exists!");
291             }
292
293             if (itemDir.mkdir())
294             {
295                 // make it this far, now start exporting
296
writeMetadata(c, myItem, itemDir);
297                 writeBitstreams(c, myItem, itemDir);
298                 writeHandle(c, myItem, itemDir);
299             }
300             else
301             {
302                 throw new Exception JavaDoc("Error, can't make dir " + itemDir);
303             }
304         }
305         else
306         {
307             throw new Exception JavaDoc("Error, directory " + destDirName
308                     + " doesn't exist!");
309         }
310     }
311
312     /**
313      * Discover the different schemas in use and output a seperate metadata
314      * XML file for each schema.
315      *
316      * @param c
317      * @param i
318      * @param destDir
319      * @throws Exception
320      */

321     private static void writeMetadata(Context c, Item i, File JavaDoc destDir)
322             throws Exception JavaDoc
323     {
324         // Build a list of schemas for the item
325
HashMap JavaDoc map = new HashMap JavaDoc();
326         DCValue[] dcorevalues = i.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY);
327         for (int ii = 0; ii < dcorevalues.length; ii++)
328         {
329             map.put(dcorevalues[ii].schema, null);
330         }
331
332         // Save each of the schemas into it's own metadata file
333
Iterator JavaDoc iterator = map.keySet().iterator();
334         while (iterator.hasNext())
335         {
336             String JavaDoc schema = (String JavaDoc) iterator.next();
337             writeMetadata(c, schema, i, destDir);
338         }
339     }
340
341     // output the item's dublin core into the item directory
342
private static void writeMetadata(Context c, String JavaDoc schema, Item i, File JavaDoc destDir)
343             throws Exception JavaDoc
344     {
345         String JavaDoc filename;
346         if (schema.equals(MetadataSchema.DC_SCHEMA)) {
347             filename = "dublin_core.xml";
348         } else {
349             filename = "metadata_" + schema + ".xml";
350         }
351         
352         File JavaDoc outFile = new File JavaDoc(destDir, filename);
353
354         System.out.println("Attempting to create file " + outFile);
355
356         if (outFile.createNewFile())
357         {
358             BufferedOutputStream JavaDoc out = new BufferedOutputStream JavaDoc(
359                     new FileOutputStream JavaDoc(outFile));
360
361             DCValue[] dcorevalues = i.getMetadata(schema, Item.ANY, Item.ANY, Item.ANY);
362
363             // XML preamble
364
byte[] utf8 = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n"
365                     .getBytes("UTF-8");
366             out.write(utf8, 0, utf8.length);
367
368             String JavaDoc dcTag = "<dublin_core schema=\""+schema+"\">\n";
369             utf8 = dcTag.getBytes("UTF-8");
370             out.write(utf8, 0, utf8.length);
371
372             for (int j = 0; j < dcorevalues.length; j++)
373             {
374                 DCValue dcv = dcorevalues[j];
375                 String JavaDoc qualifier = dcv.qualifier;
376
377                 if (qualifier == null)
378                 {
379                     qualifier = "none";
380                 }
381
382                 utf8 = (" <dcvalue element=\"" + dcv.element + "\" "
383                         + "qualifier=\"" + qualifier + "\">"
384                         + Utils.addEntities(dcv.value) + "</dcvalue>\n").getBytes("UTF-8");
385
386                 out.write(utf8, 0, utf8.length);
387             }
388
389             utf8 = "</dublin_core>\n".getBytes("UTF-8");
390             out.write(utf8, 0, utf8.length);
391
392             out.close();
393         }
394         else
395         {
396             throw new Exception JavaDoc("Cannot create dublin_core.xml in " + destDir);
397         }
398     }
399
400     // create the file 'handle' which contains the handle assigned to the item
401
private static void writeHandle(Context c, Item i, File JavaDoc destDir)
402             throws Exception JavaDoc
403     {
404         String JavaDoc filename = "handle";
405
406         File JavaDoc outFile = new File JavaDoc(destDir, filename);
407
408         if (outFile.createNewFile())
409         {
410             PrintWriter JavaDoc out = new PrintWriter JavaDoc(new FileWriter JavaDoc(outFile));
411
412             out.println(i.getHandle());
413
414             // close the contents file
415
out.close();
416         }
417         else
418         {
419             throw new Exception JavaDoc("Cannot create file " + filename + " in "
420                     + destDir);
421         }
422     }
423
424     /**
425      * Create both the bitstreams and the contents file. Any bitstreams that
426      * were originally registered will be marked in the contents file as such.
427      * However, the export directory will contain actual copies of the content
428      * files being exported.
429      *
430      * @param c the DSpace context
431      * @param i the item being exported
432      * @param destDir the item's export directory
433      * @throws Exception if there is any problem writing to the export
434      * directory
435      */

436     private static void writeBitstreams(Context c, Item i, File JavaDoc destDir)
437             throws Exception JavaDoc
438     {
439         File JavaDoc outFile = new File JavaDoc(destDir, "contents");
440
441         if (outFile.createNewFile())
442         {
443             PrintWriter JavaDoc out = new PrintWriter JavaDoc(new FileWriter JavaDoc(outFile));
444
445             Bundle[] bundles = i.getBundles();
446
447             for (int j = 0; j < bundles.length; j++)
448             {
449                 // bundles can have multiple bitstreams now...
450
Bitstream[] bitstreams = bundles[j].getBitstreams();
451
452                 String JavaDoc bundleName = bundles[j].getName();
453
454                 for (int k = 0; k < bitstreams.length; k++)
455                 {
456                     Bitstream b = bitstreams[k];
457
458                     String JavaDoc myName = b.getName();
459                     String JavaDoc oldName = myName;
460                     int myPrefix = 1; // only used with name conflict
461

462                     InputStream JavaDoc is = b.retrieve();
463
464                     boolean isDone = false; // done when bitstream is finally
465
// written
466

467                     while (!isDone)
468                     {
469                         File JavaDoc fout = new File JavaDoc(destDir, myName);
470
471                         if (fout.createNewFile())
472                         {
473                             FileOutputStream JavaDoc fos = new FileOutputStream JavaDoc(fout);
474                             Utils.bufferedCopy(is, fos);
475                             // close streams
476
is.close();
477                             fos.close();
478
479                             // write the manifest file entry
480
if (b.isRegisteredBitstream()) {
481                                 out.println("-r -s " + b.getStoreNumber()
482                                         + " -f " + myName
483                                         + "\tbundle:" + bundleName);
484                             } else {
485                                 out.println(myName + "\tbundle:" + bundleName);
486                             }
487
488                             isDone = true;
489                         }
490                         else
491                         {
492                             myName = myPrefix + "_" + oldName; // keep appending
493
// numbers to the
494
// filename until
495
// unique
496
myPrefix++;
497                         }
498                     }
499                 }
500             }
501
502             // close the contents file
503
out.close();
504         }
505         else
506         {
507             throw new Exception JavaDoc("Cannot create contents in " + destDir);
508         }
509     }
510 }
511
Popular Tags