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-15 17:40:40 -0700 (Fri, 15 Sep 2000) $'
11
 * '$Revision: 457 $'
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

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

    
28
  private Connection	conn;
29
  private DBSAXNode	parentNode;
30

    
31
  /** 
32
   * Construct a new node instance for DOCUMENT nodes
33
   *
34
   * @param conn the JDBC Connection to which all information is written
35
   */
36
  public DBSAXNode (Connection conn, String docid) {
37
    super();
38
    this.conn = conn;
39
    this.parentNode = null;
40
    writeChildNodeToDB("DOCUMENT", null, null, docid);
41
  }
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
  public DBSAXNode (Connection conn, String tagname, DBSAXNode parentNode, 
51
                    long rootnodeid, String docid, String doctype) {
52

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

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

    
117
      if (nodetype.equals("DOCUMENT") || nodetype.equals("ELEMENT")) {
118

    
119
        // Record the node id that was generated from the database
120
        setNodeID(nid);
121

    
122
        // Record the node type that was passed to the method
123
        setNodeType(nodetype);
124

    
125
      }
126

    
127
    } catch (SQLException e) {
128
      System.err.println("Error inserting node: (" + nodetype + ", " +
129
                                                     nodename + ", " + 
130
                                                     data + ")" );
131
      System.err.println(e.getMessage());
132
    }
133
  }
134

    
135
  /** 
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

    
146
        // Bind the values to the query
147
        pstmt.setString(1, nodename);
148
        pstmt.setLong(2, getNodeID());
149
        // Do the insertion
150
        pstmt.execute();
151
        pstmt.close();
152
      } catch (SQLException e) {
153
        System.out.println(e.getMessage());
154
      }
155
  }
156

    
157
  /** 
158
   * creates SQL code to put doc ID for the document node and for 
159
   * comment/PI nodes under document node into DB connection 
160
   */
161
  public void writeDocID(String doc_id) {
162
      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
        pstmt.setString(1, doc_id);
170
        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
        pstmt.setString(1, doc_id);
181
        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
      }   
188
  }
189

    
190
  /** get next node id from DB connection */
191
  private long generateNodeID() {
192
      long nid=0;
193
      Statement stmt;
194
      try {
195
        stmt = conn.createStatement();
196
        stmt.execute("SELECT xml_nodes_id_seq.nextval FROM dual");
197
        ResultSet rs = stmt.getResultSet();
198
        boolean tableHasRows = rs.next();
199
        if (tableHasRows) {
200
          nid = rs.getLong(1);
201
        }
202
        stmt.close();
203
      } catch (SQLException e) {
204
        System.out.println("Error getting id: " + e.getMessage());
205
      }
206

    
207
      return nid;
208
  }
209

    
210
  /** Add a new attribute to this node, or set its value */
211
  public void setAttribute(String attName, String attValue, String docid) {
212
    if (attName != null) {
213
      // Enter the attribute in the hash table
214
      super.setAttribute(attName, attValue);
215

    
216
      // And enter the attribute in the database
217
      writeChildNodeToDB("ATTRIBUTE", attName, attValue, docid);
218
    } else {
219
      System.err.println("Attribute name must not be null!");
220
    }
221
  }
222

    
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
  private void updateNodeIndex(String docid, String doctype) {
229
    Hashtable pathlist = new Hashtable();
230
    boolean atStartingNode = true;
231
    boolean atRootDocumentNode = false;
232
    DBSAXNode nodePointer = this;
233
    StringBuffer currentPath = new StringBuffer();
234
    int counter = 0;
235

    
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
        counter++;
243
        atStartingNode = false;
244
      } else {
245
        currentPath.insert(0, "/");
246
        currentPath.insert(0, nodePointer.getTagName());
247
        pathlist.put(currentPath.toString(), new Long(getNodeID()));
248
        counter++;
249
      }
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
        counter++;
260
        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
              "INSERT INTO xml_index (nodeid, path, docid, doctype, " + 
268
               "parentnodeid) " + 
269
              "VALUES (?, ?, ?, ?, ?)");
270
      ((OraclePreparedStatement)pstmt).setExecuteBatch(counter);
271
  
272
      pstmt.setString(3, docid);
273
      pstmt.setString(4, doctype);
274
      pstmt.setLong(5, getParentID());
275
      
276
      // 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
        pstmt.executeUpdate();
284
  
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
}
(10-10/28)