/*

License $Id: AdapterFinder.java,v 1.1 2001/05/06 14:55:01 Hendrik Exp $

Copyright (c) 2001 tagtraum industries.

The sixbs library 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 library 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 library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

For LGPL see <http://www.fsf.org/copyleft/lesser.txt>

We encourage your feedback and suggestions and want to use your feedback to
improve the Software. Send all such feedback to:
feedback@tagtraum.com

For more information on tagtraum industries, Hendrik Schreiber and sixbs
please see <http://www.tagtraum.com/>.

*/

package com.tagtraum.sixbs;

import java.util.Vector;
import java.util.Enumeration;
import com.tagtraum.sixbs.adapters.util.ArrayListAdapt;

/**
 * Searches for Adapater classes. First the same package as the class's is
 * checked. Then the package searchpath is searched.
 * 
 * @author 	Hendrik Schreiber
 * @version $Id: AdapterFinder.java,v 1.1 2001/05/06 14:55:01 Hendrik Exp $
 * @see Adapter
 */
public class AdapterFinder {

    /**
     * Source-Version
     */
    public static String	vcid = 
	"$Id: AdapterFinder.java,v 1.1 2001/05/06 14:55:01 Hendrik Exp $";
    
    private static final String ADAPT = "Adapt";
    private static AdapterFinder defaultAdapterFinder = new AdapterFinder();
    
    private Vector searchPath;
    
    public AdapterFinder() {
        searchPath = new Vector();
        addDefaultPackages();
    }
    
    /**
     * Is called by the constructor and adds <code>com.tagtraum.sixbs.adapters.util</code>.
     */
    protected void addDefaultPackages() {
        // add default packages
        // util
        addPackage("com.tagtraum.sixbs.adapters.util");
        // net
        //addPackage("com.tagtraum.sixbs.adapters.net");
    }
    
    
    /**
     * Adds a package to the searchpath.
     * Type-safe adding of packages to the searchpath. Note that package objects
     * are not necessarily available.
     *
     * @see java.lang.Package#getPackage(String)
     * @see #addPackage(String)
     */
    public void addPackage(Package pakkage) {
        searchPath.add(pakkage.getName());
    }
    
    /**
     * Removes a package from the searchpath.
     * Type-safe removing of packages to the searchpath. Note that package objects
     * are not necessarily available.
     *
     * @see java.lang.Package#getPackage(String)
     * @see #removePackage(String)
     */
    public void removePackage(Package pakkage) {
        searchPath.remove(pakkage.getName());
    }

    /**
     * Adds a package to the searchpath.
     */
    public void addPackage(String pakkage) {
        searchPath.add(pakkage);
    }
    
    /**
     * Removes a package from the searchpath.
     */
    public void removePackage(String pakkage) {
        searchPath.remove(pakkage);
    }

    /**
     * Enumeration of all package in the searchpath.
     */
    public Enumeration packages() {
        return searchPath.elements();
    }

    /**
     * Returns default AdapterFinder.
     */
    public static AdapterFinder getDefaultAdapterFinder() {
        return defaultAdapterFinder;
    }
    
    /**
     * Returns an Adapter class for the given object or null if none is found.
     */
    public Class find(Object object) {
        return find(object.getClass());
    }

    /**
     * Returns an Adapter class for the given class or null if none is found.
     */
    public Class find(Class klass) {
        // try same package first
        Class adapterClass = getAdapterClass(klass);
        String className = getClassName(klass);
        for (int i=0; i<searchPath.size() && adapterClass == null; i++) {
            adapterClass = getAdapterClass((String)searchPath.get(i), className);
        }
        return adapterClass;
    }
    
    
    private Class getAdapterClass(Class klass) {
        try {
            return Class.forName(klass.getName() + ADAPT);
        }
        catch (ClassNotFoundException cnfe) {
            // ignore
        }
        return null;
    }

    private Class getAdapterClass(String pakkage, String className) {
        try {
            // check for default package.
            if ("".equals(pakkage)) return Class.forName(className);
            else return Class.forName(pakkage + "." + className);
        }
        catch (ClassNotFoundException cnfe) {
            // ignore
        }
        return null;
    }
    
    private static final String getClassName(Class klass) {
        String classname = klass.getName();
        int dot = classname.lastIndexOf('.');
        if (dot != -1) {
            classname = classname.substring(dot + 1);
        }
        return classname + ADAPT;
    } 
}