package net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree.expanders;
/*
* Copyright (C) 2002-2003 Colin Bell and Johan Compagner
* colbell@users.sourceforge.net
* jcompagner@j-com.nl
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.SwingUtilities;
import net.sourceforge.squirrel_sql.client.session.ISession;
import net.sourceforge.squirrel_sql.client.session.schemainfo.ObjFilterMatcher;
import net.sourceforge.squirrel_sql.client.session.schemainfo.SchemaFilterMatcher;
import net.sourceforge.squirrel_sql.client.session.schemainfo.CatalogFilterMatcher;
import net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree.INodeExpander;
import net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree.ObjectTreeNode;
import net.sourceforge.squirrel_sql.fw.sql.DatabaseObjectInfo;
import net.sourceforge.squirrel_sql.fw.sql.DatabaseObjectType;
import net.sourceforge.squirrel_sql.fw.sql.IDatabaseObjectInfo;
import net.sourceforge.squirrel_sql.fw.sql.ISQLConnection;
import net.sourceforge.squirrel_sql.fw.sql.SQLDatabaseMetaData;
import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
/**
* This class handles the expanding of database, catalog and schema nodes
* in the object tree.
*
* @author <A HREF="mailto:colbell@users.sourceforge.net">Colin Bell</A>
*/
public class DatabaseExpander implements INodeExpander
{
/** Logger for this class. */
private static ILogger s_log =
LoggerController.createLogger(DatabaseExpander.class);
/** Array of the different types of tables in this database. */
private String[] _tableTypes = new String[] {};
/**
* Ctor.
*
* @param session Current session.
*
* @throws IllegalArgumentException
* Thrown if <TT>null</TT> <TT>ISession</TT> passed.
*/
public DatabaseExpander(ISession session)
{
super();
if (session == null)
{
throw new IllegalArgumentException("ISession == null");
}
GetTableTypes task = new GetTableTypes(session);
if (SwingUtilities.isEventDispatchThread()) {
session.getApplication().getThreadPool().addTask(task);
} else {
task.run();
}
}
private class GetTableTypes implements Runnable {
ISession _session = null;
public GetTableTypes(ISession session) {
_session = session;
}
public void run() {
try
{
_tableTypes = _session.getSQLConnection().getSQLMetaData().getTableTypes();
}
catch (SQLException ex)
{
s_log.debug("DBMS doesn't support 'getTableTypes()", ex);
}
}
}
/**
* Create the child nodes for the passed parent node and return them. Note
* that this method should <B>not</B> actually add the child nodes to the
* parent node as this is taken care of in the caller.
*
* @param session Current session.
* @param node Node to be expanded.
*
* @return A list of <TT>ObjectTreeNode</TT> objects representing the child
* nodes for the passed node.
*/
public List<ObjectTreeNode> createChildren(ISession session, ObjectTreeNode parentNode)
throws SQLException
{
final IDatabaseObjectInfo parentDbinfo = parentNode.getDatabaseObjectInfo();
final ISQLConnection conn = session.getSQLConnection();
final SQLDatabaseMetaData md = conn.getSQLMetaData();
boolean supportsCatalogs = false;
try
{
supportsCatalogs = md.supportsCatalogs();
}
catch (SQLException ex)
{
s_log.debug("DBMS doesn't support 'supportsCatalogs()", ex);
}
boolean supportsSchemas = false;
try
{
supportsSchemas = md.supportsSchemas();
}
catch (SQLException ex)
{
s_log.debug("DBMS doesn't support 'supportsSchemas()", ex);
}
List<ObjectTreeNode> childNodes = new ArrayList<ObjectTreeNode>();
if (parentDbinfo.getDatabaseObjectType() == DatabaseObjectType.SESSION)
{
// If a driver says it supports schemas/catalogs but doesn't
// provide schema/catalog nodes, try to get other nodes.
List<ObjectTreeNode> addedChildren = new ArrayList<ObjectTreeNode>();
if (supportsCatalogs)
{
addedChildren = createCatalogNodes(session, md);
childNodes.addAll(addedChildren);
}
// else if (supportsSchemas)
if (addedChildren.size() == 0 && supportsSchemas)
{
addedChildren = createSchemaNodes(session, md, null);
childNodes.addAll(addedChildren);
}
// else
if (addedChildren.size() == 0)
{
childNodes.addAll(createObjectTypeNodes(session, null, null));
}
}
else if (parentDbinfo.getDatabaseObjectType() == DatabaseObjectType.CATALOG)
{
// If a driver says it supports schemas but doesn't
// provide schema nodes, try to get other nodes.
final String catalogName = parentDbinfo.getSimpleName();
List<ObjectTreeNode> addedChildren = new ArrayList<ObjectTreeNode>();
if (supportsSchemas)
{
addedChildren = createSchemaNodes(session, md, catalogName);
childNodes.addAll(addedChildren);
}
//else
if (addedChildren.size() == 0)
{
childNodes.addAll(createObjectTypeNodes(session, catalogName, null));
}
}
else if (parentDbinfo.getDatabaseObjectType() == DatabaseObjectType.SCHEMA)
{
final String catalogName = parentDbinfo.getCatalogName();
final String schemaName = parentDbinfo.getSimpleName();
childNodes.addAll(createObjectTypeNodes(session, catalogName, schemaName));
}
return childNodes;
}
private List<ObjectTreeNode> createCatalogNodes(ISession session, SQLDatabaseMetaData md)
throws SQLException
{
final List<ObjectTreeNode> childNodes = new ArrayList<ObjectTreeNode>();
if (session.getProperties().getLoadSchemasCatalogs())
{
final String[] catalogs = md.getCatalogs();
CatalogFilterMatcher filterMatcher = new CatalogFilterMatcher(session.getProperties());
for (int i = 0; i < catalogs.length; ++i)
{
IDatabaseObjectInfo dbo = new DatabaseObjectInfo(null, null,
catalogs[i],
DatabaseObjectType.CATALOG,
md);
if (filterMatcher.matches(dbo.getSimpleName()))
{
childNodes.add(new ObjectTreeNode(session, dbo));
}
}
}
return childNodes;
}
protected List<ObjectTreeNode> createSchemaNodes(ISession session,
SQLDatabaseMetaData md,
String catalogName)
throws SQLException
{
final List<ObjectTreeNode> childNodes = new ArrayList<ObjectTreeNode>();
if (session.getProperties().getLoadSchemasCatalogs())
{
session.getSchemaInfo().waitTillSchemasAndCatalogsLoaded();
final String[] schemas = session.getSchemaInfo().getSchemas();
SchemaFilterMatcher filterMatcher = new SchemaFilterMatcher(session.getProperties());
for (int i = 0; i < schemas.length; ++i)
{
IDatabaseObjectInfo dbo = new DatabaseObjectInfo(catalogName, null,
schemas[i],
DatabaseObjectType.SCHEMA, md);
if(filterMatcher.matches(dbo.getSimpleName()))
{
childNodes.add(new ObjectTreeNode(session, dbo));
}
}
}
return childNodes;
}
private List<ObjectTreeNode> createObjectTypeNodes(ISession session, String catalogName,
String schemaName)
{
final List<ObjectTreeNode> list = new ArrayList<ObjectTreeNode>();
if (session.getProperties().getLoadSchemasCatalogs())
{
final ISQLConnection conn = session.getSQLConnection();
final SQLDatabaseMetaData md = conn.getSQLMetaData();
// Add table types to list.
if (_tableTypes.length > 0)
{
for (int i = 0; i < _tableTypes.length; ++i)
{
IDatabaseObjectInfo dbo = new DatabaseObjectInfo(catalogName,
schemaName, _tableTypes[i],
DatabaseObjectType.TABLE_TYPE_DBO, md);
ObjectTreeNode child = new ObjectTreeNode(session, dbo);
list.add(child);
}
}
else
{
s_log.debug("List of table types is empty so trying null table type to load all tables");
IDatabaseObjectInfo dbo = new DatabaseObjectInfo(catalogName,
schemaName, null,
DatabaseObjectType.TABLE_TYPE_DBO, md);
ObjectTreeNode child = new ObjectTreeNode(session, dbo);
child.setUserObject("TABLE");
list.add(child);
}
// Add stored proc parent node.
boolean supportsStoredProcs = false;
try
{
supportsStoredProcs = md.supportsStoredProcedures();
}
catch (SQLException ex)
{
s_log.debug("DBMS doesn't support 'supportsStoredProcedures()'", ex);
}
if (supportsStoredProcs)
{
IDatabaseObjectInfo dbo = new DatabaseObjectInfo(catalogName,
schemaName, "PROCEDURE",
DatabaseObjectType.PROC_TYPE_DBO, md);
ObjectTreeNode child = new ObjectTreeNode(session, dbo);
list.add(child);
}
// Add UDT parent node.
{
IDatabaseObjectInfo dbo = new DatabaseObjectInfo(catalogName,
schemaName, "UDT",
DatabaseObjectType.UDT_TYPE_DBO, md);
ObjectTreeNode child = new ObjectTreeNode(session, dbo);
list.add(child);
}
}
return list;
}
}