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 349 jones
 *    Release: @release@
9 17 jones
 *
10 203 jones
 *   '$Author$'
11
 *     '$Date$'
12
 * '$Revision$'
13 669 jones
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 2 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27 17 jones
 */
28
29 75 jones
package edu.ucsb.nceas.metacat;
30 51 jones
31 1590 tao
import edu.ucsb.nceas.morpho.datapackage.Triple;
32
import edu.ucsb.nceas.morpho.datapackage.TripleCollection;
33
34 17 jones
import java.sql.*;
35 638 bojilova
import java.io.StringReader;
36 17 jones
import java.util.Stack;
37 471 bojilova
import java.util.Vector;
38 821 bojilova
import java.util.Hashtable;
39 471 bojilova
import java.util.Enumeration;
40 18 jones
import java.util.EmptyStackException;
41 17 jones
42 185 jones
import org.xml.sax.Attributes;
43
import org.xml.sax.SAXException;
44 204 jones
import org.xml.sax.SAXParseException;
45 186 jones
import org.xml.sax.ext.DeclHandler;
46 185 jones
import org.xml.sax.ext.LexicalHandler;
47
import org.xml.sax.helpers.DefaultHandler;
48 17 jones
49 1359 tao
/**
50 31 jones
 * A database aware Class implementing callback bethods for the SAX parser to
51
 * call when processing the XML stream and generating events
52
 */
