Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that represents an XML node and its contents
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Matt Jones
7
 *    Release: @release@
8
 *
9
 *   '$Author: bojilova $'
10
 *     '$Date: 2000-09-26 16:02:11 -0700 (Tue, 26 Sep 2000) $'
11
 * '$Revision: 471 $'
12
 */
13

    
14
package edu.ucsb.nceas.metacat;
15

    
16
import java.sql.*;
17
import java.io.IOException;
18
import java.util.Hashtable;
19
import java.util.Enumeration;
20
import oracle.jdbc.driver.*;
21
import org.xml.sax.SAXException;
22

    
23
/** 
24
 * A Class that represents an XML node and its contents and
25
 * can write its own representation to a database connection
26
 */
27
public class DBSAXNode extends BasicNode {
28

    
29
  private Connection	conn;
30
  private DBSAXNode	parentNode;
31

    
32
  /** 
33
   * Construct a new node instance for DOCUMENT nodes
34
   *
35
   * @param conn the JDBC Connection to which all information is written
36
   */
37
  public DBSAXNode (Connection conn, String docid) throws SAXException {
38
    super();
39
    this.conn = conn;
40
    this.parentNode = null;
41
    writeChildNodeToDB("DOCUMENT", null, null, docid);
42
  }
43

    
44
  /** 
45
   * Construct a new node instance for ELEMENT nodes
46
   *
47
   * @param conn the JDBC Connection to which all information is written
48
   * @param tagname the name of the node
49
   * @param parentNode the parent node for this node being created
50
   */
51
  public DBSAXNode (Connection conn, String tagname, DBSAXNode parentNode, 
52
                    long rootnodeid, String docid, String doctype) 
53
                    throws SAXException {
54

    
55
    super(tagname);
56
    setParentID(parentNode.getNodeID());
57
    setRootNodeID(rootnodeid);
58
    setDocID(docid);
59
    setNodeIndex(parentNode.incChildNum());
60
    this.conn = conn;
61
    this.parentNode = parentNode;
62
    writeChildNodeToDB("ELEMENT", getTagName(), null, docid);
63
    //No writing XML Index from here. New Thread used instead.
64
    //updateNodeIndex(docid, doctype);
65
  }
66
    
67
  /** creates SQL code and inserts new node into DB connection */
68
  public void writeChildNodeToDB(String nodetype, String nodename,
69
                                 String data, String docid) 
70
                                 throws SAXException {
71
    try {
72
      PreparedStatement pstmt;
73
      if (nodetype == "DOCUMENT") {
74
        pstmt = conn.prepareStatement(
75
            "INSERT INTO xml_nodes " +
76
            "(nodeid, nodetype, nodename, docid, rootnodeid) " +
77
            "VALUES (?, ?, ?, ?, ?)");
78
        MetaCatUtil.debugMessage("INSERTING DOCNAME: " + nodename);
79
      } else {
80
        pstmt = conn.prepareStatement(
81
            "INSERT INTO xml_nodes " +
82
            "(nodeid, nodetype, nodename, docid, " +
83
            "rootnodeid, parentnodeid, nodedata, nodeindex) " +
84
            "VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
85
      }
86

    
87
      // Bind the values to the query
88
      long nid = generateNodeID();
89
      pstmt.setLong(1, nid);
90
      pstmt.setString(2, nodetype);
91
      pstmt.setString(3, nodename);
92
      pstmt.setString(4, docid);
93
      if (nodetype == "DOCUMENT") {
94
        pstmt.setLong(5, nid);
95
      } else {
96
        if (nodetype == "ELEMENT") {
97
          pstmt.setLong(5, getRootNodeID());
98
          pstmt.setLong(6, getParentID());
99
          pstmt.setString(7, data);
100
          pstmt.setInt(8, getNodeIndex());
101
        } else {
102
          pstmt.setLong(5, getRootNodeID());
103
          pstmt.setLong(6, getNodeID());
104
          if ( nodetype == "TEXT" && getTagName().equals("meta_file_id") ) {
105
            pstmt.setString(7, getDocID());
106
          } else {
107
            pstmt.setString(7, data);
108
          }  
109
          pstmt.setInt(8, incChildNum());
110
        }
111
      }
112
      // Do the insertion
113
      pstmt.execute();
114
      pstmt.close();
115
      
116
      if (nodetype.equals("DOCUMENT")) {
117
        // Record the root node id that was generated from the database
118
        setRootNodeID(nid);
119
      }
120

    
121
      if (nodetype.equals("DOCUMENT") || nodetype.equals("ELEMENT")) {
122

    
123
        // Record the node id that was generated from the database
124
        setNodeID(nid);
125

    
126
        // Record the node type that was passed to the method
127
        setNodeType(nodetype);
128

    
129
      }
130

    
131
    } catch (SQLException e) {
132
      System.err.println("Error inserting node: (" + nodetype + ", " +
133
                                                     nodename + ", " + 
134
                                                     data + ")" );
135
      System.err.println(e.getMessage());
136
      throw new SAXException(e.getMessage());
137
    }
138
  }
139

    
140
  /** 
141
   * creates SQL code to put nodename for the document node 
142
   * into DB connection 
143
   */
144
  public void writeNodename(String nodename) throws SAXException {
145
      try {
146
        PreparedStatement pstmt;
147
        pstmt = conn.prepareStatement(
148
              "UPDATE xml_nodes set nodename = ? " +
149
              "WHERE nodeid = ?");
150

    
151
        // Bind the values to the query
152
        pstmt.setString(1, nodename);
153
        pstmt.setLong(2, getNodeID());
154
        // Do the insertion
155
        pstmt.execute();
156
        pstmt.close();
157
      } catch (SQLException e) {
158
        System.out.println(e.getMessage());
159
        throw new SAXException(e.getMessage());
160
      }
161
  }
162

    
163
  /** get next node id from DB connection */
164
  private long generateNodeID() throws SAXException {
165
      long nid=0;
166
      Statement stmt;
167
      try {
168
        stmt = conn.createStatement();
169
        stmt.execute("SELECT xml_nodes_id_seq.nextval FROM dual");
170
        ResultSet rs = stmt.getResultSet();
171
        boolean tableHasRows = rs.next();
172
        if (tableHasRows) {
173
          nid = rs.getLong(1);
174
        }
175
        stmt.close();
176
      } catch (SQLException e) {
177
        System.out.println("Error getting id: " + e.getMessage());
178
        throw new SAXException(e.getMessage());
179
      }
180

    
181
      return nid;
182
  }
183

    
184
  /** Add a new attribute to this node, or set its value */
185
  public void setAttribute(String attName, String attValue, String docid)
186
              throws SAXException {
187
    if (attName != null) {
188
      // Enter the attribute in the hash table
189
      super.setAttribute(attName, attValue);
190

    
191
      // And enter the attribute in the database
192
      writeChildNodeToDB("ATTRIBUTE", attName, attValue, docid);
193
    } else {
194
      System.err.println("Attribute name must not be null!");
195
      throw new SAXException("Attribute name must not be null!");
196
    }
197
  }
198

    
199
  /** 
200
   * NOT USED
201
   * Update the node index (xml_index) for this node by generating
202
   * test strings that represent all of the relative and absolute
203
   * paths through the XML tree from document root to this node
204
   */
205
  private void updateNodeIndex(String docid, String doctype) 
206
               throws SAXException
207
  {
208
    Hashtable pathlist = new Hashtable();
209
    boolean atStartingNode = true;
210
    boolean atRootDocumentNode = false;
211
    DBSAXNode nodePointer = this;
212
    StringBuffer currentPath = new StringBuffer();
213
    int counter = 0;
214

    
215
    // Create a Hashtable of all of the paths to reach this node
216
    // including absolute paths and relative paths
217
    while (!atRootDocumentNode) {
218
      if (atStartingNode) {
219
        currentPath.insert(0, nodePointer.getTagName());
220
        pathlist.put(currentPath.toString(), new Long(getNodeID()));
221
        counter++;
222
        atStartingNode = false;
223
      } else {
224
        currentPath.insert(0, "/");
225
        currentPath.insert(0, nodePointer.getTagName());
226
        pathlist.put(currentPath.toString(), new Long(getNodeID()));
227
        counter++;
228
      }
229

    
230
      // advance to the next parent node
231
      nodePointer = nodePointer.getParentNode();
232

    
233
      // If we're at the DOCUMENT node (root of DOM tree), add
234
      // the root "/" to make the absolute path
235
      if (nodePointer.getNodeType().equals("DOCUMENT")) {
236
        currentPath.insert(0, "/");
237
        pathlist.put(currentPath.toString(), new Long(getNodeID()));
238
        counter++;
239
        atRootDocumentNode = true;
240
      } 
241
    }
242

    
243
    try {
244
      // Create an insert statement to reuse for all of the path insertions
245
      PreparedStatement pstmt = conn.prepareStatement(
246
              "INSERT INTO xml_index (nodeid, path, docid, doctype, " + 
247
               "parentnodeid) " + 
248
              "VALUES (?, ?, ?, ?, ?)");
249
      ((OraclePreparedStatement)pstmt).setExecuteBatch(counter);
250
  
251
      pstmt.setString(3, docid);
252
      pstmt.setString(4, doctype);
253
      pstmt.setLong(5, getParentID());
254
      
255
      // Step through the hashtable and insert each of the path values
256
      Enumeration en = pathlist.keys();
257
      while (en.hasMoreElements()) {
258
        String path = (String)en.nextElement();
259
        Long nodeid = (Long)pathlist.get(path);
260
        pstmt.setLong(1, nodeid.longValue());
261
        pstmt.setString(2, path);
262
        pstmt.executeUpdate();
263
  
264
        //System.out.println(nodeid + " ==> " + path);
265
      }
266

    
267
      // Close the database statement
268
      pstmt.close();
269
    } catch (SQLException sqe) {
270
      System.err.println("SQL Exception while inserting path to index.");
271
      System.err.println(sqe.getMessage());
272
      throw new SAXException(sqe.getMessage());
273
    }
274
  }
275

    
276
  /** 
277
   * USED FROM SEPARATE THREAD RUNNED from DBSAXHandler on endDocument()
278
   * Update the node index (xml_index) for this node by generating
279
   * test strings that represent all of the relative and absolute
280
   * paths through the XML tree from document root to this node
281
   */
282
  public void updateNodeIndex(Connection conn, String docid, String doctype) 
283
               throws SAXException
284
  {
285
    Hashtable pathlist = new Hashtable();
286
    boolean atStartingNode = true;
287
    boolean atRootDocumentNode = false;
288
    DBSAXNode nodePointer = this;
289
    StringBuffer currentPath = new StringBuffer();
290
    int counter = 0;
291

    
292
    // Create a Hashtable of all of the paths to reach this node
293
    // including absolute paths and relative paths
294
    while (!atRootDocumentNode) {
295
      if (atStartingNode) {
296
        currentPath.insert(0, nodePointer.getTagName());
297
        pathlist.put(currentPath.toString(), new Long(getNodeID()));
298
        counter++;
299
        atStartingNode = false;
300
      } else {
301
        currentPath.insert(0, "/");
302
        currentPath.insert(0, nodePointer.getTagName());
303
        pathlist.put(currentPath.toString(), new Long(getNodeID()));
304
        counter++;
305
      }
306

    
307
      // advance to the next parent node
308
      nodePointer = nodePointer.getParentNode();
309

    
310
      // If we're at the DOCUMENT node (root of DOM tree), add
311
      // the root "/" to make the absolute path
312
      if (nodePointer.getNodeType().equals("DOCUMENT")) {
313
        currentPath.insert(0, "/");
314
        pathlist.put(currentPath.toString(), new Long(getNodeID()));
315
        counter++;
316
        atRootDocumentNode = true;
317
      } 
318
    }
319

    
320
    try {
321
      // Create an insert statement to reuse for all of the path insertions
322
      PreparedStatement pstmt = conn.prepareStatement(
323
              "INSERT INTO xml_index (nodeid, path, docid, doctype, " + 
324
               "parentnodeid) " + 
325
              "VALUES (?, ?, ?, ?, ?)");
326
      ((OraclePreparedStatement)pstmt).setExecuteBatch(counter);
327
  
328
      pstmt.setString(3, docid);
329
      pstmt.setString(4, doctype);
330
      pstmt.setLong(5, getParentID());
331
      
332
      // Step through the hashtable and insert each of the path values
333
      Enumeration en = pathlist.keys();
334
      while (en.hasMoreElements()) {
335
        String path = (String)en.nextElement();
336
        Long nodeid = (Long)pathlist.get(path);
337
        pstmt.setLong(1, nodeid.longValue());
338
        pstmt.setString(2, path);
339
        pstmt.executeUpdate();
340
  
341
        //System.out.println(nodeid + " ==> " + path);
342
      }
343

    
344
      // Close the database statement
345
      pstmt.close();
346
    } catch (SQLException sqe) {
347
      System.err.println("SQL Exception while inserting path to index.");
348
      System.err.println(sqe.getMessage());
349
      throw new SAXException(sqe.getMessage());
350
    }
351
  }
352
 
353
  /** get the parent of this node */
354
  public DBSAXNode getParentNode() {
355
    return parentNode;
356
  }
357
}
(10-10/29)