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-09-01 13:47:19 -0700 (Fri, 01 Sep 2000) $'
11
 * '$Revision: 428 $'
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
  static final int ALL = 1;
42
  static final int WRITE = 2;
43
  static final int READ = 4;
44

    
45
  private Connection conn = null;
46
  private String docid = null;
47
  private String docname = null;
48
  private String doctype = null;
49
  private String system_id = null;
50
  private long rootnodeid;
51
  private ElementNode rootNode = null;
52
  private String doctitle = null;
53

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

    
76
    } catch (McdbException ex) {
77
      throw ex;
78
    } catch (Throwable t) {
79
      throw new McdbException("Error reading document " + docid + ".");
80
    }
81
  }
82

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

    
113
  /**
114
   * get the document name
115
   */
116
  public String getDocname() {
117
    return docname;
118
  }
119

    
120
  /**
121
   * get the document type (which is the PublicID)
122
   */
123
  public String getDoctype() {
124
    return doctype;
125
  }
126

    
127
  /**
128
   * get the system identifier
129
   */
130
  public String getSystemID() {
131
    return system_id;
132
  }
133

    
134
  /**
135
   * get the root node identifier
136
   */
137
  public long getRootNodeID() {
138
    return rootnodeid;
139
  }
140

    
141
  /** 
142
   * Get the document identifier (docid)
143
   */
144
  public String getDocID() {
145
    return docid;
146
  }
147

    
148
  /**
149
   * Create an XML document from the database for the document with ID docid
150
   */
151
  public String toString()
152
  {
153
    StringBuffer doc = new StringBuffer();
154

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

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

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

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

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

    
218
    if (this.docname == null) {
219
      throw new McdbDocNotFoundException("Document not found: " + docid);
220
    }
221
  }
222

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

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

    
250
      // Bind the values to the query
251
      pstmt.setLong(1, rootnodeid);
252

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

    
264
        // add the data to the node record list hashtable
265
        NodeRecord currentRecord = new NodeRecord(nodeid, parentnodeid, 
266
                                   nodeindex, nodetype, nodename, nodedata);
267
        nodeRecordList.add(currentRecord);
268

    
269
        // Advance to the next node
270
        tableHasRows = rs.next();
271
      } 
272
      pstmt.close();
273

    
274
    } catch (SQLException e) {
275
      throw new McdbException("Error accessing database connection.", e);
276
    }
277

    
278
    if (nodeRecordList != null) {
279
      return nodeRecordList;
280
    } else {
281
      throw new McdbException("Error getting node data: " + docid);
282
    }
283
  }
284

    
285
  /**
286
   * Write an XML file to the database, given a filename
287
   *
288
   * @param conn the JDBC connection to the database
289
   * @param filename the filename to be loaded into the database
290
   * @param action the action to be performed (INSERT OR UPDATE)
291
   * @param docid the docid to use for the INSERT OR UPDATE
292
   */
293
  public static String write( Connection conn, String filename, String action, 
294
                              String docid, String user, String group )
295
                throws IOException, SQLException, ClassNotFoundException,
296
                       SAXException, SAXParseException, Exception {
297

    
298
    return write(conn, new FileReader(new File(filename).toString()), 
299
                  action, docid, user, group);
300
  }
301
  
302
  /**
303
   * Write an XML file to the database, given a Reader
304
   *
305
   * @param conn the JDBC connection to the database
306
   * @param xml the xml stream to be loaded into the database
307
   * @param action the action to be performed (INSERT OR UPDATE)
308
   * @param docid the docid to use for the INSERT OR UPDATE
309
   */
310
  public static String write( Connection conn, Reader xml, String action, 
311
                              String docid, String user, String group )
312
                throws IOException, SQLException, ClassNotFoundException,
