|
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$'
|
|
10 |
* '$Date$'
|
|
11 |
* '$Revision$'
|
|
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 |
/**
|
|
21 |
* A class that represents an XML document. It can be created with a simple
|
|
22 |
* document identifier from a database connection.
|
|
23 |
*/
|
|
24 |
public class DocumentImpl {
|
|
25 |
|
|
26 |
private Connection conn = null;
|
|
27 |
private String docid = null;
|
|
28 |
private String docname = null;
|
|
29 |
private String doctype = null;
|
|
30 |
private String system_id = null;
|
|
31 |
private long rootnodeid;
|
|
32 |
private ElementNode rootNode = null;
|
|
33 |
|
|
34 |
/**
|
|
35 |
* Constructor, creates document from database connection
|
|
36 |
*
|
|
37 |
* @param conn the database connection from which to read the document
|
|
38 |
* @param docid the identifier of the document to be created
|
|
39 |
*/
|
|
40 |
public DocumentImpl(Connection conn, String docid) throws McdbException
|
|
41 |
{
|
|
42 |
try {
|
|
43 |
this.conn = conn;
|
|
44 |
this.docid = docid;
|
|
45 |
|
|
46 |
// Look up the document information
|
|
47 |
getDocumentInfo(docid);
|
|
48 |
|
|
49 |
// Download all of the document nodes using a single SQL query
|
|
50 |
TreeSet nodeRecordList = getNodeRecordList(docid);
|
|
51 |
|
|
52 |
// Create the elements from the downloaded data in the TreeSet
|
|
53 |
rootNode = new ElementNode(nodeRecordList, rootnodeid);
|
|
54 |
|
|
55 |
} catch (McdbException ex) {
|
|
56 |
throw ex;
|
|
57 |
} catch (Throwable t) {
|
|
58 |
throw new McdbException("Error reading document " + docid + ".");
|
|
59 |
}
|
|
60 |
}
|
|
61 |
|
|
62 |
/**
|
|
63 |
* get the document name
|
|
64 |
*/
|
|
65 |
public String getDocname() {
|
|
66 |
return docname;
|
|
67 |
}
|
|
68 |
|
|
69 |
/**
|
|
70 |
* get the document type (which is the PublicID)
|
|
71 |
*/
|
|
72 |
public String getDoctype() {
|
|
73 |
return doctype;
|
|
74 |
}
|
|
75 |
|
|
76 |
/**
|
|
77 |
* get the system identifier
|
|
78 |
*/
|
|
79 |
public String getSystemID() {
|
|
80 |
return system_id;
|
|
81 |
}
|
|
82 |
|
|
83 |
/**
|
|
84 |
* get the root node identifier
|
|
85 |
*/
|
|
86 |
public long getRootNodeID() {
|
|
87 |
return rootnodeid;
|
|
88 |
}
|
|
89 |
|
|
90 |
/**
|
|
91 |
* Create an XML document from the database for the document with ID docid
|
|
92 |
*/
|
|
93 |
public String toString()
|
|
94 |
{
|
|
95 |
StringBuffer doc = new StringBuffer();
|
|
96 |
|
|
97 |
// Append the resulting document to the StringBuffer and return it
|
|
98 |
doc.append("<?xml version=\"1.0\"?>\n");
|
|
99 |
|
|
100 |
if (docname != null) {
|
|
101 |
if ((doctype != null) && (system_id != null)) {
|
|
102 |
doc.append("<!DOCTYPE " + docname + " PUBLIC \"" + doctype +
|
|
103 |
"\" \"" + system_id + "\">\n");
|
|
104 |
} else {
|
|
105 |
doc.append("<!DOCTYPE " + docname + ">\n");
|
|
106 |
}
|
|
107 |
}
|
|
108 |
doc.append(rootNode.toString());
|
|
109 |
|
|
110 |
return (doc.toString());
|
|
111 |
}
|
|
112 |
|
|
113 |
/**
|
|
114 |
* Look up the document type information from the database
|
|
115 |
*
|
|
116 |
* @param docid the id of the document to look up
|
|
117 |
*/
|
|
118 |
private void getDocumentInfo(String docid) throws McdbException
|
|
119 |
{
|
|
120 |
PreparedStatement pstmt;
|
|
121 |
|
|
122 |
try {
|
|
123 |
pstmt =
|
|
124 |
conn.prepareStatement("SELECT docname,doctype,rootnodeid " +
|
|
125 |
"FROM xml_documents " +
|
|
126 |
"WHERE docid = ?");
|
|
127 |
// Bind the values to the query
|
|
128 |
pstmt.setString(1, docid);
|
|
129 |
|
|
130 |
pstmt.execute();
|
|
131 |
ResultSet rs = pstmt.getResultSet();
|
|
132 |
boolean tableHasRows = rs.next();
|
|
133 |
if (tableHasRows) {
|
|
134 |
this.docname = rs.getString(1);
|
|
135 |
this.doctype = rs.getString(2);
|
|
136 |
this.rootnodeid = rs.getLong(3);
|
|
137 |
}
|
|
138 |
pstmt.close();
|
|
139 |
|
|
140 |
if (this.doctype != null) {
|
|
141 |
pstmt =
|
|
142 |
conn.prepareStatement("SELECT system_id " +
|
|
143 |
"FROM xml_catalog " +
|
|
144 |
"WHERE public_id = ?");
|
|
145 |
// Bind the values to the query
|
|
146 |
pstmt.setString(1, doctype);
|
|
147 |
|
|
148 |
pstmt.execute();
|
|
149 |
rs = pstmt.getResultSet();
|
|
150 |
tableHasRows = rs.next();
|
|
151 |
if (tableHasRows) {
|
|
152 |
this.system_id = rs.getString(1);
|
|
153 |
}
|
|
154 |
pstmt.close();
|
|
155 |
}
|
|
156 |
} catch (SQLException e) {
|
|
157 |
throw new McdbException("Error accessing database connection.", e);
|
|
158 |
}
|
|
159 |
|
|
160 |
if (this.docname == null) {
|
|
161 |
throw new McdbDocNotFoundException("Document not found: " + docid);
|
|
162 |
}
|
|
163 |
}
|
|
164 |
|
|
165 |
/**
|
|
166 |
* Look up the node data from the database
|
|
167 |
*
|
|
168 |
* @param docid the id of the document to look up
|
|
169 |
*/
|
|
170 |
private TreeSet getNodeRecordList(String docid) throws McdbException
|
|
171 |
{
|
|
172 |
PreparedStatement pstmt;
|
|
173 |
TreeSet nodeRecordList = new TreeSet(new NodeComparator());
|
|
174 |
long nodeid = 0;
|
|
175 |
long parentnodeid = 0;
|
|
176 |
long nodeindex = 0;
|
|
177 |
String nodetype = null;
|
|
178 |
String nodename = null;
|
|
179 |
String nodedata = null;
|
|
180 |
|
|
181 |
try {
|
|
182 |
pstmt =
|
|
183 |
conn.prepareStatement("SELECT nodeid,parentnodeid,nodeindex, " +
|
|
184 |
"nodetype,nodename,"+
|
|
185 |
"replace(" +
|
|
186 |
"replace(" +
|
|
187 |
"replace(nodedata,'&','&') " +
|
|
188 |
",'<','<') " +
|
|
189 |
",'>','>') " +
|
|
190 |
"FROM xml_nodes WHERE docid = ?");
|
|
191 |
|
|
192 |
// Bind the values to the query
|
|
193 |
pstmt.setString(1, docid);
|
|
194 |
|
|
195 |
pstmt.execute();
|
|
196 |
ResultSet rs = pstmt.getResultSet();
|
|
197 |
boolean tableHasRows = rs.next();
|
|
198 |
while (tableHasRows) {
|
|
199 |
nodeid = rs.getLong(1);
|
|
200 |
parentnodeid = rs.getLong(2);
|
|
201 |
nodeindex = rs.getLong(3);
|
|
202 |
nodetype = rs.getString(4);
|
|
203 |
nodename = rs.getString(5);
|
|
204 |
nodedata = rs.getString(6);
|
|
205 |
|
|
206 |
// add the data to the node record list hashtable
|
|
207 |
NodeRecord currentRecord = new NodeRecord(nodeid, parentnodeid,
|
|
208 |
nodeindex, nodetype, nodename, nodedata);
|
|
209 |
nodeRecordList.add(currentRecord);
|
|
210 |
|
|
211 |
// Advance to the next node
|
|
212 |
tableHasRows = rs.next();
|
|
213 |
}
|
|
214 |
pstmt.close();
|
|
215 |
|
|
216 |
} catch (SQLException e) {
|
|
217 |
throw new McdbException("Error accessing database connection.", e);
|
|
218 |
}
|
|
219 |
|
|
220 |
if (nodeRecordList != null) {
|
|
221 |
return nodeRecordList;
|
|
222 |
} else {
|
|
223 |
throw new McdbException("Error getting node data: " + docid);
|
|
224 |
}
|
|
225 |
}
|
|
226 |
|
|
227 |
/**
|
|
228 |
* main routine used for testing.
|
|
229 |
* <p>
|
|
230 |
* Usage: java DocumentImpl <docid>
|
|
231 |
*
|
|
232 |
* @param docid the id number of the document to display
|
|
233 |
*/
|
|
234 |
static public void main(String[] args) {
|
|
235 |
|
|
236 |
if (args.length < 1)
|
|
237 |
{
|
|
238 |
System.err.println("Wrong number of arguments!!!");
|
|
239 |
System.err.println("USAGE: java DocumentImpl <docid>");
|
|
240 |
return;
|
|
241 |
} else {
|
|
242 |
try {
|
|
243 |
|
|
244 |
String docid = args[0];
|
|
245 |
|
|
246 |
// Open a connection to the database
|
|
247 |
MetaCatUtil util = new MetaCatUtil();
|
|
248 |
Connection dbconn = util.openDBConnection();
|
|
249 |
|
|
250 |
DocumentImpl xmldoc = new DocumentImpl( dbconn, docid );
|
|
251 |
System.out.println(xmldoc);
|
|
252 |
|
|
253 |
} catch (McdbException me) {
|
|
254 |
me.toXml(new PrintWriter(System.err));
|
|
255 |
} catch (Exception e) {
|
|
256 |
System.err.println("EXCEPTION HANDLING REQUIRED");
|
|
257 |
System.err.println(e.getMessage());
|
|
258 |
e.printStackTrace(System.err);
|
|
259 |
}
|
|
260 |
}
|
|
261 |
}
|
|
262 |
}
|
0 |
263 |
|
Created new class "DocumentImpl" which represents an XML Document. This
document will eventually implment the DOM Document interface. For now,
it implments all of the functionality that was present in DBReader, plus
cuts down on the number of database calls required to read a document. And
it simplifies the API for interacting with a DOM Document. When the
"toString()" method is called, this class emits the document as an XML
serialization of the DOM structure.
The functionality of DBSAXDocument will be folded into this class as well,
so that we will have one class that can both read documents from the
database and write a document to the database. This functionality is not
yet implmented, however.
Modified MetaCatServlet to utilize this new class instead of DBReader.