Project

General

Profile

1
/**
2
 *  '$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
 *
9
 *   '$Author: jones $'
10
 *     '$Date: 2000-06-26 21:31:07 -0700 (Mon, 26 Jun 2000) $'
11
 * '$Revision: 204 $'
12
 */
13

    
14
package edu.ucsb.nceas.metacat;
15

    
16
import java.sql.*;
17
import java.util.Stack;
18
import java.util.EmptyStackException;
19

    
20
import org.xml.sax.Attributes;
21
import org.xml.sax.SAXException;
22
import org.xml.sax.SAXParseException;
23
import org.xml.sax.ext.DeclHandler;
24
import org.xml.sax.ext.LexicalHandler;
25
import org.xml.sax.helpers.DefaultHandler;
26

    
27
/** 
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
public class DBSAXHandler extends DefaultHandler 
32
                          implements LexicalHandler, DeclHandler {
33

    
34
   private boolean	atFirstElement;
35
   private String 	docname = null;
36
   private String 	doctype;
37
   private String 	systemid;
38
   private boolean 	stackCreated = false;
39
   private Stack 	nodeStack;
40
   private Connection	conn = null;
41
   private DBSAXDocument currentDocument;
42
   private DBSAXNode    rootNode;
43
   private String       action = null;
44
   private String       docid = null;
45

    
46
   /** Construct an instance of the handler class 
47
    *
48
    * @param conn the JDBC connection to which information is written
49
    */
50
   public DBSAXHandler(Connection conn) {
51
     this.conn = conn;
52
     this.atFirstElement = true;
53

    
54
     // Create the stack for keeping track of node context
55
     // if it doesn't already exist
56
     if (!stackCreated) {
57
       nodeStack = new Stack();
58
       stackCreated = true;
59
     }
60
   }
61
 
62
   /** Construct an instance of the handler class 
63
    *
64
    * @param conn the JDBC connection to which information is written
65
    */
66
   public DBSAXHandler(Connection conn, String action, String docid) {
67
     this(conn);
68
     this.action = action;
69
     this.docid = docid;
70
   }
71

    
72
   /** SAX Handler that receives notification of beginning of the document */
73
   public void startDocument() throws SAXException {
74
     MetaCatUtil.debugMessage("start Document");
75

    
76
     // Create the document node representation as root
77
     rootNode = new DBSAXNode(conn, docname);
78
     MetaCatUtil.debugMessage("PRINTING DOCNAME FROM ROOTNODE: " + 
79
                               rootNode.getTagName());
80
     // Add the node to the stack, so that any text data can be 
81
     // added as it is encountered
82
     nodeStack.push(rootNode);
83
   }
84

    
85
   /** SAX Handler that receives notification of end of the document */
86
   public void endDocument() throws SAXException {
87
     currentDocument.setTitleFromChildElement();
88
     MetaCatUtil.debugMessage("end Document");
89
     if ((docid != null) && (!docid.equals(currentDocument.getDocID()))) {
90
       throw (new SAXException("New document ID generated:",
91
           new AccessionNumberGeneratedException(currentDocument.getDocID())));
92
     } else {
93
       throw (new SAXException("New document ID generated:",
94
           new AccessionNumberGeneratedException(currentDocument.getDocID())));
95
     }
96
   }
97

    
98
   /** SAX Handler that is called at the start of each XML element */
99
   public void startElement(String uri, String localName,
100
                            String qName, Attributes atts) 
