Recours aux fonctionnalités externes à l'aide d'expressions

Les expressions sont disponibles à divers emplacements d'un script pour définir le comportement des boucles, des conditions, etc. Voir l'annexe Expression Syntaxe du manuelAuthoring Scripts using Intelligent Evidence Gathering (IEG) pour plus d'informations.

Ces expressions peuvent faire référence à des réponses et être combinées à l'aide de différents opérateurs. Elles peuvent même appeler les fonctions (sauf lorsqu'elles sont utilisées sur des clusters conditionnels dynamiques car ces expressions sont évaluées dans le navigateur).

Les fonctions décrites ci-dessus sont appelées Fonctions personnalisées et définies à l'aide du code Java™ . Selon leur utilisation, elles peuvent être de deux types :

Les exemples qui peuvent nécessiter l'appel de fonctionnalités externes sont la validation d'un code postal américain qu'un utilisateur a fourni et le remplissage d'une zone d'état en fonction du code postal indiqué. Nous allons maintenant démontrer ces deux usages.

Le schéma du DS devra être développé pour ajouter les 2 attributs suivants à l'entité Personne, comme suit :

Figure 1. Attributs de personne supplémentaires dans le schéma du DS
<xsd:attribute name="state" type="IEG_STRING"/>
<xsd:attribute name="zipCode" type="IEG_STRING"/>

Tout d'abord, commençons par valider un code postal américain : celui-ci se compose de cinq chiffres et les trois premiers indiquent l'état.

La page de détails de la personne mentionnée précédemment et la page récapitulative correspondante peuvent être modifiées via deux questions obligatoires supplémentaires : Etat et Code postal américain :

Figure 2. Questions Etat et Code postal américain dans la définition du script
<question id="state" mandatory="true">
    <label id="State.Label">
        State:
    </label>
    <help-text id="State.HelpText">
        Votre état de résidenced
    </help-text>
</question>
<question id="zipCode" mandatory="true">
    <label id="ZipCode.Label">
        ZIP Code:
    </label>
    <help-text id="ZipCode.HelpText">
        Votre code postal américain
    </help-text>
</question>

La fonction personnalisée qui procèdera à la validation doit alors être créée en tant que classe Java dans le module curam.rules.functions:

Figure 3. Fonction personnalisée pour valider le code postal américain
...
public class CustomFunctionValidateZipCode extends CustomFunctor {

  public Adaptor getAdaptorValue(final RulesParameters rp)
  throws AppException, InformationalException {

    final List<Adaptor> parameters = getParameters();
    final String zipCode =
      ((StringAdaptor) parameters.get(0)).getStringValue(rp);
    final String state =
      ((StringAdaptor) parameters.get(1)).getStringValue(rp);
    boolean valid = false;

    if (zipCode.length() == 5) {
      final String prefix = zipCode.substring(0, 3);
      //rechercher les préfixes d'état
      if (prefix.equals("100")
        && state.equalsIgnoreCase("New York")) {
        valid = true;
      }
      if (prefix.equals("900")
        && state.equalsIgnoreCase("Californie")) {
        valid = true;
      }
    }

    return AdaptorFactory.getBooleanAdaptor(Boolean.valueOf(valid));
  }

}

Les métadonnées suivantes de la fonction personnalisée doivent être insérées dans<yourcomponent>/rulesets/functions/CustomFunctionMetaData.xml:

Figure 4. Métadonnées de fonction personnalisée
<CustomFunctor name="CustomFunctionValidateZipCode">
  <parameters>
    <parameter>
      curam.util.rules.functor.Adaptor$StringAdaptor
    </parameter>
    <parameter>
      curam.util.rules.functor.Adaptor$StringAdaptor
    </parameter>
  </parameters>
  <returns>curam.util.rules.functor.Adaptor$BooleanAdaptor</returns>
</CustomFunctor>

Pour plus d'informations sur la définition des fonctions personnalisées, voir le manuel Cúram Rules Codification Guide.

