Project

General

Profile

1 15 jones
/**
2 203 jones
 *  '$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 349 jones
 *    Release: @release@
8 15 jones
 *
9 203 jones
 *   '$Author$'
10
 *     '$Date$'
11
 * '$Revision$'
12 15 jones
 */
13
14 75 jones
package edu.ucsb.nceas.metacat;
15 15 jones
16
import java.sql.*;
17
import java.io.IOException;
18
import java.util.Hashtable;
19
import java.util.Enumeration;
20 457 bojilova
import oracle.jdbc.driver.*;
21 461 bojilova
import org.xml.sax.SAXException;
22 15 jones
23 31 jones
/**
24 137 jones
 * A Class that represents an XML node and its contents and
25 31 jones
 * can write its own representation to a database connection
26
 */
27 137 jones
public class DBSAXNode extends BasicNode {
28 15 jones
29 176 jones
  private Connection	conn;
30
  private DBSAXNode	parentNode;
31 15 jones
32 133 jones
  /**
33 136 jones
   * Construct a new node instance for DOCUMENT nodes
34 133 jones
   *
35
   * @param conn the JDBC Connection to which all information is written
36
   */
37 461 bojilova
  public DBSAXNode (Connection conn, String docid) throws SAXException {
38 408 jones
    super();
39 136 jones
    this.conn = conn;
40 176 jones
    this.parentNode = null;
41 457 bojilova
    writeChildNodeToDB("DOCUMENT", null, null, docid);
42 136 jones
  }
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 176 jones
  public DBSAXNode (Connection conn, String tagname, DBSAXNode parentNode,
52 461 bojilova
                    long rootnodeid, String docid, String doctype)
53
                    throws SAXException {
54 21 jones
55 136 jones
    super(tagname);
56
    setParentID(parentNode.getNodeID());
57 457 bojilova
    setRootNodeID(rootnodeid);
58
    setDocID(docid);
59 136 jones
    setNodeIndex(parentNode.incChildNum());
60 133 jones
    this.conn = conn;
61 176 jones
    this.parentNode = parentNode;
62 457 bojilova
    writeChildNodeToDB("ELEMENT", getTagName(), null, docid);
63 471 bojilova
    //No writing XML Index from here. New Thread used instead.
64
    //updateNodeIndex(docid, doctype);
65 133 jones
  }
66 15 jones
67 133 jones
  /** creates SQL code and inserts new node into DB connection */
68
  public void writeChildNodeToDB(String nodetype, String nodename,
69 461 bojilova
                                 String data, String docid)
70
                                 throws SAXException {
71 133 jones
    try {
72
      PreparedStatement pstmt;
73
      if (nodetype == "DOCUMENT") {
74
        pstmt = conn.prepareStatement(
75
            "INSERT INTO xml_nodes " +
76 457 bojilova
            "(nodeid, nodetype, nodename, docid, rootnodeid) " +
77
            "VALUES (?, ?, ?, ?, ?)");
78 204 jones
        MetaCatUtil.debugMessage("INSERTING DOCNAME: " + nodename);
79 133 jones
      } else {
80
        pstmt = conn.prepareStatement(
81
            "INSERT INTO xml_nodes " +
82 457 bojilova
            "(nodeid, nodetype, nodename, docid, " +
83
            "rootnodeid, parentnodeid, nodedata, nodeindex) " +
84 174 bojilova
            "VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
85 133 jones
      }
86 19 jones
87 133 jones
      // Bind the values to the query
88 176 jones
      long nid = generateNodeID();
89 174 bojilova
      pstmt.setLong(1, nid);
90
      pstmt.setString(2, nodetype);
91
      pstmt.setString(3, nodename);
92 457 bojilova
      pstmt.setString(4, docid);
93 408 jones
      if (nodetype == "DOCUMENT") {
94 457 bojilova
        pstmt.setLong(5, nid);
95 408 jones
      } else {
96 133 jones
        if (nodetype == "ELEMENT") {
97 457 bojilova
          pstmt.setLong(5, getRootNodeID());
98
          pstmt.setLong(6, getParentID());
99 174 bojilova
          pstmt.setString(7, data);
100
          pstmt.setInt(8, getNodeIndex());
101 133 jones
        } else {
102 457 bojilova
          pstmt.setLong(5, getRootNodeID());
103
          pstmt.setLong(6, getNodeID());
104 452 bojilova
          if ( nodetype == "TEXT" && getTagName().equals("meta_file_id") ) {
105
            pstmt.setString(7, getDocID());
106
          } else {
107
            pstmt.setString(7, data);
108
          }
109 174 bojilova
          pstmt.setInt(8, incChildNum());
110 72 bojilova
        }
111 133 jones
      }
112
      // Do the insertion
113
      pstmt.execute();
114
      pstmt.close();
115 174 bojilova
116 408 jones
      if (nodetype.equals("DOCUMENT")) {
117
        // Record the root node id that was generated from the database
118
        setRootNodeID(nid);
119
      }
120
121 177 jones
      if (nodetype.equals("DOCUMENT") || nodetype.equals("ELEMENT")) {
122 176 jones
123 177 jones
        // Record the node id that was generated from the database
124
        setNodeID(nid);
125 176 jones
126 177 jones
        // Record the node type that was passed to the method
127
        setNodeType(nodetype);
128
129
      }
130
131 133 jones
    } catch (SQLException e) {
132
      System.err.println("Error inserting node: (" + nodetype + ", " +
133
                                                     nodename + ", " +
134 136 jones
                                                     data + ")" );
135 133 jones
      System.err.println(e.getMessage());
136 461 bojilova
      throw new SAXException(e.getMessage());
137 110 bojilova
    }
138 133 jones
  }
139 110 bojilova
140 133 jones
  /**
141
   * creates SQL code to put nodename for the document node
142
   * into DB connection
143
   */
144 461 bojilova
  public void writeNodename(String nodename) throws SAXException {
145 133 jones
      try {
146
        PreparedStatement pstmt;
147
        pstmt = conn.prepareStatement(
148
              "UPDATE xml_nodes set nodename = ? " +
149
              "WHERE nodeid = ?");
150 16 jones
151 133 jones
        // Bind the values to the query
152
        pstmt.setString(1, nodename);
153 134 jones
        pstmt.setLong(2, getNodeID());
154 133 jones
        // Do the insertion
155
        pstmt.execute();
156
        pstmt.close();
157
      } catch (SQLException e) {
158
        System.out.println(e.getMessage());
159 461 bojilova
        throw new SAXException(e.getMessage());
160 133 jones
      }
161
  }
162 16 jones
163 174 bojilova
  /** get next node id from DB connection */
164 461 bojilova
  private long generateNodeID() throws SAXException {
165 174 bojilova
      long nid=0;
166 133 jones
      Statement stmt;
167
      try {
168
        stmt = conn.createStatement();
169 174 bojilova
        stmt.execute("SELECT xml_nodes_id_seq.nextval FROM dual");
170 133 jones
        ResultSet rs = stmt.getResultSet();
171
        boolean tableHasRows = rs.next();
172
        if (tableHasRows) {
173 174 bojilova
          nid = rs.getLong(1);
174 19 jones
        }
175 133 jones
        stmt.close();
176
      } catch (SQLException e) {
177
        System.out.println("Error getting id: " + e.getMessage());
178 461 bojilova
        throw new SAXException(e.getMessage());
179 15 jones
      }
180
181 174 bojilova
      return nid;
182 133 jones
  }
183 18 jones
184 137 jones
  /** Add a new attribute to this node, or set its value */
185 461 bojilova
  public void setAttribute(String attName, String attValue, String docid)
186
              throws SAXException {
187 133 jones
    if (attName != null) {
188
      // Enter the attribute in the hash table
189
      super.setAttribute(attName, attValue);
190 18 jones
191 133 jones
      // And enter the attribute in the database
192 457 bojilova
      writeChildNodeToDB("ATTRIBUTE", attName, attValue, docid);
193 133 jones
    } else {
194
      System.err.println("Attribute name must not be null!");
195 461 bojilova
      throw new SAXException("Attribute name must not be null!");
196 18 jones
    }
197 133 jones
  }
198 176 jones
199
  /**
200 471 bojilova
   * NOT USED
201 176 jones
   * 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 461 bojilova
  private void updateNodeIndex(String docid, String doctype)
206
               throws SAXException
207
  {
208 176 jones
    Hashtable pathlist = new Hashtable();
209
    boolean atStartingNode = true;
210
    boolean atRootDocumentNode = false;
211
    DBSAXNode nodePointer = this;
212
    StringBuffer currentPath = new StringBuffer();
213 457 bojilova
    int counter = 0;
214 176 jones
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 457 bojilova
        counter++;
222 176 jones
        atStartingNode = false;
223
      } else {
224
        currentPath.insert(0, "/");
225
        currentPath.insert(0, nodePointer.getTagName());
226
        pathlist.put(currentPath.toString(), new Long(getNodeID()));
227 457 bojilova
        counter++;
228 176 jones
      }
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 457 bojilova
        counter++;
239 176 jones
        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 449 berkley
              "INSERT INTO xml_index (nodeid, path, docid, doctype, " +
247
               "parentnodeid) " +
248
              "VALUES (?, ?, ?, ?, ?)");
249 457 bojilova
      ((OraclePreparedStatement)pstmt).setExecuteBatch(counter);
250 176 jones
251 314 bojilova
      pstmt.setString(3, docid);
252
      pstmt.setString(4, doctype);
253 449 berkley
      pstmt.setLong(5, getParentID());
254 314 bojilova
255 176 jones
      // Step through the hashtable and insert each of the path values
256 471 bojilova
      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 176 jones
      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 457 bojilova
        pstmt.executeUpdate();
340 176 jones
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 461 bojilova
      throw new SAXException(sqe.getMessage());
350 176 jones
    }
351
  }
352
353
  /** get the parent of this node */
354
  public DBSAXNode getParentNode() {
355
    return parentNode;
356
  }
357 15 jones
}