313
                       SAXException, SAXParseException, Exception {
314

    
315
    if ( action.equals("UPDATE") ) {
316
      // Determine if the docid is OK for an UPDATE
317
      AccessionNumber ac = new AccessionNumber();
318
      String newdocid = ac.generate(docid, "UPDATE");
319

    
320
      // b' of the command line invocation
321
      if ( (user != null) &&  (group != null) ) { 
322
        if ( !hasWritePermission(conn, docid, user, group) ) {
323
          throw new Exception("User " + user + 
324
                " does not have permission to update XML Document #" + docid);
325
        }        
326
      }          
327
    }
328

    
329
    try {
330
        XMLReader parser = initializeParser(conn, action, docid, user);
331
        conn.setAutoCommit(false);
332
        parser.parse(new InputSource(xml));
333
        conn.commit();
334
        conn.setAutoCommit(true);
335
        return docid;
336
      } catch (SAXParseException e) {
337
        conn.rollback();
338
        throw e;
339
      } catch (SAXException e) {
340

    
341
        // If its a problem with the accession number its ok, just the 
342
        // accession number was regenerated
343
        AccessionNumberGeneratedException ang = null;
344
        try {
345
          Exception embedded = e.getException();
346
          if ((embedded != null) && 
347
              (embedded instanceof AccessionNumberGeneratedException)) {
348
            ang = (AccessionNumberGeneratedException)e.getException();
349
          }
350
        } catch (ClassCastException cce) {
351
          // Do nothing and just fall through to the ang != null test
352
        }
353
        if (ang != null) {
354
          conn.commit();
355
          conn.setAutoCommit(true);
356
          return (ang.getMessage());
357
        } else {
358
          conn.rollback();
359
          throw e;
360
        }
361
      } catch (Exception e) {
362
        conn.rollback();
363
        throw e;
364
      }
365
  }
366

    
367
  /**
368
   * Delete an XML file from the database (actually, just make it a revision
369
   * in the xml_revisions table)
370
   *
371
   * @param docid the ID of the document to be deleted from the database
372
   */
373
  public static void delete( Connection conn, String docid,
374
                                 String user, String group )
375
                throws IOException, SQLException, ClassNotFoundException, 
376
                       AccessionNumberException, Exception {
377

    
378
    AccessionNumber ac = new AccessionNumber();
379
    String newdocid = ac.generate(docid, "DELETE");
380

    
381
    if ( (user != null) &&  (group != null) ) {
382
      if ( !hasWritePermission(conn, docid, user, group) ) {
383
        throw new Exception("User " + user + 
384
                " does not have permission to delete XML Document #" + docid);
385
      }          
386
    }
387

    
388
    conn.setAutoCommit(false);
389
    // Copy the record to the xml_revisions table
390
    DocumentImpl.archiveDocRevision( conn, docid, user );
391

    
392
    // Now delete it from the xml_documents table
393
    Statement stmt = conn.createStatement();
394
    stmt.execute("DELETE FROM xml_index WHERE docid = '" + docid + "'");
395
    stmt.execute("DELETE FROM xml_documents WHERE docid = '" + docid + "'");
396
    stmt.close();
397
    conn.commit();
398
  }
399
  
400
  /** Check for "write" permissions from DB connection */
401
  private static boolean hasWritePermission(Connection conn, String docid, 
402
                                     String user, String group) 