Dans notre exemple, la fonction personnalisée ValidateZipCode n'accède pas à une base de données externe de recherche pour recherche l'état correspondant. Idéalement, elle devrait effectuer cette recherche, puis vérifier l'état renvoyé par rapport à l'état saisi. A des fins de simplification, seuls deux préfixes de code postal américain sont codés en dur ci-dessus.

La validation sera alors insérée dans la page des détails personnels :

Figure 5. Validation du code postal américain dans la définition du script
<validation
  expression="ValidateZipCode(Person.zipCode, Person.state)">
    <message id="InvalidZipCode">
        Le code postal américain est non valide.
    </message>
</validation>

Lorsque l'utilisateur clique sur Suivant, les réponses aux questions Code postal américain et Etat sont transmises à la fonction personnalisée, qui renvoie la valeur true si les réponses sont valides. La page suivante est ensuite affichée.

Si la fonction personnalisée renvoie la valeur false, le message indiqué dans la validation s'affiche en haut de la page Détails de la personne, bloquant l'accès à la page Suivant jusqu'à la soumission des réponses valides.

La fonction personnalisée n'a pas d'effet secondaire car elle ne modifie aucune donnée. Elle n'effectue qu'une opération en fonction des paramètres et renvoie un résultat.

Il serait également possible de supprimer l'indicateur obligatoire sur les deux nouvelles questions et de valider les réponses uniquement si elles ont toutes deux été fournies. L'expression de validation doit alors être modifiée comme suit, à l'aide de la fonction personnalisée prête à l'emploi isNotNull qui vérifie si le paramètre fourni possède la valeur NULL :

Figure 6. Expression de validation alternative
"not(isNotNull(Person.zipCode) and isNotNull(Person.state))
    or ValidateZipCode(Person.zipCode, Person.state)"

Vous pouvez sinon renseigner la question Etat en fonction du code postal américain. Pour ce faire, la page Détails de la personne ne demande que le code postal américain (avec l'indicateur obligatoire) et la page récapitulative affiche l'état et le code postal américain.

La fonction personnalisée suivante doit être définie :

Figure 7. Fonction personnalisée pour renseigner l'état
...
public class CustomFunctionpopulateState extends CustomFunctor {

  public Adaptor getAdaptorValue(final RulesParameters rp)
  throws AppException, InformationalException {

    final IEG2Context ieg2Context = (IEG2Context) rp;
    final long rootEntityID = ieg2Context.getRootEntityID();
    String schemaName; 
    //schemaName doit être codé en dur ou extrait en dehors d'IEG
    Datastore ds = null;
    try {
      ds =
        DatastoreFactory.newInstance().openDatastore(
            schemaName);
    } catch (NoSuchSchemaException e) {
      throw new AppException(IEG.ID_SCHEMA_NOT_FOUND);
    }

    Entity applicationEntity = ds.readEntity(rootEntityID);

    Entity personEntity =
      applicationEntity.getChildEntities(
        ds.getEntityType("Person"))[0];
    String zipCode = personEntity.getAttribute("zipCode");
    String state = "Unknown";
    final String prefix = zipCode.substring(0, 3);
    //rechercher les préfixes d'état
    if (prefix.equals("100")) {
      state = "New York";
    }
    if (prefix.equals("900")) {
      state = "Californie";
    }
    personEntity.setAttribute("state", state);
    personEntity.update();
    return AdaptorFactory.getBooleanAdaptor(new Boolean(true));
  }

}

Et ses métadonnées :

Figure 8. Métadonnées de fonction personnalisée
<CustomFunctor name="CustomFunctionpopulateState">
  <returns>curam.util.rules.functor.Adaptor$BooleanAdaptor</returns>
</CustomFunctor>

Un élément d'appel doit être inséré entre la page Détails de la personne et la page récapitulative pour appel cette fonction personnalisée :

Figure 9. Appel pour renseigner l'état dans la définition de script
<callout id="populateAddress" expression="populateState()"/>

Cette fois, la fonction personnalisée modifie le DS en renseignant l'état dans l'entité Person. Le contexte contient l'ID d'entité racine et l'ID d'exécution, afin de faciliter la mise à jour du DS. Si l'appel se trouve dans une boucle, le contexte contient également l'ID d'entité en cours.