// (c) MIT 2003.  All rights reserved.

// -*-Mode: Java-*- 
// $Id: ClassFinder.java,v 1.8 2003/05/09 21:22:32 moltmans Exp $
// ClassFinder.java -- 
// Author: Michael Oltmans <moltmans@ai.mit.edu> 
// Created: <Wed Feb  9 19:29:46 2000> 
// Time-stamp: <2003-04-17 15:46:24 moltmans> 
package rec.util;

import java.io.File;
import java.lang.ClassLoader;
import java.net.*;
import java.util.*;
import javax.swing.ImageIcon;

public class ClassFinder 
{
  static ClassFinder m_finder = new ClassFinder();
  
  public static Class find( String name )
  {
    try {
      return Class.forName( name );
    }
    catch( ClassNotFoundException e ) {
      Assert.error( "bad/unrecognized widget class name: " + name);
      e.printStackTrace();
    }
    return null;
  }


//    /**
//     * Return a url to the directory containing rec
//     *
//     * Will genererally return the equivalent of:
//     *   file:/home/user/hal/classes/
//     * Where rec is in the classes directory.
//     * One important note is that it ends with "/"
//     **/
//    public static URL getRecLoadBase()
//    {
//      URL rec = ClassLoader.getSystemResource( "rec" );
//      Assert.check( rec != null,
//  		  "Could not find the rec directory" );

//      String base = rec.getFile();

//      int i = base.lastIndexOf( "rec" );
//      try {
//        return new URL( rec, base.substring( 0, i ) );
//      }
//      catch( MalformedURLException e ) {
//        e.printStackTrace();
//        return null;
//      }

//    /**
//     * @param resource Should be of the form
//     * rec/subdir/file.ext
//     **/
//    public static URL getRecResource( String resource )
//    {
//      try {
//        return new URL( getRecLoadBase(), resource );
//      }
//      catch( MalformedURLException e ) {
//        e.printStackTrace();
//        return null;
//      }
//    }

  public static URL getResource(String resource) 
  {
    return getResource(m_finder, resource);
  }

  public static URL getResource(Object root, String resource)
  {
    URL url = root.getClass().getResource(resource);
    if (url == null) {
      url = root.getClass().getResource("/" + resource);
    }
    if (url == null) {
      url = root.getClass().getResource("/rec/" + resource);
    }
    if (url == null) {
      url = ClassLoader.getSystemResource(resource);
    }
    if (url == null && resource.indexOf(":") != -1 ) {
      File file = new File( resource );
      if ( file.exists() ) {
	try {
	  url = file.toURL();
	}
	catch ( MalformedURLException e ){
	}
      }
    }
    if (url == null) {
      Assert.note("Could not find the requested resource: " + resource);
    }
    return url;
  }

  /**
   * It first tries to find resource relative to the path that the
   * root class is in.  Second it searches in the root of the
   * classpath.  Finally, it searches in the rec subdirectory.
   **/
  public static String getResourcePath( String resource ) 
  {
    return getResourcePath(m_finder, resource);
  }

  /**
   * It first tries to find resource relative to the path that the
   * root class is in.  Second it searches in the root of the
   * classpath.  Finally, it searches in the rec subdirectory.
   **/
  public static String getResourcePath( Object root, String resource )
  {
    URL url = getResource(root, resource);
    File f = new File(url.getFile());
    return f.getAbsolutePath();
  }

  /**
   * Get all the super classes and interfaces cls is derived from.
   **/
  public static Collection getSupers( Class cls )
  {
    return getSupers( cls, find( "java.lang.Object" ) );
  }

  /**
   * Get all the super classes and interfaces cls is derived from up
   * to and including the given root class.
   **/
  public static Collection getSupers( Class cls, Class root ) 
  {
    HashSet set = new HashSet();

    if (cls == null) {
      return set;
    }
    
    LinkedList queue = new LinkedList();

    Class parent;
    queue.add( cls );
    
    while ( ! queue.isEmpty() )
    {
      parent = (Class)queue.removeFirst();
      set.add( parent );
      if ( (parent.getSuperclass() != null) &&
	   (parent != root))
      {	
	queue.addAll( Arrays.asList( parent.getInterfaces() ) );
	queue.add( parent.getSuperclass() );
      }
      
    }

    return set;
  }

  /**
   * Get an icon with the given textual description and the given path
   * to its image.
   **/
  public static ImageIcon getIcon( String imageLocation )
  {
    ImageIcon icon = null;
    URL iconURL = getResource( imageLocation );
    if (iconURL != null) {
      return new ImageIcon(iconURL );
    }
    return null;
  }
  

  public static void main( String[] argv ) 
  {
    if ( argv.length == 1 ) {
      System.out.println(getSupers(find(argv[0])));
    }
    else if (argv.length == 2 ) {
      System.out.println(getSupers(find(argv[0]), find(argv[1])));
    }
    else {
      System.out.println( "must give a class name" );
    }
  }
  
}
