Ajouter une expression

Pour créer une nouvelle expression, commencez par créer une nouvelle classe qui héritera de la classe ScriptExpression. Puis, implémentez les méthodes abstraites de la classe mère. Jusqu'ici, l'expression nouvellement créée n'a aucune utilité. Comme pour les types, il faut l'enregistrer, via l'annotation @Expression. Cette annotation est légèrement plus complexe à compléter.

Premièrement, il faut fournir un nom, et une liste de @Feature qui ne sont rien d'autre qu'un pattern, une description et des exemples d'usage du pattern que l'on veut définir. Ces paramètres servent uniquement à la génération de documentation et à une meilleure lecture du code. En effet, plusieurs expressions peuvent être reconnues par une même classe, le nom doit donc être le plus générique possible.

La partie la plus importante concerne les patterns. Il faut en fournir un par expression à créer (donc par feature), en notant l'ordre dans lequel ils sont ajoutés. C'est cet ordre qui permet de savoir quel pattern est à traiter. Pour rappel, la syntaxe pour les expressions est : pattern:type de retour. Par exemple, le pattern type of {element}:string retournera une chaîne de caractère. N'hésitez pas à regarder les autres paramètres de l'annotation @Feature qui permettent une meilleure configuration d'un pattern, notamment en ce qui concerne sa priorité, ou son côté d'exécution.


La méthode la plus importante à implémenter est la méthode get(ScriptContext, ScriptType[]). C'est elle qui permet de retourner un élément en particulier. La méthode set(ScriptContext, ScriptType, ScriptType[]) permet de mettre à jour la valeur de l'expression lorsque l'action set sera appelée. Dans les deux cas, la première étape est de savoir quel pattern a été reconnu, afin d'adapter notre code. Le plus simple est d'utiliser un switch sur la valeur de retour de la méthode getMatchedIndex():

    @Override
    public ScriptType get(ScriptContext context, ScriptType[] parameters) {
        switch(getMatchedIndex()){
            case 1:
                //C'est le premier pattern qui a été reconnu.
                ...
            case 2:
                //C'est le deuxième pattern qui a été reconnu.
               ...
            etc.
        }
    }

Pour obtenir les références aux paramètres renseignés dans le pattern, on utilise l'argument parameters, qui est une liste contenant les éléments, dans l'ordre, renseignés dans le pattern. Par exemple, dans le pattern type of {element}:string, parameters[0] retournera l'élément passé à l'expression dans le script (les listes en java commencent à l'indice 0).

La deuxième méthode à implémenter pour les expressions est la méthode set(ScriptContext, ScriptType, ScriptType[]). Elle permet de mettre à jour une valeur lors du passage de l'expression dans l'action set. De la même manière, récupère le pattern reconnu, puis en fonction de ce dernier on effectue les changements sur les variables passées en paramètres. Si l'expression ou un pattern en particulier ne peut pas être modifié, il faut retourner la valeur false, sinon, une fois le changement effectué, il faut retourner true. Dans le cas où la valeur retournée est false, une erreur est levée car l'expression n'est pas censée être modifiée par l'action set.

Par exemple, voici une classe ScriptExpression complète :

@Expression(name = "Format Expressions",
        features = {
                @Feature(name = "Format", description = "Format things.", examples = "5.643 formatted as \"--,--\"", pattern = "{element} formatted as {string}", type = "string")
        }
)
public class ExprFormat extends ScriptExpression {

    @Override
    public ScriptType get(ScriptContext context, ScriptType[] parameters) throws ScriptException {

        switch (getMatchedIndex()) {
            case 0:
                ScriptType element = parameters[0];
                String format = (String) parameters[1].getObject();
                if (!(element instanceof IFormatable)) {
                    throw new ScriptException.ScriptInterfaceNotImplementedException(line, IFormatable.class, element.getClass());
                }
                IFormatable formatable = (IFormatable) element;
                return new TypeString(formatable.format(format));

        }
        return null;
    }

    @Override
    public boolean set(ScriptContext context, ScriptType to, ScriptType[] parameters) {
        return false;
    }
}
Retour en haut de la page