Package gnu.jel

# Class Library

java.lang.Object
gnu.jel.Library

    public class Library
    extends java.lang.Object

A namespace for JEL expressions.

There are two types of members in the library, those which are stateless (i.e. their value depends only on their arguments, if there are any) and stateful (also called here dynamic). The result of evaluation of stateful members may depend on other factors besides their arguments.

Examples of possible stateless members are : `Math.sin(double)`, `Math.PI`.

Examples of possible stateful members are : `Math.random()`, `System.currentTimeMillis()`.

Stateless members of this library are always static members of the classes, which define them. The inverse is generally not true. However, this library goes as far as assuming that static members are stateless, if this assumption does not hold for some of Your members it is possible to mark them as stateful using the `markStateDependent()` method of this class.

The most crucial difference between the two kind of members of this library is that evaluation of stateless methods is attempted by JEL at a compile time during the constants folding phase.

- ## Field Summary

  Fields
  Modifier and Type | Field | Description
  --- | --- | ---
  `java.util.HashMap<java.lang.String,​java.lang.Class<?>>` | `cnmap` |
  `DVMap` | `resolver` |

- ## Constructor Summary

  Constructors
  Constructor | Description
  --- | ---
  `Library​(java.lang.Class<?>[] staticLib, java.lang.Class<?>[] dynamicLib, java.lang.Class<?>[] dotClasses, DVMap resolver, java.util.HashMap<java.lang.String,​java.lang.Class<?>> cnmap)` | Creates a library for JEL.

- ## Method Summary

  Modifier and Type | Method | Description
  --- | --- | ---
  `protected static java.lang.String` | `describe​(java.lang.String name, java.lang.Class<?>[] params)` |
  `protected java.util.List<java.lang.reflect.Member>` | `getApplicable​(java.lang.Class<?> container, java.lang.String name, java.lang.Class<?>[] params, java.util.HashMap<java.lang.String,​java.lang.reflect.Member> signatures, int np)` | Returns applicable methods, for the call.
  `int` | `getDynamicMethodClassID​(java.lang.reflect.Member m)` | Returns ID (position in the object array) of the dynamic method.
  `java.lang.reflect.Member` | `getMember​(java.lang.Class<?> container, java.lang.String name, java.lang.Class<?>[] params)` | Searches the namespace defined by this library object for method or field.
  `protected java.lang.reflect.Member` | `getMostSpecific​(java.lang.Class<?> container, java.lang.String name, java.lang.Class<?>[] params, java.util.List<java.lang.reflect.Member> applicable_methods, int np)` | Returns the most specific method, matching the call.
  `static java.lang.Class<?>[]` | `getParameterTypes​(java.lang.reflect.Member m, int np)` | Used to get types of formal parameters of a member.
  `static java.lang.String` | `getSignature​(java.lang.Class<?> cls)` | Computes the signature of the given class.
  `static java.lang.String` | `getSignature​(java.lang.reflect.Member m)` | Computes signature of the given member.
  `static java.lang.Class<?>` | `getType​(java.lang.reflect.Member m)` | Used to get return type of a class member.
  `static boolean` | `isField​(java.lang.reflect.Member m)` |
  `boolean` | `isStateless​(java.lang.reflect.Member o)` | Used to check if the given method is stateless.
  `void` | `markStateDependent​(java.lang.String name, java.lang.Class<?>[] params)` | This method marks a static member as having the internal state.
  `static java.lang.String` | `toHistoricalForm​(java.lang.String className)` |

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### resolver

    public DVMap resolver

  - ### cnmap

    public java.util.HashMap<java.lang.String,​java.lang.Class<?>> cnmap

- ## Constructor Details

  - ### Library

    public Library​(java.lang.Class<?>[] staticLib, java.lang.Class<?>[] dynamicLib, java.lang.Class<?>[] dotClasses, DVMap resolver, java.util.HashMap<java.lang.String,​java.lang.Class<?>> cnmap)
    Creates a library for JEL.

    The following should be kept in mind when constructing a library:

    1. This constructor may throw IllegalArgumentException if it does not like something in Your library. The requirements to the method names are somewhat more strict, than in Java because members of several classes can be merged in root namespace.
    2. When calling the `CompiledExpression.evaluate(Object[] dynalib)` of the expression, using dynamic library methods it is needed to pass as `dynalib` parameter the array of objects, of the classes _exactly_ in the same order as they are appearing in the `dynamicLib` parameter of this constructor. If You do not allow to call dynamic methods (there is no sense, then, to use a compiler) it is possible to pass `null` istead of `dynalib`.
    3. Generally speaking, this class should not let You to create wrong libraries. It's methods will throw exceptions, return `false`'s , ignore Your actions,... ;)
    If methods in the library classes conflict with each other, the last conflicting method will be skipped. You will not get any messages unless debugging is ON (see `gnu.jel.debug.Debug.enabled`). This is done to avoid unnecessary error messages in the production code of the compiler.

    The array (dotClasses), which is the third argument of this constructor determines how (and whether) to compile the dot operators encountered in expressions. These operators are of the form <object>.(<method>|<field>), which means to call method (access field) of an <object>. There can be three types of the behaviour:

    1) dot operators are prohibited (`dotClasses==null`), this is behaviour of older version of JEL.

    2) dot operators are allowed on all classes (`dotClasses==new Class[0]`, an empty array). Depending on the types of objects returned by the static/dynamic library classes this may pose a security risk.

    3) dot operators are allowed only on some classes. This is achieved by listing these classes in the dotClasses array.

    Parameters:
      `staticLib` - is the array of classes, whose public static methods are exported.
      `dynamicLib` - is the array of classes, whose public virutal methods are exported.
      `dotClasses` - is the array of classes on which the dot ('.') operation is allowed.
      `resolver` - is the object used to resolve the names.
      `cnmap` - Maps class names into classes for non-primitive type casts.

