//  Copyright 2004 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.apache.tapestry.enhance.javassist;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.LoaderClassPath;
import javassist.NotFoundException;

import org.apache.tapestry.IResourceResolver;
import org.apache.tapestry.enhance.CodeGenerationException;
import org.apache.tapestry.enhance.EnhancedClassLoader;
import org.apache.tapestry.enhance.IEnhancedClass;
import org.apache.tapestry.enhance.IEnhancedClassFactory;

/**
 *  This class defines the factory for creation of new Javassist enhanced classes. 
 *  There is typically only one object of this class in the system. 
 *  Common functionality objects for Javassist enhancement are stored here.
 * 
 *  @author Mindbridge
 *  @version $Id: EnhancedClassFactory.java 385802 2006-03-14 13:47:10Z jkuhnert $
 *  @since 3.0
 */
public class EnhancedClassFactory implements IEnhancedClassFactory
{
    private IResourceResolver _resourceResolver;
    private EnhancedClassLoader _enhancedClassLoader;
    private ClassPool _classPool;

    private ClassMapping _typeMap = null;

    public EnhancedClassFactory(IResourceResolver resourceResolver)
    {
        _resourceResolver = resourceResolver;

        reset();
    }
    
    protected ClassPool createClassPool()
    {
        ClassLoader loader = _resourceResolver.getClassLoader();
        
        // create a new ClassPool and make sure it uses the application resource resolver 
        ClassPool classPool = new ClassPool(null);
        classPool.insertClassPath(new LoaderClassPath(loader));
        
        return classPool;
    }
    
    /**
     * @see org.apache.tapestry.enhance.IEnhancedClassFactory#reset()
     */
    public synchronized void reset()
    {
        // create a new class pool and discard the previous one
        _classPool = createClassPool();
        _typeMap = new ClassMapping(_classPool);

        ClassLoader loader = _resourceResolver.getClassLoader();
        _enhancedClassLoader = new EnhancedClassLoader(loader);
    }
   

    /**
     * @see org.apache.tapestry.enhance.IEnhancedClassFactory#createEnhancedClass(java.lang.String, java.lang.Class)
     */
    public IEnhancedClass createEnhancedClass(String className, Class parentClass)
    {
        return new EnhancedClass(className, parentClass, this);
    }

    public ClassPool getClassPool()
    {
        return _classPool;
    }

    public ClassMapping getClassMapping()
    {
        return _typeMap;
    }

    /**
     *  Given the java class, returns the equivalent {@link CtClass type}.  In addition,
     *  knows about scalar types, arrays of scalar types, java.lang.Object[] and
     *  java.lang.String[].
     * 
     **/

    public CtClass getObjectType(String type)
    {

            synchronized (this) {
                CtClass result = getClassMapping().getType(type);

                if (result == null)
                {
                    try
                    {
                        result = _classPool.get(type);
                        getClassMapping().recordType(type, result);
                    }
                    catch (NotFoundException e)
                    {
                        throw new CodeGenerationException(e);
                    }
                }
                return result;
            }

    }


    /**
     * @return The class loader to be used to create the enhanced class
     */
    public EnhancedClassLoader getEnhancedClassLoader()
    {
        return _enhancedClassLoader;
    }

}