53 1359 tao
public class DBSAXHandler extends DefaultHandler
54 471 bojilova
                          implements LexicalHandler, DeclHandler, Runnable {
55 17 jones
56 1396 tao
   protected boolean	atFirstElement;
57 1510 tao
   protected boolean	processingDTD;
58 1396 tao
   protected String 	docname = null;
59
   protected String 	doctype;
60
   protected String 	systemid;
61 17 jones
   private boolean 	stackCreated = false;
62 1396 tao
   protected Stack 	  nodeStack;
63
   protected Vector   nodeIndex;
64
   protected DBConnection	  connection = null;
65
   protected DocumentImpl currentDocument;
66
   protected DBSAXNode    rootNode;
67
   protected String   action = null;
68
   protected String   docid = null;
69
   protected String   revision = null;
70
   protected String   user = null;
71
   protected String[] groups = null;
72
   protected String   pub = null;
73
   protected Thread   xmlIndex;
74 471 bojilova
   private boolean endDocument = false;
75 1396 tao
   protected int serverCode = 1;
76
   protected Hashtable namespaces = new Hashtable();
77 1411 tao
   protected boolean hitTextNode = false; // a flag to hit text node
78
   // a buffer to keep all text nodes for same element
79
   // it is for element was splited
80
   protected StringBuffer textBuffer = new StringBuffer();
81
   protected Stack textBufferStack = new Stack();
82 17 jones
83 1404 tao
   protected static final int MAXDATACHARS = 4000;
84 1761 tao
   //protected static final int MAXDATACHARS = 50;
85 1396 tao
   protected static final long INDEXDELAY = 10000;
86 1415 tao
   // methods writeChildNodeToDB, setAttribute, setNamespace,
87
   // writeTextForDBSAXNode will increase endNodeId.
88
   protected long  endNodeId = -1;    // The end node id for a substree
89 691 bojilova
// DOCTITLE attr cleared from the db
90
//   private static final int MAXTITLELEN = 1000;
91 1590 tao
   //HandlerTriple stuff
92
   TripleCollection tripleList = new TripleCollection();
93
   Triple currentTriple        = new Triple();
94
   boolean startParseTriple    = false;
95
   boolean hasTriple           = false;
96 220 jones
97 1359 tao
   /** Construct an instance of the handler class
98 31 jones
    *
99
    * @param conn the JDBC connection to which information is written
100
    */
101 1217 tao
   public DBSAXHandler(DBConnection conn) {
102
     this.connection = conn;
103 204 jones
     this.atFirstElement = true;
104 243 jones
     this.processingDTD = false;
105 17 jones
106 185 jones
     // Create the stack for keeping track of node context
107
     // if it doesn't already exist
108
     if (!stackCreated) {
109
       nodeStack = new Stack();
110 471 bojilova
       nodeIndex = new Vector();
111 185 jones
       stackCreated = true;
112
     }
113 17 jones
   }
114 1359 tao
115
  /** Construct an instance of the handler class
116 203 jones
    *
117
    * @param conn the JDBC connection to which information is written
118 425 bojilova
    * @param action - "INSERT" or "UPDATE"
119
    * @param docid to be inserted or updated into JDBC connection
120 680 bojilova
    * @param user the user connected to MetaCat servlet and owns the document
121 802 bojilova
    * @param groups the groups to which user belongs
122 680 bojilova
    * @param pub flag for public "read" access on document
123
    * @param serverCode the serverid from xml_replication on which this document
124
    *        resides.
125
    *
126 203 jones
    */
127 1359 tao
   public DBSAXHandler(DBConnection conn, String action, String docid,
128 955 tao
                      String user, String[] groups, String pub, int serverCode)
129 425 bojilova
   {
130 203 jones
     this(conn);
131
     this.action = action;
132
     this.docid = docid;
133 425 bojilova
     this.user = user;
134 802 bojilova
     this.groups = groups;
135 680 bojilova
     this.pub = pub;
136
     this.serverCode = serverCode;
137 471 bojilova
     this.xmlIndex = new Thread(this);
138 1359 tao
   }
139
140 955 tao
  /** Construct an instance of the handler class
141
    * In this constructor, user can specify the version need to upadate
142
    *
143
    * @param conn the JDBC connection to which information is written
144
    * @param action - "INSERT" or "UPDATE"
145
    * @param docid to be inserted or updated into JDBC connection
146
    * @param revision, the user specified the revision need to be update
147
    * @param user the user connected to MetaCat servlet and owns the document
148
    * @param groups the groups to which user belongs
149
    * @param pub flag for public "read" access on document
150
    * @param serverCode the serverid from xml_replication on which this document
151
    *        resides.
152
    *
153
    */
154 1359 tao
   public DBSAXHandler(DBConnection conn, String action, String docid,
155 955 tao
     String revision, String user, String[] groups, String pub, int serverCode)
156
   {
157
     this(conn);
158
     this.action = action;
159
     this.docid = docid;
160
     this.revision = revision;
161
     this.user = user;
162
     this.groups = groups;
163
     this.pub = pub;
164
     this.serverCode = serverCode;
165
     this.xmlIndex = new Thread(this);
166 203 jones
   }
167 1359 tao
168 72 bojilova
   /** SAX Handler that receives notification of beginning of the document */
169 122 jones
   public void startDocument() throws SAXException {
170 1062 tao
     MetaCatUtil.debugMessage("start Document", 50);
171 203 jones
172 185 jones
     // Create the document node representation as root
173 1217 tao
     rootNode = new DBSAXNode(connection, this.docid);
174 1359 tao
     // Add the node to the stack, so that any text data can be
175 185 jones
     // added as it is encountered
176
     nodeStack.push(rootNode);
177 72 bojilova
   }
178
179
   /** SAX Handler that receives notification of end of the document */
180 122 jones
   public void endDocument() throws SAXException {
181 1062 tao
     MetaCatUtil.debugMessage("end Document", 50);
182 471 bojilova
     // Starting new thread for writing XML Index.
183
     // It calls the run method of the thread.
184 1590 tao
185
     //if it is data package insert triple into relationtion table;
186
     if ( doctype != null &&
187
         MetaCatUtil.getOptionList(MetaCatUtil.getOption("packagedoctype")).
188
         contains(doctype) && hasTriple)
189
      {
190
        try
191
        {
192
          //initial handler and write into relationdb
193
          RelationHandler handler =
194
                        new RelationHandler(docid,doctype, connection, tripleList);
195
        }
196
        catch (Exception e)
197
        {
198
          MetaCatUtil.debugMessage
199 1594 tao
                            ("Failed to write triples into relation table" +
200
                                                           e.getMessage(), 30);
201 1597 tao
          throw new SAXException("Failed to write triples into relation table "+ e.getMessage());
202 1590 tao
        }
203
      }
204
205
206 471 bojilova
     try {
207
       xmlIndex.start();
208
     } catch (NullPointerException e) {
209
       xmlIndex = null;
210 1359 tao
       throw new
211 471 bojilova
       SAXException("Problem with starting thread for writing XML Index. " +
212
                    e.getMessage());
213
     }
214 72 bojilova
   }
215
216 821 bojilova
   /** SAX Handler that is called at the start of Namespace */
217 1359 tao
   public void startPrefixMapping(String prefix, String uri)
218 821 bojilova
                                          throws SAXException
219
   {
220 1062 tao
    MetaCatUtil.debugMessage("NAMESPACE", 50);
221 821 bojilova
222
    namespaces.put(prefix, uri);
223
   }
224 1359 tao
225 185 jones
   /** SAX Handler that is called at the start of each XML element */
226
   public void startElement(String uri, String localName,
227 1359 tao
                            String qName, Attributes atts)
228 185 jones
               throws SAXException {
229 1389 tao
     // for element <eml:eml...> qname is "eml:eml", local name is "eml"
230
     // for element <acl....> both qname and local name is "eml"
231
     // uri is namesapce
232
     MetaCatUtil.debugMessage("Start ELEMENT(qName) " + qName, 50);
233
     MetaCatUtil.debugMessage("Start ELEMENT(localName) " + localName, 50);
234
     MetaCatUtil.debugMessage("Start ELEMENT(uri) " + uri, 50);
235
236 203 jones
     DBSAXNode parentNode = null;
237
     DBSAXNode currentNode = null;
238 17 jones
239 203 jones
     // Get a reference to the parent node for the id
240
     try {
241
       parentNode = (DBSAXNode)nodeStack.peek();
242
     } catch (EmptyStackException e) {
243 408 jones
       parentNode = null;
244 203 jones
     }
245 1411 tao
246
     // If hit a text node, we need write this text for current's parent node
247
     // This will happend if the element is mixted
248
     if (hitTextNode && parentNode != null)
249
     {
250
       // write the textbuffer into db for parent node.
251 1761 tao
        endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer, parentNode);
252 1411 tao
        // rest hitTextNode
253
        hitTextNode =false;
254
        // reset textbuffer
255
        textBuffer = null;
256
        textBuffer = new StringBuffer();
257
258
     }
259 18 jones
260 203 jones
     // Document representation that points to the root document node
261 1389 tao
     if (atFirstElement)
262
     {
263 204 jones
       atFirstElement = false;
264 1389 tao
       // If no DOCTYPE declaration: docname = root element
265
       // doctype = root element name or name space
266
       if (docname == null)
267
       {
268 203 jones
         docname = localName;
269 1389 tao
         // if uri isn't null doctype = uri(namespace)
270
         // othewise root element
271
         if (uri != null && !(uri.trim()).equals(""))
272
         {
273
           doctype = uri;
274
         }
275
         else
276
         {
277
           doctype = docname;
278
         }
279
         MetaCatUtil.debugMessage("DOCNAME-a: " + docname, 30);
280
         MetaCatUtil.debugMessage("DOCTYPE-a: " + doctype, 30);
281
       }
282
       else if (doctype == null)
283
       {
284
         // because docname is not null and it is declared in dtd
285
         // so could not be in schema, no namespace
286 204 jones
         doctype = docname;
287 1389 tao
         MetaCatUtil.debugMessage("DOCTYPE-b: " + doctype, 30);
288 203 jones
       }
289
       rootNode.writeNodename(docname);
290
       try {
291 697 bojilova
         // for validated XML Documents store a reference to XML DB Catalog
292 1217 tao
         // Because this is select statement and it needn't to roll back if
293
         // insert document action fialed.
294 1359 tao
         // In order to decrease DBConnection usage count, we get a new
295 1217 tao
         // dbconnection from pool
296 697 bojilova
         String catalogid = null;
297 1217 tao
         DBConnection dbConn = null;
298
         int serialNumber = -1;
299 1359 tao
300 697 bojilova
         if ( systemid != null ) {
301 1217 tao
           try
302
           {
303
            // Get dbconnection
304
            dbConn=DBConnectionPool.getDBConnection
305
                                          ("DBSAXHandler.startElement");
306
            serialNumber=dbConn.getCheckOutSerialNumber();
307 1359 tao
308 1217 tao
            Statement stmt = dbConn.createStatement();
309
            ResultSet rs = stmt.executeQuery(
310 697 bojilova
                          "SELECT catalog_id FROM xml_catalog " +
311 1359 tao
                          "WHERE entry_type = 'DTD' " +
312 697 bojilova
                          "AND public_id = '" + doctype + "'");
313 1217 tao
            boolean hasRow = rs.next();
314
            if ( hasRow ) {
315
              catalogid = rs.getString(1);
316
            }
317
            stmt.close();
318
           }//try
319
           finally
320
           {
321
             // Return dbconnection
322
             DBConnectionPool.returnDBConnection(dbConn, serialNumber);
323
           }//finally
324 697 bojilova
         }
325 1359 tao
326 955 tao
         //create documentImpl object by the constructor which can specify
327
         //the revision
328 1359 tao
         currentDocument = new DocumentImpl(connection, rootNode.getNodeID(),
329
                               docname, doctype, docid, revision, action, user,
330 697 bojilova
                               this.pub, catalogid, this.serverCode);
331 1359 tao
332
333 457 bojilova
       } catch (Exception ane) {
334 1359 tao
         throw (new SAXException("Error in DBSaxHandler.startElement " +
335 675 berkley
                                 action, ane));
336 408 jones
       }
337 1359 tao
     }
338 135 jones
339 203 jones
     // Create the current node representation
340 1217 tao
     currentNode = new DBSAXNode(connection, qName, localName, parentNode,
341 457 bojilova
                                 currentDocument.getRootNodeID(),docid,
342
                                 currentDocument.getDoctype());
343 1359 tao
344 821 bojilova
     // Add all of the namespaces
345
     String prefix;
346
     String nsuri;
347
     Enumeration prefixes = namespaces.keys();
348
     while ( prefixes.hasMoreElements() ) {
349
       prefix = (String)prefixes.nextElement();
350
       nsuri = (String)namespaces.get(prefix);
351
       currentNode.setNamespace(prefix, nsuri, docid);
352
     }
353
     namespaces = null;
354
     namespaces = new Hashtable();
355
356 203 jones
     // Add all of the attributes
357 1396 tao
     for (int i=0; i<atts.getLength(); i++)
358
     {
359
       String attributeName = atts.getQName(i);
360
       String attributeValue = atts.getValue(i);
361 1415 tao
       endNodeId =
362
                currentNode.setAttribute(attributeName, attributeValue, docid);
363 1396 tao
364
       // To handle name space and schema location if the attribute name is
365
       // xsi:schemaLocation. If the name space is in not in catalog table
366
       // it will be regeistered.
367
       if (attributeName != null &&
368
           attributeName.indexOf(MetaCatServlet.SCHEMALOCATIONKEYWORD) != -1)
369
       {
370
         SchemaLocationResolver resolver =
371
                                  new SchemaLocationResolver(attributeValue);
372
         resolver.resolveNameSpace();
373
374
       }
375 1359 tao
     }
376 17 jones
377 1359 tao
     // Add the node to the stack, so that any text data can be
378 203 jones
     // added as it is encountered
379
     nodeStack.push(currentNode);
380 471 bojilova
     // Add the node to the vector used by thread for writing XML Index
381
     nodeIndex.addElement(currentNode);
382 1590 tao
     // start parsing triple
383
     if ( doctype != null &&
384
         MetaCatUtil.getOptionList(MetaCatUtil.getOption("packagedoctype")).contains(doctype)
385
         && localName.equals("triple"))
386
      {
387
        startParseTriple = true;
388
        hasTriple = true;
389
        currentTriple = new Triple();
390
      }
391 203 jones
  }
