+++ /dev/null
-package org.lilie.services.eliot.temps.importcommun
-
-import org.lilie.services.eliot.scolarite.Etablissement
-import org.lilie.services.eliot.scolarite.etablissement.EtablissementService
-import org.lilie.services.eliot.scolarite.AnneeScolaire
-import org.lilie.services.eliot.scolarite.anneescolaire.AnneeScolaireService
-import org.lilie.services.eliot.temps.importsts.StsImportUtil
-import java.text.SimpleDateFormat
-
-/**
- * @author jtra
- */
-abstract class AbstractImportDonneesManager {
-
- EtablissementService etablissementService
- AnneeScolaireService anneeScolaireService
-
- // Préfixe du nom des dossiers des établissements
- protected final static String PREFIXE_NOM_DOSSIER_ETABLISSEMENT = "ETAB_"
-
- // Nom du dossier contenant les données en attente de synchronisation
- private final static String NOM_DOSSIER_EN_ATTENTE = 'EnAttente'
-
- // Nom du dossier contenant les données d'un import en cours d'exécution
- private final static String NOM_DOSSIER_EN_COURS = 'EnCours'
-
- // Nom du dossier contenant les données des imports traités
- private final static String NOM_DOSSIER_TRAITES = 'Traites'
-
- // Nom du fichier de verrou (pour gérer la synchronisation des imports)
- private final static String NOM_FICHIER_LOCK = 'lock'
-
- // Préfixe du nom des dossiers contenant les données d'un import finalisé
- final static String PREFIXE_IMPORT_TRAITE = "IMPORT_"
-
- // Nom des fichiers rapports qui seront enregistrés
- private final static String NOM_FICHIER_RAPPORT = "rapport.html"
-
- /**
- * Teste pour un établissent s'il existe des données importer
- * @param etablissement un établissement
- * @return true s'il y a des données STS à importer pour l'établissement,
- * false sinon
- */
- abstract boolean hasDonneesAImporter(Etablissement etablissement)
-
- /**
- * Teste pour un établissement si un import STS est en cours
- * @param etablissement un établissement
- * @return true si un import STS est cours pour cet établissement, false sinon
- */
- abstract boolean hasImportEnCours(Etablissement etablissement)
-
- /**
- * @return le code du traitement (utilisé pour construire l'arborescence des dossiers)
- */
- abstract String getTraitementCode()
-
- /**
- * @return le chemin du dossier racine de l'import
- */
- abstract String getUriRacineTraitement()
-
- /**
- * Retourne le dossier des données pour un établissement et un état d'import
- * Note: l'arborescence des dossiers sera créée si nécessaire
- * @param etablissement un établissement
- * @param etat un état d'import (EN_ATTENTE, EN_COURS, ou TRAITE)
- * @return le dossier pour l'établissement et l'état passé en paramètre
- */
- File getFileDossierForEtablissementAndEtat(Etablissement etablissement,
- ImportEtat etat) {
- File fileDossierEtablissement = getFileDossierForEtablissement(etablissement)
- String strNomSousDossier
- switch (etat) {
- case ImportEtat.EN_ATTENTE: strNomSousDossier = NOM_DOSSIER_EN_ATTENTE
- break
- case ImportEtat.EN_COURS: strNomSousDossier = NOM_DOSSIER_EN_COURS
- break
- case ImportEtat.TRAITE: strNomSousDossier = NOM_DOSSIER_TRAITES
- break
- default: throw new IllegalStateException(
- "L'état $etat est inconnu"
- )
- }
-
- File file = new File(fileDossierEtablissement, strNomSousDossier)
-
- // Crée l'arborescence des dossiers si nécessaires
- file.mkdirs()
-
- return file
- }
-
- /**
- * Retourne le dossier racine des imports pour un établissement (le
- * dossier qui contient les sous-dossiers EnAttente, EnCours, Traites)
- * @param etablissement un établissement
- * @return le dossier racine des imports STS pour cet établissement
- */
- protected File getFileDossierForEtablissement(Etablissement etablissement) {
- AnneeScolaire anneeScolaire = anneeScolaireService.anneeScolaireEnCours()
- String result = uriRacineTraitement
- result += "/$traitementCode"
- result += "/${PREFIXE_NOM_DOSSIER_ETABLISSEMENT}${etablissement.uai}"
- result += "/${anneeScolaire.code}"
-
- File file = new File(result)
- // Crée l'arborescence si nécessaire
- file.mkdirs()
-
- return file
- }
-
- /**
- * Retourne l'établissement associé à un dossier d'import STS d'un
- * établissement
- * @param nomDossier le nom du dossier
- * @return l'établissement associé à ce dossier, ou null si ce dossier ne
- * correspond pas à un dossier d'import STS d'un établissement
- */
- protected Etablissement parseEtablissementFromNomDossier(String nomDossier) {
- if (!nomDossier.startsWith(PREFIXE_NOM_DOSSIER_ETABLISSEMENT)) {
- return null
- }
-
- String uai = nomDossier.substring(
- PREFIXE_NOM_DOSSIER_ETABLISSEMENT.size()
- )
-
- return etablissementService.findEtablissementByUai(
- uai
- )
- }
-
- /**
- * @param etablissement
- * @return retourne la date (sous forme de Long) à laquelle les fichiers STS
- * ont été déposés pour cet établissement, ou null s'il n'y a pas de fichiers
- * STS en attente pour
- * cet établissement
- */
- abstract protected Long getTimeDepot(Etablissement etablissement)
-
- /**
- * Méthode utilitaire pour supprimer un fichier (s'il existe)
- * Les exceptions éventuelles sont catchées et loggées
- * @param file le fichier à supprimer
- */
- protected void safeDelete(File file) {
- if (file.exists()) {
- try {
- file.delete()
- }
- catch (Exception e) {
- log.error("Impossible de supprimer le fichier $file", e)
- }
- }
- }
-
- /**
- * Retourne un pointeur sur un fichier pour un
- * établissement et un état (en attente, en cours, traité)
- * @param etablissement un établissement
- * @param nomFichier NOM_FICHIER_EMP_STS ou NOM_FICHIER_STS_EMP
- * @param etat un état d'import Sts (en attente, en cours, traité)
- * @param dateTraitement ce paramètre doit être fournit si
- * etat == StsImportEtat.TRAITE, il correspond à la date du traitement
- * @return le fichier EmpSts correspondant
- * @throws IllegalArgumentException si nomFichier n'est pas une des 2 valeurs
- * permises
- * @throws IllegalArgumentException si etat == StsImportEtat.TRAITE et
- * dateTraitement == null
- */
- protected File getFile(Etablissement etablissement,
- String nomFichier,
- ImportEtat etat,
- Date dateTraiment = null)
- throws IllegalArgumentException {
- // Vérifie l'argument 'dateTraitement' si 'etat' == TRAITE
- if (etat == ImportEtat.TRAITE && !dateTraiment) {
- throw new IllegalArgumentException(
- "Le paramètre 'dateTraitement' doit être renseigné pour " +
- "etat == 'StsImportEtat.TRAITE'"
- )
- }
-
- if (etat != ImportEtat.TRAITE) {
- File fileDossierEtablissementEtat = getFileDossierForEtablissementAndEtat(
- etablissement,
- etat
- )
-
- return new File(fileDossierEtablissementEtat, nomFichier)
- }
- else {
- File fileDossierImportTraite = getFileDossierImportTraites(
- etablissement,
- dateTraiment
- )
-
- return new File(fileDossierImportTraite, nomFichier)
- }
- }
-
- /**
- * Retourne un pointeur sur le dossier d'un import traité pour un
- * établissement et une date de traitement
- * l'établissement fournit en argument
- * Note : l'arborescence des dossier sera créée si elle n'existe pas
- * @param etablissement un établissement
- * @param dateTraitement la date de traitement de l'import
- * @return le pointeur sur le dossier
- */
- protected File getFileDossierImportTraites(Etablissement etablissement,
- Date dateTraitement) {
-
- // Récupère le dossier racine des imports terminés
- File fileDossierRacineImportsTraites = getFileDossierForEtablissementAndEtat(
- etablissement,
- ImportEtat.TRAITE
- )
-
- // Dossier import traite (daté)
- File fileDossierImportTraite = new File(
- fileDossierRacineImportsTraites,
- PREFIXE_IMPORT_TRAITE + dateTraitement.format(
- StsImportUtil.FORMAT_DATE_HEURE_DOSSIER
- )
- )
-
- // Crée l'arborescence de dossiers si nécessaires
- fileDossierImportTraite.mkdirs()
-
- return fileDossierImportTraite
- }
-
- /**
- * Retourne un pointeur sur le fichier du rapport d'un import pour un
- * établissement et une date de traitement
- * @param etablissement un établissement
- * @param dateTraitement une date de traitement
- * @return
- */
- public File getFileRapport(Etablissement etablissement, Date dateTraitement) {
- File fileDossierImportTraite = getFileDossierImportTraites(
- etablissement,
- dateTraitement
- )
-
- return new File(
- fileDossierImportTraite,
- AbstractImportDonneesManager.NOM_FICHIER_RAPPORT
- )
- }
-
- /**
- * Essaie de verrouiller les données d'un établissement
- * @param etablissement un établissement
- * @return true si les données de l'établissement ont pu être vérouillées,
- * false sinon
- */
- boolean verrouilleEtablissement(Etablissement etablissement) {
- File fileVerrou = getFileVerrouForEtablissement(etablissement)
-
- if (fileVerrou.exists()) {
- log.error(
- "Impossible de poser un verrou pour l'établissement ${etablissement?.uai}. " +
- "Un verrou pour cet établissement existe déjà."
- )
- return false
- }
-
- try {
- fileVerrou.createNewFile()
- log.info("Pose du verrou pour l'établissement ${etablissement?.uai}")
- return true // Le verrou a été posé
- }
- catch (Exception e) {
- log.error("Impossible de poser un verrou pour l'établissement ${etablissement?.uai}", e)
- return false // Le verrou n'a pas pu être posé
- }
- }
-
- /**
- * Déverouille les données d'un établissement
- * @param etablissement
- */
- void deverrouilleEtablissement(Etablissement etablissement) {
- File fileVerrou = getFileVerrouForEtablissement(etablissement)
- if (fileVerrou.exists()) {
- try {
- fileVerrou.delete()
- log.info("Suppression du verrou pour l'établissement ${etablissement.uai}")
- }
- catch (Exception e) {
- log.error "Echec de l'opération de dévérouillage : ${e.message}"
- }
- }
- }
-
- /**
- * Teste si un établissement est verrouillé
- * @param etablissement
- * @return true si l'établissement est verrouillé, false sinon
- */
- boolean isVerrouille(Etablissement etablissement) {
- File fileVerrou = getFileVerrouForEtablissement(etablissement)
- return fileVerrou.exists()
- }
-
- /**
- * Retourne un pointeur sur le fichier de verrou pour un établissement
- * @param etablissement un établissement
- * @return Retourne un pointeur sur le fichier de verrou pour un établissement
- */
- protected File getFileVerrouForEtablissement(Etablissement etablissement) {
- File fileDossier = getFileDossierForEtablissement(etablissement)
- return new File(fileDossier, NOM_FICHIER_LOCK)
- }
-
- /**
- * @return l'établissement en attente d'un import depuis le plus longtemps,
- * ou null si aucun établissement n'est en attente d'un import STS
- */
- public Etablissement piocheEtablissementEnAttenteImport(String identifiantJob) {
- File fileRacineImportSts = new File("$uriRacineTraitement/$traitementCode")
-
- if (!fileRacineImportSts.exists()) {
- return null
- }
-
- Etablissement etablissementSelectionne = null
- Long timeDepotLePlusAncien = Long.MAX_VALUE
-
- Iterator it = fileRacineImportSts.list().iterator()
- while (it.hasNext()) {
- String nomDossier = it.next()
- Etablissement etablissement = null
- try {
- etablissement = parseEtablissementFromNomDossier(nomDossier)
- }
- catch (Exception e) {
- log.error(
- "Erreur lors du traitement du dossier $nomDossier : " +
- "(Job : $identifiantJob).",
- e
- )
- }
-
- if (etablissement) {
- Long timeDepot = getTimeDepot(etablissement)
-
- // Recherche l'établissement dont le dépôt est le plus ancien
- if (hasDonneesAImporter(etablissement) &&
- timeDepot < timeDepotLePlusAncien &&
- !isVerrouille(etablissement)) {
- timeDepotLePlusAncien = timeDepot
- etablissementSelectionne = etablissement
- }
- }
- }
-
- if (etablissementSelectionne) {
- log.info(
- "Prise en charge de l'établissement ${etablissementSelectionne.uai} " +
- "(par le job $identifiantJob.) " +
- "- en attente depuis " +
- new Date(timeDepotLePlusAncien)
- )
- return etablissementSelectionne
- }
-
- // Aucun établissement en attente d'un import STS
- return null
- }
-
- /**
- * Retourne tous les rapports d'import pour un établissement
- * @param etablissement
- * @return
- */
- public List<ImportRapportInfo> getListeRapportFichierInfo(Etablissement etablissement) {
- List<ImportRapportInfo> listeRapportFichierInfo = (List) []
-
- File fileDossierImportsTraites = getFileDossierForEtablissementAndEtat(
- etablissement,
- ImportEtat.TRAITE
- )
-
- File[] listeDossiersImportsTraites =
- fileDossierImportsTraites.listFiles(
- {
- File dir, String name ->
- return name.startsWith(PREFIXE_IMPORT_TRAITE)
- } as FilenameFilter
- )
-
- listeDossiersImportsTraites.each { File fileDossier ->
- File fileRapport = new File(
- fileDossier,
- AbstractImportDonneesManager.NOM_FICHIER_RAPPORT
- )
-
- if (fileRapport.exists()) {
-
- try {
- // Récupère la date de l'import
- String strDate = fileRapport.parentFile.name.substring(
- PREFIXE_IMPORT_TRAITE.size()
- )
-
- Date date =
- new SimpleDateFormat(
- StsImportUtil.FORMAT_DATE_HEURE_DOSSIER,
- Locale.FRANCE
- ).parse(strDate)
-
- listeRapportFichierInfo << new ImportRapportInfo(
- etablissementNom: etablissement.nomAffichage,
- etablissementUai: etablissement.uai,
- dateRapport: date,
- fileRapport: fileRapport
- )
- }
- catch (Exception e) {
- log.error "Erreur durant la récupération des informations dans le " +
- "nom du dossier : ${e.message}"
- }
- }
- }
-
- return listeRapportFichierInfo
- }
-
- /**
- * @return Retourne la liste des établissements qui sont en attente d'un import
- */
- public List<Etablissement> getEtablissementsEnAttenteImport() {
- File fileRacineImportSts = new File("$uriRacineTraitement/$traitementCode")
-
- if (!fileRacineImportSts.exists()) {
- return []
- }
-
- List<Etablissement> etablissementsEnAttente = []
-
- // Note (jtra) : L'extraction des établissements à partir des dossiers physiques
- // devrait être dans une méthode dédiée
- fileRacineImportSts.list().each { String name ->
- Etablissement etablissement = parseEtablissementFromNomDossier(name)
-
- if (etablissement && hasDonneesAImporter(etablissement)) {
- etablissementsEnAttente << etablissement
- }
- }
-
- return etablissementsEnAttente
- }
-}