:: Enseignements :: Master :: M1 :: 2022-2023 :: Java Avancé ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) | Examen de Java Avancé |
Le but de ce TP noté est d'implanter deux Interpolator différents.
Un Interpolator est une classe qui prend en entrée un texte avec des trous (holes)
et qui, étant donnés des arguments, renvoie un nouveau texte contenant le texte original
dont les trous sont comblés par les arguments.
Vos sources Java produites pendant l'examen devront être placées sous le répertoire EXAM
de votre compte ($HOME) (qui est vide dans l'environnement de TP noté).
Sinon, elles ne seront pas récupérées.
Tout document papier est proscrit.
Vous pouvez consulter la javadoc à travers Eclipse (onglet Javadoc), en utilisant
jdoc dans un terminal
Sinon la doc est là:
/usr/local/apps/java17/docs/api/index.html.
Les seuls documents électroniques autorisés sont les supports de cours à l'url
http://igm.univ-mlv.fr/~forax/ens/java-avance/cours/pdf/.
Vous avez le droit de lire le sujet jusqu'au bout, cela vous donnera une bonne idée de là où on veut aller !
Exercice 1 - Interpolator
Il y a deux façons de spécifier un texte à trous :
-
Soit par une liste de segment, un segment pouvant être un trou (hole) ou un texte (text).
Les trous sont numérotés à partir de 0, comme cela on sait que dans le trou i, il faudra insérer
l'argument i.
Par exemple, le texte "Hello @ !" (@ représente un trou) correspond à une liste à 3 segments contenant un
objet Text("Hello "), un objet Hole(0) et enfin un objet Text(" !")
-
Soit par une chaîne de caractères (un template) qui utilise le caractère @ pour indiquer
un trou.
Par exemple, la chaîne de caractères "name: @, age: @" est un template avec deux trous.
Pour vous aider, voici le code du record
Hole dans le fichier
Hole.java qui définit un trou
package fr.uge.interpolation;
public record Hole(int argumentIndex) {
@Override
public String toString() {
return "Hole(" + argumentIndex + ')';
}
}
et le code du record
Text dans le fichier
Text.java qui définit un texte
package fr.uge.interpolation;
public record Text(String text) {
@Override
public String toString() {
return "Text(" + text + ')';
}
}
L'algorithme pour transformer un texte à trou (
template) en liste de segments qui sont
soit des trous soit des textes est le suivant:
Si le premier caractère est un '@', alors c'est trou, et on recommence,
sinon c'est pas un trou et on va chercher le prochain trou, si on le trouve, alors les caractères entre
sont du texte et on recommence, sinon il n'y a plus de trou et le dernier segment est un texte jusqu'à
la fin de la chaîne de caractères
En pseudo code, cela donne
index = 0;
loop: tant que index < length(template):
si template[index] == '@':
index = index + 1
print "HOLE !"
continue loop;
i = index + 1
tant que i < template.length():
si template[i] == '@'
print "TEXT" avec les caractères de template entre index et i (non compris)
index = i;
continue loop;
i = i + 1
print "TEXT" avec caractères de template entre index et length(template) (non compris)
index = length(template);
La classe
MutableInterpolator est un
Interpolator qui possède les opérations suivantes :
-
addHole() qui permet d'ajouter un trou.
-
holeCount() qui renvoie le nombre de trou.
-
addText(text) qui permet d'ajouter un texte.
-
segments() qui renvoie une liste non modifiable des segments (trous et textes)
dans l'ordre d'insertion
-
addTemplate(template) qui utilise l'algorithme ci-dessus pour décomposer le template
pris en argument pour ajouter les trous et textes correspondants.
-
interpolate(arguments) qui prend une liste d'arguments en paramètre (il doit y avoir autant
d'arguments que de segments) et renvoie une chaîne de caractères qui est créée à partir des segments
en remplaçant tous les trous par les valeurs des arguments et en concaténant les valeurs des arguments
et des textes.
L'interface
Interpolator possède les méthodes suivantes :
-
interpolate(arguments) qui est abstraite et fonctionne comme la méthode interpolate
de la classe MutableInterpolator.
-
interpolateFields(interpolator, element, fieldAccessors) qui prend en paramètre un Tnterpolator,
un élément et des accesseurs et utilise les valeurs des champs pour faire l'interpolation.
-
iteratorFromTemplate(template) renvoie un itérateur sur les segments du template
au fur et à mesure des besoins.
-
lazyInterpolator(template) renvoie un Interpolator paresseux qui utilise l'itérateur
renvoyé par iteratorFromTemplate pour faire l'interpolation.
-
streamFromTemplate(template) renvoie un Stream des segments du template.
Aucune des méthodes qui prend des objets en paramètre n'accepte
null.
-
On cherche à créer la classe MutableInterpolator avec les méthodes addHole, holeCount,
addText et segments. La méthode segment doit renvoyer une liste qui agit comme
une vue, toute modification de l'Interpolator (par exemple, l'ajout d'un trou) devra être visible dans la liste
même après que celle-ci ait déjà été créée.
Implanter la classe MutableInterpolator sachant que les trous et les textes sont stockés
dans une liste.
Vérifier que les tests unitaires marqués "Q1" passent.
-
On souhaite maintenant implanter la méthode interpolate(arguments) qui effectue l'interpolation
en remplaçant les trous des segments par les arguments pris en paramètre.
De plus, on veut pouvoir manipuler la classe MutableInterpolator par son interface
Interpolator.
Créer l'interface Interpolator avec la méthode interpolate et implanter celle-ci
dans la classe MutableInterpolator.
Vérifier que les tests unitaires marqués "Q2" passent.
Note : Java permet de faire des switchs sur les objets, et vous ne devriez pas avoir besoin de default.
-
On souhaite écrire dans l'interface Interpolator la méthode interpolateFields
qui utilise les accesseurs d'une instance pour trouver les arguments utilisés pour l'interpolation.
Par exemple, si on pré-suppose un record Person(String name, int age) et une instance
new Person("John", 33), alors l'appel à interpolateFields avec un Interprolator,
l'instance et les références sur les accesseurs Person::name et Person::age
est équivalent à appeler la méthode interpolate avec les arguments "John" et 33.
Vérifier que les tests unitaires marqués "Q3" passent.
-
On veut maintenant ajouter la méthode addTemplate(template) à la classe
MutableInterpolator qui utilise l'algorithme de décomposition du template vu plus haut
(en cherchant les '@') pour ajouter les segments correspondant.
Écrire la méthode addTemplate et vérifier que les tests unitaires marqués "Q4" passent.
-
On souhaite écrire dans l'interface Interpolator la méthode iteratorFromTemplate(template)
qui pour un template renvoie un itérateur qui permet de parcourir les trous et les textes
toujours en utilisant le même algorithme. Bien sûr, l'itérateur doit être paresseux et ne pas découper
la totalité du template au démarrage mais faire le travail au fur et à mesure.
Écrire la méthode iteratorFromTemplate et vérifier que les tests unitaires marqués "Q5" passent.
-
On souhaite écrire dans l'interface Interpolator la méthode lazyInterpolator(template)
qui pour un template, renvoie un Interpolator qui va utiliser l'itérateur écrit précédemment
lors de l'interpolation. Chaque appel à la méthode interpolate devra utiliser un nouvel itérateur.
Implanter la méthode lazyInterpolator et vérifier que les tests unitaires marqués "Q6" passent.
Note : on peut remarquer que l'interface Interpolator a une seule méthode abstraite donc
que l'Interpolator paresseux peut être écrit sous forme d'une lambda.
-
On souhaite écrire toujours dans l'interface Interpolator la méthode
streamFromTemplate(template) qui renvoie un Stream des trous et des textes correspondant
au template pris en paramètre en utilisant l'algorithme vu plus haut.
Vérifier que les tests unitaires marqués "Q7" passent.
Note : pour la taille estimée, on peut remarquer que l'on peut calculer facilement le nombre maximal
de segments possibles pour un template.
-
Modifier l'implantation de la méthode streamFromTemplate(template) pour que le Stream
renvoyé soit parallélisable.
Vérifier que les tests unitaires marqués "Q8" passent.
Attention : les index dans les trous sont ordonnés !
© Université de Marne-la-Vallée