Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that writes an XML document main data
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Jivka Bojilova, Matt Jones
7
 *    Release: @release@
8
 *
9
 *   '$Author: jones $'
10
 *     '$Date: 2000-08-14 13:53:34 -0700 (Mon, 14 Aug 2000) $'
11
 * '$Revision: 349 $'
12
 */
13

    
14
package edu.ucsb.nceas.metacat;
15

    
16
import java.sql.*;
17
import java.io.IOException;
18
import java.util.Hashtable;
19
import java.util.Enumeration;
20

    
21
/** 
22
 * A Class that writes an XML document main data to a database connection
23
 */
24
public class DBSAXDocument {
25

    
26
    private Connection      conn;
27
    private long            rootnodeid;
28
    private String          docname;
29
    private String          doctype;
30
    private String          doctitle;
31
    private String          docid;
32

    
33
    /** 
34
     * Construct a new document instance
35
     *
36
     * @param conn the JDBC Connection to which all information is written
37
     * @param rootnodeid - sequence id of the root node in the document
38
     * @param docname - the name of DTD, i.e. the name immediately following 
39
     *        the DOCTYPE keyword ( should be the root element name ) or
40
     *        the root element name if no DOCTYPE declaration provided
41
     *        (Oracle's and IBM parsers are not aware if it is not the 
42
     *        root element name)
43
     * @param doctype - Public ID of the DTD, i.e. the name immediately 
44
     *                  following the PUBLIC keyword in DOCTYPE declaration or
45
     *                  the docname if no Public ID provided or
46
     *                  null if no DOCTYPE declaration provided
47
     *
48
     */
49
    public DBSAXDocument (Connection conn, long rootnodeid, String docname, 
50
                          String doctype, String docid, String action)
51
                          throws AccessionNumberException {
52
      this.conn = conn;
53
      this.rootnodeid = rootnodeid;
54
      this.docname = docname;
55
      this.doctype = doctype;
56
      this.docid = docid;
57
      writeDocumentToDB(action);
58
    }
59
    
60
    /** 
61
     * Construct a new document instance, used for deleting documents
62
     *
63
     * @param conn the JDBC Connection to which all information is written
64
     */
65
    public DBSAXDocument (Connection conn) {
66
      this.conn = conn;
67
    }
68

    
69
    /** creates SQL code and inserts new document into DB connection */
70
    private void writeDocumentToDB(String action) 
71
                          throws AccessionNumberException {
72
        try {
73
          PreparedStatement pstmt = null;
74

    
75
          if (action.equals("INSERT")) {
76
            this.docid = AccessionNumber.generate(docid, "INSERT");
77
            pstmt = conn.prepareStatement(
78
                "INSERT INTO xml_documents " +
79
                "(docid, rootnodeid, docname, doctype, " +
80
                "date_created, date_updated) " +
81
                "VALUES (?, ?, ?, ?, sysdate, sysdate)");
82
            // Bind the values to the query
83
            pstmt.setString(1, this.docid);
84
            pstmt.setLong(2, rootnodeid);
85
            pstmt.setString(3, docname);
86
            pstmt.setString(4, doctype);
87
          } else if (action.equals("UPDATE")) {
88

    
89
            // Determine if the docid is OK for an UPDATE
90
            this.docid = AccessionNumber.generate(docid, "UPDATE");
91

    
92
            // Save the old document entry in a backup table
93
            saveDocument(docid);
94

    
95
            // Update the new document to reflect the new node tree
96
            pstmt = conn.prepareStatement(
97
                "UPDATE xml_documents " +
98
                "SET rootnodeid = ?, docname = ?, doctype = ?, " +
99
                "date_updated = sysdate WHERE docid LIKE ?");
100
            // Bind the values to the query
101
            pstmt.setLong(1, rootnodeid);
102
            pstmt.setString(2, docname);
103
            pstmt.setString(3, doctype);
104
            pstmt.setString(4, this.docid);
105
          } else {
106
            System.err.println("Action not supported: " + action);
107
          }
108

    
109
          // Do the insertion
110
          pstmt.execute();
111
          pstmt.close();
112

    
113
        } catch (SQLException e) {
114
          System.out.println(e.getMessage());
115
        } catch (AccessionNumberException ane) {
116
          MetaCatUtil.debugMessage("Invalid accession number.");
117
          MetaCatUtil.debugMessage(ane.getMessage());
118
          throw ane;
119
        } catch (Exception e) {
120
          System.out.println(e.getMessage());
121
        }
122
    }
123

    
124
    /** Get doctype */
125
    public String getDoctype() {
126
      return doctype;
127
    }
128

    
129
    /** Get doc id */
130
    public String getDocID() {
131
      return docid;
132
    }
133

    
134
    /** Get root node id */
135
    public long getRootNodeID() {
136
      return rootnodeid;
137
    }
138

    
139
    /**
140
     * Get the document title
141
     */
142
    public String getTitle() {
143
      return doctitle;
144
    }
145

    
146
    /**
147
     * Set the document title
148
     *
149
     * @param title the new title for the document
150
     */
151
    public void setTitle( String title ) {
152
      this.doctitle = title;
153
      try {
154
        PreparedStatement pstmt;
155
        pstmt = conn.prepareStatement(
156
              "UPDATE xml_documents " +
157
              " SET doctitle = ? " +
158
              "WHERE docid = ?");
159

    
160
        // Bind the values to the query
161
        pstmt.setString(1, doctitle);
162
        pstmt.setString(2, docid);
163

    
164
        // Do the insertion
165
        pstmt.execute();
166
        pstmt.close();
167
      } catch (SQLException e) {
168
        System.out.println(e.getMessage());
169
      }
170
    }
171

    
172
    /**
173
     * Look up the title of the first child element named "title"
174
     * and record it as the document title
175
     */
176
    public void setTitleFromChildElement() {
177
        String title = null;
178
        long assigned_id=0;
179
        PreparedStatement pstmt;
180
        try {
181
          pstmt = conn.prepareStatement(
182
                  "SELECT nodedata FROM xml_nodes " +
183
                  "WHERE nodetype = 'TEXT' " +
184
                  "AND rootnodeid = ? " +
185
                  "AND parentnodeid IN " +
186
                  "  (SELECT nodeid FROM xml_nodes " +
187
                  "  WHERE nodename = 'title' " +
188
                  "  AND nodetype =  'ELEMENT' " +
189
                  "  AND rootnodeid = ? ) " +
190
                  "ORDER BY nodeid");
191

    
192
          // The above query might be slow, and probably will be because
193
          // it gets ALL of the title elements while searching for one
194
          // title in a small subtree but it avoids the problem of using
195
          // Oracle's Hierarchical Query syntax which is not portable --
196
          // the commented out SQL that follows shows an equivalent query
197
          // using Oracle-specific hierarchical query
198
/*
199
          pstmt = conn.prepareStatement(
200
                  "SELECT nodedata FROM xml_nodes " +
201
                  "WHERE nodetype = 'TEXT' " +
202
                  "AND parentnodeid IN " +
203
                  "(SELECT nodeid FROM xml_nodes " +
204
                  "WHERE nodename = 'title' " +
205
                  "START WITH nodeid = ? " +
206
                  "CONNECT BY PRIOR nodeid = parentnodeid)");
207
*/
208

    
209
          // Bind the values to the query
210
          pstmt.setLong(1, rootnodeid);
211
          pstmt.setLong(2, rootnodeid);
212

    
213
          pstmt.execute();
214
          ResultSet rs = pstmt.getResultSet();
215
          boolean tableHasRows = rs.next();
216
          if (tableHasRows) {
217
            title = rs.getString(1);
218
          }
219
          pstmt.close();
220
        } catch (SQLException e) {
221
          System.out.println("Error getting id: " + e.getMessage());
222
        }
223

    
224
        // assign the new title
225
        this.setTitle(title);
226
    }
227

    
228
  /** Save a document entry in the xml_revisions table */
229
  public void saveDocument(String docid) throws SQLException {
230
    // First get all of the values we need
231
    long rnodeid = -1;
232
    String docname = null;
233
    String doctype = null;
234
    String doctitle = null;
235
    Date date_created = null;
236
    PreparedStatement pstmt = conn.prepareStatement(
237
       "SELECT rootnodeid, docname, doctype, doctitle, date_created " +
238
       "FROM xml_documents " +
239
       "WHERE docid = ?");
240
    // Bind the values to the query and execute it
241
    pstmt.setString(1, docid);
242
    pstmt.execute();
243

    
244
    ResultSet rs = pstmt.getResultSet();
245
    boolean tableHasRows = rs.next();
246
    if (tableHasRows) {
247
      rnodeid      = rs.getLong(1);
248
      docname      = rs.getString(2);
249
      doctype      = rs.getString(3);
250
      doctitle     = rs.getString(4);
251
      date_created = rs.getDate(5);
252
    }
253
    pstmt.close();
254

    
255
    MetaCatUtil.debugMessage(new Long(rnodeid).toString());
256
    MetaCatUtil.debugMessage(docname);
257
    MetaCatUtil.debugMessage(doctitle);
258
    //MetaCatUtil.debugMessage(date_created.toString());
259

    
260
    // Next create the new record in the other table using the values selected
261
    pstmt = conn.prepareStatement(
262
       "INSERT INTO xml_revisions " +
263
       "(revisionid, docid, rootnodeid, docname, doctype, doctitle, " +
264
       "date_created, date_updated) " +
265
       "VALUES (null, ?, ?, ?, ?, ?, sysdate, sysdate)");
266
    // Bind the values to the query and execute it
267
    pstmt.setString(1, docid);
268
    pstmt.setLong(2, rnodeid);
269
    pstmt.setString(3, docname);
270
    pstmt.setString(4, doctype);
271
    pstmt.setString(5, doctitle);
272
    //pstmt.setDate(6, date_created);
273
    pstmt.execute();
274
    pstmt.close();
275
  }
276
}
277

    
278
/**
279
 * '$Log$
280
 * 'Revision 1.16  2000/08/03 23:15:11  bojilova
281
 * 'Added public method to return the rootnodeid of the document
282
 * '
283
 * 'Revision 1.15  2000/06/27 04:31:07  jones
284
 * 'Fixed bugs associated with the new UPDATE and DELETE functions of
285
 * 'DBWriter.  There were problematic interactions between some static
286
 * 'variables used in DBEntityResolver and the way in which the
287
 * 'Servlet objects are re-used across multiple client invocations.
288
 * '
289
 * 'Generally cleaned up error reporting.  Now all errors and success
290
 * 'results are reported as XML documents from MetaCatServlet.  Need
291
 * 'to make the command line tools do the same.
292
 * '
293
 * 'Revision 1.14  2000/06/26 10:35:05  jones
294
 * 'Merged in substantial changes to DBWriter and associated classes and to
295
 * 'the MetaCatServlet in order to accomodate the new UPDATE and DELETE
296
 * 'functions.  The command line tools and the parameters for the
297
 * 'servlet have changed substantially.
298
 * '
299
 * 'Revision 1.13.2.8  2000/06/26 08:38:02  jones
300
 * 'Added DELETE feature to DBWriter.  Now takes an action "DELETE" and a
301
 * 'docid and will move the record from the xml_documents table to the
302
 * 'xml_revisions table.
303
 * 'Modified option parsing to support option symbols on command line.
304
 * '
305
 * 'Revision 1.13.2.7  2000/06/26 03:04:31  jones
306
 * 'Completed UPDATE function.  Included new table "xml_revisions" to store a
307
 * 'single document record for each revision to a document.  It is identical
308
 * 'to "xml_documents" with the addition of a "revisionid" column to
309
 * 'allow more than one revision per docid.
310
 * '
311
 * 'Revision 1.13.2.6  2000/06/26 02:02:20  jones
312
 * 'Continued fixing problems with exception handling that deals
313
 * 'with INSERT and UPDATE actions and the docid passed to DBWriter
314
 * '
315
 * 'Revision 1.13.2.5  2000/06/25 23:38:16  jones
316
 * 'Added RCSfile keyword
317
 * '
318
 * 'Revision 1.13.2.4  2000/06/25 23:34:17  jones
319
 * 'Changed documentation formatting, added log entries at bottom of source files
320
 * ''
321
 */
(10-10/27)