392 1359 tao
393 819 bojilova
  /* The run method of xmlIndex thread. It writes XML Index for the document. */
394 471 bojilova
  public void run () {
395
    DBSAXNode currNode = null;
396
    DBSAXNode prevNode = null;
397 1217 tao
    DBConnection dbConn = null;
398
    int serialNumber = -1;
399 638 bojilova
    String doctype = currentDocument.getDoctype();
400 471 bojilova
    int step = 0;
401
    int counter = 0;
402 17 jones
403 1841 tao
    try
404
    {
405
      // stop 5 second
406
      Thread.sleep(5000);
407 471 bojilova
      // Opening separate db connection for writing XML Index
408 1217 tao
      dbConn=DBConnectionPool.getDBConnection("DBSAXHandler.run");
409
      serialNumber=dbConn.getCheckOutSerialNumber();
410
      dbConn.setAutoCommit(false);
411 1841 tao
      //make sure record is done
412
      checkDocumentTable();
413
      // Going through the elements of the document and writing its Index
414
      Enumeration nodes = nodeIndex.elements();
415
      while ( nodes.hasMoreElements() ) {
416
        currNode = (DBSAXNode)nodes.nextElement();
417
        currNode.updateNodeIndex(dbConn, docid, doctype);
418
      }
419
      dbConn.commit();
420 1359 tao
421 1841 tao
    } catch (Exception e) {
422
      try {
423
        dbConn.rollback();
424
        //dbconn.close();
425
      } catch (SQLException sqle) {}
426
      MetaCatUtil.debugMessage("Error in DBSAXHandler.run " +
427
                                e.getMessage(), 30);
428
429
    }
430
    finally
431
    {
432
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
433
    }//finally
434
  }