403
                                     throws SQLException {
404
    PreparedStatement pstmt;
405
    // checking if user is owner of docid
406
    try {
407
      pstmt = conn.prepareStatement(
408
                   "SELECT docid FROM xml_documents " +
409
                   "WHERE docid LIKE ? AND user_owner LIKE ?");
410
      // Bind the values to the query
411
      pstmt.setString(1, docid);
412
      pstmt.setString(2, user);
413

    
414
      pstmt.execute();
415
      ResultSet rs = pstmt.getResultSet();
416
      boolean hasRow = rs.next();
417
      pstmt.close();
418
      if (hasRow) {
419
        return true;
420
      }
421
      
422
    } catch (SQLException e) {
423
      throw new 
424
        SQLException("Error getting document's owner: " + e.getMessage());
425
    }
426

    
427
    // checking access type from xml_access table
428
    int accesstype = 0;
429
    try {
430
      pstmt = conn.prepareStatement(
431
                   "SELECT access_type FROM xml_access " +
432
                   "WHERE docid LIKE ? " + 
433
                   "AND principal_name LIKE ? " +
434
                   "AND principal_type = 'user' " +
435
                   "AND sysdate BETWEEN begin_time AND end_time " +
436
                   "UNION " +
437
                   "SELECT access_type FROM xml_access " +
438
                   "WHERE docid LIKE ? " + 
439
                   "AND principal_name LIKE ? " +
440
                   "AND principal_type = 'group' " +
441
                   "AND sysdate BETWEEN begin_time AND end_time");
442
      // Bind the values to the query
443
      pstmt.setString(1, docid);
444
      pstmt.setString(2, user);
445
      pstmt.setString(3, docid);
446
      pstmt.setString(2, group);
447

    
448
      pstmt.execute();
449
      ResultSet rs = pstmt.getResultSet();
450
      boolean hasRows = rs.next();
451
      while ( hasRows ) {
452
        accesstype = rs.getInt(1);
453
        if ( (accesstype & WRITE) == WRITE ) {
454
          pstmt.close();
455
          return true;
456
        }
457
        hasRows = rs.next();
458
      }
459

    
460
      pstmt.close();
461
      return false;
462
      
463
    } catch (SQLException e) {
464
      throw new 
465
      SQLException("Error getting document's permissions: " + e.getMessage());
466
    }
467
  }
468

    
469
  /** creates SQL code and inserts new document into DB connection */
470
  private void writeDocumentToDB(String action, String user) 
471
               throws AccessionNumberException {
472
    try {
473
      PreparedStatement pstmt = null;
474

    
475
      if (action.equals("INSERT")) {
476
        AccessionNumber ac = new AccessionNumber();
477
        this.docid = ac.generate(docid, "INSERT");
478
        pstmt = conn.prepareStatement(
479
            "INSERT INTO xml_documents " +
480
            "(docid, rootnodeid, docname, doctype, " +
481
            "user_owner, user_updated, date_created, date_updated) " +
482
            "VALUES (?, ?, ?, ?, ?, ?, sysdate, sysdate)");
483
        // Bind the values to the query
484
        pstmt.setString(1, this.docid);
485
        pstmt.setLong(2, rootnodeid);
486
        pstmt.setString(3, docname);
487
        pstmt.setString(4, doctype);
488
        pstmt.setString(5, user);
489
        pstmt.setString(6, user);
490
      } else if (action.equals("UPDATE")) {
491

    
492
        // Save the old document entry in a backup table
493
        DocumentImpl.archiveDocRevision( conn, docid, user );
494

    
495
        // Delete index for the old version of docid
496
        // The new index is inserting on the next calls to DBSAXNode
497
        pstmt = conn.prepareStatement(
498
                "DELETE FROM xml_index WHERE docid='" + this.docid + "'");
499
        pstmt.execute();
500
        pstmt.close();
501

    
502
        // Update the new document to reflect the new node tree
503
        pstmt = conn.prepareStatement(
504
            "UPDATE xml_documents " +
505
            "SET rootnodeid = ?, docname = ?, doctype = ?, " +
506
            "user_updated = ?, date_updated = sysdate WHERE docid LIKE ?");
507
        // Bind the values to the query
508
        pstmt.setLong(1, rootnodeid);
509
        pstmt.setString(2, docname);
510
        pstmt.setString(3, doctype);
511
        pstmt.setString(4, user);
512
        pstmt.setString(5, this.docid);
513
      } else {
514
        System.err.println("Action not supported: " + action);
515
      }
516

    
517
      // Do the insertion
518
      pstmt.execute();
519
      pstmt.close();
520

    
521
    } catch (SQLException e) {
522
      System.out.println(e.getMessage());
523
    } catch (AccessionNumberException ane) {
524
      MetaCatUtil.debugMessage("Invalid accession number.");
525
      MetaCatUtil.debugMessage(ane.getMessage());
526
      throw ane;
527
    } catch (Exception e) {
528
      System.out.println(e.getMessage());
529
    }
530
  }
531

    
532
  /**
533
   * Get the document title
534
   */
