/*
 * CatalogTreeNode.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.io.Serializable;

import javax.swing.Icon;
import javax.swing.tree.TreeNode;
import javax.swing.tree.DefaultMutableTreeNode;

import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.SearchResult;
import javax.naming.directory.SearchControls;
import javax.naming.directory.DirContext;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;

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

import oracle.dss.util.persistence.PersistableConstants;

/**
 * A node of a {@link CatalogTree}.
 * This object can represent a folder, a crosstab, a graph, or a saved
 * selection.
 * 
 * @see CatalogExplorer
 * @see FavoritesExplorer
 */
public class CatalogTreeNode extends DefaultMutableTreeNode implements BITreeNode
{
    private BISearchResult m_entry;
    private String m_name;              
    private String m_fullPathName;    
    private String m_type;
    private boolean m_loaded = false;   
    private int m_children = -1;      
    private BIContext m_context;
    private boolean m_isRoot = false;
    private int[] m_indexes;
    private BITreeModel m_model = null;

    /**
     * Constructor for the root node.
     * 
     * @param model The tree model to which this node belongs.
     * @param rootName The label for this node.
     */
    public CatalogTreeNode(BITreeModel model, String rootName)
    {
        m_model = model;
        setAllowsChildren(true);
        m_name = rootName;
        m_fullPathName = "";
        m_context = m_model.getInitialContext();

        // this is the root node, get entries
        m_isRoot = true;
        load();
    }

    /**
     * Constructor for nodes other than the root node.
     * 
     * @param model The tree model to which this node belongs.
     * @param pathName The location of this object in the Catalog, relative
     *                 to the root folder.
     * @param entry The search result that contains information about 
     *                 the object that this node represents.
     *                 The search result comes from a call to the 
     *                 search method of a BIContext.
     */
    public CatalogTreeNode(BITreeModel model, String pathName, BISearchResult entry)
    {
        m_model = model;
        m_fullPathName = pathName;
        m_entry = entry;
        setAllowsChildren(true);
        setUserObject(entry);
        initializeFromEntry(entry);
    }

    /** 
     * Initializes this node from information in a SearchResult.
     * This method gets information about the object that the node
     * represents, from the search result object.
     * It gets the full path name, the number of children (for folders), 
     * the Catalog label for the object, and the object type.
     * 
     * @param entry The search result that has information about the object
     *              that this node represents.
     *              oracle.dss.bicontext.BIContext.search returns an enumeration 
     *              of search results.
     */ 
    private void initializeFromEntry(SearchResult entry)
    {
        if (m_fullPathName.equals(""))
            m_fullPathName = entry.getName();
        else
            m_fullPathName = m_fullPathName+"/"+entry.getName();

        m_children = getChildCount();

        if (entry instanceof BISearchResult)
        {
            m_name = ((BISearchResult)entry).getLabel();
            m_type = ((BISearchResult)entry).getObjectType();
        }
        else
            m_name = entry.getName();
    }

    /**
     * Gets the indexes of displayed child nodes.
     * 
     * @return An array of indexes, one for each child node.
     */
    public int[] getIndexes()
    {
        int n = getChildCount();
        if (m_indexes != null)
        {
            if (m_indexes.length == n)
                return m_indexes;
        }

        m_indexes = new int[n];
        for (int i=0; i<n; i++)
            m_indexes[i] = i;

        return m_indexes;
    }

    /**
     * Gets the folder for the object that this node represents.
     * 
     * @return The folder for the object that this node represents.
     */
    private BIContext getDirContext()
    {
        if (m_context == null)
            m_context = (BIContext)m_entry.getObject();

    	return m_context;
    }

    /**
     * Gets the object that this node represents.
     * 
     * @return The object that this node represents.
     */
    private BISearchResult getSearchResult()
    {
        return (BISearchResult)getUserObject();
    }

    /**
     * Gets the Catalog name of the object that this node represents.
     * 
     * @return The name of the object that this node represents.
     */
    public String getName()
    {
        return m_name;
    }

