/*
 *  @author Ranides Atterwim <ranides@gmail.com>
 *  @copyright Ranides Atterwim
 *  @license WTFPL
 *  @url http://ranides.net/projects/assira
 */

package net.ranides.assira.reflection.util;

import net.ranides.assira.reflection.InspectException;
import net.ranides.assira.reflection.MethodFactory.ConstructorPointer;
import net.ranides.assira.reflection.inspect.MethodInspector;

/**
 *
 * @author ranides
 */
public final class ObjectUtils {

    private ObjectUtils() {
    }

    /**
     * Tworzy obiekt podanej klasy wywołując <b>najlepiej pasujący</b> konstruktor.
     * Uwzględnia niepubliczne konstruktory.
     * @param <T>
     * @param clazz
     * @param arguments 
     * @return
     * @throws InspectException  
     */
    public static <T> T create(Class<T> clazz, Object... arguments) throws InspectException {
        return MethodInspector
            .inclass(clazz).constructors().paramsMatch(arguments).first()
            .call(arguments);
    }

    /**
     * Tworzy obiekt podanej klasy wywołując domyślny konstruktor. Uwzględnia 
     * bezargumentowy konstruktor prywatny, jeśli taki zadeklarowano.
     * @param <T>
     * @param clazz
     * @return
     * @throws InspectException
     */
    public static <T> T create(Class<T> clazz) throws InspectException {
        ConstructorPointer<T> ctor = MethodInspector
            .inclass(clazz).constructors().params().first();
        if(null != ctor) {
            return ctor.call();
        }
        // jeśli nie znaleziono zadeklarowanego konstruktora bezargumentowego, 
        // spróbujmy utworzyć za pomocą konstruktora domyślnego
        try {
            return clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException cause) {
            throw new InspectException(cause);
        } 
    }

}
