## Creating Function Libraries

The Able Rule Language supports function libraries which enables a class you provide to be imported so that its public methods are available from the ruleset. Now that ARL supports direct invocation of methods on imported objects, the value of function libraries is limited. Each method in a function library is converted to a UserDefinedFunction object and UDF use is slower than direct method invocation. We have considered removing all function library support but have not yet done so, opting instead to convert methods that once were part of function libraries to direct method calls or to include static helper methods in the ARL class.

If you wish to use function libraries, the class you provide must:

- include a public no-argument constructor
- be serializable, if you intend to serialize your Able ruleset

Public methods should be distinctly named to avoid name conflicts. Both built-in functions and externally attached functions will take preferece over imported function library methods. Prefixing the method with the object type is a convention followed in the function libraries provided with Able. For example, rather than generic methods such as reset or indexOf, AbleBeanLib provides resetBean and AbleStringLib provides stringIndexOf.

Numeric parameters should be passed as doubles and cast as necessary. Parameters may be validated and exceptions logged or thrown as desired. Parameters are typically double, String, Vector, or user-defined objects. Results may be returned if desired. Methods may use the logging and tracing facilities provided with Able. Methods that are not static must be used as function library methods which internally are user defined functions. Static methods may be called with standard Java class.method invocation.

### Examples

This stringIndexOf method based on the AbleStringLib implementation illustrates parameter validatation, String passing, exception handling, message and trace logging, and returns an int obtained from the java.lang.String indexOf method. In this case its left up to the indexOf method to throw a runtime exception.

>     public int  stringIndexOf(String target, String str) {
>         enterMethod("stringIndexOf()");
>         if (target == null) {
>     	String eMsg = Able.NlsMsg(Able.Ex_BeanLibNullArg, new Object[]{"target"});
>             Able.MessageLog.text(Able.MSG_ERROR, this, "stringIndexOf", eMsg);
>             Able.TraceLog.exception(Able.TRC_LOW, this, "stringIndexOf", new AbleException(eMsg));
>        }
>        return target.indexOf(str);
>     }

This removeBean method based on the obsolete AbleBeanLib implementation illustrates parameter validation, object passing, exception handling, message and trace logging, and returns a boolean if the bean was removed.

>     public boolean removeBean(AbleAgent theAgent, AbleBean theBean) throws AbleException {
>        if (theAgent == null) {
>     	String eMsg = Able.NlsMsg(Able.Ex_BeanLibNullArg, new Object[]{"theAgent"});
>             Able.MessageLog.text(Able.MSG_ERROR, this, "removeBean", eMsg);
>             throw(new AbleException(eMsg));
>        }
>        if (theBean == null) {
>     	String eMsg = Able.NlsMsg(Able.Ex_BeanLibNullArg, new Object[]{"theBean"});
>             Able.MessageLog.text(Able.MSG_ERROR, this, "removeBean", eMsg);
>             throw(new AbleException(eMsg));
>        }
>        try {
>             theAgent.removeBean(theBean);
>     	return true;
>        } catch (RemoteException theRemoteException) {
>     	Able.TraceLog.exception(Able.TRC_LOW,this, "removeBean", theRemoteException);
>        }
>        return false;
>     }