Revision 396
Added by Matt Jones over 24 years ago
src/edu/ucsb/nceas/metacat/DBSAXDocument.java | ||
---|---|---|
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$' |
|
10 |
* '$Date$' |
|
11 |
* '$Revision$' |
|
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 |
*/ |
|
322 | 0 |
src/edu/ucsb/nceas/metacat/DBSAXHandler.java | ||
---|---|---|
40 | 40 |
private boolean stackCreated = false; |
41 | 41 |
private Stack nodeStack; |
42 | 42 |
private Connection conn = null; |
43 |
private DBSAXDocument currentDocument;
|
|
43 |
private DocumentImpl currentDocument;
|
|
44 | 44 |
private DBSAXNode rootNode; |
45 | 45 |
private String action = null; |
46 | 46 |
private String docid = null; |
... | ... | |
132 | 132 |
rootNode.writeNodename(docname); |
133 | 133 |
rootNode.writeRootNodeID(rootNode.getNodeID()); |
134 | 134 |
try { |
135 |
currentDocument = new DBSAXDocument(conn, rootNode.getNodeID(),
|
|
135 |
currentDocument = new DocumentImpl(conn, rootNode.getNodeID(),
|
|
136 | 136 |
docname, doctype, docid, action); |
137 | 137 |
} catch (AccessionNumberException ane) { |
138 | 138 |
throw (new SAXException("Error with " + action, ane)); |
... | ... | |
358 | 358 |
return processingDTD; |
359 | 359 |
} |
360 | 360 |
} |
361 |
|
|
362 |
/** |
|
363 |
* '$Log$ |
|
364 |
* 'Revision 1.32 2000/08/03 23:17:03 bojilova |
|
365 |
* 'Call to DBSAXNode constructor simplified |
|
366 |
* ' |
|
367 |
* 'Revision 1.31 2000/06/29 23:27:08 jones |
|
368 |
* 'Fixed bug in DBEntityResolver so that it now properly delegates to |
|
369 |
* 'the system id found inthe database. |
|
370 |
* 'Changed DBValidate to use DBEntityResolver, rather than the OASIS |
|
371 |
* 'catalog, and to return validation results in XML format. |
|
372 |
* ' |
|
373 |
* 'Revision 1.30 2000/06/28 03:14:35 jones |
|
374 |
* 'Fixed bug where TEXT nodes couldn't be longer than 4000 characters, which |
|
375 |
* 'is the maximum length of a VARCHAR2 field in Oracle. Now, if text |
|
376 |
* 'exceeds the field length, I break the text up into a series of TEXT |
|
377 |
* 'nodes each of the max field length, and the remainder in the last |
|
378 |
* 'TEXT node. The only problem with this is that our current search |
|
379 |
* 'algorithms only will find phrases within a single TEXT nodes, so if |
|
380 |
* 'the search term spans the node boundary, the search algorithm will not |
|
381 |
* 'return a hit. I expect this is extremely rare, basically inconsequential. |
|
382 |
* ' |
|
383 |
* 'Revision 1.29 2000/06/27 04:31:07 jones |
|
384 |
* 'Fixed bugs associated with the new UPDATE and DELETE functions of |
|
385 |
* 'DBWriter. There were problematic interactions between some static |
|
386 |
* 'variables used in DBEntityResolver and the way in which the |
|
387 |
* 'Servlet objects are re-used across multiple client invocations. |
|
388 |
* ' |
|
389 |
* 'Generally cleaned up error reporting. Now all errors and success |
|
390 |
* 'results are reported as XML documents from MetaCatServlet. Need |
|
391 |
* 'to make the command line tools do the same. |
|
392 |
* ' |
|
393 |
* 'Revision 1.28 2000/06/26 10:35:05 jones |
|
394 |
* 'Merged in substantial changes to DBWriter and associated classes and to |
|
395 |
* 'the MetaCatServlet in order to accomodate the new UPDATE and DELETE |
|
396 |
* 'functions. The command line tools and the parameters for the |
|
397 |
* 'servlet have changed substantially. |
|
398 |
* ' |
|
399 |
* 'Revision 1.27.2.6 2000/06/26 02:02:20 jones |
|
400 |
* 'Continued fixing problems with exception handling that deals |
|
401 |
* 'with INSERT and UPDATE actions and the docid passed to DBWriter |
|
402 |
* ' |
|
403 |
* 'Revision 1.27.2.5 2000/06/26 00:51:06 jones |
|
404 |
* 'If docid passed to DBWriter.write() is not unique, classes now generate |
|
405 |
* 'an AccessionNumberException containing the new docid generated as a |
|
406 |
* 'replacement. The docid is then extracted from the exception and |
|
407 |
* 'returned to the calling application for user feedback or client processing. |
|
408 |
* ' |
|
409 |
* 'Revision 1.27.2.4 2000/06/25 23:38:16 jones |
|
410 |
* 'Added RCSfile keyword |
|
411 |
* ' |
|
412 |
* 'Revision 1.27.2.3 2000/06/25 23:34:17 jones |
|
413 |
* 'Changed documentation formatting, added log entries at bottom of source files |
|
414 |
* '' |
|
415 |
*/ |
src/edu/ucsb/nceas/metacat/DocumentImpl.java | ||
---|---|---|
30 | 30 |
private String system_id = null; |
31 | 31 |
private long rootnodeid; |
32 | 32 |
private ElementNode rootNode = null; |
33 |
private String doctitle = null; |
|
33 | 34 |
|
34 | 35 |
/** |
35 |
* Constructor, creates document from database connection |
|
36 |
* Constructor, creates document from database connection, used |
|
37 |
* for reading the document |
|
36 | 38 |
* |
37 | 39 |
* @param conn the database connection from which to read the document |
38 | 40 |
* @param docid the identifier of the document to be created |
... | ... | |
47 | 49 |
getDocumentInfo(docid); |
48 | 50 |
|
49 | 51 |
// Download all of the document nodes using a single SQL query |
50 |
TreeSet nodeRecordList = getNodeRecordList(docid);
|
|
52 |
TreeSet nodeRecordList = getNodeRecordList(rootnodeid);
|
|
51 | 53 |
|
52 | 54 |
// Create the elements from the downloaded data in the TreeSet |
53 | 55 |
rootNode = new ElementNode(nodeRecordList, rootnodeid); |
... | ... | |
59 | 61 |
} |
60 | 62 |
} |
61 | 63 |
|
64 |
/** |
|
65 |
* Construct a new document instance, writing the contents to the database |
|
66 |
* |
|
67 |
* @param conn the JDBC Connection to which all information is written |
|
68 |
* @param rootnodeid - sequence id of the root node in the document |
|
69 |
* @param docname - the name of DTD, i.e. the name immediately following |
|
70 |
* the DOCTYPE keyword ( should be the root element name ) or |
|
71 |
* the root element name if no DOCTYPE declaration provided |
|
72 |
* (Oracle's and IBM parsers are not aware if it is not the |
|
73 |
* root element name) |
|
74 |
* @param doctype - Public ID of the DTD, i.e. the name immediately |
|
75 |
* following the PUBLIC keyword in DOCTYPE declaration or |
|
76 |
* the docname if no Public ID provided or |
|
77 |
* null if no DOCTYPE declaration provided |
|
78 |
* |
|
79 |
*/ |
|
80 |
public DocumentImpl(Connection conn, long rootnodeid, String docname, |
|
81 |
String doctype, String docid, String action) |
|
82 |
throws AccessionNumberException |
|
83 |
{ |
|
84 |
this.conn = conn; |
|
85 |
this.rootnodeid = rootnodeid; |
|
86 |
this.docname = docname; |
|
87 |
this.doctype = doctype; |
|
88 |
this.docid = docid; |
|
89 |
writeDocumentToDB(action); |
|
90 |
} |
|
91 |
|
|
92 |
/** |
|
93 |
* Construct a new document instance, used for deleting documents |
|
94 |
* |
|
95 |
* @param conn the JDBC Connection to which all information is written |
|
96 |
*/ |
|
97 |
public DocumentImpl (Connection conn) |
|
98 |
{ |
|
99 |
this.conn = conn; |
|
100 |
} |
|
101 |
|
|
62 | 102 |
/** |
63 | 103 |
* get the document name |
64 | 104 |
*/ |
... | ... | |
87 | 127 |
return rootnodeid; |
88 | 128 |
} |
89 | 129 |
|
130 |
/** |
|
131 |
* Get the document identifier (docid) |
|
132 |
*/ |
|
133 |
public String getDocID() { |
|
134 |
return docid; |
|
135 |
} |
|
136 |
|
|
90 | 137 |
/** |
91 | 138 |
* Create an XML document from the database for the document with ID docid |
92 | 139 |
*/ |
... | ... | |
165 | 212 |
/** |
166 | 213 |
* Look up the node data from the database |
167 | 214 |
* |
168 |
* @param docid the id of the document to look up
|
|
215 |
* @param rootnodeid the id of the root node of the node tree to look up
|
|
169 | 216 |
*/ |
170 |
private TreeSet getNodeRecordList(String docid) throws McdbException
|
|
217 |
private TreeSet getNodeRecordList(long rootnodeid) throws McdbException
|
|
171 | 218 |
{ |
172 | 219 |
PreparedStatement pstmt; |
173 | 220 |
TreeSet nodeRecordList = new TreeSet(new NodeComparator()); |
... | ... | |
187 | 234 |
"replace(nodedata,'&','&') " + |
188 | 235 |
",'<','<') " + |
189 | 236 |
",'>','>') " + |
190 |
"FROM xml_nodes WHERE docid = ?");
|
|
237 |
"FROM xml_nodes WHERE rootnodeid = ?");
|
|
191 | 238 |
|
192 | 239 |
// Bind the values to the query |
193 |
pstmt.setString(1, docid);
|
|
240 |
pstmt.setLong(1, rootnodeid);
|
|
194 | 241 |
|
195 | 242 |
pstmt.execute(); |
196 | 243 |
ResultSet rs = pstmt.getResultSet(); |
... | ... | |
248 | 295 |
Connection dbconn = util.openDBConnection(); |
249 | 296 |
|
250 | 297 |
DocumentImpl xmldoc = new DocumentImpl( dbconn, docid ); |
251 |
System.out.println(xmldoc); |
|
298 |
System.out.println(xmldoc.toString());
|
|
252 | 299 |
|
253 | 300 |
} catch (McdbException me) { |
254 | 301 |
me.toXml(new PrintWriter(System.err)); |
... | ... | |
259 | 306 |
} |
260 | 307 |
} |
261 | 308 |
} |
309 |
|
|
310 |
|
|
311 |
|
|
312 |
|
|
313 |
|
|
314 |
/** creates SQL code and inserts new document into DB connection */ |
|
315 |
private void writeDocumentToDB(String action) |
|
316 |
throws AccessionNumberException { |
|
317 |
try { |
|
318 |
PreparedStatement pstmt = null; |
|
319 |
|
|
320 |
if (action.equals("INSERT")) { |
|
321 |
this.docid = AccessionNumber.generate(docid, "INSERT"); |
|
322 |
pstmt = conn.prepareStatement( |
|
323 |
"INSERT INTO xml_documents " + |
|
324 |
"(docid, rootnodeid, docname, doctype, " + |
|
325 |
"date_created, date_updated) " + |
|
326 |
"VALUES (?, ?, ?, ?, sysdate, sysdate)"); |
|
327 |
// Bind the values to the query |
|
328 |
pstmt.setString(1, this.docid); |
|
329 |
pstmt.setLong(2, rootnodeid); |
|
330 |
pstmt.setString(3, docname); |
|
331 |
pstmt.setString(4, doctype); |
|
332 |
} else if (action.equals("UPDATE")) { |
|
333 |
|
|
334 |
// Determine if the docid is OK for an UPDATE |
|
335 |
this.docid = AccessionNumber.generate(docid, "UPDATE"); |
|
336 |
|
|
337 |
// Save the old document entry in a backup table |
|
338 |
saveDocument(docid); |
|
339 |
|
|
340 |
// Update the new document to reflect the new node tree |
|
341 |
pstmt = conn.prepareStatement( |
|
342 |
"UPDATE xml_documents " + |
|
343 |
"SET rootnodeid = ?, docname = ?, doctype = ?, " + |
|
344 |
"date_updated = sysdate WHERE docid LIKE ?"); |
|
345 |
// Bind the values to the query |
|
346 |
pstmt.setLong(1, rootnodeid); |
|
347 |
pstmt.setString(2, docname); |
|
348 |
pstmt.setString(3, doctype); |
|
349 |
pstmt.setString(4, this.docid); |
|
350 |
} else { |
|
351 |
System.err.println("Action not supported: " + action); |
|
352 |
} |
|
353 |
|
|
354 |
// Do the insertion |
|
355 |
pstmt.execute(); |
|
356 |
pstmt.close(); |
|
357 |
|
|
358 |
} catch (SQLException e) { |
|
359 |
System.out.println(e.getMessage()); |
|
360 |
} catch (AccessionNumberException ane) { |
|
361 |
MetaCatUtil.debugMessage("Invalid accession number."); |
|
362 |
MetaCatUtil.debugMessage(ane.getMessage()); |
|
363 |
throw ane; |
|
364 |
} catch (Exception e) { |
|
365 |
System.out.println(e.getMessage()); |
|
366 |
} |
|
367 |
} |
|
368 |
|
|
369 |
/** |
|
370 |
* Get the document title |
|
371 |
*/ |
|
372 |
public String getTitle() { |
|
373 |
return doctitle; |
|
374 |
} |
|
375 |
|
|
376 |
/** |
|
377 |
* Set the document title |
|
378 |
* |
|
379 |
* @param title the new title for the document |
|
380 |
*/ |
|
381 |
public void setTitle( String title ) { |
|
382 |
this.doctitle = title; |
|
383 |
try { |
|
384 |
PreparedStatement pstmt; |
|
385 |
pstmt = conn.prepareStatement( |
|
386 |
"UPDATE xml_documents " + |
|
387 |
" SET doctitle = ? " + |
|
388 |
"WHERE docid = ?"); |
|
389 |
|
|
390 |
// Bind the values to the query |
|
391 |
pstmt.setString(1, doctitle); |
|
392 |
pstmt.setString(2, docid); |
|
393 |
|
|
394 |
// Do the insertion |
|
395 |
pstmt.execute(); |
|
396 |
pstmt.close(); |
|
397 |
} catch (SQLException e) { |
|
398 |
System.out.println(e.getMessage()); |
|
399 |
} |
|
400 |
} |
|
401 |
|
|
402 |
/** |
|
403 |
* Look up the title of the first child element named "title" |
|
404 |
* and record it as the document title |
|
405 |
*/ |
|
406 |
public void setTitleFromChildElement() { |
|
407 |
String title = null; |
|
408 |
long assigned_id=0; |
|
409 |
PreparedStatement pstmt; |
|
410 |
try { |
|
411 |
pstmt = conn.prepareStatement( |
|
412 |
"SELECT nodedata FROM xml_nodes " + |
|
413 |
"WHERE nodetype = 'TEXT' " + |
|
414 |
"AND rootnodeid = ? " + |
|
415 |
"AND parentnodeid IN " + |
|
416 |
" (SELECT nodeid FROM xml_nodes " + |
|
417 |
" WHERE nodename = 'title' " + |
|
418 |
" AND nodetype = 'ELEMENT' " + |
|
419 |
" AND rootnodeid = ? ) " + |
|
420 |
"ORDER BY nodeid"); |
|
421 |
|
|
422 |
// The above query might be slow, and probably will be because |
|
423 |
// it gets ALL of the title elements while searching for one |
|
424 |
// title in a small subtree but it avoids the problem of using |
|
425 |
// Oracle's Hierarchical Query syntax which is not portable -- |
|
426 |
// the commented out SQL that follows shows an equivalent query |
|
427 |
// using Oracle-specific hierarchical query |
|
428 |
/* |
|
429 |
pstmt = conn.prepareStatement( |
|
430 |
"SELECT nodedata FROM xml_nodes " + |
|
431 |
"WHERE nodetype = 'TEXT' " + |
|
432 |
"AND parentnodeid IN " + |
|
433 |
"(SELECT nodeid FROM xml_nodes " + |
|
434 |
"WHERE nodename = 'title' " + |
|
435 |
"START WITH nodeid = ? " + |
|
436 |
"CONNECT BY PRIOR nodeid = parentnodeid)"); |
|
437 |
*/ |
|
438 |
|
|
439 |
// Bind the values to the query |
|
440 |
pstmt.setLong(1, rootnodeid); |
|
441 |
pstmt.setLong(2, rootnodeid); |
|
442 |
|
|
443 |
pstmt.execute(); |
|
444 |
ResultSet rs = pstmt.getResultSet(); |
|
445 |
boolean tableHasRows = rs.next(); |
|
446 |
if (tableHasRows) { |
|
447 |
title = rs.getString(1); |
|
448 |
} |
|
449 |
pstmt.close(); |
|
450 |
} catch (SQLException e) { |
|
451 |
System.out.println("Error getting title: " + e.getMessage()); |
|
452 |
} |
|
453 |
|
|
454 |
// assign the new title |
|
455 |
this.setTitle(title); |
|
456 |
} |
|
457 |
|
|
458 |
/** Save a document entry in the xml_revisions table */ |
|
459 |
public void saveDocument(String docid) throws SQLException { |
|
460 |
// First get all of the values we need |
|
461 |
long rnodeid = -1; |
|
462 |
String docname = null; |
|
463 |
String doctype = null; |
|
464 |
String doctitle = null; |
|
465 |
Date date_created = null; |
|
466 |
PreparedStatement pstmt = conn.prepareStatement( |
|
467 |
"SELECT rootnodeid, docname, doctype, doctitle, date_created " + |
|
468 |
"FROM xml_documents " + |
|
469 |
"WHERE docid = ?"); |
|
470 |
// Bind the values to the query and execute it |
|
471 |
pstmt.setString(1, docid); |
|
472 |
pstmt.execute(); |
|
473 |
|
|
474 |
ResultSet rs = pstmt.getResultSet(); |
|
475 |
boolean tableHasRows = rs.next(); |
|
476 |
if (tableHasRows) { |
|
477 |
rnodeid = rs.getLong(1); |
|
478 |
docname = rs.getString(2); |
|
479 |
doctype = rs.getString(3); |
|
480 |
doctitle = rs.getString(4); |
|
481 |
date_created = rs.getDate(5); |
|
482 |
} |
|
483 |
pstmt.close(); |
|
484 |
|
|
485 |
MetaCatUtil.debugMessage(new Long(rnodeid).toString()); |
|
486 |
MetaCatUtil.debugMessage(docname); |
|
487 |
MetaCatUtil.debugMessage(doctitle); |
|
488 |
//MetaCatUtil.debugMessage(date_created.toString()); |
|
489 |
|
|
490 |
// Next create the new record in the other table using the values selected |
|
491 |
pstmt = conn.prepareStatement( |
|
492 |
"INSERT INTO xml_revisions " + |
|
493 |
"(revisionid, docid, rootnodeid, docname, doctype, doctitle, " + |
|
494 |
"date_created, date_updated) " + |
|
495 |
"VALUES (null, ?, ?, ?, ?, ?, sysdate, sysdate)"); |
|
496 |
// Bind the values to the query and execute it |
|
497 |
pstmt.setString(1, docid); |
|
498 |
pstmt.setLong(2, rnodeid); |
|
499 |
pstmt.setString(3, docname); |
|
500 |
pstmt.setString(4, doctype); |
|
501 |
pstmt.setString(5, doctitle); |
|
502 |
//pstmt.setDate(6, date_created); |
|
503 |
pstmt.execute(); |
|
504 |
pstmt.close(); |
|
505 |
} |
|
262 | 506 |
} |
src/edu/ucsb/nceas/metacat/DBSAXNode.java | ||
---|---|---|
49 | 49 |
* @param parentNode the parent node for this node being created |
50 | 50 |
*/ |
51 | 51 |
public DBSAXNode (Connection conn, String tagname, DBSAXNode parentNode, |
52 |
DBSAXDocument currentDocument) {
|
|
52 |
DocumentImpl currentDocument) {
|
|
53 | 53 |
|
54 | 54 |
super(tagname); |
55 | 55 |
setParentID(parentNode.getNodeID()); |
... | ... | |
303 | 303 |
return parentNode; |
304 | 304 |
} |
305 | 305 |
} |
306 |
|
|
307 |
/** |
|
308 |
* '$Log$ |
|
309 |
* 'Revision 1.33 2000/08/03 23:17:19 bojilova |
|
310 |
* 'DBSAXNode constructor simplified |
|
311 |
* ' |
|
312 |
* 'Revision 1.32 2000/06/27 04:31:07 jones |
|
313 |
* 'Fixed bugs associated with the new UPDATE and DELETE functions of |
|
314 |
* 'DBWriter. There were problematic interactions between some static |
|
315 |
* 'variables used in DBEntityResolver and the way in which the |
|
316 |
* 'Servlet objects are re-used across multiple client invocations. |
|
317 |
* ' |
|
318 |
* 'Generally cleaned up error reporting. Now all errors and success |
|
319 |
* 'results are reported as XML documents from MetaCatServlet. Need |
|
320 |
* 'to make the command line tools do the same. |
|
321 |
* ' |
|
322 |
* 'Revision 1.31 2000/06/26 10:35:05 jones |
|
323 |
* 'Merged in substantial changes to DBWriter and associated classes and to |
|
324 |
* 'the MetaCatServlet in order to accomodate the new UPDATE and DELETE |
|
325 |
* 'functions. The command line tools and the parameters for the |
|
326 |
* 'servlet have changed substantially. |
|
327 |
* ' |
|
328 |
* 'Revision 1.30.2.2 2000/06/25 23:38:16 jones |
|
329 |
* 'Added RCSfile keyword |
|
330 |
* ' |
|
331 |
* 'Revision 1.30.2.1 2000/06/25 23:34:17 jones |
|
332 |
* 'Changed documentation formatting, added log entries at bottom of source files |
|
333 |
* '' |
|
334 |
*/ |
src/edu/ucsb/nceas/metacat/DBWriter.java | ||
---|---|---|
238 | 238 |
|
239 | 239 |
conn.setAutoCommit(false); |
240 | 240 |
// Copy the record to the xml_revisions table |
241 |
DBSAXDocument document = new DBSAXDocument(conn);
|
|
241 |
DocumentImpl document = new DocumentImpl(conn);
|
|
242 | 242 |
document.saveDocument( docid ); |
243 | 243 |
|
244 | 244 |
// Now delete it from the xml_documents table |
... | ... | |
249 | 249 |
conn.commit(); |
250 | 250 |
} |
251 | 251 |
} |
252 |
|
|
253 |
/** |
|
254 |
* '$Log$ |
|
255 |
* 'Revision 1.24 2000/08/14 17:59:32 bojilova |
|
256 |
* 'on "DELETE" added delete from xml_index table for a given docid |
|
257 |
* 'before delete from xml_documents, b' of foreign key in xml_index(docid) |
|
258 |
* 'to xml_documents(docid) |
|
259 |
* ' |
|
260 |
* 'Revision 1.23 2000/06/29 23:27:08 jones |
|
261 |
* 'Fixed bug in DBEntityResolver so that it now properly delegates to |
|
262 |
* 'the system id found inthe database. |
|
263 |
* 'Changed DBValidate to use DBEntityResolver, rather than the OASIS |
|
264 |
* 'catalog, and to return validation results in XML format. |
|
265 |
* ' |
|
266 |
* 'Revision 1.22 2000/06/27 04:31:07 jones |
|
267 |
* 'Fixed bugs associated with the new UPDATE and DELETE functions of |
|
268 |
* 'DBWriter. There were problematic interactions between some static |
|
269 |
* 'variables used in DBEntityResolver and the way in which the |
|
270 |
* 'Servlet objects are re-used across multiple client invocations. |
|
271 |
* ' |
|
272 |
* 'Generally cleaned up error reporting. Now all errors and success |
|
273 |
* 'results are reported as XML documents from MetaCatServlet. Need |
|
274 |
* 'to make the command line tools do the same. |
|
275 |
* ' |
|
276 |
* 'Revision 1.21 2000/06/26 10:35:05 jones |
|
277 |
* 'Merged in substantial changes to DBWriter and associated classes and to |
|
278 |
* 'the MetaCatServlet in order to accomodate the new UPDATE and DELETE |
|
279 |
* 'functions. The command line tools and the parameters for the |
|
280 |
* 'servlet have changed substantially. |
|
281 |
* ' |
|
282 |
* 'Revision 1.20.2.7 2000/06/26 10:18:06 jones |
|
283 |
* 'Partial fix for MetaCatServlet INSERT?UPDATE bug. Only will work on |
|
284 |
* 'the first call to the servlet. Subsequent calls fail. Seems to be |
|
285 |
* 'related to exception handling. Multiple successive DELETE actions |
|
286 |
* 'work fine. |
|
287 |
* ' |
|
288 |
* 'Revision 1.20.2.6 2000/06/26 08:38:02 jones |
|
289 |
* 'Added DELETE feature to DBWriter. Now takes an action "DELETE" and a |
|
290 |
* 'docid and will move the record from the xml_documents table to the |
|
291 |
* 'xml_revisions table. |
|
292 |
* 'Modified option parsing to support option symbols on command line. |
|
293 |
* ' |
|
294 |
* 'Revision 1.20.2.5 2000/06/26 02:02:20 jones |
|
295 |
* 'Continued fixing problems with exception handling that deals |
|
296 |
* 'with INSERT and UPDATE actions and the docid passed to DBWriter |
|
297 |
* ' |
|
298 |
* 'Revision 1.20.2.4 2000/06/26 00:51:06 jones |
|
299 |
* 'If docid passed to DBWriter.write() is not unique, classes now generate |
|
300 |
* 'an AccessionNumberException containing the new docid generated as a |
|
301 |
* 'replacement. The docid is then extracted from the exception and |
|
302 |
* 'returned to the calling application for user feedback or client processing. |
|
303 |
* ' |
|
304 |
* 'Revision 1.20.2.3 2000/06/25 23:38:16 jones |
|
305 |
* 'Added RCSfile keyword |
|
306 |
* ' |
|
307 |
* 'Revision 1.20.2.2 2000/06/25 23:34:18 jones |
|
308 |
* 'Changed documentation formatting, added log entries at bottom of source files |
|
309 |
* '' |
|
310 |
*/ |
Also available in: Unified diff
Folded the functionality from DBSAXDocument into the DocumentImpl class.
Now DocumentImpl handles both the reads and the writes to the database.
Eventually, it will implment the full DOM Document interface. Eliminated
the DBSAXDocument.java file as it is no longer relevant.
Updated DBSAXHandler, DBSAXNode, and DBWriter to use the new class.
Some methods from DBWriter should probably be moved into DocumentImpl,
such as the "write" and "delete" methods. Need to evaluate the consequences
of making such a change.