435
436
  /* method to make sure insert is finished before create index table
437
   * If new version of record is in xml_documents every thing will be fine
438
   */
439
  private void checkDocumentTable() throws Exception
440
  {
441
442
    DBConnection dbConn = null;
443
    int serialNumber = -1;
444
445
    try
446
    {
447
       // Opening separate db connection for writing XML Index
448
      dbConn=DBConnectionPool.getDBConnection("DBSAXHandler.checkDocumentTable");
449
      serialNumber=dbConn.getCheckOutSerialNumber();
450
451 899 berkley
      //the following while loop construct checks to make sure that the docid
452
      //of the document that we are trying to index is already
453
      //in the xml_documents table.  if this is not the case, the foreign
454
      //key relationship between xml_documents and xml_index is temporarily
455
      //broken causing multiple problems.
456
      boolean inxmldoc = false;
457 1396 tao
      long startTime = System.currentTimeMillis();
458 899 berkley
      while(!inxmldoc)
459
      {
460 1841 tao
        String xmlDocumentsCheck = "select distinct docid from xml_documents" +
461
                                   " where docid ='" + docid + "' and " +
462
                                   " rev ='" + revision + "'";
463
464 1359 tao
        PreparedStatement xmlDocCheck =
465 1217 tao
                                 dbConn.prepareStatement(xmlDocumentsCheck);
466
        // Increase usage count
467
        dbConn.increaseUsageCount(1);
468 899 berkley
        xmlDocCheck.execute();
469
        ResultSet doccheckRS = xmlDocCheck.getResultSet();
470
        boolean tableHasRows = doccheckRS.next();
471 1841 tao
        if (tableHasRows)
472 899 berkley
        {
473 1841 tao
           MetaCatUtil.debugMessage("=========== find the correct document", 35);
474
           inxmldoc = true;
475 899 berkley
        }
476 1841 tao
         doccheckRS.close();
477
         xmlDocCheck.close();
478
         // make sure the while loop will be ended in reseaonable time
479
         long stopTime = System.currentTimeMillis();
480
         if ((stopTime - startTime) > INDEXDELAY)
481
         {
482
           throw new Exception("Couldn't find the docid for index build in" +
483 1396 tao
                              "reseaonable time!");
484 1841 tao
         }
485
       }//while
486
    }
487
    catch (Exception e)
488
    {
489
      try
490
      {
491 1217 tao
        dbConn.rollback();
492
        //dbconn.close();
493 1841 tao
      }
494
      catch (SQLException sqle)
495
      {}
496 1396 tao
      MetaCatUtil.debugMessage("Error in DBSAXHandler.run " +
497
                                e.getMessage(), 30);
498
499 1217 tao
    }
500
    finally
501
    {
502
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
503 1359 tao
    }//finally
504 1841 tao
505 471 bojilova
  }
