lojix/state/src/main/com/thesett/aima/state/impl/PropertyIntrospectorBase.java
protected void setProperty(Object callee, String property, Object value)
    {
        // Initialize this meta bean if it has not already been initialized.
        if (!initialized)
        {
            initialize(callee);
        }

        // Check that at least one setter method exists for the property.
        Method[] setterMethods = setters.get(property);

        if ((setterMethods == null) || (setterMethods.length == 0))
        {
            throw new IllegalArgumentException("No setter method for the property " + property + " exists.");
        }

        // Choose which setter method to call based on the type of the value argument. If the value argument is null
        // then call the first available one.
        Method setterMethod = null;
        Class valueType = (value == null) ? null : value.getClass();

        // Check if the value is null and use the first available setter if so, as type cannot be extracted.
        if (value == null)
        {
            setterMethod = setterMethods[0];
        }

        // Loop through the available setter methods for one that matches the arguments type.
        else
        {
            for (Method method : setterMethods)
            {
                Class argType = method.getParameterTypes()[0];

                if (argType.isAssignableFrom(valueType))
                {
                    setterMethod = method;

                    break;
                }

                // Check if the arg type is primitive but the value type is a wrapper type that matches it.
                else if (argType.isPrimitive() && !valueType.isPrimitive() &&
                        isAssignableFromPrimitive(valueType, argType))
                {
                    setterMethod = method;

                    break;
                }

                // Check if the arg type is a wrapper but the value type is a primitive type that matches it.
                else if (valueType.isPrimitive() && !argType.isPrimitive() &&
                        isAssignableFromPrimitive(argType, valueType))
                {
                    setterMethod = method;

                    break;
                }
            }

            // Check if this point has been reached but no matching setter method could be found, in which case raise
            // an exception.
            if (setterMethod == null)
            {
                Class calleeType = (callee == null) ? null : callee.getClass();

                throw new IllegalArgumentException("No setter method for property " + property + ", of type, " +
                    calleeType + " will accept the type of value specified, " + valueType + ".");
            }
        }

        // Call the setter method with the value.
        try
        {
            Object[] args = new Object[] { value };
            setterMethod.invoke(callee, args);
        }
        catch (InvocationTargetException e)
        {
            throw new IllegalArgumentException("The setter method for the property " + property +
                " threw an invocation target exception.", e);
        }

        // This should never happen as the initiliazed method should already have checked this.
        catch (IllegalAccessException e)
        {
            throw new IllegalStateException("The setter method for the property " + property + " cannot be accessed.", e);
        }
    }
protected void setProperty(Object callee, String property, Object value)
    {
        // Initialize this meta bean if it has not already been initialized.
        if (!initialized)
        {
            initialize(callee);
        }

        // Check that at least one setter method exists for the property.
        Method[] setterMethods = setters.get(property);

        if ((setterMethods == null) || (setterMethods.length == 0))
        {
            throw new IllegalArgumentException("No setter method for the property " + property + " exists.");
        }

        // Choose which setter method to call based on the type of the value argument. If the value argument is null
        // then call the first available one.
        Method setterMethod = null;
        Class valueType = (value == null) ? null : value.getClass();

        // Check if the value is null and use the first available setter if so, as type cannot be extracted.
        if (value == null)
        {
            setterMethod = setterMethods[0];
        }

        // Loop through the available setter methods for one that matches the arguments type.
        else
        {
            for (Method method : setterMethods)
            {
                Class argType = method.getParameterTypes()[0];

                if (argType.isAssignableFrom(valueType))
                {
                    setterMethod = method;

                    break;
                }

                // Check if the arg type is primitive but the value type is a wrapper type that matches it.
                else if (argType.isPrimitive() && !valueType.isPrimitive() &&
                        isAssignableFromPrimitive(valueType, argType))
                {
                    setterMethod = method;

                    break;
                }

                // Check if the arg type is a wrapper but the value type is a primitive type that matches it.
                else if (valueType.isPrimitive() && !argType.isPrimitive() &&
                        isAssignableFromPrimitive(argType, valueType))
                {
                    setterMethod = method;

                    break;
                }
            }

            // Check if this point has been reached but no matching setter method could be found, in which case raise
            // an exception.
            if (setterMethod == null)
            {
                Class calleeType = (callee == null) ? null : callee.getClass();

                throw new IllegalArgumentException("No setter method for property " + property + ", of type, " +
                    calleeType + " will accept the type of value specified, " + valueType + ".");
            }
        }

        // Call the setter method with the value.
        try
        {
            Object[] args = new Object[] { value };
            setterMethod.invoke(callee, args);
        }
        catch (InvocationTargetException e)
        {
            throw new IllegalArgumentException("The setter method for the property " + property +
                " threw an invocation target exception.", e);
        }

        // This should never happen as the initiliazed method should already have checked this.
        catch (IllegalAccessException e)
        {
            throw new IllegalStateException("The setter method for the property " + property + " cannot be accessed.", e);
        }
    }
Sets the value of a property of the bean by name.

@param callee   The object to call the setter method on.
@param property The name of the property to set.
@param value    The value of the property to set.