535
  public String getTitle() {
536
    return doctitle;
537
  }
538

    
539
  /**
540
   * Set the document title
541
   *
542
   * @param title the new title for the document
543
   */
544
  public void setTitle( String title ) {
545
    this.doctitle = title;
546
    try {
547
      PreparedStatement pstmt;
548
      pstmt = conn.prepareStatement(
549
            "UPDATE xml_documents " +
550
            " SET doctitle = ? " +
551
            "WHERE docid = ?");
552

    
553
      // Bind the values to the query
554
      pstmt.setString(1, doctitle);
555
      pstmt.setString(2, docid);
556

    
557
      // Do the insertion
558
      pstmt.execute();
559
      pstmt.close();
560
    } catch (SQLException e) {
561
      System.out.println(e.getMessage());
562
    }
563
  }
564

    
565
  /**
566
   * Look up the title of the first child element named "title"
567
   * and record it as the document title
568
   */
569
  public void setTitleFromChildElement() {
570
    String title = null;
571
    long assigned_id=0;
572
    PreparedStatement pstmt;
573
    try {
574
      pstmt = conn.prepareStatement(
575
              "SELECT nodedata FROM xml_nodes " +
576
              "WHERE nodetype = 'TEXT' " +
577
              "AND rootnodeid = ? " +
578
              "AND parentnodeid IN " +
579
              "  (SELECT nodeid FROM xml_nodes " +
580
              "  WHERE nodename = 'title' " +
581
              "  AND nodetype =  'ELEMENT' " +
582
              "  AND rootnodeid = ? ) " +
583
              "ORDER BY nodeid");
584

    
585
      // The above query might be slow, and probably will be because
586
      // it gets ALL of the title elements while searching for one
587
      // title in a small subtree but it avoids the problem of using
588
      // Oracle's Hierarchical Query syntax which is not portable --
589
      // the commented out SQL that follows shows an equivalent query
590
      // using Oracle-specific hierarchical query
591
      /*
592
      pstmt = conn.prepareStatement(
593
              "SELECT nodedata FROM xml_nodes " +
594
              "WHERE nodetype = 'TEXT' " +
595
              "AND parentnodeid IN " +
596
              "(SELECT nodeid FROM xml_nodes " +
597
              "WHERE nodename = 'title' " +
598
              "START WITH nodeid = ? " +
599
              "CONNECT BY PRIOR nodeid = parentnodeid)");
600
      */
601

    
602
      // Bind the values to the query
603
      pstmt.setLong(1, rootnodeid);
604
      pstmt.setLong(2, rootnodeid);
605

    
606
      pstmt.execute();
607
      ResultSet rs = pstmt.getResultSet();
608
      boolean tableHasRows = rs.next();
609
      if (tableHasRows) {
610
        title = rs.getString(1);
611
      }
612
      pstmt.close();
613
    } catch (SQLException e) {
614
      System.out.println("Error getting title: " + e.getMessage());
615
    }
616

    
617
    // assign the new title
618
    this.setTitle(title);
619
  }
620

    
621
  /** Save a document entry in the xml_revisions table */
622
  private static void archiveDocRevision(Connection conn, String docid,
623
                                         String user) throws SQLException {
624
    // create a record in xml_revisions table 
625
    // for that document as selected from xml_documents
626
    PreparedStatement pstmt = conn.prepareStatement(
627
      "INSERT INTO xml_revisions " +
628
        "(revisionid, docid, rootnodeid, docname, doctype, doctitle, " +
629
        "user_owner, user_updated, date_created, date_updated) " +
630
      "SELECT null, ?, rootnodeid, docname, doctype, doctitle," + 
631
        "user_owner, ?, sysdate, sysdate "+
632
      "FROM xml_documents " +
633
      "WHERE docid = ?");
634
    // Bind the values to the query and execute it
635
    pstmt.setString(1, docid);
636
    pstmt.setString(2, user);
637
    pstmt.setString(3, docid);
638
    pstmt.execute();
639
    pstmt.close();
640

    
641
  }
642

    
643
  /** Save a document entry in the xml_revisions table */
