package net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree;
/*
* Copyright (C) 2002-2004 Colin Bell and Johan Compagner
* colbell@users.sourceforge.net
* jcompagner@j-com.nl
*
* Modifications Copyright (c) 2004 Jason Height.
*
* 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.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import net.sourceforge.squirrel_sql.client.plugin.IPluginManager;
import net.sourceforge.squirrel_sql.client.plugin.ISessionPlugin;
import net.sourceforge.squirrel_sql.client.plugin.SessionPluginInfo;
import net.sourceforge.squirrel_sql.client.session.ISession;
import net.sourceforge.squirrel_sql.client.session.schemainfo.FilterMatcher;
import net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree.expanders.DatabaseExpander;
import net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree.expanders.ProcedureTypeExpander;
import net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree.expanders.TableTypeExpander;
import net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree.expanders.UDTTypeExpander;
import net.sourceforge.squirrel_sql.fw.id.IIdentifier;
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.util.log.ILogger;
import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
/**
* This is the model for the object tree.
*
* @author <A HREF="mailto:colbell@users.sourceforge.net">Colin Bell</A>
*/
public class ObjectTreeModel extends DefaultTreeModel
{
private static final long serialVersionUID = 1L;
private static ILogger logger =
LoggerController.createLogger(ObjectTreeModel.class);
/**
* Collection of <TT>INodeExpander</TT> objects. Each entry is a <TT>List</TT>
* of <TT>INodeExpander</TT> objects. The key to the list is the
* node type.
*/
private Map<IIdentifier, List<INodeExpander>> _expanders =
new HashMap<IIdentifier, List<INodeExpander>>();
private final Set<DatabaseObjectType> _objectTypes =
new TreeSet<DatabaseObjectType>(new DatabaseObjectTypeComparator());
/**
* ctor specifying session.
*
* @param session Current session.
*
* @throws IllegalArgumentException
* Thrown if <TT>null</TT> <TT>ISession</TT> passed.
*/
public ObjectTreeModel(final ISession session)
{
super(createRootNode(session), true);
if (session == null)
{
throw new IllegalArgumentException("ISession == null");
}
// Standard expanders.
session.getApplication().getThreadPool().addTask(new Runnable() {
public void run() {
// must *not* be done in the GUI thread
final INodeExpander expander = new DatabaseExpander(session);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// *must* be done in the GUI thread
addExpander(DatabaseObjectType.CATALOG, expander);
addExpander(DatabaseObjectType.SCHEMA, expander);
boolean foundTableExp = false;
boolean foundProcExp = false;
boolean foundUDTExp = false;
boolean foundDatabaseExp = false;
final IPluginManager pmgr = session.getApplication().getPluginManager();
for (Iterator<SessionPluginInfo> pluginItr = pmgr.getSessionPluginIterator(); pluginItr.hasNext();)
{
ISessionPlugin p = (pluginItr.next()).getSessionPlugin();
INodeExpander tableExp = p.getDefaultNodeExpander(session, DatabaseObjectType.TABLE_TYPE_DBO);
if (tableExp != null)
{
foundTableExp = true;
addExpander(DatabaseObjectType.TABLE_TYPE_DBO, tableExp);
}
INodeExpander procExp = p.getDefaultNodeExpander(session, DatabaseObjectType.PROC_TYPE_DBO);
if (procExp != null)
{
foundProcExp = true;
addExpander(DatabaseObjectType.PROC_TYPE_DBO, procExp);
}
INodeExpander udtExp = p.getDefaultNodeExpander(session, DatabaseObjectType.UDT_TYPE_DBO);
if (udtExp != null)
{
foundUDTExp = true;
addExpander(DatabaseObjectType.UDT_TYPE_DBO, udtExp);
}
INodeExpander databaseExp = p.getDefaultNodeExpander(session, DatabaseObjectType.DATABASE_TYPE_DBO);
if (databaseExp != null) {
foundDatabaseExp = true;
addExpander(DatabaseObjectType.SESSION, databaseExp);
}
}
if (!foundTableExp)
{
addExpander(DatabaseObjectType.TABLE_TYPE_DBO, new TableTypeExpander());
}
if (!foundProcExp)
{
addExpander(DatabaseObjectType.PROC_TYPE_DBO, new ProcedureTypeExpander());
}
if (!foundUDTExp)
{
addExpander(DatabaseObjectType.UDT_TYPE_DBO, new UDTTypeExpander());
}
if (!foundDatabaseExp)
{
addExpander(DatabaseObjectType.SESSION, expander);
}
reload();
}
});
}
});
}
/**
* Add an expander for the specified database object type in the
* object tree.
*
* @param dboType Database object type.
* @param expander Expander called to add children to a parent node.
*
* @throws IllegalArgumentException
* Thrown if a <TT>null</TT> <TT>INodeExpander</TT> or
* <TT>ObjectTreeNodeType</TT> passed.
*/
public synchronized void addExpander(DatabaseObjectType dboType,
INodeExpander expander)
{
if (dboType == null)
{
throw new IllegalArgumentException("Null DatabaseObjectType passed");
}
if (expander == null)
{
throw new IllegalArgumentException("Null INodeExpander passed");
}
getExpandersList(dboType).add(expander);
addKnownDatabaseObjectType(dboType);
}
/**
* Return an array of the node expanders for the passed database object type.
*
* @param dboType Database object type.
* @return an array of the node expanders for the passed database object type.
*
* @throws IllegalArgumentException
* Thrown if null ObjectTreeNodeType passed.
*/
public synchronized INodeExpander[] getExpanders(DatabaseObjectType dboType)
{
if (dboType == null)
{
throw new IllegalArgumentException("Null DatabaseObjectType passed");
}
List<INodeExpander> list = getExpandersList(dboType);
return list.toArray(new INodeExpander[list.size()]);
}
/**
* Retrieve details about all object types that can be in this
* tree.
*
* @return DatabaseObjectType[] Array of object type info objects.
*/
public synchronized DatabaseObjectType[] getDatabaseObjectTypes()
{
DatabaseObjectType[] ar = new DatabaseObjectType[_objectTypes.size()];
return _objectTypes.toArray(ar);
}
synchronized void addKnownDatabaseObjectType(DatabaseObjectType dboType)
{
_objectTypes.add(dboType);
}
/**
* Return the root node.
*
* @return the root node.
*/
ObjectTreeNode getRootObjectTreeNode()
{
return (ObjectTreeNode)getRoot();
}
/**
* Get the collection of expanders for the passed node type. If one
* doesn't exist then create an empty one.
*
* @param dboType Database object type.
*/
private List<INodeExpander> getExpandersList(DatabaseObjectType dboType)
{
if (dboType == null)
{
throw new IllegalArgumentException("Null DatabaseObjectType passed");
}
IIdentifier key = dboType.getIdentifier();
List<INodeExpander> list = _expanders.get(key);
if (list == null)
{
list = new ArrayList<INodeExpander>();
_expanders.put(key, list);
}
return list;
}
/**
* Create the root node for this tree.
*
* @param session Current session.
*
* @throws IllegalArgumentException
* Thrown if <TT>null</TT> <TT>ISession</TT> passed.
*/
private static ObjectTreeNode createRootNode(ISession session)
{
if (session == null)
{
throw new IllegalArgumentException("ISession == null");
}
return new RootNode(session);
}
public TreePath getPathToDbInfo(String catalog, String schema, FilterMatcher objectMatcher, ObjectTreeNode startNode, boolean useExpanders)
{
if(dbObjectInfoEquals(catalog, schema, objectMatcher, startNode.getDatabaseObjectInfo()))
{
return new TreePath(startNode.getPath());
}
else
{
if(useExpanders && 0 == startNode.getChildCount())
{
INodeExpander[] expanders = getExpanders(startNode.getDatabaseObjectType());
for (int i = 0; i < expanders.length; i++)
{
try
{
List<ObjectTreeNode> children =
expanders[i].createChildren(startNode.getSession(), startNode);
for (int j = 0; j < children.size(); j++)
{
ObjectTreeNode newChild = children.get(j);
if(0 == getExpanders(newChild.getDatabaseObjectType()).length)
{
newChild.setAllowsChildren(false);
}
else
{
newChild.setAllowsChildren(true);
}
startNode.add(newChild);
}
}
catch (Exception e)
{
String msg =
"Error loading object type " + startNode.getDatabaseObjectType() +
". Error: " + e.toString() + ". See SQuirreL Logs for stackttrace.";
startNode.getSession().showErrorMessage(msg);
logger.error(msg, e);
}
}
}
for(int i=0; i < startNode.getChildCount(); ++i)
{
TreePath ret = getPathToDbInfo(catalog, schema, objectMatcher, (ObjectTreeNode) startNode.getChildAt(i), useExpanders);
if(null != ret)
{
return ret;
}
}
}
return null;
}
private boolean dbObjectInfoEquals(String catalog, String schema, FilterMatcher objectMatcher, IDatabaseObjectInfo doi)
{
if(null != catalog)
{
if(false == catalog.equalsIgnoreCase(doi.getCatalogName()))
{
return false;
}
}
if(null != schema)
{
if(false == schema.equalsIgnoreCase(doi.getSchemaName()))
{
return false;
}
}
if(null != objectMatcher.getMetaDataMatchString())
{
if( false == objectMatcher.matches(doi.getSimpleName())
&& false == objectMatcher.getMetaDataMatchString().equalsIgnoreCase(doi.getQualifiedName()))
{
return false;
}
}
return true;
}
public boolean isRootNode(Object node)
{
return node instanceof RootNode;
}
private static final class RootNode extends ObjectTreeNode
{
private static final long serialVersionUID = 1L;
RootNode(ISession session)
{
super(session, createDbo(session));
}
private static final IDatabaseObjectInfo createDbo(ISession session)
{
return new DatabaseObjectInfo(null, null, session.getAlias().getName(),
DatabaseObjectType.SESSION,
session.getMetaData());
}
}
private static final class DatabaseObjectTypeComparator
implements Comparator<DatabaseObjectType>, Serializable
{
private static final long serialVersionUID = 1L;
public int compare(DatabaseObjectType o1, DatabaseObjectType o2)
{
return o1.getName().compareToIgnoreCase(o2.getName());
}
}
}