/*
 * Copyright (c) 2009 JSCAPE
 * 1147 S. 53rd Pl., Mesa, Arizona, 85206, U.S.A.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * JSCAPE. ("Confidential Information").  You shall not disclose such
 * Confidential Information and shall use it only in accordance with
 * the terms of the license agreement you entered into with JSCAPE.
 *
 */

package com.jscape.util.reflection;

import com.jscape.util.functor.UnaryFunction;
import com.jscape.util.functor.UnaryPredicate;

import java.lang.reflect.Field;

import static com.jscape.util.Parameters.assertNotNull;
import static com.jscape.util.reflection.FieldFinder.find;

/**
 * @author Alex Usun
 */
public class FieldGetter<T>
        extends UnaryFunction<Object, T> {

    private final UnaryPredicate<? super Field> predicate;

    @SuppressWarnings("unchecked")
    public static <T> T get(Object target, UnaryPredicate<? super Field> predicate)
            throws ReflectionException {
        try {
            Field field = find(target instanceof Class ? (Class) target : target.getClass(), predicate);
            field.setAccessible(true);
            return (T) field.get(target);
        } catch (Exception e) {
            throw new ReflectionException(e);
        }
    }

    public static <T> T get(Object target, String field)
            throws ReflectionException {
        return FieldGetter.<T>get(target, new FieldNameEquals(field));
    }

    public FieldGetter(UnaryPredicate<? super Field> predicate) {
        assertNotNull(predicate);
        this.predicate = predicate;
    }

    public T evaluate(Object value) {
        try {
            return FieldGetter.<T>get(value, this.predicate);
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }

    public String toString() {
        return "FieldGetter{"
                + "predicate=" + this.predicate
                + '}';
    }
}