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 15 jones
22 31 jones
/**
23 137 jones
 * A Class that represents an XML node and its contents and
24 31 jones
 * can write its own representation to a database connection
25
 */
26 137 jones
public class DBSAXNode extends BasicNode {
27 15 jones
28 176 jones
  private Connection	conn;
29
  private DBSAXNode	parentNode;
30 15 jones
31 133 jones
  /**
32 136 jones
   * Construct a new node instance for DOCUMENT nodes
33 133 jones
   *
34
   * @param conn the JDBC Connection to which all information is written
35
   */
36 457 bojilova
  public DBSAXNode (Connection conn, String docid) {
37 408 jones
    super();
38 136 jones
    this.conn = conn;
39 176 jones
    this.parentNode = null;
40 457 bojilova
    writeChildNodeToDB("DOCUMENT", null, null, docid);
41 136 jones
  }
42
43
  /**
44
   * Construct a new node instance for ELEMENT nodes
45
   *
46
   * @param conn the JDBC Connection to which all information is written
47
   * @param tagname the name of the node
48
   * @param parentNode the parent node for this node being created
49
   */
50 176 jones
  public DBSAXNode (Connection conn, String tagname, DBSAXNode parentNode,
51 457 bojilova
                    long rootnodeid, String docid, String doctype) {
52 21 jones
53 136 jones
    super(tagname);
54
    setParentID(parentNode.getNodeID());
55 457 bojilova
    setRootNodeID(rootnodeid);
56
    setDocID(docid);
57 136 jones
    setNodeIndex(parentNode.incChildNum());
58 133 jones
    this.conn = conn;
59 176 jones
    this.parentNode = parentNode;
60 457 bojilova
    writeChildNodeToDB("ELEMENT", getTagName(), null, docid);
61
    updateNodeIndex(docid, doctype);
62 133 jones
  }
63 15 jones
64 133 jones
  /** creates SQL code and inserts new node into DB connection */
65
  public void writeChildNodeToDB(String nodetype, String nodename,
66 457 bojilova
                                 String data, String docid) {
67 133 jones
    try {
68
      PreparedStatement pstmt;
69
      if (nodetype == "DOCUMENT") {
70
        pstmt = conn.prepareStatement(
71
            "INSERT INTO xml_nodes " +
72 457 bojilova
            "(nodeid, nodetype, nodename, docid, rootnodeid) " +
73
            "VALUES (?, ?, ?, ?, ?)");
74 204 jones
        MetaCatUtil.debugMessage("INSERTING DOCNAME: " + nodename);
75 133 jones
      } else {
76
        pstmt = conn.prepareStatement(
77
            "INSERT INTO xml_nodes " +
78 457 bojilova
            "(nodeid, nodetype, nodename, docid, " +
79
            "rootnodeid, parentnodeid, nodedata, nodeindex) " +
80 174 bojilova
            "VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
81 133 jones
      }
82 19 jones
83 133 jones
      // Bind the values to the query
84 176 jones
      long nid = generateNodeID();
85 174 bojilova
      pstmt.setLong(1, nid);
86
      pstmt.setString(2, nodetype);
87
      pstmt.setString(3, nodename);
88 457 bojilova
      pstmt.setString(4, docid);
89 408 jones
      if (nodetype == "DOCUMENT") {
90 457 bojilova
        pstmt.setLong(5, nid);
91 408 jones
      } else {
92 133 jones
        if (nodetype == "ELEMENT") {
93 457 bojilova
          pstmt.setLong(5, getRootNodeID());
94
          pstmt.setLong(6, getParentID());
95 174 bojilova
          pstmt.setString(7, data);
96
          pstmt.setInt(8, getNodeIndex());
97 133 jones
        } else {
98 457 bojilova
          pstmt.setLong(5, getRootNodeID());
99
          pstmt.setLong(6, getNodeID());
100 452 bojilova
          if ( nodetype == "TEXT" && getTagName().equals("meta_file_id") ) {
101
            pstmt.setString(7, getDocID());
102
          } else {
103
            pstmt.setString(7, data);
104
          }
105 174 bojilova
          pstmt.setInt(8, incChildNum());
106 72 bojilova
        }
107 133 jones
      }
108
      // Do the insertion
109
      pstmt.execute();
110
      pstmt.close();
111 174 bojilova
112 408 jones
      if (nodetype.equals("DOCUMENT")) {
113
        // Record the root node id that was generated from the database
114
        setRootNodeID(nid);
115
      }
116
117 177 jones
      if (nodetype.equals("DOCUMENT") || nodetype.equals("ELEMENT")) {
118 176 jones
119 177 jones
        // Record the node id that was generated from the database
120
        setNodeID(nid);
121 176 jones
122 177 jones
        // Record the node type that was passed to the method
123
        setNodeType(nodetype);
124
125
      }
126
127 133 jones
    } catch (SQLException e) {
128
      System.err.println("Error inserting node: (" + nodetype + ", " +
129
                                                     nodename + ", " +
130 136 jones
                                                     data + ")" );
131 133 jones
      System.err.println(e.getMessage());
132 110 bojilova
    }
133 133 jones
  }
134 110 bojilova
135 133 jones
  /**
136
   * creates SQL code to put nodename for the document node
137
   * into DB connection
138
   */
139
  public void writeNodename(String nodename) {
140
      try {
141
        PreparedStatement pstmt;
142
        pstmt = conn.prepareStatement(
143
              "UPDATE xml_nodes set nodename = ? " +
144
              "WHERE nodeid = ?");
145 16 jones
146 133 jones
        // Bind the values to the query
147
        pstmt.setString(1, nodename);
148 134 jones
        pstmt.setLong(2, getNodeID());
149 133 jones
        // Do the insertion
150
        pstmt.execute();
151
        pstmt.close();
152
      } catch (SQLException e) {
153
        System.out.println(e.getMessage());
154
      }
155
  }
156 16 jones
157 149 bojilova
  /**
158 176 jones
   * creates SQL code to put doc ID for the document node and for
159
   * comment/PI nodes under document node into DB connection
160 149 bojilova
   */
161 162 bojilova
  public void writeDocID(String doc_id) {
162 149 bojilova
      try {
163
        PreparedStatement pstmt;
164
        pstmt = conn.prepareStatement(
165
              "UPDATE xml_nodes set docid = ? " +
166
              "WHERE nodeid = ?");
167
168
        // Bind the values to the query
169 162 bojilova
        pstmt.setString(1, doc_id);
170 149 bojilova
        pstmt.setLong(2, getNodeID());
171
        // Do the insertion
172
        pstmt.execute();
173
        pstmt.close();
174
175
        // for comments and PI on the top
176
        pstmt = conn.prepareStatement(
177
              "UPDATE xml_nodes set docid = ? " +
178
              "WHERE parentnodeid = ?");
179
        // Bind the values to the query
180 162 bojilova
        pstmt.setString(1, doc_id);
181 149 bojilova
        pstmt.setLong(2, getNodeID());
182
        // Do the insertion
183
        pstmt.execute();
184
        pstmt.close();
185
      } catch (SQLException e) {
186
        System.out.println(e.getMessage());
187 174 bojilova
      }
188 149 bojilova
  }
189
190 174 bojilova
  /** get next node id from DB connection */
191 176 jones
  private long generateNodeID() {
192 174 bojilova
      long nid=0;
193 133 jones
      Statement stmt;
194
      try {
195
        stmt = conn.createStatement();
196 174 bojilova
        stmt.execute("SELECT xml_nodes_id_seq.nextval FROM dual");
197 133 jones
        ResultSet rs = stmt.getResultSet();
198
        boolean tableHasRows = rs.next();
199
        if (tableHasRows) {
200 174 bojilova
          nid = rs.getLong(1);
201 19 jones
        }
202 133 jones
        stmt.close();
203
      } catch (SQLException e) {
204
        System.out.println("Error getting id: " + e.getMessage());
205 15 jones
      }
206
207 174 bojilova
      return nid;
208 133 jones
  }
209 18 jones
210 137 jones
  /** Add a new attribute to this node, or set its value */
211 457 bojilova
  public void setAttribute(String attName, String attValue, String docid) {
212 133 jones
    if (attName != null) {
213
      // Enter the attribute in the hash table
214
      super.setAttribute(attName, attValue);
215 18 jones
216 133 jones
      // And enter the attribute in the database
217 457 bojilova
      writeChildNodeToDB("ATTRIBUTE", attName, attValue, docid);
218 133 jones
    } else {
219
      System.err.println("Attribute name must not be null!");
220 18 jones
    }
221 133 jones
  }
222 176 jones
223
  /**
224
   * Update the node index (xml_index) for this node by generating
225
   * test strings that represent all of the relative and absolute
226
   * paths through the XML tree from document root to this node
227
   */
228 314 bojilova
  private void updateNodeIndex(String docid, String doctype) {
229 176 jones
    Hashtable pathlist = new Hashtable();
230
    boolean atStartingNode = true;
231
    boolean atRootDocumentNode = false;
232
    DBSAXNode nodePointer = this;
233
    StringBuffer currentPath = new StringBuffer();
234 457 bojilova
    int counter = 0;
235 176 jones
236
    // Create a Hashtable of all of the paths to reach this node
237
    // including absolute paths and relative paths
238
    while (!atRootDocumentNode) {
239
      if (atStartingNode) {
240
        currentPath.insert(0, nodePointer.getTagName());
241
        pathlist.put(currentPath.toString(), new Long(getNodeID()));
242 457 bojilova
        counter++;
243 176 jones
        atStartingNode = false;
244
      } else {
245
        currentPath.insert(0, "/");
246
        currentPath.insert(0, nodePointer.getTagName());
247
        pathlist.put(currentPath.toString(), new Long(getNodeID()));
248 457 bojilova
        counter++;
249 176 jones
      }
250
251
      // advance to the next parent node
252
      nodePointer = nodePointer.getParentNode();
253
254
      // If we're at the DOCUMENT node (root of DOM tree), add
255
      // the root "/" to make the absolute path
256
      if (nodePointer.getNodeType().equals("DOCUMENT")) {
257
        currentPath.insert(0, "/");
258
        pathlist.put(currentPath.toString(), new Long(getNodeID()));
259 457 bojilova
        counter++;
260 176 jones
        atRootDocumentNode = true;
261
      }
262
    }
263
264
    try {
265
      // Create an insert statement to reuse for all of the path insertions
266
      PreparedStatement pstmt = conn.prepareStatement(
267 449 berkley
              "INSERT INTO xml_index (nodeid, path, docid, doctype, " +
268
               "parentnodeid) " +
269
              "VALUES (?, ?, ?, ?, ?)");
270 457 bojilova
      ((OraclePreparedStatement)pstmt).setExecuteBatch(counter);
271 176 jones
272 314 bojilova
      pstmt.setString(3, docid);
273
      pstmt.setString(4, doctype);
274 449 berkley
      pstmt.setLong(5, getParentID());
275 314 bojilova
276 176 jones
      // Step through the hashtable and insert each of the path values
277
      Enumeration en = pathlist.keys();
278
      while (en.hasMoreElements()) {
279
        String path = (String)en.nextElement();
280
        Long nodeid = (Long)pathlist.get(path);
281
        pstmt.setLong(1, nodeid.longValue());
282
        pstmt.setString(2, path);
283 457 bojilova
        pstmt.executeUpdate();
284 176 jones
285
        //System.out.println(nodeid + " ==> " + path);
286
      }
287
288
      // Close the database statement
289
      pstmt.close();
290
    } catch (SQLException sqe) {
291
      System.err.println("SQL Exception while inserting path to index.");
292
      System.err.println(sqe.getMessage());
293
    }
294
  }
295
296
  /** get the parent of this node */
297
  public DBSAXNode getParentNode() {
298
    return parentNode;
299
  }
300 15 jones
}