/* Clear all existing nodes from the tree model and rebuild from scratch.
   */
  protected void refreshTree() {

    DefaultMutableTreeNode propertiesNode;
    DefaultMutableTreeNode leaf;

    // First clear the existing tree by simply enumerating
    // over the root node's children and removing them one by one.
    while (treeModel.getChildCount(rootNode) > 0) {
      DefaultMutableTreeNode child = (DefaultMutableTreeNode) treeModel.getChild(rootNode, 0);

      treeModel.removeNodeFromParent(child);
      child.removeAllChildren();
      child.removeFromParent();
    }

    treeModel.nodeStructureChanged(rootNode);
    treeModel.reload();
    tScrollPane.repaint();

    // Now rebuild the tree below its root
    try {

      // Start by naming the root node from its URL:
      rootNode.setUserObject(dMeta.getURL());

      // get metadata about user tables by building a vector of table names
      String usertables[] = {"TABLE", "GLOBAL TEMPORARY", "VIEW"};
      ResultSet result = dMeta.getTables(null, null, null, usertables);
      Vector tables = new Vector();

      // sqlbob@users Added remarks.
      Vector remarks = new Vector();

      while (result.next()) {
        tables.addElement(result.getString(3));
        remarks.addElement(result.getString(5));
      }

      result.close();

      // For each table, build a tree node with interesting info
      for (int i = 0; i < tables.size(); i++) {
        String name = (String) tables.elementAt(i);
        DefaultMutableTreeNode tableNode = makeNode(name, rootNode);
        ResultSet col = dMeta.getColumns(null, null, name, null);

        // sqlbob@users Added remarks.
        String remark = (String) remarks.elementAt(i);

        if ((remark != null) && !remark.trim().equals("")) {
          makeNode(remark, tableNode);
        }

        // With a child for each column containing pertinent attributes
        while (col.next()) {
          String c = col.getString(4);
          DefaultMutableTreeNode columnNode = makeNode(c, tableNode);
          String type = col.getString(6);

          makeNode("Type: " + type, columnNode);

          boolean nullable = col.getInt(11) != DatabaseMetaData.columnNoNulls;

          makeNode("Nullable: " + nullable, columnNode);
        }

        col.close();

        DefaultMutableTreeNode indexesNode = makeNode("Indices", tableNode);
        ResultSet ind = dMeta.getIndexInfo(null, null, name, false, false);
        String oldiname = null;

        // A child node to contain each index - and its attributes
        while (ind.next()) {
          DefaultMutableTreeNode indexNode = null;
          boolean nonunique = ind.getBoolean(4);
          String iname = ind.getString(6);

          if ((oldiname == null || !oldiname.equals(iname))) {
            indexNode = makeNode(iname, indexesNode);

            makeNode("Unique: " + !nonunique, indexNode);

            oldiname = iname;
          }

          // And the ordered column list for index components
          makeNode(ind.getString(9), indexNode);
        }

        ind.close();
      }

      // Finally - a little additional metadata on this connection
      propertiesNode = makeNode("Properties", rootNode);

      makeNode("User: "******"ReadOnly: " + cConn.isReadOnly(), propertiesNode);
      makeNode("AutoCommit: " + cConn.getAutoCommit(), propertiesNode);
      makeNode("Driver: " + dMeta.getDriverName(), propertiesNode);
      makeNode("Product: " + dMeta.getDatabaseProductName(), propertiesNode);
      makeNode("Version: " + dMeta.getDatabaseProductVersion(), propertiesNode);
    } catch (SQLException se) {
      propertiesNode = makeNode("Error getting metadata:", rootNode);

      makeNode(se.getMessage(), propertiesNode);
      makeNode(se.getSQLState(), propertiesNode);
    }

    treeModel.nodeStructureChanged(rootNode);
    treeModel.reload();
    tScrollPane.repaint();
  }