/*
 * (C) 2004 - Geotechnical Software Services
 * 
 * This code 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 code 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 program; if not, write to the Free 
 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, 
 * MA  02111-1307, USA.
 */
package no.geosoft.cc.directory;



import java.util.*;



/**
 * An abstract class representing an entry in a generic
 * directory structure. To an entry there is associated
 * a back-end object, the item, which is client specific.
 * 
 * @author <a href="mailto:info@geosoft.no">GeoSoft</a>
 */   
public abstract class DirectoryEntry
  implements Comparable
{
  private Collection  symbolicLinks_;
  private Folder      parent_;
  private String      name_;
  private Object      item_;  // The object that this entry represents


  
  /**
   * Create a directory entry.
   * 
   * @param item  Item contained in this directory entry.
   * @param name  Name of this directory entry.
   */
  public DirectoryEntry (Object item, String name)
  {
    item_          = item;
    name_          = name;
    symbolicLinks_ = null;
    parent_        = null;
  }
  

  
  /**
   * Create a directory entry with name according to the
   * item toString().
   * 
   * @param item  Item contained in this directory entry.
   */
  public DirectoryEntry (Object item)
  {
    this (item, item.toString());
  }



  /**
   * Compare names of the two entries.
   * 
   * @param  object  Object to compare to.
   * @return  @see String.compareTo()
   */
  public int compareTo (Object object)
  {
    return toString().compareTo (object.toString());
  }

  

  /**
   * Return true if this entry equals the specified entry.
   * 
   * @param object  Object to compare to.
   * @return        True if thw two equals, false otherwise.
   */
  public boolean equals (Object object)
  {
    if (!(object instanceof DirectoryEntry))
      return false;

    DirectoryEntry entry = (DirectoryEntry) object;

    if (item_ == null)
      return entry.item_ == null;
    else
      return item_.equals (entry.item_);
  }
  

  
  /**
   * Return true if this is a leaf entry.
   * 
   * @return  True if this is a leaf entry, false otherwise.
   */
  public abstract boolean isLeaf();
  

  
  /**
   * Return true if this is a folder entry.
   * 
   * @return  True if this is a folder entry, false otherwise.
   */
  public boolean isFolder()
  {
    return !isLeaf();
  }
  

  
  /**
   * Set name of this entry.
   * 
   * @param name
   */
  public void setName (String name)
  {
    name_ = name;
  }


  
  /**
   * Get name of this entry.
   * 
   * @return 
   */
  public String getName()
  {
    return name_;
  }


  
  /**
   * Represent this entry as a string.
   * 
   * @return  String representation of this entry.
   */
  public String toString()
  {
    return item_ != null ? item_.toString() : name_;
  }
  

  
  /**
   * Set the item of this entry.
   * 
   * @param item  Item of this entry.
   */
  public void setItem (Object item)
  {
    item_ = item;
  }


  
  /**
   * Get item of this entry.
   * 
   * @return  Item of this entry.
   */
  public Object getItem()
  {
    return item_;
  }


  
  /**
   * Add symbolic link to this entry. Entries keep set of
   * all symbolic links to self.
   * 
   * @param symbolicLink  Symbolic link to add.
   */
  void addSymbolicLink (SymbolicLink symbolicLink)
  {
    if (symbolicLinks_ == null)
      symbolicLinks_ = new ArrayList();
    symbolicLinks_.add (symbolicLink);
  }


  
  /**
   * Delete all symbolic links and the associated actual entries
   * of this entry.
   */
  void removeSymbolicLinks()
  {
    if (symbolicLinks_ == null) return;
    
    for (Iterator i = symbolicLinks_.iterator(); i.hasNext(); ) {
      DirectoryEntry directoryEntry = (DirectoryEntry) i.next();
      Folder folder = directoryEntry.getParent();
      if (folder != null) folder.remove (directoryEntry);
    }

    symbolicLinks_ = null;
  }

  

  /**
   * Set parent of this entry.
   * 
   * @param parent  Parent folder of this entry.
   */
  void setParent (Folder parent)
  {
    parent_ = parent;
  }

  

  /**
   * Get parent of this entry.
   * 
   * @return  Parent folder of this entry.
   */
  public Folder getParent()
  {
    return parent_;
  }


  
  /**
   * Return the path structure of this entry.
   * The array is suitable for use with the TreePath class.
   * 
   * @return  Array of acenstor entries.
   */
  public Object[] getPath()
  {
    List path = new ArrayList();
    path.add (this);
    DirectoryEntry parent = getParent();
    while (parent != null) {
      path.add (0, parent);
      parent = parent.getParent();
    }

    return path.toArray();
  }


  
  // DEBUG
  public abstract void print (int indent);
}