Project

General

Profile

1 17 jones
/**
2 203 jones
 *  '$RCSfile$'
3
 *    Purpose: A Class that handles the SAX XML events as they
4
 *             are generated from XML documents
5
 *  Copyright: 2000 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Matt Jones, Jivka Bojilova
8 17 jones
 *
9 203 jones
 *   '$Author$'
10
 *     '$Date$'
11
 * '$Revision$'
12 17 jones
 */
13
14 75 jones
package edu.ucsb.nceas.metacat;
15 51 jones
16 17 jones
import java.sql.*;
17
import java.util.Stack;
18 18 jones
import java.util.EmptyStackException;
19 17 jones
20 185 jones
import org.xml.sax.Attributes;
21
import org.xml.sax.SAXException;
22 204 jones
import org.xml.sax.SAXParseException;
23 186 jones
import org.xml.sax.ext.DeclHandler;
24 185 jones
import org.xml.sax.ext.LexicalHandler;
25
import org.xml.sax.helpers.DefaultHandler;
26 17 jones
27 31 jones
/**
28
 * A database aware Class implementing callback bethods for the SAX parser to
29
 * call when processing the XML stream and generating events
30
 */
31 186 jones
public class DBSAXHandler extends DefaultHandler
32
                          implements LexicalHandler, DeclHandler {
33 17 jones
34 204 jones
   private boolean	atFirstElement;
35
   private String 	docname = null;
36 135 jones
   private String 	doctype;
37
   private String 	systemid;
38 17 jones
   private boolean 	stackCreated = false;
39 137 jones
   private Stack 	nodeStack;
40 17 jones
   private Connection	conn = null;
41 142 jones
   private DBSAXDocument currentDocument;
42 185 jones
   private DBSAXNode    rootNode;
43 203 jones
   private String       action = null;
44
   private String       docid = null;
45 17 jones
46 220 jones
   private static final int MAXDATACHARS = 4000;
47
48 31 jones
   /** Construct an instance of the handler class
49
    *
50
    * @param conn the JDBC connection to which information is written
51
    */
52 122 jones
   public DBSAXHandler(Connection conn) {
53 185 jones
     this.conn = conn;
54 204 jones
     this.atFirstElement = true;
55 17 jones
56 185 jones
     // Create the stack for keeping track of node context
57
     // if it doesn't already exist
58
     if (!stackCreated) {
59
       nodeStack = new Stack();
60
       stackCreated = true;
61
     }
62 17 jones
   }
63
64 203 jones
   /** Construct an instance of the handler class
65
    *
66
    * @param conn the JDBC connection to which information is written
67
    */
68
   public DBSAXHandler(Connection conn, String action, String docid) {
69
     this(conn);
70
     this.action = action;
71
     this.docid = docid;
72
   }
73
74 72 bojilova
   /** SAX Handler that receives notification of beginning of the document */
75 122 jones
   public void startDocument() throws SAXException {
76 203 jones
     MetaCatUtil.debugMessage("start Document");
77
78 185 jones
     // Create the document node representation as root
79
     rootNode = new DBSAXNode(conn, docname);
80 204 jones
     MetaCatUtil.debugMessage("PRINTING DOCNAME FROM ROOTNODE: " +
81
                               rootNode.getTagName());
82 185 jones
     // Add the node to the stack, so that any text data can be
83
     // added as it is encountered
84
     nodeStack.push(rootNode);
85 72 bojilova
   }
86
87
   /** SAX Handler that receives notification of end of the document */
88 122 jones
   public void endDocument() throws SAXException {
89 185 jones
     currentDocument.setTitleFromChildElement();
90 203 jones
     MetaCatUtil.debugMessage("end Document");
91
     if ((docid != null) && (!docid.equals(currentDocument.getDocID()))) {
92
       throw (new SAXException("New document ID generated:",
93 204 jones
           new AccessionNumberGeneratedException(currentDocument.getDocID())));
94 203 jones
     } else {
95
       throw (new SAXException("New document ID generated:",
96 204 jones
           new AccessionNumberGeneratedException(currentDocument.getDocID())));
97 122 jones
     }
98 72 bojilova
   }
99
100 185 jones
   /** SAX Handler that is called at the start of each XML element */
101
   public void startElement(String uri, String localName,
102
                            String qName, Attributes atts)
103
               throws SAXException {
104 203 jones
     MetaCatUtil.debugMessage("Start ELEMENT " + localName);
105 72 bojilova
106 203 jones
     DBSAXNode parentNode = null;
107
     DBSAXNode currentNode = null;
108 17 jones
109 203 jones
     // Get a reference to the parent node for the id
110
     try {
111
       parentNode = (DBSAXNode)nodeStack.peek();
112
     } catch (EmptyStackException e) {
113
     }
114 18 jones
115 203 jones
     // Document representation that points to the root document node
116 204 jones
     if (atFirstElement) {
117
       atFirstElement = false;
118 203 jones
       // If no DOCTYPE declaration: docname = root element name
119
       if (docname == null) {
120
         docname = localName;
121 204 jones
         doctype = docname;
122
         MetaCatUtil.debugMessage("DOCNAME-a: " + docname);
123
         MetaCatUtil.debugMessage("DOCTYPE-a: " + doctype);
124 203 jones
       } else if (doctype == null) {
125 204 jones
         doctype = docname;
126
         //doctype = DBEntityResolver.doctype;
127
         MetaCatUtil.debugMessage("DOCTYPE-b: " + doctype);
128 203 jones
       }
129
       rootNode.writeNodename(docname);
130
       rootNode.writeRootNodeID(rootNode.getNodeID());
131
       try {
132
         currentDocument = new DBSAXDocument(conn, rootNode.getNodeID(),
133
                                           docname, doctype, docid, action);
134
         } catch (AccessionNumberException ane) {
135 204 jones
           throw (new SAXException("Error with " + action, ane));
136 203 jones
         }
137
       rootNode.writeDocID(currentDocument.getDocID());
138
     }
139 135 jones
140 203 jones
     // Create the current node representation
141
     currentNode = new DBSAXNode(conn, localName, parentNode,
142
                                 rootNode, currentDocument);
143 17 jones
144 203 jones
     // Add all of the attributes
145
     for (int i=0; i<atts.getLength(); i++) {
146
       currentNode.setAttribute(atts.getLocalName(i), atts.getValue(i));
147
     }
148 17 jones
149 203 jones
     // Add the node to the stack, so that any text data can be
150
     // added as it is encountered
151
     nodeStack.push(currentNode);
152
  }
153 17 jones
154 31 jones
   /** SAX Handler that is called for each XML text node */
155 122 jones
   public void characters(char[] cbuf, int start, int len) {
156 203 jones
     MetaCatUtil.debugMessage("CHARACTERS");
157 186 jones
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
158 220 jones
     String data = null;
159
     int leftover = len;
160
     int offset = start;
161
     boolean moredata = true;
162
163
     // This loop deals with the case where there are more characters
164
     // than can fit in a single database text field (limit is
165
     // MAXDATACHARS).  If the text to be inserted exceeds MAXDATACHARS,
166
     // write a series of nodes that are MAXDATACHARS long, and then the
167
     // final node contains the remainder
168
     while (moredata) {
169
       if (leftover > MAXDATACHARS) {
170
         data = new String(cbuf, offset, MAXDATACHARS);
171
         leftover -= MAXDATACHARS;
172
         offset += MAXDATACHARS;
173
       } else {
174
         data = new String(cbuf, offset, leftover);
175
         moredata = false;
176
       }
177 122 jones
178 220 jones
       // Write the content of the node to the database
179
       currentNode.writeChildNodeToDB("TEXT", null, data);
180
     }
181 17 jones
   }
182
183 31 jones
   /**
184
    * SAX Handler that is called for each XML text node that is Ignorable
185
    * white space
186
    */
187 122 jones
   public void ignorableWhitespace(char[] cbuf, int start, int len) {
188 203 jones
     MetaCatUtil.debugMessage("IGNORABLEWHITESPACE");
189 17 jones
   }
190
191 122 jones
   /**
192
    * SAX Handler called once for each processing instruction found:
193
    * node that PI may occur before or after the root element.
194
    */
195
   public void processingInstruction(String target, String data)
196
          throws SAXException {
197 203 jones
     MetaCatUtil.debugMessage("PI");
198 186 jones
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
199
     currentNode.writeChildNodeToDB("PI", target, data);
200 92 bojilova
   }
201 72 bojilova
202 31 jones
   /** SAX Handler that is called at the end of each XML element */
203 185 jones
   public void endElement(String uri, String localName,
204
                          String qName) throws SAXException {
205 203 jones
     MetaCatUtil.debugMessage("End ELEMENT " + localName);
206 17 jones
207 185 jones
     // Get the node from the stack
208
     DBSAXNode currentNode = (DBSAXNode)nodeStack.pop();
209 17 jones
   }
210
211 185 jones
   //
212
   // the next section implements the LexicalHandler interface
213
   //
214
215
   /** SAX Handler that receives notification of DOCTYPE. Sets the DTD */
216
   public void startDTD(String name, String publicId, String systemId)
217
               throws SAXException {
218
     docname = name;
219
     doctype = publicId;
220
     systemid = systemId;
221
222 204 jones
     MetaCatUtil.debugMessage("Start DTD");
223 203 jones
     MetaCatUtil.debugMessage("DOCNAME: " + docname);
224
     MetaCatUtil.debugMessage("DOCTYPE: " + doctype);
225
     MetaCatUtil.debugMessage("  SYSID: " + systemid);
226 185 jones
   }
227
228
   /**
229
    * SAX Handler that receives notification of end of DTD
230
    */
231
   public void endDTD() throws SAXException {
232 204 jones
     MetaCatUtil.debugMessage("end DTD");
233 185 jones
   }
234
235
   /**
236
    * SAX Handler that receives notification of comments in the DTD
237
    */
238
   public void comment(char[] ch, int start, int length) throws SAXException {
239 203 jones
     MetaCatUtil.debugMessage("COMMENT");
240 186 jones
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
241
     currentNode.writeChildNodeToDB("COMMENT", null, new String(ch));
242 185 jones
   }
243
244
   /**
245
    * SAX Handler that receives notification of the start of CDATA sections
246
    */
247
   public void startCDATA() throws SAXException {
248 203 jones
     MetaCatUtil.debugMessage("start CDATA");
249 185 jones
   }
250
251
   /**
252
    * SAX Handler that receives notification of the end of CDATA sections
253
    */
254
   public void endCDATA() throws SAXException {
255 203 jones
     MetaCatUtil.debugMessage("end CDATA");
256 185 jones
   }
257
258
   /**
259
    * SAX Handler that receives notification of the start of entities
260
    */
261
   public void startEntity(String name) throws SAXException {
262 203 jones
     MetaCatUtil.debugMessage("start ENTITY");
263 185 jones
   }
264
265
   /**
266
    * SAX Handler that receives notification of the end of entities
267
    */
268
   public void endEntity(String name) throws SAXException {
269 203 jones
     MetaCatUtil.debugMessage("end ENTITY");
270 185 jones
   }
271 186 jones
272
   /**
273
    * SAX Handler that receives notification of element declarations
274
    */
275
   public void elementDecl(String name, String model)
276
                        throws org.xml.sax.SAXException {
277 203 jones
     MetaCatUtil.debugMessage("ELEMENTDECL");
278 186 jones
   }
279
280
   /**
281
    * SAX Handler that receives notification of attribute declarations
282
    */
283
   public void attributeDecl(String eName, String aName,
284
                        String type, String valueDefault, String value)
285
                        throws org.xml.sax.SAXException {
286 203 jones
     MetaCatUtil.debugMessage("ATTRIBUTEDECL");
287 186 jones
   }
288
289
   /**
290
    * SAX Handler that receives notification of internal entity declarations
291
    */
292
   public void internalEntityDecl(String name, String value)
293
                        throws org.xml.sax.SAXException {
294 203 jones
     MetaCatUtil.debugMessage("INTERNENTITYDECL");
295 186 jones
   }
296
297
   /**
298
    * SAX Handler that receives notification of external entity declarations
299
    */
300
   public void externalEntityDecl(String name, String publicId,
301
                        String systemId)
302
                        throws org.xml.sax.SAXException {
303 203 jones
     MetaCatUtil.debugMessage("EXTERNENTITYDECL");
304 186 jones
   }
305
306 204 jones
   //
307
   // the next section implements the ErrorHandler interface
308
   //
309 186 jones
310 204 jones
   /**
311
    * SAX Handler that receives notification of fatal parsing errors
312
    */
313
   public void fatalError(SAXParseException exception) throws SAXException {
314
     MetaCatUtil.debugMessage("FATALERROR");
315
     throw (new SAXException("Fatal processing error.", exception));
316
   }
317
318
   /**
319
    * SAX Handler that receives notification of recoverable parsing errors
320
    */
321
   public void error(SAXParseException exception) throws SAXException {
322
     MetaCatUtil.debugMessage("ERROR");
323
   }
324
325
   /**
326
    * SAX Handler that receives notification of warnings
327
    */
328
   public void warning(SAXParseException exception) throws SAXException {
329
     MetaCatUtil.debugMessage("FATALERROR");
330
   }
331
332
   //
333
   // Helper, getter and setter methods
334
   //
335
336
   /**
337
    * get the document name
338
    */
339
   public String getDocname() {
340
     return docname;
341
   }
342
343
   /**
344
    * get the document processing state
345
    */
346
   public boolean atFirstElement() {
347
     return atFirstElement;
348
   }
349 17 jones
}
350 203 jones
351
/**
352
 * '$Log$
353 220 jones
 * 'Revision 1.29  2000/06/27 04:31:07  jones
354
 * 'Fixed bugs associated with the new UPDATE and DELETE functions of
355
 * 'DBWriter.  There were problematic interactions between some static
356
 * 'variables used in DBEntityResolver and the way in which the
357
 * 'Servlet objects are re-used across multiple client invocations.
358
 * '
359
 * 'Generally cleaned up error reporting.  Now all errors and success
360
 * 'results are reported as XML documents from MetaCatServlet.  Need
361
 * 'to make the command line tools do the same.
362
 * '
363 204 jones
 * 'Revision 1.28  2000/06/26 10:35:05  jones
364
 * 'Merged in substantial changes to DBWriter and associated classes and to
365
 * 'the MetaCatServlet in order to accomodate the new UPDATE and DELETE
366
 * 'functions.  The command line tools and the parameters for the
367
 * 'servlet have changed substantially.
368
 * '
369 203 jones
 * 'Revision 1.27.2.6  2000/06/26 02:02:20  jones
370
 * 'Continued fixing problems with exception handling that deals
371
 * 'with INSERT and UPDATE actions and the docid passed to DBWriter
372
 * '
373
 * 'Revision 1.27.2.5  2000/06/26 00:51:06  jones
374
 * 'If docid passed to DBWriter.write() is not unique, classes now generate
375
 * 'an AccessionNumberException containing the new docid generated as a
376
 * 'replacement.  The docid is then extracted from the exception and
377
 * 'returned to the calling application for user feedback or client processing.
378
 * '
379
 * 'Revision 1.27.2.4  2000/06/25 23:38:16  jones
380
 * 'Added RCSfile keyword
381
 * '
382
 * 'Revision 1.27.2.3  2000/06/25 23:34:17  jones
383
 * 'Changed documentation formatting, added log entries at bottom of source files
384
 * ''
385
 */