644
/*
645
  private static void archiveDocRevision(Connection conn, String docid,
646
                                         String user) throws SQLException {
647
    // First get all of the values we need
648
    long rnodeid = -1;
649
    String docname = null;
650
    String doctype = null;
651
    String doctitle = null;
652
    String user_owner = null;
653
    Date date_created = null;
654
    PreparedStatement pstmt = conn.prepareStatement(
655
      "SELECT rootnodeid,docname,doctype,doctitle,user_owner,date_created " +
656
      "FROM xml_documents " +
657
      "WHERE docid = ?");
658
    // Bind the values to the query and execute it
659
    pstmt.setString(1, docid);
660
    pstmt.execute();
661

    
662
    ResultSet rs = pstmt.getResultSet();
663
    boolean tableHasRows = rs.next();
664
    if (tableHasRows) {
665
      rnodeid      = rs.getLong(1);
666
      docname      = rs.getString(2);
667
      doctype      = rs.getString(3);
668
      doctitle     = rs.getString(4);
669
      user_owner   = rs.getString(5);
670
      date_created = rs.getDate(6);
671
    }
672
    pstmt.close();
673

    
674
    MetaCatUtil.debugMessage(new Long(rnodeid).toString());
675
    MetaCatUtil.debugMessage(docname);
676
    MetaCatUtil.debugMessage(doctitle);
677
    //MetaCatUtil.debugMessage(date_created.toString());
678

    
679
    // Next create the new record in the other table using the values selected
680
    pstmt = conn.prepareStatement(
681
       "INSERT INTO xml_revisions " +
682
       "(revisionid, docid, rootnodeid, docname, doctype, doctitle, " +
683
       "user_owner, user_updated, date_created, date_updated) " +
684
       "VALUES (null, ?, ?, ?, ?, ?, ?, ?, sysdate, sysdate)");
685
    // Bind the values to the query and execute it
686
    pstmt.setString(1, docid);
687
    pstmt.setLong(2, rnodeid);
688
    pstmt.setString(3, docname);
689
    pstmt.setString(4, doctype);
690
    pstmt.setString(5, doctitle);
691
    pstmt.setString(6, user_owner);
692
    pstmt.setString(7, user);
693
    //pstmt.setDate(6, date_created);
694
    pstmt.execute();
695
    pstmt.close();
696
  }
697
*/
698
  /**
699
   * Set up the parser handlers for writing the document to the database
700
   */
701
  private static XMLReader initializeParser(Connection conn,
702
                           String action, String docid, String user) {
703
    XMLReader parser = null;
704
    //
705
    // Set up the SAX document handlers for parsing
706
    //
707
    try {
708
      ContentHandler chandler   = new DBSAXHandler(conn, action, docid, user);
709
      EntityResolver dbresolver = new DBEntityResolver(conn, 
710
                                      (DBSAXHandler)chandler);
711
      DTDHandler dtdhandler     = new DBDTDHandler(conn);
712

    
713
      // Get an instance of the parser
714
      MetaCatUtil util = new MetaCatUtil();
715
      String parserName = util.getOption("saxparser");
716
      parser = XMLReaderFactory.createXMLReader(parserName);
717

    
718
      // Turn off validation
719
      parser.setFeature("http://xml.org/sax/features/validation", false);
720
      
721
      // Set Handlers in the parser
722
      parser.setProperty("http://xml.org/sax/properties/declaration-handler",
723
                         chandler);
724
      parser.setProperty("http://xml.org/sax/properties/lexical-handler",
725
                         chandler);
726
      parser.setContentHandler((ContentHandler)chandler);
727
      parser.setEntityResolver((EntityResolver)dbresolver);
728
      parser.setDTDHandler((DTDHandler)dtdhandler);
729
      parser.setErrorHandler((ErrorHandler)chandler);
730

    
731
    } catch (Exception e) {
732
       System.err.println(e.toString());
733
    }
734

    
735
    return parser;
736
  }
