Présentation
Cette macro permet de parcourir une séquence d'objets Hash qui a été au préalable ordonnée par application d'un ou de plusieurs ordonnancements. Un ordonnancement est un processus qui consiste à transformer une séquence d'objets en séquence de groupes d'objets. Un groupe est un regroupement virtuel d'objets : le processus d'ordonnancement ne modifie pas la structure de la séquence ni la valeur des objets qui constituent cette séquence ; seul l'ordre des objets est modifié. A chaque groupe est associé une valeur (déduite des valeurs des objets le constituant), qui peut être utilisée comme étiquette lors de l'affichage de la séquence dans le document résultat.
Chaque groupe peut contenir un ou plusieurs objets de la séquence initiale, mais deux groupes distincts ne peuvent pas contenir le même objet. Après un ordonnancement, tous les objets appartiennent à un groupe.
L'ordonnancement peut se réaliser :
- en créant des groupes triés,
- en créant des groupes nommés définis par l'utilisateur (l'ordre des groupes entre eux n'est pas défini par un tri mais par l'utilisateur).
L'ordonnancement se base sur une clé (un nom d'attribut d'objet commun à tous les objets Hash de la séquence) et s'applique sur les valeurs de cet attribut. Il est possible d'exécuter sur une même séquence plusieurs ordonnancements différents (sur plusieurs attributs différents). Dans ce cas, chaque ordonnancement est appliqué dans l'ordre défini par l'utilisateur et est appliqué sur la séquence résultat de l'ordonnancement qui le précède.
La syntaxe d'appel de cette macro est la suivante :
<@hardisAdv.groupList seqToOrder orderingCriteria; aHashObjInSeq> … ${ aHashObjInSeq.fooAttribute } … </@hardisAdv.groupList>
Avec :
- seqToOrder : séquence d'objets Hash à ordonner et à parcourir,
- orderingCriteria : objet Sequence définissant les ordonnancements à appliquer sur la séquence seqToOrder,
- aHashObjInSeq : variable de boucle dont le nom est défini par l'utilisateur et qui est mis à jour par la macro groupList à chaque itération de lecture des éléments de la séquence résultat. La valeur de cette variable est l'objet Hash lu,
- un contenu imbriqué (… ${ aHashObjInSeq.fooAttribute } …). Une fois que la séquence est ordonnée, elle est parcourue du premier élément au dernier élément. Lors de ce parcours, la valeur de l'élément lu est stockée dans la variable de boucle aHashObjInSeq, et le contenu imbriqué de la macro (le texte compris entre la balise de début et de fin de macro) est exécuté. Lors de cette exécution, il est possible de savoir dans quel groupe appartient l'élément lu. Le contenu imbriqué est donc exécuté autant de fois qu'il y a d'éléments dans la séquence ordonnée. La macro ne produira aucun résultat dans le document de sortie si la séquence est vide.
↑ Haut de page
Chaque ordonnancement se base sur la comparaison de valeurs : la macro groupList supporte les comparaisons de type Boolean, Number, String, Date, Time et Date-time.
Clé d'ordonnancement
La clé correspond à un nom d'attribut d'objet Hash appartenant à la séquence. Il est possible (à l'instar de la fonction built-in Freemarker ?sort_by) d'adresser un attribut d'objet de premier niveau ou de Nième niveau :
Niveau |
Séquence |
Clés de premier niveau : "price" / "id" |
[ { "id": 123, "price": 12}, { "id": 4, "price": 5.5}] |
Clés de deuxième niveau : "stock.current" / "stock.command" |
[ { "id": 123, "price": 12, "stock" : {"current": 10, "command": 5}}, |
Une clé doit représenter un attribut ayant un type supporté. Une clé de Nième niveau est définie en utilisant la notation "point", et représente le chemin d'accès à l'attribut depuis le premier niveau. Chaque niveau intermédiaire fait référence à un attribut qui doit être de type Hash.
↑ Haut de page
Groupes triés
Le processus de création des groupes triés se base sur :
- Le type de la clé. Il faut distinguer deux cas :
- une clé de type String / Number ou
- une clé de type Boolean / Date / Time / Date-time.
- L'ordre de tri. Il existe plusieurs ordres de tri possible :
- ordre ascendant (ordre croissant),
- ordre descendant (ordre décroissant),
- ordre d'origine (ordre inchangé).
- Un critère d'appartenance. Pour chaque élément du groupe, ce critère doit être vérifié.
Clé de type String / Number
Le processus de création de groupes est le suivant :
- Tri de la séquence suivant la clé et l'ordre de tri,
- Parcours de la séquence pour assigner à chaque élément un groupe ayant le critère d'appartenance imposé "Tous les éléments ont la même valeur". La valeur d'un groupe est la valeur du (des) élément(s) le constituant.
Par exemple
Groupe trié |
Clé : "age", ordre : "d" |
||||||||||
Séquence |
[{"age":19}, {"age":20}, {"age":17}, {"age":18}, {"age":17}, {"age":20}, {"age":16}, {"age":20}] |
||||||||||
Séquence ordonnée |
|
Clé de type Boolean / Date / Time / Date-time
Le processus de création de groupes est le suivant :
- Parcours de la séquence pour assigner à chaque élément un groupe ayant un critère d'appartenance choisi par l'utilisateur. La valeur du groupe dépend du critère.
- Tri des groupes suivant la valeur de chaque groupe et l'ordre de tri. Le nouvel ordre des groupes définit la séquence résultat.
La nature du critère dépend du type de la clé. Chaque critère est décrit dans le tableau suivant :
Critère | Description du groupe |
Valeur du groupe |
|
Type date | |||
day |
Toutes les dates définissent le même jour (c'est-à-dire ont la même valeur) |
Date dudit jour |
|
week |
Toutes les dates appartiennent à la même semaine |
Date du premier jour de ladite semaine |
|
twoWeeks |
Toutes les dates appartiennent à une période de deux semaines consécutives |
Date du premier jour de la première semaine de ladite période |
|
fortnight |
Toutes les dates appartiennent à la même quinzaine (du 1er au 15 de chaque mois) |
Date du premier jour de ladite quinzaine |
|
month |
Toutes les dates appartiennent au même mois |
Date un premier jour dudit mois |
|
quarter |
Toutes les dates appartiennent au même trimestre |
Date du premier jour du premier mois dudit trimestre |
|
semester |
Toutes les dates appartiennent au même semestre |
Date du premier jour du premier mois dudit semestre |
|
year |
Toutes les dates appartiennent à la même année |
Date du premier jour du premier mois de ladite année |
|
Type date-time |
|||
Tous les critères du type Date plus : |
|||
second |
Toutes les date-time appartiennent à la même seconde |
Date-time de ladite seconde |
|
minute |
Toutes les date-time appartiennent à la même minute |
Date-time de ladite minute |
|
hour |
Toutes les date-time appartiennent à la même heure |
Date-time de ladite heure |
|
amPm |
Toutes les date-time appartiennent à la même période AM ou PM |
Date-time de la première seconde de ladite période |
|
Type Time |
|||
second |
Toutes les heures appartiennent à la même seconde |
Heure de ladite seconde |
|
minute |
Toutes les heures appartiennent à la même minute |
Heure de ladite minute |
|
hour |
Toutes les heures appartiennent à la même heure |
Heure de ladite heure |
|
amPm |
Toutes les heures appartiennent à la même période AM ou PM |
Heure de la première heure de ladite période |
|
Type Boolean |
|||
everyChange |
Regroupe les booléens ayant la même valeur ("true" ou "false") |
Première valeur du groupe |
|
toChangeInYes |
Regroupe les booléens faisant partie de la même sous-séquence (valeurs booléennes consécutives dans la séquence passée en paramètre) de façon à ce que le dernier booléen de la sous-séquence vaut "false" et que booléen qui le suit ait la valeur "true". La sous-séquence doit être minimale (on ne doit pas retrouver la suite "false" "true" dans celle-ci). Si les conditions ne sont pas remplies, on crée un groupe avec les valeurs restantes. |
Première valeur du groupe |
|
toChangeInNo |
Regroupe les booléens faisant partie de la même sous-séquence (valeurs booléennes consécutives dans la séquence passée en paramètre) de façon à ce que le dernier booléen de la sous-séquence vaut "true" et que booléen qui le suit ait la valeur "false". La sous-séquence doit être minimale (on ne doit pas retrouver la suite "true" "false" dans celle-ci). Si les conditions ne sont pas remplies, on crée un groupe avec les valeurs restantes. |
Première valeur du groupe |
|
everyYes |
Regroupe les booléens faisant partie de la même sous-séquence (valeurs booléennes consécutives dans la séquence passée en paramètre) de façon à ce que le dernier booléen de la sous-séquence ait la valeur "true". La sous-séquence doit être minimale (elle ne peut contenir plus d'un "true"). Si les conditions ne sont pas remplies, on crée un groupe avec les valeurs restantes. |
Première valeur du groupe |
|
everyNo |
Regroupe les booléens faisant partie de la même sous-séquence (valeurs booléennes consécutives dans la séquence passée en paramètre) de façon à ce que le dernier booléen de la sous-séquence vaut "false" et que booléen qui le suit ait la valeur "true". La sous-séquence doit être minimale (elle ne peut contenir plus d'un "false"). Si les conditions ne sont pas remplies, on crée un groupe avec les valeurs restantes. |
Première valeur du groupe |
|
toTheNextYes |
Regroupe les booléens faisant partie de la même sous-séquence (valeurs booléennes consécutives dans la séquence passée en paramètre) de façon à ce que le premier booléen de la sous-séquence ait la valeur "true". La sous-séquence doit être minimale (elle ne peut contenir plus d'un "true". De plus, elle peut contenir aucun "true" si la séquence commence par "false" par exemple). Si les conditions ne sont pas remplies, on crée un groupe avec les valeurs restantes. |
Première valeur du groupe |
|
toTheNextNo |
Regroupe les booléens faisant partie de la même sous-séquence (valeurs booléennes consécutives dans la séquence passée en paramètre) de façon à ce que le premier booléen de la sous-séquence ait la valeur "false". La sous-séquence doit être minimale (elle ne peut contenir plus d'un "false". De plus, elle peut contenir aucun "false" si la séquence commence par "true" par exemple). Si les conditions ne sont pas remplies, on crée un groupe avec les valeurs restantes. |
Première valeur du groupe |
↑ Haut de page
Groupe nommé
Un groupe nommé permet de regrouper des valeurs suivant un ou plusieurs critères d'appartenance (multicritères). Contrairement à un groupe typé :
- Le groupe nommé peut être utilisé pour tous les types simples de la clé (Boolean / Date / Time / Date-time / Number / String).
- Le groupe nommé a un nom unique défini par l'utilisateur.
- Le groupe nommé a une valeur associée qui est un label défini par l'utilisateur (chaîne alphanumérique) : ce texte peut servir de "titre" lors de l'affichage de la séquence ordonnée.
- Le groupe nommé a un ordre qui est défini par l'utilisateur : l'ordonnancement d'une séquence par groupes nommés implique généralement la création de plusieurs groupes, et l'ordre des groupes entre eux est à la charge de l'utilisateur (pas de "tri" des groupes comme avec les groupes typés).
- Suivant la nature des critères définis par l'utilisateur, un élément peut n'appartenir à aucun groupe nommé. Dans ce cas, l'utilisateur peut choisir pour cet élément :
- de ne pas le traiter : cet élément ne sera pas présent dans la séquence ordonnée et ne sera pas traité lors du parcours de cette séquence dans la macro groupList (donc non affiché),
- de le placer dans un groupe nommé spécial, de nom "other". Ce groupe est toujours le dernier groupe des groupes nommés. L'élément sera traité comme les autres éléments lors du parcours de cette séquence dans la macro groupList,
- de le placer dans un nouveau groupe qui contiendra seulement cet élément. Ce nouveau groupe est inséré en fin de liste des groupes nommés. L'élément sera traité comme les autres éléments lors du parcours de cette séquence dans la macro groupList.
↑ Haut de page
La création des groupes nommés se fait en parcourant la séquence (utilisation de l'ordre naturel de parcours). Lors du parcours, chaque élément est testé pour savoir à quel groupe nommé il appartient : le premier groupe nommé (dans la liste des groupes nommés) ayant un critère de regroupement valide est choisi s'il existe. Sinon l'élément est traité comme spécifié par l'utilisateur (voir plus haut).
Critère d'appartenance
Il dépend du type de la clé. Plusieurs critères peuvent être associés pour la définition d'un groupe nommé. Dans ce cas, pour qu'un élément appartienne à un groupe nommé, il suffit qu'un critère soit vérifié. Suivant la nature du critère, l'utilisateur doit fournir une ou plusieurs valeurs littérales du même type que la clé pour compléter la description du critère. Chaque critère est décrit dans le tableau suivant :
Critère |
Description |
Valeurs à fournir |
|
Type String | |||
|
isAnyValue |
Critère vérifié quelle que soit la valeur alphanumérique |
Aucune |
|
isEqualTo |
Critère vérifié si la valeur alphanumérique est égale à la valeur eqValue |
eqValue (valeur alphanumérique) |
|
isNotEqualTo |
Critère vérifié si la valeur alphanumérique est différente de eqValue |
eqValue (valeur alphanumérique) |
|
isAmong |
Critère vérifié si la valeur alphanumérique est présente dans la séquence seqValues |
seqValues (séquence de valeurs alphanumériques) |
|
isNotAmong |
Critère vérifié si la valeur alphanumérique n'est pas présente dans la séquence seqValues |
seqValues (séquence de valeurs alphanumériques) |
|
isLessTo |
Critère vérifié si la valeur alphanumérique est strictement inférieure à lessValue |
lessValue (valeur alphanumérique) |
|
isLessOrEqualTo |
Critère vérifié si la valeur alphanumérique est inférieure ou égale à lessValue |
lessValue (valeur alphanumérique) |
|
isGreaterTo |
Critère vérifié si la valeur alphanumérique est strictement supérieure à greaterValue |
greaterValue (valeur alphanumérique) |
|
isGreaterOrEqualTo |
Critère vérifié si la valeur alphanumérique est supérieure ou égale à greaterValue |
greaterValue (valeur alphanumérique) |
|
isBetween |
Critère vérifié si la valeur alphanumérique est comprise entre minValue et maxValue |
minValue et maxValue (valeurs alphanumériques) |
|
isNotBetween |
Critère vérifié si la valeur alphanumérique n'est pas comprise entre minValue et maxValue |
minValue et maxValue (valeurs alphanumériques) |
|
startWith |
Critère vérifié si la valeur alphanumérique commence par une des valeurs de la séquence seqValues |
seqValues (séquence de valeurs alphanumériques) |
|
doNotStartWith |
Critère vérifié si la valeur alphanumérique ne commence par aucune des valeurs de la séquence seqValues |
seqValues (séquence de valeurs alphanumériques) |
|
isLike |
Critère vérifié si la valeur alphanumérique satisfait au moins une des "expressions régulières" présente dans la séquence seqValues |
seqValues (séquence de valeurs alphanumériques). Dans la chaîne alphanumérique représentant une "expression régulière", |
|
isNotLike |
Critère vérifié si la valeur alphanumérique ne satisfait aucune des "expressions régulières" présente dans la séquence seqValues |
seqValues (séquence de valeurs alphanumériques). Dans la chaîne alphanumérique représentant une "expression régulière", |
Type Number / Date / Time / Date-time | |||
|
isAnyValue |
Critère vérifié quelle que soit la valeur |
Aucune |
|
isEqualTo |
Critère vérifié si la valeur est égale à la valeur eqValue |
eqValue (une valeur) |
|
isNotEqualTo |
Critère vérifié si la valeur est différente de eqValue |
eqValue (une valeur) |
|
isAmong |
Critère vérifié si la valeur est présente dans la séquence seqValues |
seqValues (séquence de valeurs) |
|
isNotAmong |
Critère vérifié si la valeur n'est pas présente dans la séquence seqValues |
seqValues (séquence de valeurs) |
|
isLessTo |
Critère vérifié si la valeur est strictement inférieure à lessValue |
lessValue (une valeur) |
|
isLessOrEqualTo |
Critère vérifié si la valeur est inférieure ou égale à lessValue |
lessValue (une valeur) |
|
isGreaterTo |
Critère vérifié si la valeur est strictement supérieure à greaterValue |
greaterValue (une valeur) |
|
isGreaterOrEqualTo |
Critère vérifié si la valeur est supérieure ou égale à greaterValue |
greaterValue (une valeur) |
|
isBetween |
Critère vérifié si la valeur est comprise entre minValue et maxValue |
minValue et maxValue (deux valeurs) |
|
isNotBetween |
Critère vérifié si la valeur n'est pas comprise entre minValue et maxValue |
minValue et maxValue (deux valeurs) |
Type Boolean | |||
|
isAnyValue |
Critère vérifié quelle que soit la valeur "true" / "false" |
Aucune |
|
isTrue |
Critère vérifié si la valeur est "true" |
Aucune |
|
isFalse |
Critère vérifié si la valeur est "false" |
Aucune |
↑ Haut de page
Information d'ordonnancements
Dans la macro groupList, l'information sur le ou les ordonnancements à appliquer est portée par le paramètre orderingCriteria. Il doit être de type Hash ou Sequence de Hash. Chaque objet Hash décrit un ordonnancement. Il doit avoir les attributs suivants :
- name : nom du groupe (chaîne alphanumérique). Il doit être unique et sert à référencer un groupe dans les macros groupHeader et groupFooter. Cet attribut est obligatoire,
- colName : nom de la clé en notation "point" (chaîne alphanumérique). Cet attribut est obligatoire,
- order : ordre de tri (chaîne alphanumérique). Les valeurs possibles sont :
- "a" : ordre ascendant (ordre croissant),
- "d" : ordre descendant (ordre décroissant),
- "o" : ordre d'origine (ordre inchangé).
- "s" : ordre spécifié.
Les valeurs "a", "d" et "s" définissent un ordonnancement de type "groupes triés". La dernière valeur définit un ordonnancement de type "groupes nommés". Cet attribut est optionnel : sa valeur par défaut est "a".
- groupCriteria : (chaîne alphanumérique) définit le critère d'appartenance pour un ordonnancement de type "groupes triés" lorsque le type de colName est Boolean / Date / Time / Date-time. Sert aussi de critère lorsque l'ordonnancement est de type "groupes nommé"s et que le groupe nommé "other" a la propriété grouping à "ownGroups". Cet attribut est optionnel : sa valeur par défaut est "week" lorsque le type de colName est Date / Date-time; "second" lorsque le type de colName est Time et "everyChange" lorsque le type de colName est Boolean,
- namedGroups : groupe nommé ou séquence de groupes nommés (Hash ou Sequence de Hash). Cet attribut n'est pris en compte que si l'attribut "order" vaut "s". Chaque groupe nommé est un objet Hash ayant les attributs suivants :
- name (chaîne alphanumérique) : nom du groupe nommé. Il doit être unique et sert à référencer un groupe nommé dans les macros groupHeader et groupFooter. Cet attribut est optionnel.
- label : titre du groupe nommé (chaîne alphanumérique). Il peut être affiché dans les macros groupHeader et groupFooter. Cet attribut est optionnel.
- criteria : critère(s) d'appartenance au groupe nommé (Hash ou Sequence de Hash). Cet attribut est obligatoire (un groupe nommé doit avoir au moins un critère d'appartenance). Chaque critère est un objet Hash ayant les attributs suivants :
- name : nom du critère (chaîne alphanumérique). Cet attribut est obligatoire.
- values : valeurs associées au critère pour calculer sa validité (Type de colName ou Sequence de type de ColName). Cet attribut est optionnel.
- otherGroup : définition des propriétés du groupe nommé "other" (Hash). Cet attribut est obligatoire si "order" vaut "s". Ce groupe nommé est un objet Hash ayant les attributs suivants :
- grouping : type de regroupement (chaîne alphanumérique). Cet attribut est obligatoire. Les valeurs possibles sont :
- "ignore" : les éléments de ce groupe ne sont pas traités par la macro,
- "oneGroup" : les éléments font partie du même groupe "other",
- "ownGroups" : chaque élément appartient à un groupe trié (ordre d'origine et critère d'appartenance par défaut en fonction du type de colName).
- label : titre du groupe "other" (chaîne alphanumérique). Il peut être affiché dans les macros groupHeader et groupFooter. Cet attribut est optionnel.
- grouping : type de regroupement (chaîne alphanumérique). Cet attribut est obligatoire. Les valeurs possibles sont :
<#macro groupList dataList sortingGroup>
Directive vide : Non
Paramètres
Sequence de Hash |
seqData |
Séquence d'objets Hash à ordonner |
Obligatoire |
Hash / Sequence de Hash |
orderingCriteria |
Objet Hash ou séquence d'objets Hash définissant les ordonnancements à appliquer sur seqData. L'utilisateur peut définir un seul ordonnancement (objet Hash) pour plusieurs (séquence d'objets Hash) |
Obligatoire |
Par exemple
<#assign myData = [{"name": "Franck", "age": 19 }, {"name": "Alice", "age": 22 }, {"name": "Paul", "age": 15 } ] /> <#assign orderingCriteria = [{"name": "ascending_order_by_age", "colName": "age"}, {"name": "descending_order_by_name", "colName": "name", "order": "d"} ] /> <@hardisAdv.groupList myData orderingCriteria ; aPerson> Hello ${aPerson.name}! You have ${aPerson.age} years old. </@hardisAdv.groupList>