:: Enseignements :: ESIPE :: E4INFO :: 2026-2027 :: Java Avancé ::
[LOGO]

TP noté intermédiaire de Java Avancé 2026 - 2027


Le but de ce TP noté est d'implanter une petite application permettant de gérer les emprunts d'une bibliothèque et de calculer les éventuelles pénalités de retard.

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.
La javadoc 27 est disponible à l'adresse : https://ligm.univ-eiffel.fr/~juge/javadoc-27/.
Les seuls documents électroniques autorisés sont les supports de cours à l'URL https://ligm.univ-eiffel.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 - Library

Notre bibliothèque propose des livres, des magazines et des bandes dessinées. Les adhérents peuvent emprunter des documents pendant une durée maximale de 15 jours. Au-delà de cette durée, l'adhérent doit payer une pénalité pour chaque jour de retard.
Les pénalités journalières sont fixées par la bibliothèque (pour le moment) :
  • Un livre : 5 euros par jour ;
  • Un magazine : 2 euros par jour ;
  • Une bande dessiné : 3 euros par jour

On souhaite tout d'abord modéliser les documents et emprunts de notre bibliothèque.
Un document est soit un livre avec un titre (Book(title)), soit un magazine avec un titre (Magazine(title)) soit une bande dessinée avec un titre (Comic(title)).
Un emprunt (Loan) est caractérisé par le nom de l'adhérent (member de type String) qui emprunte le document, un document et la date à laquelle le document a été emprunté (borrowedOn de type LocalDate).
Une classe Library contient la liste des emprunts et permet d'ajouter de nouveaux emprunts.

Les tests JUnit 5 de cet exercice sont LibraryTest.java.
Note : comme on utilise les tests unitaires JUnit sans Maven, dans la configuration de votre projet, il faut ajouter la librairie JUnit 5, soit à partir du fichier LibraryTest.java, en cliquant sur l'annotation @Test et en sélectionnant le quickfix "Fixup project ...", soit en sélectionnant les "Properties" du projet (avec le bouton droit de la souris sur le projet) puis en ajoutant la librairie JUnit 5 (jupiter) au ClassPath.

  1. Dans le package fr.uge.loanlibrary, créer les classes dont vous avez besoin pour modéliser les emprunts.
    Créer également une classe Library permettant de stocker les emprunts.
    Elle doit proposer les méthodes : addLoan(Loan loan) qui ajoute un emprunt et loans() qui renvoie la liste des emprunts.
    Vérifier que les tests marqués "Q1" passent.

  2. Dans Library, déclarer trois constantes correspondantes aux pénalités journalières (des entiers longs pour représenter les valeurs en euro).
    Écrire une méthode d'aide lateFee(Loan loan, LocalDate date) qui calcule le montant de la pénalité associée à un emprunt à une date donnée. Cette méthode doit être testable par les tests, mais ne pas faire partie de l'API.
    Exemple d'utilisation : si un emprunt a été effectué le 1er juin, il n'y a aucune pénalité le 16 juin : les quinze jours d'emprunt sont encore écoulés exactement. Le 17 juin, un jour de retard est facturé.
    Écrire ensuite la méthode publique lateFeeForMember(String member, LocalDate date) qui calcule la somme des pénalités dues par un adhérent.
    Pour calculer les pénalités, on peut soit utiliser le polymorphisme soit utiliser le pattern matching.
    Avant de programmer, expliquez en commentaire laquelle des deux approches vous semble la plus adaptée ici et pourquoi.
    Implanter l'approche retenue, sachant que l'on vous demande d'utiliser la programmation impérative.
    Note: pour calculer le nombre de jours entre deux dates, on peut utiliser ChronoUnit.DAYS.between(startDate, endDate).
    Vérifier que les tests marqués "Q2" passent.

  3. Commenter le code la méthode lateFeeForMember précédente. Réécrire une nouvelle implantation de la méthode lateFeeForMember en utilisant un Stream.
    Note: attention à ne pas faire de boxing inutile, vous serez sévèrement sanctionné sur ce point.
    Vérifier que les tests marqués "Q3" passent.

  4. On souhaite maintenant pouvoir effectuer différentes recherches dans la bibliothèque sans pour autant multiplier le nombre de méthodes spécialisées.
    C'est à dire, au lieu d'avoir une méthode findLoansByMember, findLoansByDate, etc. On cherche à écrire une seule méthode findLoans(???) qui prend en paramètre la recherche exacte que l'on veut faire.
    Ajouter à Library la méthode findLoans qui renvoie la liste des emprunts correspondant à la recherche.
    Note: L'implémentation doit utiliser un Stream.
    Vérifier que les tests marqués "Q4" passent.

  5. Une recherche peut être décrite par plusieurs conditions. Par exemple, on peut vouloir trouver les emprunts d'Alice qui correspondent à un certain type de document.
    On souhaite donc ajouter la méthode findAllLoans(???) qui prend une liste de critère de recherche et renvoie les emprunts qui vérifient tous les critères.
    Implémenter findAllLoans.
    Note: en termes d'implantation, Attention à ne parcourir la liste des emprunts qu’une seule fois.
    Vérifier que les tests marqués "Q5" passent.

  6. On souhaite maintenant pouvoir produire des statistiques sur les emprunts, dans notre cas, deux statistiques.
    On souhaite tout d'abord connaître le nombre d'emprunts pour chaque type de document.
    Pour cela, ajouter une classe DocumentKind ayant les valeurs BOOK, MAGAZINE et COMIC.
    Écrire une méthode : countByDocument() qui renvoie une Map contenant pour chaque type de document, le nombre d'emprunts correspondants (un entier long). Si un type de document n'a pas d'emprunt, il ne doit pas être présent dans la Map.
    Ajouter ensuite une méthode borrowDaysByDocument(date) permettant de calculer, pour chaque type de document, la somme des jours d'emprunts.
    Vérifier que les tests marqués "Q6" passent.

  7. On souhaite généraliser les deux méthodes précédentes et écrire une méthode statsByDocument(???) qui permet d'effectuer n'importe quelles statistiques par type de document.
    Mettre en commentaire le code des méthode countByDocument() et borrowDaysByDocument(date). Puis réimplanter celles-ci en utilisant une méthode statsByDocument() intermédiaire.
    Vérifier que les tests marqués "Q7" passent.

  8. Les pénalités définies comme constantes dans Library sont pratiques, mais elles ne permettent pas de calculer les pénalités avec une autre politique tarifaire.
    On souhaite donc ajouter une surcharge de lateFeeForMember qui reçoit en dernier paramètre (fees) une table associant chaque type de document (DocumentKind) à une pénalité journalière.
    Ajouter la méthode lateFeeForMember(member, date, fees)
    Réfléchissez à ne PAS dupliquer le code existant, mais à comment faire pour factoriser le code correctement.
    Réfléchissez également au comportement à adopter lorsqu'un DocumentKind n'a pas de pénalité journalière définie.
    Vérifier que les tests marqués "Q8" passent.