    /**
     * Gets the path name for the object that this node represents,
     * relative to the root folder.
     * 
     * @return The full path name.
     */
    public String getFullPathName()
    {
    	return m_fullPathName;
    }

    /**
     * Gets the type of object that this node represents.
     * Valid return values are specified in the 
     * oracle.dss.util.persistence.PersistableConstants interface.
     * This application handles values of:
     * oracle.dss.util.persistence.PersistableConstants.FOLDER,
     * oracle.dss.util.persistence.PersistableConstants.GRAPH,
     * oracle.dss.util.persistence.PersistableConstants.CROSSTAB, and
     * oracle.dss.util.persistence.PersistableConstants.SELECTION.
     * 
     * @return The Object type for the object that this node represents.
     */
    public String getObjectType()
    {
        return m_type;
    }
    /**
     * Displays child nodes of this node.
     * This method calls getChildList to create the child nodes.
     * 
     * @see #getChildList
     */
    public void load()
    {
    	getChildList();
        m_loaded = true;
    }

    /**
     * Creates a node for each child of this node.
     * Also calls the fireTreeStructureChanged method on the model, to
     * fire a TreeModelEvent.
     */
    private void getChildList()
    {
        removeAllChildren();
        try
        {
            getDirContext();
            if (m_context == null)
                return;

            // Search for immediate children
            Attributes _attrs = m_model.getSearchFilters();
            BISearchControls _control = (BISearchControls)m_model.getSearchControls();
            if (_control == null)
                _control = new BISearchControls();
            _control.setSortingOn(true);
            NamingEnumeration _results = null;
            if (_control != null)
                _results = m_context.search("", _attrs, _control);
            else
                _results = m_context.search("", _attrs);

            while (_results.hasMoreElements())
            {
                try
                {
                    // Add each entry found to the tree
                    BISearchResult _result = (BISearchResult)_results.next();
                    CatalogTreeNode _node = new CatalogTreeNode(m_model, m_fullPathName, _result);

                    insert(_node, super.getChildCount());
                }
                catch (Exception e)
                {
                }
            }
            m_children = super.getChildCount();
        }
        catch (NamingException ne)
        {
            ne.printStackTrace();
        }

        m_model.fireTreeStructureChanged(this);
    }

    /**
     * Indicates whether child nodes for this node are displayed.
     * 
     * @return <code>true</code> if child nodes are displayed,
     *         <code>false</code> if they are not.
     */
    public boolean isLoaded()
    {
        return m_loaded;
    }

    /**
     * Indicates whether this node represents a folder.
     * 
     * @param entry The search result that provides access to the object
     *              that this node represents.
     *              
     * @return <code>true</code> if this node represents a folder,
     *         <code>false</code> if it represents an object, such as a 
     *                            graph.
     */
    public boolean isFolder(BISearchResult entry)
    {
        if (entry != null)
            return PersistableConstants.FOLDER.equals(entry.getObjectType());
        else
            return true;
    }

    /**
     * Gets a child node, from an index.
     * 
     * @param index The index of the child node you want.
     */
    public TreeNode getChildAt(int index)
    {
        return super.getChildAt(index);
    }

    /**
     * Removes all child nodes.
     */
    public void removeAllChildren()
    {
        m_children = 0;
        super.removeAllChildren();
    }

    /**
     * Indicates whether this node is a leaf node (has no children).
     * 
     * @return <code>true</code> if this node has no child nodes,
     *         <code>false</code> if it has child nodes.
     */
    public boolean isLeaf()
    {
        if (isFolder(m_entry) || m_isRoot)
            return false;
        else
            return true;
    }

    /**
     * Indicates whether this node is the root node.
     * The root node represents the root folder in the Catalog.
     * 
     * @return <code>true</code> if this node is the root node,
     *         <code>false</code> if it is not.
     */
    public boolean isRoot()
    {
        return m_isRoot;
    }

    /**
     * Gets a String representation of this node.
     * 
     * @return The Catalog name of the object that this node represents.
     */
    public String toString()
    {
        return m_name;
    }
}