101
               throws SAXException {
102
     MetaCatUtil.debugMessage("Start ELEMENT " + localName);
103

    
104
     DBSAXNode parentNode = null;
105
     DBSAXNode currentNode = null;
106

    
107
     // Get a reference to the parent node for the id
108
     try {
109
       parentNode = (DBSAXNode)nodeStack.peek();
110
     } catch (EmptyStackException e) {
111
     }
112

    
113
     // Document representation that points to the root document node
114
     if (atFirstElement) {
115
       atFirstElement = false;
116
       // If no DOCTYPE declaration: docname = root element name 
117
       if (docname == null) {
118
         docname = localName;
119
         doctype = docname;
120
         MetaCatUtil.debugMessage("DOCNAME-a: " + docname);
121
         MetaCatUtil.debugMessage("DOCTYPE-a: " + doctype);
122
       } else if (doctype == null) {
123
         doctype = docname;
124
         //doctype = DBEntityResolver.doctype;
125
         MetaCatUtil.debugMessage("DOCTYPE-b: " + doctype);
126
       }
127
       rootNode.writeNodename(docname);
128
       rootNode.writeRootNodeID(rootNode.getNodeID());
129
       try {
130
         currentDocument = new DBSAXDocument(conn, rootNode.getNodeID(), 
131
                                           docname, doctype, docid, action);
132
         } catch (AccessionNumberException ane) {
133
           throw (new SAXException("Error with " + action, ane));
134
         }
135
       rootNode.writeDocID(currentDocument.getDocID());
136
     }      
137

    
138
     // Create the current node representation
139
     currentNode = new DBSAXNode(conn, localName, parentNode, 
140
                                 rootNode, currentDocument);
141

    
142
     // Add all of the attributes
143
     for (int i=0; i<atts.getLength(); i++) {
144
       currentNode.setAttribute(atts.getLocalName(i), atts.getValue(i));
145
     }      
146

    
147
     // Add the node to the stack, so that any text data can be 
148
     // added as it is encountered
149
     nodeStack.push(currentNode);
150
  }
151

    
152
   /** SAX Handler that is called for each XML text node */
153
   public void characters(char[] cbuf, int start, int len) {
154
     MetaCatUtil.debugMessage("CHARACTERS");
155
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
156
     String data = new String(cbuf, start, len);
157

    
158
     // Write the content of the node to the database
159
     currentNode.writeChildNodeToDB("TEXT", null, data);
160
   }
161

    
162
   /** 
163
    * SAX Handler that is called for each XML text node that is Ignorable
164
    * white space
165
    */
166
   public void ignorableWhitespace(char[] cbuf, int start, int len) {
167
     MetaCatUtil.debugMessage("IGNORABLEWHITESPACE");
168
   }
169

    
170
   /** 
171
    * SAX Handler called once for each processing instruction found: 
172
    * node that PI may occur before or after the root element.
173
    */
174
   public void processingInstruction(String target, String data) 
175
          throws SAXException {
176
     MetaCatUtil.debugMessage("PI");
177
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
178
     currentNode.writeChildNodeToDB("PI", target, data);
179
   }
180

    
181
   /** SAX Handler that is called at the end of each XML element */
182
   public void endElement(String uri, String localName,
183
                          String qName) throws SAXException {
184
     MetaCatUtil.debugMessage("End ELEMENT " + localName);
185

    
186
     // Get the node from the stack
187
     DBSAXNode currentNode = (DBSAXNode)nodeStack.pop();
188
   }
189

    
190
   //
191
   // the next section implements the LexicalHandler interface
192
   //
193

    
194
   /** SAX Handler that receives notification of DOCTYPE. Sets the DTD */
195
   public void startDTD(String name, String publicId, String systemId) 
196
               throws SAXException {
197
     docname = name;
198
     doctype = publicId;
199
     systemid = systemId;
200

    
201
     MetaCatUtil.debugMessage("Start DTD");
202
     MetaCatUtil.debugMessage("DOCNAME: " + docname);
203
     MetaCatUtil.debugMessage("DOCTYPE: " + doctype);
204
     MetaCatUtil.debugMessage("  SYSID: " + systemid);
205
   }
206

    
207
   /** 
208
    * SAX Handler that receives notification of end of DTD 
209
    */
210
   public void endDTD() throws SAXException {
211
     MetaCatUtil.debugMessage("end DTD");
212
   }
213

    
214
   /** 
215
    * SAX Handler that receives notification of comments in the DTD
216
    */
217
   public void comment(char[] ch, int start, int length) throws SAXException {
218
     MetaCatUtil.debugMessage("COMMENT");
219
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
220
     currentNode.writeChildNodeToDB("COMMENT", null, new String(ch));
221
   }
222

    
223
   /** 
224
    * SAX Handler that receives notification of the start of CDATA sections
225
    */
226
   public void startCDATA() throws SAXException {
227
     MetaCatUtil.debugMessage("start CDATA");
228
   }
229

    
230
   /** 
231
    * SAX Handler that receives notification of the end of CDATA sections
232
    */
233
   public void endCDATA() throws SAXException {
234
     MetaCatUtil.debugMessage("end CDATA");
235
   }
