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