Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that represents an XML document
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Matt Jones
7
 *    Release: @release@
8
 *
9
 *   '$Author: bojilova $'
10
 *     '$Date: 2000-08-30 11:19:41 -0700 (Wed, 30 Aug 2000) $'
11
 * '$Revision: 421 $'
12
 */
13

    
14
package edu.ucsb.nceas.metacat;
15

    
16
import java.sql.*;
17
import java.io.PrintWriter;
18
import java.util.TreeSet;
19

    
20
import java.io.*;
21
import java.util.Stack;
22

    
23
import org.xml.sax.AttributeList;
24
import org.xml.sax.ContentHandler;
25
import org.xml.sax.DTDHandler;
26
import org.xml.sax.EntityResolver;
27
import org.xml.sax.ErrorHandler;
28
import org.xml.sax.InputSource;
29
import org.xml.sax.XMLReader;
30
import org.xml.sax.SAXException;
31
import org.xml.sax.SAXParseException;
32
import org.xml.sax.helpers.XMLReaderFactory;
33

    
34
/**
35
 * A class that represents an XML document. It can be created with a simple
36
 * document identifier from a database connection.  It also will write an
37
 * XML text document to a database connection using SAX.
38
 */
39
public class DocumentImpl {
40

    
41
  private Connection conn = null;
42
  private String docid = null;
43
  private String docname = null;
44
  private String doctype = null;
45
  private String system_id = null;
46
  private long rootnodeid;
47
  private ElementNode rootNode = null;
48
  private String doctitle = null;
49

    
50
  /**
51
   * Constructor, creates document from database connection, used 
52
   * for reading the document
53
   *
54
   * @param conn the database connection from which to read the document
55
   * @param docid the identifier of the document to be created
56
   */
57
  public DocumentImpl(Connection conn, String docid) throws McdbException 
58
  {
59
    try {
60
      this.conn = conn;
61
      this.docid = docid;
62
  
63
      // Look up the document information
64
      getDocumentInfo(docid);
65
      
66
      // Download all of the document nodes using a single SQL query
67
      TreeSet nodeRecordList = getNodeRecordList(rootnodeid);
68
  
69
      // Create the elements from the downloaded data in the TreeSet
70
      rootNode = new ElementNode(nodeRecordList, rootnodeid);
71

    
72
    } catch (McdbException ex) {
73
      throw ex;
74
    } catch (Throwable t) {
75
      throw new McdbException("Error reading document " + docid + ".");
76
    }
77
  }
78

    
79
  /** 
80
   * Construct a new document instance, writing the contents to the database.
81
   * This method is called from DBSAXHandler because we need to know the
82
   * root element name for documents without a DOCTYPE before creating it.
83
   *
84
   * @param conn the JDBC Connection to which all information is written
85
   * @param rootnodeid - sequence id of the root node in the document
86
   * @param docname - the name of DTD, i.e. the name immediately following 
87
   *        the DOCTYPE keyword ( should be the root element name ) or
88
   *        the root element name if no DOCTYPE declaration provided
89
   *        (Oracle's and IBM parsers are not aware if it is not the 
90
   *        root element name)
91
   * @param doctype - Public ID of the DTD, i.e. the name immediately 
92
   *                  following the PUBLIC keyword in DOCTYPE declaration or
93
   *                  the docname if no Public ID provided or
94
   *                  null if no DOCTYPE declaration provided
95
   *
96
   */
97
  public DocumentImpl(Connection conn, long rootnodeid, String docname, 
98
                      String doctype, String docid, String action)
99
                      throws AccessionNumberException 
100
  {
101
    this.conn = conn;
102
    this.rootnodeid = rootnodeid;
103
    this.docname = docname;
104
    this.doctype = doctype;
105
    this.docid = docid;
106
    writeDocumentToDB(action);
107
  }
108

    
109
  /**
110
   * get the document name
111
   */
112
  public String getDocname() {
113
    return docname;
114
  }
115

    
116
  /**
117
   * get the document type (which is the PublicID)
118
   */
119
  public String getDoctype() {
120
    return doctype;
121
  }
122

    
123
  /**
124
   * get the system identifier
125
   */
126
  public String getSystemID() {
127
    return system_id;
128
  }
129

    
130
  /**
131
   * get the root node identifier
132
   */
133
  public long getRootNodeID() {
134
    return rootnodeid;
135
  }
136

    
137
  /** 
138
   * Get the document identifier (docid)
139
   */
140
  public String getDocID() {
141
    return docid;
142
  }
143

    
144
  /**
145
   * Create an XML document from the database for the document with ID docid
146
   */
147
  public String toString()
148
  {
149
    StringBuffer doc = new StringBuffer();
150

    
151
    // Append the resulting document to the StringBuffer and return it
152
    doc.append("<?xml version=\"1.0\"?>\n");
153
      
154
    if (docname != null) {
155
      if ((doctype != null) && (system_id != null)) {
156
        doc.append("<!DOCTYPE " + docname + " PUBLIC \"" + doctype + 
157
                   "\" \"" + system_id + "\">\n");
158
      } else {
159
        doc.append("<!DOCTYPE " + docname + ">\n");
160
      }
161
    }
162
    doc.append(rootNode.toString());
163
  
164
    return (doc.toString());
165
  }
166

    
167
  /**
168
   * Look up the document type information from the database
169
   *
170
   * @param docid the id of the document to look up
171
   */
172
  private void getDocumentInfo(String docid) throws McdbException 
173
  {
174
    PreparedStatement pstmt;
175

    
176
    try {
177
      pstmt =
178
        conn.prepareStatement("SELECT docname,doctype,rootnodeid " +
179
                                "FROM xml_documents " +
180
                               "WHERE docid = ?");
181
      // Bind the values to the query
182
      pstmt.setString(1, docid);
183

    
184
      pstmt.execute();
185
      ResultSet rs = pstmt.getResultSet();
186
      boolean tableHasRows = rs.next();
187
      if (tableHasRows) {
188
        this.docname    = rs.getString(1);
189
        this.doctype    = rs.getString(2);
190
        this.rootnodeid = rs.getLong(3);
191
      } 
192
      pstmt.close();
193

    
194
      if (this.doctype != null) {
195
        pstmt =
196
          conn.prepareStatement("SELECT system_id " +
197
                                  "FROM xml_catalog " +
198
                                 "WHERE public_id = ?");
199
        // Bind the values to the query
200
        pstmt.setString(1, doctype);
201
  
202
        pstmt.execute();
203
        rs = pstmt.getResultSet();
204
        tableHasRows = rs.next();
205
        if (tableHasRows) {
206
          this.system_id  = rs.getString(1);
207
        } 
208
        pstmt.close();
209
      }
210
    } catch (SQLException e) {
211
      throw new McdbException("Error accessing database connection.", e);
212
    }
213

    
214
    if (this.docname == null) {
215
      throw new McdbDocNotFoundException("Document not found: " + docid);
216
    }
217
  }
218

    
219
  /**
220
   * Look up the node data from the database
221
   *
222
   * @param rootnodeid the id of the root node of the node tree to look up
223
   */
224
  private TreeSet getNodeRecordList(long rootnodeid) throws McdbException 
225
  {
226
    PreparedStatement pstmt;
227
    TreeSet nodeRecordList = new TreeSet(new NodeComparator());
228
    long nodeid = 0;
229
    long parentnodeid = 0;
230
    long nodeindex = 0;
231
    String nodetype = null;
232
    String nodename = null;
233
    String nodedata = null;
234

    
235
    try {
236
      pstmt =
237
      conn.prepareStatement("SELECT nodeid,parentnodeid,nodeindex, " +
238
           "nodetype,nodename,"+               
239
           "replace(" +
240
           "replace(" +
241
           "replace(nodedata,'&','&amp;') " +
242
           ",'<','&lt;') " +
243
           ",'>','&gt;') " +
244
           "FROM xml_nodes WHERE rootnodeid = ?");
245

    
246
      // Bind the values to the query
247
      pstmt.setLong(1, rootnodeid);
248

    
249
      pstmt.execute();
250
      ResultSet rs = pstmt.getResultSet();
251
      boolean tableHasRows = rs.next();
252
      while (tableHasRows) {
253
        nodeid = rs.getLong(1);
254
        parentnodeid = rs.getLong(2);
255
        nodeindex = rs.getLong(3);
256
        nodetype = rs.getString(4);
257
        nodename = rs.getString(5);
258
        nodedata = rs.getString(6);
259

    
260
        // add the data to the node record list hashtable
261
        NodeRecord currentRecord = new NodeRecord(nodeid, parentnodeid, 
262
                                   nodeindex, nodetype, nodename, nodedata);
263
        nodeRecordList.add(currentRecord);
264

    
265
        // Advance to the next node
266
        tableHasRows = rs.next();
267
      } 
268
      pstmt.close();
269

    
270
    } catch (SQLException e) {
271
      throw new McdbException("Error accessing database connection.", e);
272
    }
273

    
274
    if (nodeRecordList != null) {
275
      return nodeRecordList;
276
    } else {
277
      throw new McdbException("Error getting node data: " + docid);
278
    }
279
  }
280

    
281
  /**
282
   * Write an XML file to the database, given a filename
283
   *
284
   * @param conn the JDBC connection to the database
285
   * @param filename the filename to be loaded into the database
286
   * @param action the action to be performed (INSERT OR UPDATE)
287
   * @param docid the docid to use for the INSERT OR UPDATE
288
   */
289
  public static String write( Connection conn, String filename, String action, 
290
                              String docid )
291
                throws Exception, IOException, SQLException, 
292
                       ClassNotFoundException, SAXException, SAXParseException {
293
     return write(conn, new FileReader(new File(filename).toString()), 
294
                  action, docid);
295
  }
296
  
297
  /**
298
   * Write an XML file to the database, given a Reader
299
   *
300
   * @param conn the JDBC connection to the database
301
   * @param xml the xml stream to be loaded into the database
302
   * @param action the action to be performed (INSERT OR UPDATE)
303
   * @param docid the docid to use for the INSERT OR UPDATE
304
   */
305
  public static String write( Connection conn, Reader xml, String action, 
306
                              String docid )
307
                throws Exception, IOException, SQLException, 
308
                       ClassNotFoundException, SAXException, SAXParseException {
309
    try {
310
        XMLReader parser = initializeParser(conn, action, docid);
311
        conn.setAutoCommit(false);
312
        parser.parse(new InputSource(xml));
313
        conn.commit();
314
        conn.setAutoCommit(true);
315
        return docid;
316
      } catch (SAXParseException e) {
317
        conn.rollback();
318
        throw e;
319
      } catch (SAXException e) {
320

    
321
        // If its a problem with the accession number its ok, just the 
322
        // accession number was regenerated
323
        AccessionNumberGeneratedException ang = null;
324
        try {
325
          Exception embedded = e.getException();
326
          if ((embedded != null) && 
327
              (embedded instanceof AccessionNumberGeneratedException)) {
328
            ang = (AccessionNumberGeneratedException)e.getException();
329
          }
330
        } catch (ClassCastException cce) {
331
          // Do nothing and just fall through to the ang != null test
332
        }
333
        if (ang != null) {
334
          conn.commit();
335
          conn.setAutoCommit(true);
336
          return (ang.getMessage());
337
        } else {
338
          conn.rollback();
339
          throw e;
340
        }
341
      } catch (Exception e) {
342
        conn.rollback();
343
        throw e;
344
      }
345
  }
346

    
347
  /**
348
   * Delete an XML file from the database (actually, just make it a revision
349
   * in the xml_revisions table)
350
   *
351
   * @param docid the ID of the document to be deleted from the database
352
   */
353
  public static void delete( Connection conn, String docid )
354
                  throws IOException, SQLException, 
355
                         ClassNotFoundException, AccessionNumberException {
356

    
357
    AccessionNumber ac = new AccessionNumber();
358
    String newdocid = ac.generate(docid, "DELETE");
359

    
360
    conn.setAutoCommit(false);
361
    // Copy the record to the xml_revisions table
362
    DocumentImpl.archiveDocRevision( conn, docid );
363

    
364
    // Now delete it from the xml_documents table
365
    Statement stmt = conn.createStatement();
366
    stmt.execute("DELETE FROM xml_index WHERE docid LIKE '" + docid + "'");
367
    stmt.execute("DELETE FROM xml_documents WHERE docid LIKE '" + docid + "'");
368
    stmt.close();
369
    conn.commit();
370
  }
371

    
372
  /** creates SQL code and inserts new document into DB connection */
373
  private void writeDocumentToDB(String action) 
374
               throws AccessionNumberException {
375
    try {
376
      PreparedStatement pstmt = null;
377

    
378
      if (action.equals("INSERT")) {
379
        AccessionNumber ac = new AccessionNumber();
380
        this.docid = ac.generate(docid, "INSERT");
381
        pstmt = conn.prepareStatement(
382
            "INSERT INTO xml_documents " +
383
            "(docid, rootnodeid, docname, doctype, " +
384
            "date_created, date_updated) " +
385
            "VALUES (?, ?, ?, ?, sysdate, sysdate)");
386
        // Bind the values to the query
387
        pstmt.setString(1, this.docid);
388
        pstmt.setLong(2, rootnodeid);
389
        pstmt.setString(3, docname);
390
        pstmt.setString(4, doctype);
391
      } else if (action.equals("UPDATE")) {
392

    
393
        // Determine if the docid is OK for an UPDATE
394
        AccessionNumber ac = new AccessionNumber();
395
        this.docid = ac.generate(docid, "UPDATE");
396

    
397
        // Save the old document entry in a backup table
398
        DocumentImpl.archiveDocRevision( conn, docid );
399

    
400
        // Update the new document to reflect the new node tree
401
        pstmt = conn.prepareStatement(
402
            "UPDATE xml_documents " +
403
            "SET rootnodeid = ?, docname = ?, doctype = ?, " +
404
            "date_updated = sysdate WHERE docid LIKE ?");
405
        // Bind the values to the query
406
        pstmt.setLong(1, rootnodeid);
407
        pstmt.setString(2, docname);
408
        pstmt.setString(3, doctype);
409
        pstmt.setString(4, this.docid);
410
      } else {
411
        System.err.println("Action not supported: " + action);
412
      }
413

    
414
      // Do the insertion
415
      pstmt.execute();
416
      pstmt.close();
417

    
418
    } catch (SQLException e) {
419
      System.out.println(e.getMessage());
420
    } catch (AccessionNumberException ane) {
421
      MetaCatUtil.debugMessage("Invalid accession number.");
422
      MetaCatUtil.debugMessage(ane.getMessage());
423
      throw ane;
424
    } catch (Exception e) {
425
      System.out.println(e.getMessage());
426
    }
427
  }
428

    
429
  /**
430
   * Get the document title
431
   */
432
  public String getTitle() {
433
    return doctitle;
434
  }
435

    
436
  /**
437
   * Set the document title
438
   *
439
   * @param title the new title for the document
440
   */
441
  public void setTitle( String title ) {
442
    this.doctitle = title;
443
    try {
444
      PreparedStatement pstmt;
445
      pstmt = conn.prepareStatement(
446
            "UPDATE xml_documents " +
447
            " SET doctitle = ? " +
448
            "WHERE docid = ?");
449

    
450
      // Bind the values to the query
451
      pstmt.setString(1, doctitle);
452
      pstmt.setString(2, docid);
453

    
454
      // Do the insertion
455
      pstmt.execute();
456
      pstmt.close();
457
    } catch (SQLException e) {
458
      System.out.println(e.getMessage());
459
    }
460
  }
461

    
462
  /**
463
   * Look up the title of the first child element named "title"
464
   * and record it as the document title
465
   */
466
  public void setTitleFromChildElement() {
467
    String title = null;
468
    long assigned_id=0;
469
    PreparedStatement pstmt;
470
    try {
471
      pstmt = conn.prepareStatement(
472
              "SELECT nodedata FROM xml_nodes " +
473
              "WHERE nodetype = 'TEXT' " +
474
              "AND rootnodeid = ? " +
475
              "AND parentnodeid IN " +
476
              "  (SELECT nodeid FROM xml_nodes " +
477
              "  WHERE nodename = 'title' " +
478
              "  AND nodetype =  'ELEMENT' " +
479
              "  AND rootnodeid = ? ) " +
480
              "ORDER BY nodeid");
481

    
482
      // The above query might be slow, and probably will be because
483
      // it gets ALL of the title elements while searching for one
484
      // title in a small subtree but it avoids the problem of using
485
      // Oracle's Hierarchical Query syntax which is not portable --
486
      // the commented out SQL that follows shows an equivalent query
487
      // using Oracle-specific hierarchical query
488
      /*
489
      pstmt = conn.prepareStatement(
490
              "SELECT nodedata FROM xml_nodes " +
491
              "WHERE nodetype = 'TEXT' " +
492
              "AND parentnodeid IN " +
493
              "(SELECT nodeid FROM xml_nodes " +
494
              "WHERE nodename = 'title' " +
495
              "START WITH nodeid = ? " +
496
              "CONNECT BY PRIOR nodeid = parentnodeid)");
497
      */
498

    
499
      // Bind the values to the query
500
      pstmt.setLong(1, rootnodeid);
501
      pstmt.setLong(2, rootnodeid);
502

    
503
      pstmt.execute();
504
      ResultSet rs = pstmt.getResultSet();
505
      boolean tableHasRows = rs.next();
506
      if (tableHasRows) {
507
        title = rs.getString(1);
508
      }
509
      pstmt.close();
510
    } catch (SQLException e) {
511
      System.out.println("Error getting title: " + e.getMessage());
512
    }
513

    
514
    // assign the new title
515
    this.setTitle(title);
516
  }
517

    
518
  /** Save a document entry in the xml_revisions table */
519
  private static void archiveDocRevision(Connection conn, String docid) 
520
                      throws SQLException {
521
    // First get all of the values we need
522
    long rnodeid = -1;
523
    String docname = null;
524
    String doctype = null;
525
    String doctitle = null;
526
    Date date_created = null;
527
    PreparedStatement pstmt = conn.prepareStatement(
528
       "SELECT rootnodeid, docname, doctype, doctitle, date_created " +
529
       "FROM xml_documents " +
530
       "WHERE docid = ?");
531
    // Bind the values to the query and execute it
532
    pstmt.setString(1, docid);
533
    pstmt.execute();
534

    
535
    ResultSet rs = pstmt.getResultSet();
536
    boolean tableHasRows = rs.next();
537
    if (tableHasRows) {
538
      rnodeid      = rs.getLong(1);
539
      docname      = rs.getString(2);
540
      doctype      = rs.getString(3);
541
      doctitle     = rs.getString(4);
542
      date_created = rs.getDate(5);
543
    }
544
    pstmt.close();
545

    
546
    MetaCatUtil.debugMessage(new Long(rnodeid).toString());
547
    MetaCatUtil.debugMessage(docname);
548
    MetaCatUtil.debugMessage(doctitle);
549
    //MetaCatUtil.debugMessage(date_created.toString());
550

    
551
    // Next create the new record in the other table using the values selected
552
    pstmt = conn.prepareStatement(
553
       "INSERT INTO xml_revisions " +
554
       "(revisionid, docid, rootnodeid, docname, doctype, doctitle, " +
555
       "date_created, date_updated) " +
556
       "VALUES (null, ?, ?, ?, ?, ?, sysdate, sysdate)");
557
    // Bind the values to the query and execute it
558
    pstmt.setString(1, docid);
559
    pstmt.setLong(2, rnodeid);
560
    pstmt.setString(3, docname);
561
    pstmt.setString(4, doctype);
562
    pstmt.setString(5, doctitle);
563
    //pstmt.setDate(6, date_created);
564
    pstmt.execute();
565
    pstmt.close();
566
  }
567

    
568
  /**
569
   * Set up the parser handlers for writing the document to the database
570
   */
571
  private static XMLReader initializeParser(Connection conn,
572
                           String action, String docid) {
573
    XMLReader parser = null;
574
    //
575
    // Set up the SAX document handlers for parsing
576
    //
577
    try {
578
      ContentHandler chandler   = new DBSAXHandler(conn, action, docid);
579
      EntityResolver dbresolver = new DBEntityResolver(conn, 
580
                                      (DBSAXHandler)chandler);
581
      DTDHandler dtdhandler     = new DBDTDHandler(conn);
582

    
583
      // Get an instance of the parser
584
      MetaCatUtil util = new MetaCatUtil();
585
      String parserName = util.getOption("saxparser");
586
      parser = XMLReaderFactory.createXMLReader(parserName);
587

    
588
      // Turn off validation
589
      parser.setFeature("http://xml.org/sax/features/validation", false);
590
      
591
      // Set Handlers in the parser
592
      parser.setProperty("http://xml.org/sax/properties/declaration-handler",
593
                         chandler);
594
      parser.setProperty("http://xml.org/sax/properties/lexical-handler",
595
                         chandler);
596
      parser.setContentHandler((ContentHandler)chandler);
597
      parser.setEntityResolver((EntityResolver)dbresolver);
598
      parser.setDTDHandler((DTDHandler)dtdhandler);
599
      parser.setErrorHandler((ErrorHandler)chandler);
600

    
601
    } catch (Exception e) {
602
       System.err.println(e.toString());
603
    }
604

    
605
    return parser;
606
  }
607

    
608
  /**
609
   * the main routine used to test the DBWriter utility.
610
   * <p>
611
   * Usage: java DocumentImpl <-f filename -a action -d docid>
612
   *
613
   * @param filename the filename to be loaded into the database
614
   * @param action the action to perform (READ, INSERT, UPDATE, DELETE)
615
   * @param docid the id of the document to process
616
   */
617
  static public void main(String[] args) {
618
     
619
    try {
620
      String filename = null;
621
      String action   = null;
622
      String docid    = null;
623

    
624
      // Parse the command line arguments
625
      for ( int i=0 ; i < args.length; ++i ) {
626
        if ( args[i].equals( "-f" ) ) {
627
          filename =  args[++i];
628
        } else if ( args[i].equals( "-a" ) ) {
629
          action =  args[++i];
630
        } else if ( args[i].equals( "-d" ) ) {
631
          docid =  args[++i];
632
        } else {
633
          System.err.println
634
            ( "   args[" +i+ "] '" +args[i]+ "' ignored." );
635
        }
636
      }
637
      
638
      // Check if the required arguments are provided
639
      boolean argsAreValid = false;
640
      if (action != null) {
641
        if (action.equals("INSERT")) {
642
          if (filename != null) {
643
            argsAreValid = true;
644
          } 
645
        } else if (action.equals("UPDATE")) {
646
          if ((filename != null) && (docid != null)) {
647
            argsAreValid = true;
648
          } 
649
        } else if (action.equals("DELETE")) {
650
          if (docid != null) {
651
            argsAreValid = true;
652
          } 
653
        } else if (action.equals("READ")) {
654
          if (docid != null) {
655
            argsAreValid = true;
656
          } 
657
        } 
658
      } 
659

    
660
      // Print usage message if the arguments are not valid
661
      if (!argsAreValid) {
662
        System.err.println("Wrong number of arguments!!!");
663
        System.err.println(
664
              "USAGE: java DocumentImpl <-a INSERT> [-d docid] <-f filename>");
665
        System.err.println(
666
              "   OR: java DocumentImpl <-a UPDATE -d docid -f filename>");
667
        System.err.println(
668
              "   OR: java DocumentImpl <-a DELETE -d docid>");
669
        System.err.println(
670
              "   OR: java DocumentImpl <-a READ -d docid>");
671
        return;
672
      }
673
 
674
      // Open a connection to the database
675
      MetaCatUtil util = new MetaCatUtil();
676
      Connection dbconn = util.openDBConnection();
677

    
678
      // Execute the action requested (READ, INSERT, UPDATE, DELETE)
679
      if (action.equals("READ")) {
680
          DocumentImpl xmldoc = new DocumentImpl( dbconn, docid );
681
          System.out.println(xmldoc.toString());
682
      } else if (action.equals("DELETE")) {
683
        DocumentImpl.delete(dbconn, docid);
684
        System.out.println("Document deleted: " + docid);
685
      } else {
686
        String newdocid = DocumentImpl.write(dbconn, filename, action, docid);
687
        if ((docid != null) && (!docid.equals(newdocid))) {
688
          if (action.equals("INSERT")) {
689
            System.out.println("New document ID generated!!! ");
690
          } else if (action.equals("UPDATE")) {
691
            System.out.println("ERROR: Couldn't update document!!! ");
692
          }
693
        } else if ((docid == null) && (action.equals("UPDATE"))) {
694
          System.out.println("ERROR: Couldn't update document!!! ");
695
        }
696
        System.out.println("Document processing finished for: " + filename
697
              + " (" + newdocid + ")");
698
      }
699

    
700
    } catch (McdbException me) {
701
      me.toXml(new PrintWriter(System.err));
702
    } catch (AccessionNumberException ane) {
703
      System.out.println("ERROR: Couldn't delete document!!! ");
704
      System.out.println(ane.getMessage());
705
    } catch (Exception e) {
706
      System.err.println("EXCEPTION HANDLING REQUIRED");
707
      System.err.println(e.getMessage());
708
      e.printStackTrace(System.err);
709
    }
710
  }
711
}
(15-15/27)