737

    
738
  /**
739
   * the main routine used to test the DBWriter utility.
740
   * <p>
741
   * Usage: java DocumentImpl <-f filename -a action -d docid>
742
   *
743
   * @param filename the filename to be loaded into the database
744
   * @param action the action to perform (READ, INSERT, UPDATE, DELETE)
745
   * @param docid the id of the document to process
746
   */
747
  static public void main(String[] args) {
748
     
749
    try {
750
      String filename = null;
751
      String action   = null;
752
      String docid    = null;
753

    
754
      // Parse the command line arguments
755
      for ( int i=0 ; i < args.length; ++i ) {
756
        if ( args[i].equals( "-f" ) ) {
757
          filename =  args[++i];
758
        } else if ( args[i].equals( "-a" ) ) {
759
          action =  args[++i];
760
        } else if ( args[i].equals( "-d" ) ) {
761
          docid =  args[++i];
762
        } else {
763
          System.err.println
764
            ( "   args[" +i+ "] '" +args[i]+ "' ignored." );
765
        }
766
      }
767
      
768
      // Check if the required arguments are provided
769
      boolean argsAreValid = false;
770
      if (action != null) {
771
        if (action.equals("INSERT")) {
772
          if (filename != null) {
773
            argsAreValid = true;
774
          } 
775
        } else if (action.equals("UPDATE")) {
776
          if ((filename != null) && (docid != null)) {
777
            argsAreValid = true;
778
          } 
779
        } else if (action.equals("DELETE")) {
780
          if (docid != null) {
781
            argsAreValid = true;
782
          } 
783
        } else if (action.equals("READ")) {
784
          if (docid != null) {
785
            argsAreValid = true;
786
          } 
787
        } 
788
      } 
789

    
790
      // Print usage message if the arguments are not valid
791
      if (!argsAreValid) {
792
        System.err.println("Wrong number of arguments!!!");
793
        System.err.println(
794
              "USAGE: java DocumentImpl <-a INSERT> [-d docid] <-f filename>");
795
        System.err.println(
796
              "   OR: java DocumentImpl <-a UPDATE -d docid -f filename>");
797
        System.err.println(
798
              "   OR: java DocumentImpl <-a DELETE -d docid>");
799
        System.err.println(
800
              "   OR: java DocumentImpl <-a READ -d docid>");
801
        return;
802
      }
803
 
804
      // Open a connection to the database
805
      MetaCatUtil util = new MetaCatUtil();
806
      Connection dbconn = util.openDBConnection();
807

    
808
      // Execute the action requested (READ, INSERT, UPDATE, DELETE)
809
      if (action.equals("READ")) {
810
          DocumentImpl xmldoc = new DocumentImpl( dbconn, docid );
811
          System.out.println(xmldoc.toString());
812
      } else if (action.equals("DELETE")) {
813
        DocumentImpl.delete(dbconn, docid, null, null);
814
        System.out.println("Document deleted: " + docid);
815
      } else {
816
        String newdocid = DocumentImpl.write(dbconn, filename, action, docid,
817
                                                                  null, null);
818
        if ((docid != null) && (!docid.equals(newdocid))) {
819
          if (action.equals("INSERT")) {
820
            System.out.println("New document ID generated!!! ");
821
          } else if (action.equals("UPDATE")) {
822
            System.out.println("ERROR: Couldn't update document!!! ");
823
          }
824
        } else if ((docid == null) && (action.equals("UPDATE"))) {
825
          System.out.println("ERROR: Couldn't update document!!! ");
826
        }
827
        System.out.println("Document processing finished for: " + filename
828
              + " (" + newdocid + ")");
829
      }
830

    
831
    } catch (McdbException me) {
832
      me.toXml(new PrintWriter(System.err));
833
    } catch (AccessionNumberException ane) {
834
      System.out.println("ERROR: Couldn't delete document!!! ");
835
      System.out.println(ane.getMessage());
836
    } catch (Exception e) {
837
      System.err.println("EXCEPTION HANDLING REQUIRED");
838
      System.err.println(e.getMessage());
839
      e.printStackTrace(System.err);
840
    }
841
  }
842
}
(15-15/27)