import javax.swing.tree.TreePath;
import javax.swing.tree.TreeModel;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;

// 'data' may be null (because JTree allows it)
// can only listen to one TreeModel 
// has been changed from earlier versions in that all methods take
// the TreeModelEvent
public abstract class AbstractTreeModelListener
   implements TreeModelListener
{
    private Object root;

    protected AbstractTreeModelListener(TreeModel data)
    {
        root = data == null ? null : data.getRoot();
    }

    // Call whenever the listener is attached to another TreeModel.
    public void sourceReplaced(TreeModel old, TreeModel data)
    {
        root = data == null ? null : data.getRoot();
    }

    public final void treeNodesChanged(TreeModelEvent e)
    {
        if (e.getChildren() == null)
            rootChanged(e);
        else
            childrenChanged(e);
    }

    public final void treeNodesInserted(TreeModelEvent e)
    {
        childrenAdded(e);
    }

    public final void treeNodesRemoved(TreeModelEvent e)
    {
        childrenRemoved(e);
    }

    public final void treeStructureChanged(TreeModelEvent e)
    {
        TreePath path = e.getTreePath();

        if (path == null)
            newRoot(e);
        else if (path.getPathCount() == 1)
        {
            Object newRoot = path.getLastPathComponent();
        
            /* newRoot cannot be null (is part of TreePath) */

            if (!newRoot.equals(root))
            {
                root = newRoot;
                newRoot(e);
            }
            else
                structureChanged(e);
        }
        else
            structureChanged(e);
    }

    /** Invoked when the root has changed (i.e. properties of the root node). */
    protected abstract void rootChanged(TreeModelEvent e);

    /** Invoked when children of the event's tree path have changed. */
    protected abstract void childrenChanged(TreeModelEvent e);

    /** Invoked when children were added to the event's tree path. */
    protected abstract void childrenAdded(TreeModelEvent e);

    /** Invoked when children were removed from the event's tree path. */
    protected abstract void childrenRemoved(TreeModelEvent e);

    /** Invoked when there is a new root (i.e. a new object).
        The new root is the event's path's last component, or null */
    protected abstract void newRoot(TreeModelEvent e);
    
    /** Invoked when the structure below the event's tree path changed. */
    protected abstract void structureChanged(TreeModelEvent e);
}

