/*
 * CatalogTreeModel.java
 *
 * Copyright (c) 2003, Oracle Corporation. All rights reserved. Oracle grants
 * you ("Licensee") a non-exclusive, royalty-free, worldwide license to use,
 * modify and redistribute this software in source and binary code form, provided
 * that (i) this copyright notice and license appear on all copies of the
 * software; (ii) Licensee does not utilize the software in a manner disparaging
 * to Oracle; and (iii) Licensee does not utilize the software in a manner that
 * violates the terms of any Licensee agreement with Oracle.
 */
package samples.javaclient.analyzer;

import java.util.Vector;
import java.util.ResourceBundle;
import java.io.Serializable;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

import javax.swing.event.EventListenerList;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeExpansionEvent;

import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;

import oracle.dss.bicontext.BIContext;
import oracle.dss.bicontext.BISearchControls;

import oracle.dss.util.BIException;
import oracle.dss.util.DefaultErrorHandler;
import oracle.dss.util.ErrorHandler;

/**
 * Implementation of BITreeModel, which allows a JTree to display contents
 * of the BI Beans Catalog.
 * The {@link CatalogExplorer} and the {@link FavoritesExplorer} use this 
 * class.
 */
public class CatalogTreeModel implements BITreeModel, TreeExpansionListener
{
    /**
     * The root folder in the Catalog.
     */
    private BIContext m_context;
    /**
     * The root node in the tree.
     */
    private CatalogTreeNode m_root = null;
    /**
     * Attributes of objects to search for, to display in the tree.
     */
    private Attributes m_filters = null;
    /**
     * Search controls to refine the search for objects to display.
     */
    private BISearchControls m_controls;

    /**
     * Listeners for events that this model generates.
     */
    private EventListenerList m_listenerList = new EventListenerList();

    /**
     * Constructor.
     * 
     * @param con The root folder of the Catalog.
     * @param filters Search attributes that specify the Catalog objects to display.
     * @param controls Search controls to specify the scope of the Catalog search.
     * @param rootName A name for the root node of the tree.
     */
    public CatalogTreeModel(BIContext con, Attributes filters, BISearchControls controls, String rootName)
    {
        m_context = con;
        m_filters = filters;
        m_controls = controls;
        initialize(rootName);
    }

    /**
     * Gets the root folder in the Catalog.
     * 
     * @return The root folder.
     */
    public BIContext getInitialContext()
    {
    	return m_context;
    }

    /**
     * Gets the search attributes for this CatalogTreeModel.
     * Search attributes specify the type of objects to display in the tree.
     * 
     * @return The search attributes for this model.
     */
    public Attributes getSearchFilters()
    {
    	return m_filters;
    }

    /**
     * The search controls for this CatalogTreeModel.
     * Search controls specify the scope of the search and custom
     * filters for the search results.
     * 
     * @return The search controls for this model.
     */
    public BISearchControls getSearchControls()
    {
        return m_controls;
    }

    /**
     * Initializes this model.
     * This method creates a root node.
     * 
     * @param rootName The name for the root node.
     * 
     * @see CatalogExplorer#ROOT
     * @see CatalogExplorer#populateTree
     */
    protected void initialize(String rootName)
    {
        m_root = new CatalogTreeNode(this, rootName);
    }

    /**
     * Gets the root node for this model.
     * 
     * @return The root node.
     */
    public Object getRoot()
    {
        return m_root;
    }

    /**
     * Gets the indexes of child nodes for a node.
     * 
     * @return An array of indexes, one for each child node.
     * 
     * @see CatalogTreeNode#getIndexes
     */
    public int[] getIndexes(Object node)
    {
        CatalogTreeNode _sn = (CatalogTreeNode) node;
        return _sn.getIndexes();
    }

    /**
     * Gets a child node.
     * This method gets the specified child of the specified node.
     * 
     * @param node The node whose child you want.
     * @param index The index of the child node that you want.
     * 
     * @return The child of <code>node</code> at <code>index</code>.
     */
    public Object getChild(Object node, int index)
    {
        TreeNode _sn = (TreeNode) node;
        return _sn.getChildAt(index);
    }

    /**
     * Gets the number of child nodes that a node has.
     * 
     * @param node The node whose child nodes to count.
     * 
     * @return The number of child nodes that <code>node</code> has.
     */
    public int getChildCount(Object node)
    {
        TreeNode _sn = (TreeNode) node;
        return _sn.getChildCount();
    }

    /**
     * Gets the index of a child node.
     * 
     * @param parent The node whose child index you want.
     * @param child The child node whose index you want.
     */
    public int getIndexOfChild(Object parent, Object child)
    {
        return ((TreeNode)parent).getIndex((TreeNode)child);
    }

    /**
     * Registers a listener for this model.
     * 
     * @param l The listener to add.
     */
    public void addTreeModelListener(TreeModelListener l)
    {
        m_listenerList.add(TreeModelListener.class, l);
    }

    /**
     * Removes a listener from this model.
     * 
     * @param l The listener to remove.
     */
    public void removeTreeModelListener(TreeModelListener l)
    {
        m_listenerList.remove(TreeModelListener.class, l);
    }

    /**
     * Notifies listeners of changes to the tree structure.
     * 
     * @param node The node whose structure has changed.
     */
    public void fireTreeStructureChanged(BITreeNode node)
    {
        // Guaranteed to return a non-null array
        Object[] _listeners = m_listenerList.getListenerList();
        TreeModelEvent _evt = null;
        // Process the listeners last to first, notifying
        // those that are interested in this event
        for (int i=_listeners.length-2;i >= 0;i -= 2)
        {
            if (_listeners[i] == TreeModelListener.class)
            {
                // Lazily create the event:
                if (_evt == null)
                    _evt = new TreeModelEvent(this, ((DefaultMutableTreeNode)node).getPath());

                TreeModelListener _l = (TreeModelListener)_listeners[i + 1];
                _l.treeStructureChanged(_evt);
            }
        }
    }

    /**
     * Null implementation for TreeModel interface.
     */
    public void valueForPathChanged(TreePath treepath, Object obj)
    {
    }

    /**
     * Indicates whether a node is a leaf node (has no child nodes).
     * 
     * @param node The node that might be a leaf node.
     * 
     * @return <code>true</code> if <code>node</code> has no child nodes,
     *         <code>false</code> if <code>node</code> had child nodes.
     */
    public boolean isLeaf(Object node)
    {
        TreeNode _sn = (TreeNode)node;
        return (_sn.isLeaf());
    }

    /**
     * Null implementation for TreeExplansionListener interface.
     */
    public void treeCollapsed(TreeExpansionEvent evt)
    {
    }

    /**
     * Responds to tree expansion events.
     * 
     * @param evt Information about the tree expansion.
     */
    public void treeExpanded(TreeExpansionEvent evt)
    {
        TreePath _path = evt.getPath();
        CatalogTreeNode _node = (CatalogTreeNode)_path.getLastPathComponent();
        if (!_node.isLoaded())
            _node.load();
    }
}
