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: jones $'
10
 *     '$Date: 2000-08-14 13:53:34 -0700 (Mon, 14 Aug 2000) $'
11
 * '$Revision: 349 $'
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

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

    
27
  private Connection	conn;
28
  private DBSAXNode	parentNode;
29

    
30
  /** 
31
   * Construct a new node instance for DOCUMENT nodes
32
   *
33
   * @param conn the JDBC Connection to which all information is written
34
   * @param tagname the name of the node
35
   */
36
  public DBSAXNode (Connection conn, String tagname) {
37
    super(tagname);
38
    this.conn = conn;
39
    this.parentNode = null;
40
    writeChildNodeToDB("DOCUMENT", tagname, null);
41
    setRootNodeID(getNodeID());
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
                    DBSAXDocument currentDocument) {
53

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

    
84
      // Bind the values to the query
85
      long nid = generateNodeID();
86
      pstmt.setLong(1, nid);
87
      pstmt.setString(2, nodetype);
88
      pstmt.setString(3, nodename);
89
      if (nodetype != "DOCUMENT") {
90
        if (nodetype == "ELEMENT") {
91
          pstmt.setLong(4, getParentID());
92
          pstmt.setLong(5, getRootNodeID());
93
          pstmt.setString(6, getDocID());
94
          pstmt.setString(7, data);
95
          pstmt.setInt(8, getNodeIndex());
96
        } else {
97
          pstmt.setLong(4, getNodeID());
98
          pstmt.setLong(5, getRootNodeID());
99
          pstmt.setString(6, getDocID());
100
          pstmt.setString(7, data);
101
          pstmt.setInt(8, incChildNum());
102
        }
103
      }
104
      // Do the insertion
105
      pstmt.execute();
106
      pstmt.close();
107
      
108
      if (nodetype.equals("DOCUMENT") || nodetype.equals("ELEMENT")) {
109

    
110
        // Record the node id that was generated from the database
111
        setNodeID(nid);
112

    
113
        // Record the node type that was passed to the method
114
        setNodeType(nodetype);
115

    
116
      }
117

    
118
    } catch (SQLException e) {
119
      System.err.println("Error inserting node: (" + nodetype + ", " +
120
                                                     nodename + ", " + 
121
                                                     data + ")" );
122
      System.err.println(e.getMessage());
123
    }
124
  }
125

    
126
  /** 
127
   * creates SQL code to put nodename for the document node 
128
   * into DB connection 
129
   */
130
  public void writeNodename(String nodename) {
131
      try {
132
        PreparedStatement pstmt;
133
        pstmt = conn.prepareStatement(
134
              "UPDATE xml_nodes set nodename = ? " +
135
              "WHERE nodeid = ?");
136

    
137
        // Bind the values to the query
138
        pstmt.setString(1, nodename);
139
        pstmt.setLong(2, getNodeID());
140
        // Do the insertion
141
        pstmt.execute();
142
        pstmt.close();
143
      } catch (SQLException e) {
144
        System.out.println(e.getMessage());
145
      }
146
  }
147

    
148
  /** 
149
   * creates SQL code to put root node id for the document node 
150
   * into DB connection 
151
   */
152
  public void writeRootNodeID(long rootnode_id) {
153
      try {
154
        PreparedStatement pstmt;
155
        pstmt = conn.prepareStatement(
156
              "UPDATE xml_nodes set rootnodeid = ? " +
157
              "WHERE nodeid = ?");
158

    
159
        // Bind the values to the query
160
        pstmt.setLong(1, rootnode_id);
161
        pstmt.setLong(2, getNodeID());
162
        // Do the insertion
163
        pstmt.execute();
164
        pstmt.close();
165
      } catch (SQLException e) {
166
        System.out.println(e.getMessage());
167
      }
168
  }
169
  /** 
170
   * creates SQL code to put doc ID for the document node and for 
171
   * comment/PI nodes under document node into DB connection 
172
   */
173
  public void writeDocID(String doc_id) {
174
      try {
175
        PreparedStatement pstmt;
176
        pstmt = conn.prepareStatement(
177
              "UPDATE xml_nodes set docid = ? " +
178
              "WHERE nodeid = ?");
179

    
180
        // Bind the values to the query
181
        pstmt.setString(1, doc_id);
182
        pstmt.setLong(2, getNodeID());
183
        // Do the insertion
184
        pstmt.execute();
185
        pstmt.close();
186

    
187
        // for comments and PI on the top
188
        pstmt = conn.prepareStatement(
189
              "UPDATE xml_nodes set docid = ? " +
190
              "WHERE parentnodeid = ?");
191
        // Bind the values to the query
192
        pstmt.setString(1, doc_id);
193
        pstmt.setLong(2, getNodeID());
194
        // Do the insertion
195
        pstmt.execute();
196
        pstmt.close();
197
      } catch (SQLException e) {
198
        System.out.println(e.getMessage());
199
      }   
200
  }
201

    
202
  /** get next node id from DB connection */
