/* DefaultTreeSelectionModel.java 
   Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
   
This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing.tree;

import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.BitSet;
import java.util.EventListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.DefaultListSelectionModel;
import javax.swing.event.EventListenerList;
import javax.swing.event.SwingPropertyChangeSupport;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;

/**
 * The implementation of the default tree selection model. The installed
 * listeners are notified about the path and not the row changes. If you
 * specifically need to track the row changes, register the listener for the
 * expansion events.
 * 
 * @author Andrew Selkirk
 * @author Audrius Meskauskas
 */
public class DefaultTreeSelectionModel
    implements Cloneable, Serializable, TreeSelectionModel
{

  /**
   * According to the API docs, the method
   * {@link DefaultTreeSelectionModel#notifyPathChange} should
   * expect instances of a class PathPlaceHolder in the Vector parameter.
   * This seems to be a non-public class, so I can only make guesses about the
   * use of it.
   */
  private static class PathPlaceHolder
  {
    /**
     * The path that we wrap.
     */
    TreePath path;

    /**
     * Indicates if the path is new or already in the selection.
     */
    boolean isNew;

    /**
     * Creates a new instance.
     *
     * @param p the path to wrap
     * @param n if the path is new or already in the selection
     */
    PathPlaceHolder(TreePath p, boolean n)
    {
      path = p;
      isNew = n;
    }
  }

  /**
   * Use serialVersionUID for interoperability.
   */
  static final long serialVersionUID = 3288129636638950196L;

  /**
   * The name of the selection mode property.
   */
  public static final String SELECTION_MODE_PROPERTY = "selectionMode";

  /**
   * Our Swing property change support.
   */
  protected SwingPropertyChangeSupport changeSupport;

  /**
   * The current selection.
   */
  protected TreePath[] selection;

  /**
   * Our TreeSelectionListeners.
   */
  protected EventListenerList listenerList;

  /**
   * The current RowMapper.
   */
  protected transient RowMapper rowMapper;

  /**
   * The current listSelectionModel.
   */
  protected DefaultListSelectionModel listSelectionModel;

  /**
   * The current selection mode.
   */
  protected int selectionMode;

  /**
   * The path that has been added last.
   */
  protected TreePath leadPath;

  /**
   * The index of the last added path.
   */
  protected int leadIndex;

  /**
   * The row of the last added path according to the RowMapper.
   */
  protected int leadRow = -1;

  /**
   * A supporting datastructure that is used in addSelectionPaths() and
   * removeSelectionPaths(). It contains currently selected paths.
   *
   * @see #addSelectionPaths(TreePath[])
   * @see #removeSelectionPaths(TreePath[])
   * @see #setSelectionPaths(TreePath[])
   */
  private transient HashSet selectedPaths;

  /**
   * A supporting datastructure that is used in addSelectionPaths() and
   * removeSelectionPaths(). It contains the paths that are added or removed.
   *
   * @see #addSelectionPaths(TreePath[])
   * @see #removeSelectionPaths(TreePath[])
   * @see #setSelectionPaths(TreePath[])
   */
  private transient HashSet tmpPaths;

  /**
   * Constructs a new DefaultTreeSelectionModel.
   */
  public DefaultTreeSelectionModel()
  {
    setSelectionMode(DISCONTIGUOUS_TREE_SELECTION);
    listSelectionModel = new DefaultListSelectionModel();
    listenerList = new EventListenerList();
    leadIndex = -1;
    tmpPaths = new HashSet();
    selectedPaths = new HashSet();
  }

  /**
   * Creates a clone of this DefaultTreeSelectionModel with the same selection.
   * The cloned instance will have the same registered listeners, the listeners
   * themselves will not be cloned. The selection will be cloned.
   * 
   * @exception CloneNotSupportedException should not be thrown here
   * @return a copy of this DefaultTreeSelectionModel
   */
  public Object clone() throws CloneNotSupportedException
  {
    DefaultTreeSelectionModel cloned = 
      (DefaultTreeSelectionModel) super.clone();
    cloned.changeSupport = null;
    cloned.selection = (TreePath[]) selection.clone();
    cloned.listenerList = new EventListenerList();
    cloned.listSelectionModel =
      (DefaultListSelectionModel) listSelectionModel.clone();
    cloned.selectedPaths = new HashSet();
    cloned.tmpPaths = new HashSet();

    return cloned;
  }

  /**
   * Returns a string that shows this object's properties.
   * The returned string lists the selected tree rows, if any.
   * 
   * @return a string that shows this object's properties
   */
  public String toString() 
  {
    if (isSelectionEmpty())
      return "[selection empty]";
    else
      {
        StringBuffer b = new StringBuffer("selected rows: [");
        for (int i = 0; i < selection.length; i++)
          {
            b.append(getRow(selection[i]));
            b.append(' ');
          }
        b.append(", lead " + getLeadSelectionRow());
        return b.toString();
      }
  }

  /**
   * writeObject
   * 
   * @param value0 TODO
   * @exception IOException TODO
   */
  private void writeObject(ObjectOutputStream value0) throws IOException
  {
    // TODO
  }

  /**
   * readObject
   * 
   * @param value0 TODO
   * @exception IOException TODO
   * @exception ClassNotFoundException TODO
   */
  private void readObject(ObjectInputStream value0) throws IOException,
      ClassNotFoundException
  {
    // TODO
  }

  /**
   * Sets the RowMapper that should be used to map between paths and their rows.
   * 
   * @param mapper the RowMapper to set
   * @see RowMapper
   */
  public void setRowMapper(RowMapper mapper)
  {
    rowMapper = mapper;
    resetRowSelection();
  }

  /**
   * Returns the RowMapper that is currently used to map between paths and their
   * rows.
   * 
   * @return the current RowMapper
   * @see RowMapper
   */
  public RowMapper getRowMapper()
  {
    return rowMapper;
  }

  /**
   * Sets the current selection mode. Possible values are
   * {@link #SINGLE_TREE_SELECTION}, {@link #CONTIGUOUS_TREE_SELECTION} and
   * {@link #DISCONTIGUOUS_TREE_SELECTION}.
   * 
   * @param mode the selection mode to be set
   * @see #getSelectionMode
   * @see #SINGLE_TREE_SELECTION
   * @see #CONTIGUOUS_TREE_SELECTION
   * @see #DISCONTIGUOUS_TREE_SELECTION
   */
  public void setSelectionMode(int mode)
  {
    int oldMode = selectionMode;
    selectionMode = mode;
    // Make sure we have a valid selection mode.
    if (selectionMode != SINGLE_TREE_SELECTION
        && selectionMode != CONTIGUOUS_TREE_SELECTION
        && selectionMode != DISCONTIGUOUS_TREE_SELECTION)
      selectionMode = DISCONTIGUOUS_TREE_SELECTION;

    // Fire property change event.
    if (oldMode != selectionMode && changeSupport != null)
      changeSupport.firePropertyChange(SELECTION_MODE_PROPERTY, oldMode,
                                       selectionMode);
  }

  /**
   * Returns the current selection mode.
   * 
   * @return the current selection mode
   * @see #setSelectionMode
   * @see #SINGLE_TREE_SELECTION
   * @see #CONTIGUOUS_TREE_SELECTION
   * @see #DISCONTIGUOUS_TREE_SELECTION
   */
  public int getSelectionMode()
  {
    return selectionMode;
  }

  /**
   * Sets this path as the only selection. If this changes the selection the
   * registered TreeSelectionListeners are notified.
   * 
   * @param path the path to set as selection
   */
  public void setSelectionPath(TreePath path)
  {
    TreePath[] paths = null;
    if (path != null)
      paths = new TreePath[]{ path };
    setSelectionPaths(paths);
  }
  
  /**
   * Get the number of the tree row for the given path.
   * 
   * @param path the tree path
   * @return the tree row for this path or -1 if the path is not visible.
   */
  int getRow(TreePath path)
  {
    RowMapper mapper = getRowMapper();

    if (mapper instanceof AbstractLayoutCache)
      {
        // The absolute majority of cases, unless the TreeUI is very
        // seriously rewritten
        AbstractLayoutCache ama = (AbstractLayoutCache) mapper;
        return ama.getRowForPath(path);
      }
    else if (mapper != null)
      {
        // Generic non optimized implementation.
        int[] rows = mapper.getRowsForPaths(new TreePath[] { path });
        if (rows.length == 0)
          return - 1;
        else
          return rows[0];
      }
    return -1;
  }

  /**
   * Sets the paths as selection. This method checks for duplicates and removes
   * them. If this changes the selection the registered TreeSelectionListeners
   * are notified.
   * 
   * @param paths the paths to set as selection
   */
  public void setSelectionPaths(TreePath[] paths)
  {
    int oldLength = 0;
    if (selection != null)
      oldLength = selection.length;
    int newLength = 0;
    if (paths != null)
      newLength = paths.length;
    if (newLength > 0 || oldLength > 0)
      {
        // For SINGLE_TREE_SELECTION and for CONTIGUOUS_TREE_SELECTION with
        // a non-contiguous path, we only allow the first path element.
        if ((selectionMode == SINGLE_TREE_SELECTION && newLength > 1)
            || (selectionMode == CONTIGUOUS_TREE_SELECTION && newLength > 0
                && ! arePathsContiguous(paths)))
          {
            paths = new TreePath[] { paths[0] };
            newLength = 1;
          }
        // Find new paths.
        Vector changedPaths = null;
        tmpPaths.clear();
        int validPaths = 0;
        TreePath oldLeadPath = leadPath;
        for (int i = 0; i < newLength; i++)
          {
            if (paths[i] != null && ! tmpPaths.contains(paths[i]))
              {
                validPaths++;
                tmpPaths.add(paths[i]);
                if (! selectedPaths.contains(paths[i]))
                  {
                    if (changedPaths == null)
                      changedPaths = new Vector();
                    changedPaths.add(new PathPlaceHolder(paths[i], true));
                  }
                leadPath = paths[i];
              }
          }
        // Put together the new selection.
        TreePath[] newSelection = null;
        if (validPaths != 0)
          {
            if (validPaths != newLength)
              {
                // Some of the paths are already selected, put together
                // the new selection carefully.
                newSelection = new TreePath[validPaths];
                Iterator newPaths = tmpPaths.iterator();
                validPaths = 0;
                for (int i = 0; newPaths.hasNext(); i++)
                  newSelection[i] = (TreePath) newPaths.next();
              }
            else
              {
                newSelection = new TreePath[paths.length];
                System.arraycopy(paths, 0, newSelection, 0, paths.length);
              }
          }

        // Find paths that have been selected, but are no more.
        for (int i = 0; i < oldLength; i++)
          {
            if (selection[i] != null && ! tmpPaths.contains(selection[i]))
              {
                if (changedPaths == null)
                  changedPaths = new Vector();
                changedPaths.add(new PathPlaceHolder(selection[i], false));
              }
          }

        // Perform changes and notification.
        selection = newSelection;
        HashSet tmp = selectedPaths;
        selectedPaths = tmpPaths;
        tmpPaths = tmp;
        tmpPaths.clear();

        // Not necessary, but required according to the specs and to tests.
        if (selection != null)
          insureUniqueness();
        updateLeadIndex();
        resetRowSelection();
        if (changedPaths != null && changedPaths.size() > 0)
          notifyPathChange(changedPaths, oldLeadPath);
      }
  }

  /**
   * Adds a path to the list of selected paths. This method checks if the path
   * is already selected and doesn't add the same path twice. If this changes
   * the selection the registered TreeSelectionListeners are notified.
   * 
   * The lead path is changed to the added path. This also happen if the 
   * passed path was already selected before.
   * 
   * @param path the path to add to the selection
   */
  public void addSelectionPath(TreePath path)
  {
    if (path != null)
      {
        TreePath[] add = new TreePath[]{ path };
        addSelectionPaths(add);
      }
  }

  /**
   * Adds the paths to the list of selected paths. This method checks if the
   * paths are already selected and doesn't add the same path twice. If this
   * changes the selection the registered TreeSelectionListeners are notified.
   * 
   * @param paths the paths to add to the selection
   */
  public void addSelectionPaths(TreePath[] paths)
  {
    int length = paths != null ? paths.length : 0;
    if (length > 0)
      {
        if (selectionMode == SINGLE_TREE_SELECTION)
          setSelectionPaths(paths);
        else if (selectionMode == CONTIGUOUS_TREE_SELECTION
                 &&  ! canPathsBeAdded(paths))
          {
            if (arePathsContiguous(paths))
              setSelectionPaths(paths);
            else
              setSelectionPaths(new TreePath[] { paths[0] });
          }
        else
          {
            Vector changedPaths = null;
            tmpPaths.clear();
            int validPaths = 0;
            TreePath oldLeadPath = leadPath;
            int oldPaths = 0;
            if (selection != null)
              oldPaths = selection.length;
            int i;
            for (i = 0; i < length; i++)
              {
                if (paths[i] != null)
                  {
                    if (! selectedPaths.contains(paths[i]))
                      {
                        validPaths++;
                        if (changedPaths == null)
                          changedPaths = new Vector();
                        changedPaths.add(new PathPlaceHolder(paths[i], true));
                        selectedPaths.add(paths[i]);
                        tmpPaths.add(paths[i]);
                      }
                    leadPath = paths[i];
                  }
              }
            if (validPaths > 0)
              {
                TreePath[] newSelection = new TreePath[oldPaths + validPaths];
                if (oldPaths > 0)
                  System.arraycopy(selection, 0, newSelection, 0, oldPaths);
                if (validPaths != paths.length)
                  {
                    // Some of the paths are already selected, put together
                    // the new selection carefully.
                    Iterator newPaths = tmpPaths.iterator();
                    i = oldPaths;
                    while (newPaths.hasNext())
                      {
                        newSelection[i] = (TreePath) newPaths.next();
                        i++;
                      }
                  }
                else
                  System.arraycopy(paths, 0, newSelection, oldPaths,
                                   validPaths);
                selection = newSelection;
                insureUniqueness();
                updateLeadIndex();
                resetRowSelection();
                if (changedPaths != null && changedPaths.size() > 0)
                  notifyPathChange(changedPaths, oldLeadPath);
              }
            else
              leadPath = oldLeadPath;
            tmpPaths.clear();
          }
      }
  }

  /**
   * Removes the path from the selection. If this changes the selection the
   * registered TreeSelectionListeners are notified.
   * 
   * @param path the path to remove
   */
  public void removeSelectionPath(TreePath path)
  {
    if (path != null)
      removeSelectionPaths(new TreePath[]{ path });
  }

  /**
   * Removes the paths from the selection. If this changes the selection the
   * registered TreeSelectionListeners are notified.
   * 
   * @param paths the paths to remove
   */
  public void removeSelectionPaths(TreePath[] paths)
  {
    if (paths != null && selection != null && paths.length > 0)
      {
        if (! canPathsBeRemoved(paths))
          clearSelection();
        else
          {
            Vector pathsToRemove = null;
            for (int i = paths.length - 1; i >= 0; i--)
              {
                if (paths[i] != null && selectedPaths.contains(paths[i]))
                  {
                    if (pathsToRemove == null)
                      pathsToRemove = new Vector();
                    selectedPaths.remove(paths[i]);
                    pathsToRemove.add(new PathPlaceHolder(paths[i],
                                                          false));
                  }
              }
            if (pathsToRemove != null)
              {
                int numRemove = pathsToRemove.size();
                TreePath oldLead = leadPath;
                if (numRemove == selection.length)
                  selection = null;
                else
                  {
                    selection = new TreePath[selection.length - numRemove];
                    Iterator keep = selectedPaths.iterator();
                    for (int valid = 0; keep.hasNext(); valid++)
                      selection[valid] = (TreePath) keep.next();
                  }
                // Update lead path.
                if (leadPath != null && ! selectedPaths.contains(leadPath))
                  {
                    if (selection != null)
                      leadPath = selection[selection.length - 1];
                    else
                      leadPath = null;
                  }
                else if (selection != null)
                  leadPath = selection[selection.length - 1];
                else
                  leadPath = null;
                updateLeadIndex();
                resetRowSelection();
                notifyPathChange(pathsToRemove, oldLead);
              }
          }
      }
  }

  /**
   * Returns the first path in the selection. This is especially useful when the
   * selectionMode is {@link #SINGLE_TREE_SELECTION}.
   * 
   * @return the first path in the selection
   */
  public TreePath getSelectionPath()
  {
    if ((selection == null) || (selection.length == 0))
      return null;
    else
      return selection[0];
  }

  /**
   * Returns the complete selection.
   * 
   * @return the complete selection
   */
  public TreePath[] getSelectionPaths()
  {
    return selection;
  }

  /**
   * Returns the number of paths in the selection.
   * 
   * @return the number of paths in the selection
   */
  public int getSelectionCount()
  {
    if (selection == null)
      return 0;
    else
      return selection.length;
  }

  /**
   * Checks if a given path is in the selection.
   * 
   * @param path the path to check
   * @return <code>true</code> if the path is in the selection,
   *         <code>false</code> otherwise
   */
  public boolean isPathSelected(TreePath path)
  {
    if (selection == null)
      return false;

    for (int i = 0; i < selection.length; i++)
      {
        if (selection[i].equals(path))
          return true;
      }
    return false;
  }

  /**
   * Checks if the selection is empty.
   * 
   * @return <code>true</code> if the selection is empty, <code>false</code>
   *         otherwise
   */
  public boolean isSelectionEmpty()
  {
    return (selection == null) || (selection.length == 0);
  }

  /**
   * Removes all paths from the selection. Fire the unselection event.
   */
  public void clearSelection()
  {
    if (selection != null)
      {
        int selectionLength = selection.length;
        boolean[] news = new boolean[selectionLength];
        Arrays.fill(news, false);
        TreeSelectionEvent event = new TreeSelectionEvent(this, selection,
                                                          news, leadPath,
                                                          null);
        leadPath = null;
        leadIndex = 0;
        leadRow = 0;
        selectedPaths.clear();
        selection = null;
        resetRowSelection();
        fireValueChanged(event);
      }
  }

  /**
   * Adds a <code>TreeSelectionListener</code> object to this model.
   * 
   * @param listener the listener to add
   */
  public void addTreeSelectionListener(TreeSelectionListener listener)
  {
    listenerList.add(TreeSelectionListener.class, listener);
  }

  /**
   * Removes a <code>TreeSelectionListener</code> object from this model.
   * 
   * @param listener the listener to remove
   */
  public void removeTreeSelectionListener(TreeSelectionListener listener)
  {
    listenerList.remove(TreeSelectionListener.class, listener);
  }

  /**
   * Returns all <code>TreeSelectionListener</code> added to this model.
   * 
   * @return an array of listeners
   * @since 1.4
   */
  public TreeSelectionListener[] getTreeSelectionListeners()
  {
    return (TreeSelectionListener[]) getListeners(TreeSelectionListener.class);
  }

  /**
   * fireValueChanged
   * 
   * @param event the event to fire.
   */
  protected void fireValueChanged(TreeSelectionEvent event)
  {
    TreeSelectionListener[] listeners = getTreeSelectionListeners();

    for (int i = 0; i < listeners.length; ++i)
      listeners[i].valueChanged(event);
  }

  /**
   * Returns all added listeners of a special type.
   * 
   * @param listenerType the listener type
   * @return an array of listeners
   * @since 1.3
   */
  public <T extends EventListener> T[] getListeners(Class<T> listenerType)
  {
    return listenerList.getListeners(listenerType);
  }

  /**
   * Returns the currently selected rows.
   * 
   * @return the currently selected rows
   */
  public int[] getSelectionRows()
  {
    int[] rows = null;
    if (rowMapper != null && selection != null)
      {
        rows = rowMapper.getRowsForPaths(selection);
        if (rows != null)
          {
            // Find invisible rows.
            int invisible = 0;
            for (int i = rows.length - 1; i >= 0; i--)
              {
                if (rows[i] == -1)
                  invisible++;
                
              }
            // Clean up invisible rows.
            if (invisible > 0)
              {
                if (invisible == rows.length)
                  rows = null;
                else
                  {
                    int[] newRows = new int[rows.length - invisible];
                    int visCount = 0;
                    for (int i = rows.length - 1; i >= 0; i--)
                      {
                        if (rows[i] != -1)
                          {
                            newRows[visCount] = rows[i];
                            visCount++;
                          }
                      }
                    rows = newRows;
                  }
              }
          }
      }
    return rows;
  }

  /**
   * Returns the smallest row index from the selection.
   * 
   * @return the smallest row index from the selection
   */
  public int getMinSelectionRow()
  {
    return listSelectionModel.getMinSelectionIndex();
  }

  /**
   * Returns the largest row index from the selection.
   * 
   * @return the largest row index from the selection
   */
  public int getMaxSelectionRow()
  {
    return listSelectionModel.getMaxSelectionIndex();
  }

  /**
   * Checks if a particular row is selected.
   * 
   * @param row the index of the row to check
   * @return <code>true</code> if the row is in this selection,
   *         <code>false</code> otherwise
   * @throws NullPointerException if the row mapper is not set (can only happen
   *           if the user has plugged in the custom incorrect TreeUI
   *           implementation.
   */
  public boolean isRowSelected(int row)
  {
    return listSelectionModel.isSelectedIndex(row);
  }

  /**
   * Updates the mappings from TreePaths to row indices.
   */
  public void resetRowSelection()
  {
    listSelectionModel.clearSelection();
    if (selection != null && rowMapper != null)
      {
        int[] rows = rowMapper.getRowsForPaths(selection);
        // Update list selection model.
        for (int i = 0; i < rows.length; i++)
          {
            int row = rows[i];
            if (row != -1)
              listSelectionModel.addSelectionInterval(row, row);
          }
        // Update lead selection.
        if (leadIndex != -1 && rows != null)
          leadRow = rows[leadIndex];
        else if (leadPath != null)
          {
            TreePath[] tmp = new TreePath[]{ leadPath };
            rows = rowMapper.getRowsForPaths(tmp);
            leadRow = rows != null ? rows[0] : -1;
          }
        else
          leadRow = -1;
        insureRowContinuity();
      }
    else
      leadRow = -1;
  }

  /**
   * getLeadSelectionRow
   * 
   * @return int
   */
  public int getLeadSelectionRow()
  {
    return leadRow;
  }

  /**
   * getLeadSelectionPath
   * 
   * @return TreePath
   */
  public TreePath getLeadSelectionPath()
  {
    return leadPath;
  }

  /**
   * Adds a <code>PropertyChangeListener</code> object to this model.
   * 
   * @param listener the listener to add.
   */
  public void addPropertyChangeListener(PropertyChangeListener listener)
  {
    if (changeSupport == null)
      changeSupport = new SwingPropertyChangeSupport(this);
    changeSupport.addPropertyChangeListener(listener);
  }

  /**
   * Removes a <code>PropertyChangeListener</code> object from this model.
   * 
   * @param listener the listener to remove.
   */
  public void removePropertyChangeListener(PropertyChangeListener listener)
  {
    if (changeSupport != null)
      changeSupport.removePropertyChangeListener(listener);
  }

  /**
   * Returns all added <code>PropertyChangeListener</code> objects.
   * 
   * @return an array of listeners.
   * @since 1.4
   */
  public PropertyChangeListener[] getPropertyChangeListeners()
  {
    PropertyChangeListener[] listeners = null;
    if (changeSupport != null)
      listeners = changeSupport.getPropertyChangeListeners();
    else
      listeners = new PropertyChangeListener[0];
    return listeners;
  }

  /**
   * Makes sure the currently selected paths are valid according to the current
   * selectionMode. If the selectionMode is set to
   * {@link #CONTIGUOUS_TREE_SELECTION} and the selection isn't contiguous then
   * the selection is reset to the first set of contguous paths. If the
   * selectionMode is set to {@link #SINGLE_TREE_SELECTION} and the selection
   * has more than one path, the selection is reset to the contain only the
   * first path.
   */
  protected void insureRowContinuity()
  {
    if (selectionMode == CONTIGUOUS_TREE_SELECTION && selection != null
        && rowMapper != null)
      {
        int min = listSelectionModel.getMinSelectionIndex();
        if (min != -1)
          {
            int max = listSelectionModel.getMaxSelectionIndex();
            for (int i = min; i <= max; i++)
              {
                if (! listSelectionModel.isSelectedIndex(i))
                  {
                    if (i == min)
                      clearSelection();
                    else
                      {
                        TreePath[] newSelection = new TreePath[i - min];
                        int[] rows = rowMapper.getRowsForPaths(selection);
                        for (int j = 0; j < rows.length; j++)
                          {
                            if (rows[j] < i)
                              newSelection[rows[j] - min] = selection[j];
                          }
                        setSelectionPaths(newSelection);
                        break;
                      }
                  }
              }
          }
      }
    else if (selectionMode == SINGLE_TREE_SELECTION && selection != null
        && selection.length > 1)
      setSelectionPath(selection[0]);
  }
  
  /**
   * Returns <code>true</code> if the paths are contiguous (take subsequent
   * rows in the diplayed tree view. The method returns <code>true</code> if
   * we have no RowMapper assigned.
   * 
   * @param paths the paths to check for continuity
   * @return <code>true</code> if the paths are contiguous or we have no
   *         RowMapper assigned
   */
  protected boolean arePathsContiguous(TreePath[] paths)
  {
    if (rowMapper == null || paths.length < 2)
      return true;

    int length = paths.length;
    TreePath[] tmp = new TreePath[1];
    tmp[0] = paths[0];
    int min = rowMapper.getRowsForPaths(tmp)[0];
    BitSet selected = new BitSet();
    int valid = 0;
    for (int i = 0; i < length; i++)
      {
        if (paths[i] != null)
          {
            tmp[0] = paths[i];
            int[] rows = rowMapper.getRowsForPaths(tmp);
            if (rows == null)
              return false; // No row mapping yet, can't be selected.
            int row = rows[0];
            if (row == -1 || row < (min - length) || row > (min + length))
              return false; // Not contiguous.
            min = Math.min(min, row);
            if (! selected.get(row))
              {
                selected.set(row);
                valid++;
              }
            
          }
      }
    int max = valid + min;
    for (int i = min; i < max; i++)
      if (! selected.get(i))
        return false; // Not contiguous.
    return true;
  }

  /**
   * Checks if the paths can be added. This returns <code>true</code> if:
   * <ul>
   * <li><code>paths</code> is <code>null</code> or empty</li>
   * <li>we have no RowMapper assigned</li>
   * <li>nothing is currently selected</li>
   * <li>selectionMode is {@link #DISCONTIGUOUS_TREE_SELECTION}</li>
   * <li>adding the paths to the selection still results in a contiguous set of
   * paths</li>
   * 
   * @param paths the paths to check
   * @return <code>true</code> if the paths can be added with respect to the
   *         selectionMode
   */
  protected boolean canPathsBeAdded(TreePath[] paths)
  {
    if (paths == null || paths.length == 0 || rowMapper == null
        || selection == null || selectionMode == DISCONTIGUOUS_TREE_SELECTION)
      return true;

    BitSet selected = new BitSet();
    int min = listSelectionModel.getMinSelectionIndex();
    int max = listSelectionModel.getMaxSelectionIndex();
    TreePath[] tmp = new TreePath[1];
    if (min != -1)
      {
        // Set the bitmask of selected elements.
        for (int i = min; i <= max; i++)
          selected.set(i);
      }
    else
      {
        tmp[0] = paths[0];
        min = rowMapper.getRowsForPaths(tmp)[0];
        max = min;
      }
    // Mark new paths as selected.
    for (int i = paths.length - 1; i >= 0; i--)
      {
        if (paths[i] != null)
          {
            tmp[0] = paths[i];
            int[] rows = rowMapper.getRowsForPaths(tmp);
            if (rows == null)
              return false; // Now row mapping yet, can't be selected.
            int row = rows[0];
            if (row == -1)
              return false; // Now row mapping yet, can't be selected.
            min = Math.min(min, row);
            max = Math.max(max, row);
            selected.set(row);
          }
      }
    // Now look if the new selection would be contiguous.
    for (int i = min; i <= max; i++)
      if (! selected.get(i))
        return false;
    return true;
  }
  
  /**
   * Checks if the paths can be removed without breaking the continuity of the
   * selection according to selectionMode.
   * 
   * @param paths the paths to check
   * @return <code>true</code> if the paths can be removed with respect to the
   *         selectionMode
   */
  protected boolean canPathsBeRemoved(TreePath[] paths)
  {
    if (rowMapper == null || isSelectionEmpty()
        || selectionMode == DISCONTIGUOUS_TREE_SELECTION)
      return true;
    
    HashSet set = new HashSet();
    for (int i = 0; i < selection.length; i++)
      set.add(selection[i]);
    
    for (int i = 0; i < paths.length; i++)
      set.remove(paths[i]);
    
    TreePath[] remaining = new TreePath[set.size()];
    Iterator iter = set.iterator();
    
    for (int i = 0; i < remaining.length; i++)
      remaining[i] = (TreePath) iter.next();
    
    return arePathsContiguous(remaining);
  }

  /**
   * Notify the installed listeners that the given patches have changed. This
   * method will call listeners if invoked, but it is not called from the
   * implementation of this class.
   * 
   * @param vPaths the vector of the changed patches
   * @param oldLeadSelection the old selection index
   */
  protected void notifyPathChange(Vector vPaths, TreePath oldLeadSelection)
  {

    int numChangedPaths = vPaths.size();
    boolean[] news = new boolean[numChangedPaths];
    TreePath[] paths = new TreePath[numChangedPaths];
    for (int i = 0; i < numChangedPaths; i++)
      {
        PathPlaceHolder p = (PathPlaceHolder) vPaths.get(i);
        news[i] = p.isNew;
        paths[i] = p.path;
      }

    TreeSelectionEvent event = new TreeSelectionEvent(this, paths, news,
                                                      oldLeadSelection,
                                                      leadPath);
    fireValueChanged(event);
  }

  /**
   * Updates the lead selection row number after changing the lead selection
   * path.
   */
  protected void updateLeadIndex()
  {
    leadIndex = -1;
    if (leadPath != null)
      {
        leadRow = -1;
        if (selection == null)
          leadPath = null;
        else
          {
            for (int i = selection.length - 1; i >= 0 && leadIndex == -1; i--)
              {
                if (selection[i] == leadPath)
                  leadIndex = i;
              }
          }
      }
  }

  /**
   * This method exists due historical reasons and returns without action
   * (unless overridden). For compatibility with the applications that override
   * it, it is still called from the {@link #setSelectionPaths(TreePath[])} and
   * {@link #addSelectionPaths(TreePath[])}.
   */
  protected void insureUniqueness()
  {
    // Following the API 1.4, the method should return without action.
  }
}
