// Copyright 2006, 2007, 2010 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.tapestry5.ioc.services;

import org.apache.tapestry5.ioc.Location;
import org.apache.tapestry5.ioc.ObjectCreator;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * Service used when dynamically creating new classes.
 * 
 * @deprecated In 5.3, use {@link PlasticProxyFactory} instead
 */
public interface ClassFactory
{
    /**
     * Simplified version of {@link #newClass(String, Class)} that generates a name based on the service interface name,
     * extends from java.lang.Object, and automatically adds the serviceInterface to the returned ClassFab. This is the
     * most common use when creating the kinds of proxies used throughout Tapestry IoC.
     * 
     * @param serviceInterface
     */
    ClassFab newClass(Class serviceInterface);

    /**
     * Creates a {@link ClassFab} object for the given name; the new class is a subclass of the indicated class. The new
     * class is always public and concrete.
     * 
     * @param name
     *            the full qualified name of the class to create (note that it is common to place created classes
     *            in the default package)
     * @param superClass
     *            the parent class, which is often java.lang.Object
     */

    ClassFab newClass(String name, Class superClass);

    /**
     * Imports the class to make it referenceable within the factory. The class loader for the class is added to the
     * class path. The class itself is returned, if its bytecode is available. If not, a search up the inhertance occurs
     * until a proper class (that can be referenced in generated bytecode) is found. This is necessary to handle cases
     * where a class is generated at runtime, outside of the class factory, and bytecode is not available for it.
     * 
     * @param clazz
     * @return a referenceable super-class
     */
    Class importClass(Class clazz);

    /**
     * Returns the number of classes (and interfaces) actually created.
     */

    int getCreatedClassCount();

    /**
     * Returns the class loader used when creating new classes; this is generally the same as the current thread's
     * context class loader (except perhaps during testing).
     */
    ClassLoader getClassLoader();

    /**
     * Converts a method to a {@link Location}, which includes information about the source file name and line number.
     * 
     * @param method
     *            to look up
     * @return the location, or null if the necessary information is not available
     */
    Location getMethodLocation(Method method);

    /**
     * Return a string representation for the constructor (including class and parameters) and (if available) file name
     * and line number.
     */
    Location getConstructorLocation(Constructor constructor);

    /**
     * Creates a proxy for an interface. All methods of the interface are delegated through the
     * object returned from the {@link ObjectCreator} (which is accessed on each method invocation, so it
     * is responsible for caching of the true delegate). The description will be used for the toString() method
     * (unless toString() is part of the proxy interface).
     * 
     * @param <T>
     *            type of proxy
     * @param proxyInterface
     *            proxy interface class
     * @param delegateCreator
     *         creates the delegate
     * @param description
     *            used for the toString() method
     * @since 5.2.0
     */
    <T> T createProxy(Class<T> proxyInterface, ObjectCreator delegateCreator, String description);

    /**
     * Creates a proxy for an interface. All methods of the interface are delegated through the
     * object returned from the {@link ObjectCreator} (which is accessed on each method invocation, so it
     * is responsible for caching of the true delegate). The description will be used for the toString() method
     * (unless toString() is part of the proxy interface).
     * 
     * @param <T>
     *            type of proxy
     * @param proxyInterface
     *            proxy interface class
     * @param delegateClass
     *         delegate class
     * @param delegateCreator
     *         creates the delegate
     * @param description
     *            used for the toString() method
     * @since 5.2.0
     */
    <T> T createProxy(Class<T> proxyInterface, Class<? extends T> delegateClass, ObjectCreator delegateCreator,
            String description);
}
