package de.renew.formalism.function;

import java.lang.reflect.Array;
import java.lang.reflect.Field;

import de.renew.expression.Function;
import de.renew.unify.Impossible;
import de.renew.util.Value;

/**
 * A function that reads the value of a named field from an object.
 */
public class DynamicFieldFunction implements Function {
    /**
     * The name of the field to be read from the object.
     */
    private final String _field;

    /**
     * Creates an instance of this class describing a class field by its name.
     *
     * @param field the name of the class field
     */
    public DynamicFieldFunction(String field) {
        this._field = field;
    }

    @Override
    public Object function(Object param) throws Impossible {
        try {
            if (param.getClass().isArray()) {
                if ("length".equals(_field)) {
                    return new Value(Array.getLength(param));
                } else {
                    throw new Impossible();
                }
            }

            Field theField = param.getClass().getField(_field);

            return Value.possiblyWrap(theField.get(param), theField.getType().isPrimitive());
        } catch (Exception e) {
            throw new Impossible(
                "Exception occurred during dynamic field access (" + _field + " on object " + param
                    + "): " + e,
                e);
        }
    }

    @Override
    public String toString() {
        return "DynFieldFunc(" + _field + ")";
    }
}