506 1841 tao
507 460 bojilova
  /** SAX Handler that is called for each XML text node */
508 1411 tao
  public void characters(char[] cbuf, int start, int len) throws SAXException
509
  {
510 1518 tao
     MetaCatUtil.debugMessage("CHARACTERS", 50);
511 1411 tao
     // buffer all text nodes for same element. This is for text was splited
512
     // into different nodes
513
     textBuffer.append(new String(cbuf, start,len));
514
     // set hittextnode true
515
     hitTextNode = true;
516 1761 tao
     // if text buffer .size is greater than max, write it to db.
517
     // so we can save memory
518
     if (textBuffer.length() > MAXDATACHARS)
519
     {
520
       MetaCatUtil.debugMessage("Write text into DB in charaters" +
521
                   " when text buffer size is greater than maxmum number", 50);
522
       DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
523
       endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer, currentNode);
524
       textBuffer = null;
525
       textBuffer = new StringBuffer();
526
     }
527 1411 tao
  }
528 1359 tao
529
   /**
530 660 bojilova
    * SAX Handler that is called for each XML text node that is
531
    * Ignorable white space
532 31 jones
    */
533 660 bojilova
   public void ignorableWhitespace(char[] cbuf, int start, int len)
534
               throws SAXException {
535
     // When validation is turned "on", white spaces are reported here
536
     // When validation is turned "off" white spaces are not reported here,
537
     // but through characters() callback
538 1062 tao
     MetaCatUtil.debugMessage("IGNORABLEWHITESPACE", 50);
539 660 bojilova
540 1359 tao
541 660 bojilova
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
542
     String data = null;
543
     int leftover = len;
544
     int offset = start;
545
     boolean moredata = true;
546 1359 tao
547
     // This loop deals with the case where there are more characters
548
     // than can fit in a single database text field (limit is
549 660 bojilova
     // MAXDATACHARS).  If the text to be inserted exceeds MAXDATACHARS,
550
     // write a series of nodes that are MAXDATACHARS long, and then the
551
     // final node contains the remainder
552
     while (moredata) {
553
       if (leftover > MAXDATACHARS) {
554
         data = new String(cbuf, offset, MAXDATACHARS);
555
         leftover -= MAXDATACHARS;
556
         offset += MAXDATACHARS;
557
       } else {
558
         data = new String(cbuf, offset, leftover);
559
         moredata = false;
560
       }
561
562
       // Write the content of the node to the database
563 1415 tao
       endNodeId = currentNode.writeChildNodeToDB("TEXT", null, data, docid);
564 660 bojilova
     }
565 17 jones
   }