- ## Method Details

  - ### markStateDependent

    public void markStateDependent​(java.lang.String name, java.lang.Class<?>[] params) throws CompilationException
    This method marks a static member as having the internal state.

    If `java.lang.Math` is included into the library it is necessary to mark `java.lang.Math.random()` as having the state. This can be done by calling `markStateDependent("random",null)`.

    Please specify parameters as close as possible, otherwise you can accidentally mark another function.

    Parameters:
      `name` - is the function name.
      `params` - are the possible invocation parameters of the function.
    Throws:
      `CompilationException` - if the method can't be resolved

  - ### isStateless

    public boolean isStateless​(java.lang.reflect.Member o)
    Used to check if the given method is stateless.
    Parameters:
      `o` - is method or field to check.
    Returns:
      true if the method is stateless and can be invoked at compile time.

  - ### getMember

    public java.lang.reflect.Member getMember​(java.lang.Class<?> container, java.lang.String name, java.lang.Class<?>[] params) throws CompilationException
    Searches the namespace defined by this library object for method or field.

    The method with the same name, and closest (convertible) parameter types is returned. If there are several methods the most specific one is used.

    Ambiguities are detected. Example of detectable ambiguity:
    you ask for a call `someName(int, int)`, but there are two applicable methods `someName(int, double)` and `someName(double, int)`. Requirements to parameter types of both can be satisfied by _widening_ conversions. Thus, there is no most specific method of these two in terms of Java Language Specification (15.11.2.2). It means, that an ambiguity is present, and null will be returned.

    Java compiler normally would not allow to define such ambiguous methods in the same class. However, as this library is assembled from several Java classes, such ambiguities can happen, and should be detected.

    Parameters:
      `container` - the class to search the method within, if `null` the root namespace is searched.
      `name` - is the name of the method to find.
      `params` - are the types of formal parameters in the method invocation.
    Returns:
      the method/field object of the resolved method/field.
    Throws:
      `CompilationException` - if the method can't be resolved

  - ### getApplicable

    protected java.util.List<java.lang.reflect.Member> getApplicable​(java.lang.Class<?> container, java.lang.String name, java.lang.Class<?>[] params, java.util.HashMap<java.lang.String,​java.lang.reflect.Member> signatures, int np)
    Returns applicable methods, for the call.
    Parameters:
      `container` - class where the methods come from (if null the method is assumed to be from static and dynamic libraries).
      `name` - method name.
      `params` - parameter types in the call
      `signatures` - list of method signatires to choose from.
      `np` - number of parameters in the call (must be equal either to params.length for a varargs match or to -1 for usual match).

  - ### getMostSpecific

    protected java.lang.reflect.Member getMostSpecific​(java.lang.Class<?> container, java.lang.String name, java.lang.Class<?>[] params, java.util.List<java.lang.reflect.Member> applicable_methods, int np) throws CompilationException
    Returns the most specific method, matching the call.
    Parameters:
      `container` - class where the methods come from (if null the method is assumed to be from static and dynamic libraries).
      `name` - method name.
      `params` - parameter types in the call
      `applicable_methods` - list of applicable methods to choose from.
      `np` - number of parameters in the call (must be equal either to params.length for a varargs match or to -1 for usual match).
    Throws:
      `CompilationException`

  - ### describe

    protected static java.lang.String describe​(java.lang.String name, java.lang.Class<?>[] params)

  - ### getDynamicMethodClassID

    public int getDynamicMethodClassID​(java.lang.reflect.Member m)
    Returns ID (position in the object array) of the dynamic method.

    ID's are used to locate the pointers to the objects, implementing dynamic methods, in the array, argument of evaluate(Object[]) function.

    Parameters:
      `m` - method to get an ID of.
    Returns:
      the ID of the method or -1 if the method is static.
    Throws:
      `java.lang.NullPointerException` - if method is not a dynamic method of this library.

  - ### getType

    public static java.lang.Class<?> getType​(java.lang.reflect.Member m)
    Used to get return type of a class member.

    The type of a method is its return type, the type of a constructor is void.

    Parameters:
      `m` - member whose type is to be determined
    Returns:
      type of the member

  - ### getParameterTypes

    public static java.lang.Class<?>[] getParameterTypes​(java.lang.reflect.Member m, int np)
    Used to get types of formal parameters of a member.

    The reference to the class instance "this" is not counted by this method.

    Parameters:
      `m` - member whose formal parameters are to be obtained
      `np` - numer of parameters for varargs expansion (if np==-1 or the last argument is not an array, the expansion is not performed). It is also an error to pass the np, smaller then the number of method parameters.
    Returns:
      array of formal parameter types (empty array if none).

  - ### getSignature

    public static java.lang.String getSignature​(java.lang.reflect.Member m)
    Computes signature of the given member.
    Parameters:
      `m` - the member to compute the sugnature of.
    Returns:
      the signature.

  - ### isField

    public static boolean isField​(java.lang.reflect.Member m)

  - ### getSignature

    public static java.lang.String getSignature​(java.lang.Class<?> cls)
    Computes the signature of the given class.

    The signature of the class (Field descriptor) is the string and it's format is described in the paragraph 4.3.2 of the Java VM specification (ISBN 0-201-63451-1).

    The same can be done using `java.lang.Class.getName()` by converting it's result into the "historical form".

    This utility method can be used outside of the JEL package it does not involve any JEL specific assumptions and should follow JVM Specification precisely.

    Parameters:
      `cls` - is the class to compute the signature of. Can be primitive or array type.
    Returns:
      the class signature.

  - ### toHistoricalForm

    public static java.lang.String toHistoricalForm​(java.lang.String className)