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