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-24 18:28:34 -0700 (Thu, 24 Aug 2000) $'
11
 * '$Revision: 408 $'
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
   */
35
  public DBSAXNode (Connection conn) {
36
    super();
37
    this.conn = conn;
38
    this.parentNode = null;
39
    writeChildNodeToDB("DOCUMENT", null, null);
40
  }
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
  public DBSAXNode (Connection conn, String tagname, DBSAXNode parentNode, 
50
                    DocumentImpl currentDocument) {
51

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

    
82
      // Bind the values to the query
83
      long nid = generateNodeID();
84
      pstmt.setLong(1, nid);
85
      pstmt.setString(2, nodetype);
86
      pstmt.setString(3, nodename);
87
      if (nodetype == "DOCUMENT") {
88
        pstmt.setLong(4, nid);
89
      } else {
90
        if (nodetype == "ELEMENT") {
91
          pstmt.setLong(4, getRootNodeID());
92
          pstmt.setLong(5, getParentID());
93
          pstmt.setString(6, getDocID());
94
          pstmt.setString(7, data);
95
          pstmt.setInt(8, getNodeIndex());
96
        } else {
97
          pstmt.setLong(4, getRootNodeID());
98
          pstmt.setLong(5, getNodeID());
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")) {
109
        // Record the root node id that was generated from the database
110
        setRootNodeID(nid);
111
      }
112

    
113
      if (nodetype.equals("DOCUMENT") || nodetype.equals("ELEMENT")) {
114

    
115
        // Record the node id that was generated from the database
116
        setNodeID(nid);
117

    
118
        // Record the node type that was passed to the method
119
        setNodeType(nodetype);
120

    
121
      }
122

    
123
    } catch (SQLException e) {
124
      System.err.println("Error inserting node: (" + nodetype + ", " +
125
                                                     nodename + ", " + 
126
                                                     data + ")" );
127
      System.err.println(e.getMessage());
128
    }
129
  }
130

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

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

    
153
  /** 
154
   * creates SQL code to put doc ID for the document node and for 
155
   * comment/PI nodes under document node into DB connection 
156
   */
157
  public void writeDocID(String doc_id) {
158
      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
        pstmt.setString(1, doc_id);
166
        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
        pstmt.setString(1, doc_id);
177
        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
      }   
184
  }
185

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

    
203
      return nid;
204
  }
205

    
206
  /** Add a new attribute to this node, or set its value */
207
  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

    
212
      // And enter the attribute in the database
213
      writeChildNodeToDB("ATTRIBUTE", attName, attValue);
214
    } else {
215
      System.err.println("Attribute name must not be null!");
216
    }
217
  }
218

    
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
  private void updateNodeIndex(String docid, String doctype) {
225
    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
              "INSERT INTO xml_index (nodeid, path, docid, doctype) " + 
260
              "VALUES (?, ?, ?, ?)");
261
  
262
      pstmt.setString(3, docid);
263
      pstmt.setString(4, doctype);
264
      
265
      // 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
}
(10-10/27)