using System; using System.Collections.Generic; using MediaTekDocuments.model; using MediaTekDocuments.manager; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using System.Configuration; using System.Linq; using Serilog; namespace MediaTekDocuments.dal { /// /// Classe d'accès aux données /// public class Access { /// /// instance unique de la classe /// private static Access instance = null; /// /// instance de ApiRest pour envoyer des demandes vers l'api et recevoir la réponse /// private readonly ApiRest api = null; /// /// méthode HTTP pour select /// private const string GET = "GET"; /// /// méthode HTTP pour insert /// private const string POST = "POST"; /// /// méthode HTTP pour update /// /// /// méthode HTTP pour delete /// private const string DELETE = "DELETE"; /// /// Méthode privée pour créer un singleton /// initialise l'accès à l'API /// // Le constructeur redevient sans paramètre pour le Singleton private Access() { string authenticationString; string uriApi; Log.Logger = new LoggerConfiguration().MinimumLevel.Debug().WriteTo.File("logs/log.txt", rollingInterval: RollingInterval.Day).CreateLogger(); try { uriApi = ConfigurationManager.AppSettings["ApiUri"]; authenticationString = ConfigurationManager.AppSettings["ApiAuthentication"]; api = ApiRest.GetInstance(uriApi, authenticationString); Log.Information("Log de : {NomMethode} : {Message}", nameof(Access), "Api instanciée"); } catch (Exception e) { Log.Fatal(e, "Erreur fatale lors de l'initialisation de l'accès API"); Environment.Exit(0); } } public static Access GetInstance() { if (instance == null) { // On appelle le constructeur sans argument instance = new Access(); } return instance; } /// /// Retourne tous les genres à partir de la BDD /// /// Liste d'objets Genre public List GetAllGenres() { IEnumerable lesGenres = TraitementRecup(GET, "genre", null); return new List(lesGenres); } /// /// Retourne tous les rayons à partir de la BDD /// /// Liste d'objets Rayon public List GetAllRayons() { IEnumerable lesRayons = TraitementRecup(GET, "rayon", null); return new List(lesRayons); } /// /// Retourne toutes les catégories de public à partir de la BDD /// /// Liste d'objets Public public List GetAllPublics() { IEnumerable lesPublics = TraitementRecup(GET, "public", null); return new List(lesPublics); } /// /// Retourne toutes les livres à partir de la BDD /// /// Liste d'objets Livre public List GetAllLivres() { List lesLivres = TraitementRecup(GET, "livre", null); return lesLivres; } /// /// Retourne toutes les dvd à partir de la BDD /// /// Liste d'objets Dvd public List GetAllDvd() { List lesDvd = TraitementRecup(GET, "dvd", null); return lesDvd; } /// /// Retourne toutes les revues à partir de la BDD /// /// Liste d'objets Revue public List GetAllRevues() { List lesRevues = TraitementRecup(GET, "revue", null); return lesRevues; } /// /// Retourne les exemplaires d'une revue /// /// id de la revue concernée /// Liste d'objets Exemplaire public List GetExemplairesRevue(string idDocument) { String jsonIdDocument = convertToJson("id", idDocument); List lesExemplaires = TraitementRecup(GET, "exemplaire/" + jsonIdDocument, null); return lesExemplaires; } /// /// ecriture d'un exemplaire en base de données /// /// exemplaire à insérer /// true si l'insertion a pu se faire (retour != null) public bool CreerExemplaire(Exemplaire exemplaire) { String jsonExemplaire = JsonConvert.SerializeObject(exemplaire, new CustomDateTimeConverter()); try { List liste = TraitementRecup(POST, "exemplaire", "champs=" + jsonExemplaire); return (liste != null); } catch (Exception ex) { Console.WriteLine(ex.Message); Log.Error(ex, "Erreur dans {NomMethode} : {Message}", nameof(CreerExemplaire), ex.Message); } return false; } /// /// Traitement de la récupération du retour de l'api, avec conversion du json en liste pour les select (GET) /// /// /// verbe HTTP (GET, POST, PUT, DELETE) /// information envoyée dans l'url /// paramètres à envoyer dans le body, au format "chp1=val1&chp2=val2&..." /// liste d'objets récupérés (ou liste vide) private List TraitementRecup (String methode, String message, String parametres) { // trans List liste = new List(); try { JObject retour = api.RecupDistant(methode, message, parametres); // extraction du code retourné String code = (String)retour["code"]; if (code.Equals("200")) { if (methode.Equals(GET)) { String resultString = JsonConvert.SerializeObject(retour["result"]); liste = JsonConvert.DeserializeObject>(resultString, new CustomBooleanJsonConverter()); } } else { Console.WriteLine("code erreur = " + code + " message = " + (String)retour["message"]); Log.Warning("API Retourne une erreur - Code: {Code}, Message: {Message}", code, (string)retour["message"]); } }catch(Exception e) { Console.WriteLine("Erreur lors de l'accès à l'API : "+e.Message); Log.Error(e, "Erreur lors de l'accès à l'API via TraitementRecup"); Environment.Exit(0); } return liste; } /// /// Convertit en json un couple nom/valeur /// /// /// /// couple au format json private String convertToJson(Object nom, Object valeur) { Dictionary dictionary = new Dictionary(); dictionary.Add(nom, valeur); return JsonConvert.SerializeObject(dictionary); } /// /// Modification du convertisseur Json pour gérer le format de date /// private sealed class CustomDateTimeConverter : IsoDateTimeConverter { public CustomDateTimeConverter() { base.DateTimeFormat = "yyyy-MM-dd"; } } /// /// Modification du convertisseur Json pour prendre en compte les booléens /// classe trouvée sur le site : /// https://www.thecodebuzz.com/newtonsoft-jsonreaderexception-could-not-convert-string-to-boolean/ /// private sealed class CustomBooleanJsonConverter : JsonConverter { public override bool ReadJson(JsonReader reader, Type objectType, bool existingValue, bool hasExistingValue, JsonSerializer serializer) { return Convert.ToBoolean(reader.ValueType == typeof(string) ? Convert.ToByte(reader.Value) : reader.Value); } public override void WriteJson(JsonWriter writer, bool value, JsonSerializer serializer) { serializer.Serialize(writer, value); } } /// /// Récupère les commandes d'un document (livre ou dvd) /// /// ID du document concerné /// Liste des commandes du document public List GetCommandesDocument(string idDocument) { string jsonId = "{\"id\":\"" + idDocument + "\"}"; List lesCommandes = TraitementRecup(GET, "commandelivre/" + jsonId, null); return lesCommandes; } public bool DeleteCommande(string idCommande) { String jsonIdCommande = convertToJson("id", idCommande); try { JObject retour = api.RecupDistant("DELETE", "commande/" + jsonIdCommande, null); return (retour["code"].ToString().Equals("200")); } catch (Exception ex) { Log.Error(ex, "Erreur dans {NomMethode} : {Message}", nameof(DeleteCommande), ex.Message); return false; } } public List GetAllSuivis() { IEnumerable lesSuivis = TraitementRecup(GET, "suivi", null); return new List(lesSuivis); } public bool CreerCommande(CommandeDocument commande) { String jsonExemplaire = JsonConvert.SerializeObject(commande, new CustomDateTimeConverter()); try { List liste = TraitementRecup(POST, "commandedocument", "champs=" + jsonExemplaire); return (liste != null); } catch (Exception ex) { Log.Error(ex, "Erreur lors de la création de commande"); } return false; } public string GetNextCommandeId() { List result = TraitementRecup(GET, "maxcommande", null); if (result != null && result.Count > 0) { var firstResult = result[0]; if (firstResult != null && firstResult.maxId != null) { string lastId = firstResult.maxId.ToString(); if (lastId.Length > 1) { int nextIdVal = int.Parse(lastId.Substring(1)) + 1; return nextIdVal.ToString("D4"); } } } return "0001"; } public bool UpdateSuiviCommande(string idCommande, string idSuivi) { String jsonSuivi = convertToJson("idSuivi", idSuivi); try { // Appel PUT : http://localhost/rest_mediatekdocuments/commandedocument/C0001 JObject retour = api.RecupDistant("PUT", "commandedocument/" + idCommande, "champs=" + jsonSuivi); return (retour["code"].ToString().Equals("200")); } catch (Exception ex) { Log.Error(ex, "Erreur dans {NomMethode} : {Message}", nameof(UpdateSuiviCommande), ex.Message); return false; } } public List GetAbonnements(string idRevue) { string jsonIdRevue = convertToJson("id", idRevue); return TraitementRecup(GET, "commanderevue/" + jsonIdRevue, null); } public bool CreerAbonnement(Abonnement abonnement) { string jsonAbonnement = JsonConvert.SerializeObject(abonnement, new CustomDateTimeConverter()); try { JObject retour = api.RecupDistant(POST, "abonnement", "champs=" + jsonAbonnement); return retour["code"].ToString().Equals("200"); } catch (Exception ex) { Log.Error(ex, "Erreur dans {NomMethode} : {Message}", nameof(GetAbonnements), ex.Message); return false; } } public bool SupprimerAbonnement(string idAbonnement) { string jsonId = convertToJson("id", idAbonnement); try { JObject retour = api.RecupDistant(DELETE, "abonnement/" + jsonId, null); return retour["code"].ToString().Equals("200"); } catch(Exception ex) { Log.Error(ex, "Erreur dans {NomMethode} : {Message}", nameof(SupprimerAbonnement), ex.Message); return false; } } public Utilisateur GetConnection(string login, string pwd) { Dictionary loginInfo = new Dictionary { { "identifiant", login }, { "motDePasse", pwd } }; string jsonLogin = JsonConvert.SerializeObject(loginInfo); List lesUtilisateurs = TraitementRecup(GET, "utilisateur/" + jsonLogin, null); if (lesUtilisateurs != null && lesUtilisateurs.Count > 0) { return lesUtilisateurs[0]; } Log.Warning("Tentative de connexion échouée pour le login : {Login}", login); return null; } } }