566
567 1359 tao
   /**
568
    * SAX Handler called once for each processing instruction found:
569 122 jones
    * node that PI may occur before or after the root element.
570
    */
571 1359 tao
   public void processingInstruction(String target, String data)
572 122 jones
          throws SAXException {
573 1062 tao
     MetaCatUtil.debugMessage("PI", 50);
574 186 jones
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
575 1415 tao
     endNodeId = currentNode.writeChildNodeToDB("PI", target, data, docid);
576 92 bojilova
   }
577 72 bojilova
578 31 jones
   /** SAX Handler that is called at the end of each XML element */
579 185 jones
   public void endElement(String uri, String localName,
580
                          String qName) throws SAXException {
581 1062 tao
     MetaCatUtil.debugMessage("End ELEMENT " + qName, 50);
582 1411 tao
583
     // write buffered text nodes into db (so no splited)
584
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
585
586
     // If before the end element, the parser hit text nodes and store them
587
     // into the buffer, write the buffer to data base. The reason we put
588
     // write database here is for xerces some time split text node
589
     if (hitTextNode)
590
     {
591
       MetaCatUtil.debugMessage("Write text into DB in End Element", 50);
592 1761 tao
       endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer, currentNode);
593 1590 tao
594
       //if it is triple parsing process
595
       if (startParseTriple)
596
       {
597
598
          String content = textBuffer.toString().trim();
599
          if(localName.equals("subject"))
600
          { //get the subject content
601
            currentTriple.setSubject(content);
602
          }
603
          else if(localName.equals("relationship"))
604
          { //get the relationship content
605
            currentTriple.setRelationship(content);
606
          }
607
          else if(localName.equals("object"))
608
          { //get the object content
609
            currentTriple.setObject(content);
610
          }
611
       }
612
613 1411 tao
     }//if
614
615
     //set hitText false
616
     hitTextNode = false;
617
     // reset textbuff
618
     textBuffer = null;
619
     textBuffer = new StringBuffer();
620 17 jones
621 185 jones
     // Get the node from the stack
622 1411 tao
     currentNode = (DBSAXNode)nodeStack.pop();
623 1590 tao
     //finishing parsing single triple
624
     if (startParseTriple && localName.equals("triple"))
625
      {
626
        // add trip to triple collection
627
        tripleList.addTriple(currentTriple);
628
        //rest variable
629
        currentTriple = null;
630
        startParseTriple = false;
631
      }
632 17 jones
   }
633
634 185 jones
   //
635
   // the next section implements the LexicalHandler interface
636
   //
637
638
   /** SAX Handler that receives notification of DOCTYPE. Sets the DTD */
639 1359 tao
   public void startDTD(String name, String publicId, String systemId)
640 185 jones
               throws SAXException {
641
     docname = name;
642
     doctype = publicId;
643
     systemid = systemId;
644
645 1359 tao
     processingDTD = true;
646 1802 tao
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
647
     //create a DTD node and write docname,publicid and system id into db
648
     // we don't put the dtd node into node stack
649
     DBSAXNode dtdNode = new DBSAXNode (connection, name, publicId, systemId,
650
                               currentNode, currentNode.getRootNodeID(), docid);
651 1062 tao
     MetaCatUtil.debugMessage("Start DTD", 50);
652 1359 tao
     MetaCatUtil.debugMessage("Setting processingDTD to true", 50);
653 1062 tao
     MetaCatUtil.debugMessage("DOCNAME: " + docname, 50);
654
     MetaCatUtil.debugMessage("DOCTYPE: " + doctype, 50);
655
     MetaCatUtil.debugMessage("  SYSID: " + systemid, 50);
656 185 jones
   }