236

    
237
   /** 
238
    * SAX Handler that receives notification of the start of entities
239
    */
240
   public void startEntity(String name) throws SAXException {
241
     MetaCatUtil.debugMessage("start ENTITY");
242
   }
243

    
244
   /** 
245
    * SAX Handler that receives notification of the end of entities
246
    */
247
   public void endEntity(String name) throws SAXException {
248
     MetaCatUtil.debugMessage("end ENTITY");
249
   }
250

    
251
   /** 
252
    * SAX Handler that receives notification of element declarations
253
    */
254
   public void elementDecl(String name, String model)
255
                        throws org.xml.sax.SAXException {
256
     MetaCatUtil.debugMessage("ELEMENTDECL");
257
   }
258

    
259
   /** 
260
    * SAX Handler that receives notification of attribute declarations
261
    */
262
   public void attributeDecl(String eName, String aName,
263
                        String type, String valueDefault, String value)
264
                        throws org.xml.sax.SAXException {
265
     MetaCatUtil.debugMessage("ATTRIBUTEDECL");
266
   }
267

    
268
   /** 
269
    * SAX Handler that receives notification of internal entity declarations
270
    */
271
   public void internalEntityDecl(String name, String value)
272
                        throws org.xml.sax.SAXException {
273
     MetaCatUtil.debugMessage("INTERNENTITYDECL");
274
   }
275

    
276
   /** 
277
    * SAX Handler that receives notification of external entity declarations
278
    */
279
   public void externalEntityDecl(String name, String publicId,
280
                        String systemId)
281
                        throws org.xml.sax.SAXException {
282
     MetaCatUtil.debugMessage("EXTERNENTITYDECL");
283
   }
284

    
285
   //
286
   // the next section implements the ErrorHandler interface
287
   //
288

    
289
   /** 
290
    * SAX Handler that receives notification of fatal parsing errors
291
    */
292
   public void fatalError(SAXParseException exception) throws SAXException {
293
     MetaCatUtil.debugMessage("FATALERROR");
294
     throw (new SAXException("Fatal processing error.", exception));
295
   }
296

    
297
   /** 
298
    * SAX Handler that receives notification of recoverable parsing errors
299
    */
300
   public void error(SAXParseException exception) throws SAXException {
301
     MetaCatUtil.debugMessage("ERROR");
302
   }
303

    
304
   /** 
305
    * SAX Handler that receives notification of warnings
306
    */
307
   public void warning(SAXParseException exception) throws SAXException {
308
     MetaCatUtil.debugMessage("FATALERROR");
309
   }
310

    
311
   // 
312
   // Helper, getter and setter methods
313
   //
314
   
315
   /**
316
    * get the document name
317
    */
318
   public String getDocname() {
319
     return docname;
320
   }
321

    
322
   /**
323
    * get the document processing state
324
    */
325
   public boolean atFirstElement() {
326
     return atFirstElement;
327
   }
328
}
329

    
330
/**
331
 * '$Log$
332
 * 'Revision 1.28  2000/06/26 10:35:05  jones
333
 * 'Merged in substantial changes to DBWriter and associated classes and to
334
 * 'the MetaCatServlet in order to accomodate the new UPDATE and DELETE
335
 * 'functions.  The command line tools and the parameters for the
336
 * 'servlet have changed substantially.
337
 * '
338
 * 'Revision 1.27.2.6  2000/06/26 02:02:20  jones
339
 * 'Continued fixing problems with exception handling that deals
340
 * 'with INSERT and UPDATE actions and the docid passed to DBWriter
341
 * '
342
 * 'Revision 1.27.2.5  2000/06/26 00:51:06  jones
343
 * 'If docid passed to DBWriter.write() is not unique, classes now generate
344
 * 'an AccessionNumberException containing the new docid generated as a
345
 * 'replacement.  The docid is then extracted from the exception and
346
 * 'returned to the calling application for user feedback or client processing.
347
 * '
348
 * 'Revision 1.27.2.4  2000/06/25 23:38:16  jones
349
 * 'Added RCSfile keyword
350
 * '
351
 * 'Revision 1.27.2.3  2000/06/25 23:34:17  jones
352
 * 'Changed documentation formatting, added log entries at bottom of source files
353
 * ''
354
 */
(10-10/20)