203
  private long generateNodeID() {
204
      long nid=0;
205
      Statement stmt;
206
      try {
207
        stmt = conn.createStatement();
208
        stmt.execute("SELECT xml_nodes_id_seq.nextval FROM dual");
209
        ResultSet rs = stmt.getResultSet();
210
        boolean tableHasRows = rs.next();
211
        if (tableHasRows) {
212
          nid = rs.getLong(1);
213
        }
214
        stmt.close();
215
      } catch (SQLException e) {
216
        System.out.println("Error getting id: " + e.getMessage());
217
      }
218

    
219
      return nid;
220
  }
221

    
222
  /** Add a new attribute to this node, or set its value */
223
  public void setAttribute(String attName, String attValue) {
224
    if (attName != null) {
225
      // Enter the attribute in the hash table
226
      super.setAttribute(attName, attValue);
227

    
228
      // And enter the attribute in the database
229
      writeChildNodeToDB("ATTRIBUTE", attName, attValue);
230
    } else {
231
      System.err.println("Attribute name must not be null!");
232
    }
233
  }
234

    
235
  /** 
236
   * Update the node index (xml_index) for this node by generating
237
   * test strings that represent all of the relative and absolute
238
   * paths through the XML tree from document root to this node
239
   */
240
  private void updateNodeIndex(String docid, String doctype) {
241
    Hashtable pathlist = new Hashtable();
242
    boolean atStartingNode = true;
243
    boolean atRootDocumentNode = false;
244
    DBSAXNode nodePointer = this;
245
    StringBuffer currentPath = new StringBuffer();
246

    
247
    // Create a Hashtable of all of the paths to reach this node
248
    // including absolute paths and relative paths
249
    while (!atRootDocumentNode) {
250
      if (atStartingNode) {
251
        currentPath.insert(0, nodePointer.getTagName());
252
        pathlist.put(currentPath.toString(), new Long(getNodeID()));
253
        atStartingNode = false;
254
      } else {
255
        currentPath.insert(0, "/");
256
        currentPath.insert(0, nodePointer.getTagName());
257
        pathlist.put(currentPath.toString(), new Long(getNodeID()));
258
      }
259

    
260
      // advance to the next parent node
261
      nodePointer = nodePointer.getParentNode();
262

    
263
      // If we're at the DOCUMENT node (root of DOM tree), add
264
      // the root "/" to make the absolute path
265
      if (nodePointer.getNodeType().equals("DOCUMENT")) {
266
        currentPath.insert(0, "/");
267
        pathlist.put(currentPath.toString(), new Long(getNodeID()));
268
        atRootDocumentNode = true;
269
      } 
270
    }
271

    
272
    try {
273
      // Create an insert statement to reuse for all of the path insertions
274
      PreparedStatement pstmt = conn.prepareStatement(
275
              "INSERT INTO xml_index (nodeid, path, docid, doctype) " + 
276
              "VALUES (?, ?, ?, ?)");
277
  
278
      pstmt.setString(3, docid);
279
      pstmt.setString(4, doctype);
280
      
281
      // Step through the hashtable and insert each of the path values
282
      Enumeration en = pathlist.keys();
283
      while (en.hasMoreElements()) {
284
        String path = (String)en.nextElement();
285
        Long nodeid = (Long)pathlist.get(path);
286
        pstmt.setLong(1, nodeid.longValue());
287
        pstmt.setString(2, path);
288
        pstmt.execute();
289
  
290
        //System.out.println(nodeid + " ==> " + path);
291
      }
292

    
293
      // Close the database statement
294
      pstmt.close();
295
    } catch (SQLException sqe) {
296
      System.err.println("SQL Exception while inserting path to index.");
297
      System.err.println(sqe.getMessage());
298
    }
299
  }
300
 
301
  /** get the parent of this node */
302
  public DBSAXNode getParentNode() {
303
    return parentNode;
304
  }
305
}
306

    
307
/**
308
 * '$Log$
309
 * 'Revision 1.33  2000/08/03 23:17:19  bojilova
310
 * 'DBSAXNode constructor simplified
311
 * '
312
 * 'Revision 1.32  2000/06/27 04:31:07  jones
313
 * 'Fixed bugs associated with the new UPDATE and DELETE functions of
314
 * 'DBWriter.  There were problematic interactions between some static
315
 * 'variables used in DBEntityResolver and the way in which the
316
 * 'Servlet objects are re-used across multiple client invocations.
317
 * '
318
 * 'Generally cleaned up error reporting.  Now all errors and success
319
 * 'results are reported as XML documents from MetaCatServlet.  Need
320
 * 'to make the command line tools do the same.
321
 * '
322
 * 'Revision 1.31  2000/06/26 10:35:05  jones
323
 * 'Merged in substantial changes to DBWriter and associated classes and to
324
 * 'the MetaCatServlet in order to accomodate the new UPDATE and DELETE
325
 * 'functions.  The command line tools and the parameters for the
326
 * 'servlet have changed substantially.
327
 * '
328
 * 'Revision 1.30.2.2  2000/06/25 23:38:16  jones
329
 * 'Added RCSfile keyword
330
 * '
331
 * 'Revision 1.30.2.1  2000/06/25 23:34:17  jones
332
 * 'Changed documentation formatting, added log entries at bottom of source files
333
 * ''
334
 */
(12-12/27)