657
658 1359 tao
   /**
659
    * SAX Handler that receives notification of end of DTD
660 185 jones
    */
661
   public void endDTD() throws SAXException {
662 1359 tao
663 1364 tao
     processingDTD = false;
664 1359 tao
     MetaCatUtil.debugMessage("Setting processingDTD to false", 50);
665 1062 tao
     MetaCatUtil.debugMessage("end DTD", 50);
666 185 jones
   }
667
668 1359 tao
   /**
669 185 jones
    * SAX Handler that receives notification of comments in the DTD
670
    */
671
   public void comment(char[] ch, int start, int length) throws SAXException {
672 1062 tao
     MetaCatUtil.debugMessage("COMMENT", 50);
673 660 bojilova
     if ( !processingDTD ) {
674
       DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
675 1415 tao
       endNodeId =
676 1440 tao
        currentNode.writeChildNodeToDB("COMMENT", null,
677
                                       new String(ch, start, length), docid);
678 660 bojilova
     }
679 185 jones
   }
680
681 1359 tao
   /**
682 185 jones
    * SAX Handler that receives notification of the start of CDATA sections
683
    */
684
   public void startCDATA() throws SAXException {
685 1062 tao
     MetaCatUtil.debugMessage("start CDATA", 50);
686 185 jones
   }
687
688 1359 tao
   /**
689 185 jones
    * SAX Handler that receives notification of the end of CDATA sections
690
    */
691
   public void endCDATA() throws SAXException {
692 1062 tao
     MetaCatUtil.debugMessage("end CDATA", 50);
693 185 jones
   }
694
695 1359 tao
   /**
696 185 jones
    * SAX Handler that receives notification of the start of entities
697
    */
698
   public void startEntity(String name) throws SAXException {
699 1062 tao
     MetaCatUtil.debugMessage("start ENTITY: " + name, 50);
700 697 bojilova
//System.out.println("start ENTITY: " + name);
701 243 jones
     if (name.equals("[dtd]")) {
702
       processingDTD = true;
703
     }
704 185 jones
   }
705
706 1359 tao
   /**
707 185 jones
    * SAX Handler that receives notification of the end of entities
708
    */
709
   public void endEntity(String name) throws SAXException {
710 1062 tao
     MetaCatUtil.debugMessage("end ENTITY: " + name, 50);
711 697 bojilova
//System.out.println("end ENTITY: " + name);
712 243 jones
     if (name.equals("[dtd]")) {
713
       processingDTD = false;
714
     }
715 185 jones
   }
716 186 jones
717 1359 tao
   /**
718 186 jones
    * SAX Handler that receives notification of element declarations
719
    */
720
   public void elementDecl(String name, String model)
721
                        throws org.xml.sax.SAXException {
722 697 bojilova
//System.out.println("ELEMENTDECL: " + name + " " + model);
723 1062 tao
     MetaCatUtil.debugMessage("ELEMENTDECL: " + name + " " + model, 50);
724 186 jones
   }
725
726 1359 tao
   /**
727 186 jones
    * SAX Handler that receives notification of attribute declarations
728
    */
729
   public void attributeDecl(String eName, String aName,
730
                        String type, String valueDefault, String value)
731
                        throws org.xml.sax.SAXException {
732 821 bojilova
733 1359 tao
//System.out.println("ATTRIBUTEDECL: " + eName + " "
734 697 bojilova
//                        + aName + " " + type + " " + valueDefault + " "
735
//                        + value);
736 1359 tao
     MetaCatUtil.debugMessage("ATTRIBUTEDECL: " + eName + " "
737 243 jones
                        + aName + " " + type + " " + valueDefault + " "
738 1062 tao
                        + value, 50);
739 186 jones
   }
740
741 1359 tao
   /**
742 186 jones
    * SAX Handler that receives notification of internal entity declarations
743
    */
744
   public void internalEntityDecl(String name, String value)
745
                        throws org.xml.sax.SAXException {
746 697 bojilova
//System.out.println("INTERNENTITYDECL: " + name + " " + value);
747 1062 tao
     MetaCatUtil.debugMessage("INTERNENTITYDECL: " + name + " " + value, 50);
748 186 jones
   }
749
750 1359 tao
   /**
751 186 jones
    * SAX Handler that receives notification of external entity declarations
752
    */
753
   public void externalEntityDecl(String name, String publicId,
754
                        String systemId)
755
                        throws org.xml.sax.SAXException {
756 1359 tao
//System.out.println("EXTERNENTITYDECL: " + name + " " + publicId
757 697 bojilova
//                              + " " + systemId);
758 1359 tao
     MetaCatUtil.debugMessage("EXTERNENTITYDECL: " + name + " " + publicId
759 1062 tao
                              + " " + systemId, 50);
760 831 bojilova
     // it processes other external entity, not the DTD;
761
     // it doesn't signal for the DTD here
762
     processingDTD = false;
763 186 jones
   }
764
765 204 jones
   //
766
   // the next section implements the ErrorHandler interface
767
   //
768 186 jones
769 1359 tao
   /**
770 204 jones
    * SAX Handler that receives notification of fatal parsing errors
771
    */
772
   public void fatalError(SAXParseException exception) throws SAXException {
773 1462 tao
     MetaCatUtil.debugMessage("FATALERROR: "+exception.getMessage(), 50);
774 204 jones
     throw (new SAXException("Fatal processing error.", exception));
775
   }
776
777 1359 tao
   /**
778 204 jones
    * SAX Handler that receives notification of recoverable parsing errors
779
    */
780
   public void error(SAXParseException exception) throws SAXException {
781 1465 tao
     MetaCatUtil.debugMessage("ERROR: "+exception.getMessage(), 50);
782 660 bojilova
     throw (new SAXException("Processing error.", exception));
783 204 jones
   }
784
785 1359 tao
   /**
786 204 jones
    * SAX Handler that receives notification of warnings
787
    */
788
   public void warning(SAXParseException exception) throws SAXException {
789 1465 tao
     MetaCatUtil.debugMessage("WARNING: "+exception.getMessage(), 50);
790 660 bojilova
     throw (new SAXException("Warning.", exception));
791 204 jones
   }
792
793 1359 tao
   //
794 204 jones
   // Helper, getter and setter methods
795
   //
796 1359 tao
797 204 jones
   /**
798
    * get the document name
799
    */
800
   public String getDocname() {
801
     return docname;
802
   }
803
804
   /**
805
    * get the document processing state
806
    */
807 243 jones
   public boolean processingDTD() {
808
     return processingDTD;
809 204 jones
   }
810 1411 tao
811
   /* Method to write a text buffer for DBSAXNode*/
812 1761 tao
   protected long writeTextForDBSAXNode(long previousEndNodeId,
813
                                        StringBuffer strBuffer, DBSAXNode node)
814
                                        throws SAXException
815 1411 tao
   {
816 1761 tao
     long nodeId = previousEndNodeId;
817 1411 tao
     // Check parameter
818
     if ( strBuffer == null || node == null)
819
     {
820 1415 tao
       return nodeId;
821 1411 tao
     }
822
     boolean moredata = true;
823
     String data = null;
824
     int bufferSize = strBuffer.length();
825
     int start = 0;
826
827
     // if there are some cotent in buffer, write it
828
     if (bufferSize > 0)
829
     {
830
       MetaCatUtil.debugMessage("Write text into DB", 50);
831
       // This loop deals with the case where there are more characters
832
       // than can fit in a single database text field (limit is
833
       // MAXDATACHARS).  If the text to be inserted exceeds MAXDATACHARS,
834
       // write a series of nodes that are MAXDATACHARS long, and then the
835
       // final node contains the remainder
836
       while (moredata)
837
       {
838
          bufferSize = strBuffer.length();
839
          if (bufferSize > MAXDATACHARS)
840
         {
841
            data = strBuffer.substring(start, MAXDATACHARS);
842
            // cut the stringbuffer part that already written into db
843
            strBuffer = strBuffer.delete(start, MAXDATACHARS);
844
          }
845
          else
846
          {
847
            data = strBuffer.substring(start, bufferSize);
848
            moredata = false;
849
          }
850
851
          // Write the content of the node to the database
852 1415 tao
          nodeId = node.writeChildNodeToDB("TEXT", null, data, docid);
853 1411 tao
        }//while
854
     }//if
855 1415 tao
     return nodeId;
856 1411 tao
   }
857 17 jones
}