Subversion Repositories eFlore/Applications.cel

Rev

Rev 2618 | Go to most recent revision | Blame | Last modification | View Log | RSS feed

package org.tela_botanica.client.image;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;

import org.tela_botanica.client.interfaces.Rafraichissable;
import org.tela_botanica.client.modeles.dao.ImageAsynchroneDAO;
import org.tela_botanica.client.modeles.dao.ImageUploaderAsynchroneDAO;
import org.tela_botanica.client.modeles.dao.LiaisonMotsClesImageAsynchroneDAO;
import org.tela_botanica.client.modeles.dao.LienImageAsynchroneDAO;
import org.tela_botanica.client.modeles.dao.ListeDateImageAsynchroneDAO;
import org.tela_botanica.client.modeles.dao.ListeImageAsynchroneDAO;
import org.tela_botanica.client.modeles.dao.ListeObservationAsynchroneDAO;
import org.tela_botanica.client.modeles.dao.MotsClesAsynchroneDAO;
import org.tela_botanica.client.modeles.dao.NombreImageAsynchroneDAO;
import org.tela_botanica.client.modeles.dao.NombreObservationAsynchroneDAO;
import org.tela_botanica.client.modeles.objets.Configuration;
import org.tela_botanica.client.modeles.objets.ImageCarnet;
import org.tela_botanica.client.modeles.objets.ListeImageCarnet;
import org.tela_botanica.client.modeles.objets.ListeObservation;
import org.tela_botanica.client.modeles.objets.Utilisateur;
import org.tela_botanica.client.util.MotsClesUtilitaire;

import com.google.gwt.json.client.JSONArray;
import com.google.gwt.user.client.Window;
import com.gwtext.client.data.ArrayReader;
import com.gwtext.client.data.FieldDef;
import com.gwtext.client.data.IntegerFieldDef;
import com.gwtext.client.data.MemoryProxy;
import com.gwtext.client.data.RecordDef;
import com.gwtext.client.data.Store;
import com.gwtext.client.data.StringFieldDef;
import com.gwtext.client.data.Tree;
import com.gwtext.client.widgets.tree.TreeNode;

/**
 * Modèle d'accès aux données pour les images. C'est un singleton
 * 
 * @author aurelien
 * 
 */
public class ImageModele implements Rafraichissable {

        /**
         * Booleen indiquant si le médiateur est instancié (l'instance doit être
         * unique donc le booleen est static)
         */
        private static boolean estInstancie = false;

        /**
         * le modèle lui même
         */
        private static ImageModele thisModele = null;

        /**
         * Le médiateur associé au modèle
         */
        private ImageMediateur iMediateur = null;

        /**
         * La configuration en cours
         */
        private Configuration config = null;

        /**
         * La liste des image affichées en cours
         */
        private ListeImageCarnet cacheImage = new ListeImageCarnet(0);
        /**
         * Table de correspondance entre les mots clés et leurs identifiants
         */
        private HashMap<String, String> motsCles = new HashMap<String, String>(0);
        /**
         * Le store contenant les données à afficher, que le modèle transmet au
         * médiateur quand il le demande
         */
        private Store st = null;
        /**
         * Arbre des mots clés
         */
        private com.gwtext.client.data.Tree arbreMotsCles = new Tree();

        /**
         * Numéro de page en cours
         */
        private int pageEncours = 0;
        /**
         * Nombre de pages totales
         */
        private int pageMax = 1;
        /**
         * Taille de page (par défaut 50)
         */
        private int taillePage = 50;
        /**
         * Nombre d'éléments total correspondant à la requete
         */
        private int nbElements = 0;

        /**
         * "Presse papier" pour les images qui permet de garder en mémoire une
         * sélection
         */
        private Vector<String> selectionImages = new Vector<String>(0);

        /**
         * Retourne une instance de manière unique
         * 
         * @param im
         *            le médiateur à associer
         * @return l'instance du modèle
         */
        static ImageModele Instance(ImageMediateur im) {
                // si le modèle n'est pas encore instancié
                if (!estInstancie) {
                        // on en crée un nouveau
                        estInstancie = true;
                        thisModele = new ImageModele(im);
                }

                // sinon on retourne le "pointeur" vers le modèle lui-même
                return thisModele;

        }

        /**
         * Le constructeur est privé et seule la méthode instance y accède
         * 
         * @param im
         *            le médiateur à associer
         */
        private ImageModele(ImageMediateur im) {

                iMediateur = im;
                config = new Configuration();
        }

        /**
         * Accesseur pour le médiateur
         * 
         * @return le médiateur associé
         */
        public ImageMediateur getIMediateur() {
                return iMediateur;
        }
        
        public String[][] obtenirFiltresPourComptage() {

                String valeursFiltres[][] = getIMediateur().renvoyerFiltres();

                int tailleFiltres = valeursFiltres.length;

                String[][] criteres = new String[tailleFiltres][2];

                String[] utilisateur = {
                                "" + getIMediateur().getIdentifiant() };
                criteres[0] = utilisateur;


                for (int i = 0; i < valeursFiltres.length; i++) {
                        criteres[i] = valeursFiltres[i];
                }
                
                return criteres;
        }
        
        public String[][] obtenirFiltresPourDonnees() {

                String valeursFiltres[][] = getIMediateur().renvoyerFiltres();
                
                int tailleFiltres = valeursFiltres.length;
                
                String[][] criteres2 = new String[tailleFiltres + 2][2];
                
                String[] limite = { "limite", "" + taillePage };
                String[] taillePage = { "numero_page", "" + pageEncours };
                
                criteres2[0] = limite;
                criteres2[1] = taillePage;

                for (int i = 0; i < valeursFiltres.length; i++) {
                        criteres2[i + 2] = valeursFiltres[i];
                }
                
                return valeursFiltres;
        }

        /**
         * Appelle le DAO asynchrone pour obtenir la liste des images
         * 
         * @param r
         *            le rafraichissable auxquel on enverra les données
         */
        public void obtenirNombrePhotoGalerie(Rafraichissable r) {

                String[][] criteres = obtenirFiltresPourComptage();

                // on les crée un DAO auquel on les transmet et qui demande le nombre
                // d'images correspondantes (pour les pages)
                NombreImageAsynchroneDAO niaDAO = new NombreImageAsynchroneDAO(this);
                niaDAO.obtenirNombreImages(this, criteres);
        }
        
        public void obtenirPhotoGalerie(Rafraichissable r)
        {
                String valeursFiltres[][] = getIMediateur().renvoyerFiltres();
                
                int tailleFiltres = valeursFiltres.length;
                
                String[][] criteres2 = new String[tailleFiltres + 4][2];
                
                String[] tri = { "tri", "" + getIMediateur().getTri() };
                String[] triDir = { "dir", "" + getIMediateur().getDirectionTri()};
                
                String[] limite = { "limite", "" + taillePage };
                String[] taillePage = { "numero_page", "" + pageEncours };
                
                criteres2[0] = limite;
                criteres2[1] = taillePage;
                
                criteres2[2] = tri;
                criteres2[3] = triDir;

                for (int i = 0; i < valeursFiltres.length; i++) {
                        criteres2[i + 4] = valeursFiltres[i];
                }
                
                // et on crée un DAO auquel on les transmet et qui envoie une requete
                // pour recevoir les images
                ListeImageAsynchroneDAO liaDAO = new ListeImageAsynchroneDAO(this);
                liaDAO.ObtenirListeImages(this, criteres2);
        }

        /**
         * Appelle le DAO d'upload qui va choisir la methode d'upload adaptée et
         * lancer l'interface appropriée
         */
        @SuppressWarnings("static-access")
        public void uploaderImages(boolean multiple) {
                ImageUploaderAsynchroneDAO IuADaO = new ImageUploaderAsynchroneDAO(this);
                if(multiple) {
                        IuADaO.appelerUploadMultiple();
                }
                else 
                {
                        IuADaO.appelerUploadSimple();
                }
        }

        /**
         * Met à jour la liste des images à partir d'un objet
         * 
         * @param o
         *            la nouvelle liste d'image
         */
        public void rafraichirListeImage(Object o) {
                cacheImage = (ListeImageCarnet) o;
        }

        /**
         * Met à jour l'arbre des mots clés à partir d'un objet
         * 
         * @param o
         *            le nouvel arbre de mots clés
         */
        public void rafraichirArbreMotsCles(Object o) {
                arbreMotsCles = (com.gwtext.client.data.Tree) o;
        }

        /**
         * Met à jour la table de correspondance mots clés / ids à partir d'un objet
         * 
         * @param o
         *            la nouvelle table des mots clés
         */
        @SuppressWarnings("unchecked")
        public void rafraichirMotsCles(Object o) {
                if (o instanceof HashMap) {
                        motsCles = (HashMap<String, String>) o;
                }
        }

        /**
         * Va chercher les métadonnées associées à une image dans la liste des
         * images chargée dans le modèle
         * 
         * @param r
         *            le rafraichissable auquel on enverra les informations
         * @param id
         *            l'identifiant de l'image
         */
        public void obtenirMetadonnees(Rafraichissable r, String id) {
                ImageCarnet im = cacheImage.get(id);

                Object meta[] = new Object[3];
                meta[0] = im.getMetadonnesExif();
                meta[1] = im.getMetadonnesIptc();
                meta[2] = im.getInfoGenerales();

                r.rafraichir(meta, false);
        }

        /**
         * Va chercher les mots clés associés à une image dans la liste des images
         * chargée dans le modèle
         * 
         * @param r
         *            le rafraichissable auquel on enverra les informations
         * @param id
         *            l'identifiant de l'image
         */
        public void obtenirMotsClesId(Rafraichissable r, String id) {

                String[] motsClesIdTab = getMotsClesId(id);
                r.rafraichir(motsClesIdTab, false);
        }
        
        public String[] getMotsClesId(String idImage) {
                ImageCarnet im = cacheImage.get(idImage);
                String motsClesId = im.getMotsCles();
                String[] motsClesIdTab = motsClesId.split(",");
                
                return motsClesIdTab;
        }
        
        /**
         * Va chercher le nom du mot clé associé à un id dans le cache local
         * 
         * @param String id
         *            id du mot clé
         * @return le mot clé associé à l'identifiant
         */
        public String obtenirTexteMotCle(String id) {
                
                String correspondanceId = "";
                
                String motCleTexte = motsCles.get(id);
                
                if(motCleTexte != null) {
                        correspondanceId = motCleTexte;
                }
                
                return correspondanceId;
        }
        
        /**
         * Construit une chaine contenant le texte des mots clés séparés par des virgules
        */
        public String renvoyerChaineMotClesTexte(ImageCarnet ic) {
                String chaineMotsCles = ic.getMotsCles();
                String[] tabMotsCles = chaineMotsCles.split(",");
                String chaineMotsClesTexte = "";
                for (int i = 0; i < tabMotsCles.length; i++) {
                        chaineMotsClesTexte += motsCles.get(tabMotsCles[i]);
                        chaineMotsClesTexte += (i != tabMotsCles.length - 1) ? "," : "";
                }
                return chaineMotsClesTexte;
        }

        /**
         * Met à jour la liste des images en local et appelle le DAO de mise à jour
         * pour les commentaires et la date des images selectionnées
         * 
         * @param commentaires
         *            le commentaire à appliquer
         * @param date
         *            la date à appliquer
         * @param ids
         *            les identifiants des images selectionnées
         */
        public void mettreAJourCacheImage(String commentaires, String date,
                        String note, String ids[]) {
                for (int i = 0; i < ids.length; i++) {
                        String key = ids[i];
                        ImageCarnet ic = cacheImage.get(key);
                        ic.miseAJourInfoGenerales(commentaires, date, note);
                        mettreAjourBaseDeDonneesImageCarnet(ic);
                }

        }

        /**
         * Ajoute un nouveau mot clés à la liste des mots clés locale
         * 
         * @param text
         *            le mot clé
         * @param id
         *            l'identifiant du mot clé
         */
        public void mettreAjourMotsClesId(String text, String id) {
                motsCles.put(id, text);
        }

        /**
         * Appelle le DAO chargé de mettre à jour la base de données avec les toutes
         * les informations des images modifiées par l'utilisateur
         */
        public void mettreAJourBaseDeDonneesListeImageCarnet() {
                ListeImageAsynchroneDAO liDaO = new ListeImageAsynchroneDAO(this);

                liDaO.SynchroniserBaseDeDonnees(cacheImage);
        }

        /**
         * Appelle le DAO chargé de mettre à jour la base de données avec les toutes
         * les informations d'une image donnée
         * 
         * @param ic
         *            l'image à synchroniser avec la base
         */
        public void mettreAjourBaseDeDonneesImageCarnet(ImageCarnet ic) {
                ImageAsynchroneDAO iaDaO = new ImageAsynchroneDAO(this);
                iaDaO.SynchroniserBaseDeDonnees(ic);
        }

        /**
         * Supprime les images données du cache local et appelle le DAO qui les
         * supprime de la base de données
         * 
         * @param ids
         *            les identifiants des images selectionnées
         */
        public void supprimerImages(String[] ids) {
                String rids[] = new String[ids.length];
                ListeImageAsynchroneDAO liDao = new ListeImageAsynchroneDAO(this);

                for (int i = 0; i < ids.length; i++) {
                        String key = ids[i];
                        ImageCarnet ic = cacheImage.get(key);
                        rids[i] = ic.getId();

                        cacheImage.remove(key);
                }

                if (rids.length != 0) {
                        liDao.supprimerBaseDeDonnees(rids);
                }
        }

        /**
         * Met à jour les données locales suivant le type des nouvelles données et
         * appelle le médiateur pour le notifier de la mise à jour
         */
        @Override
        public void rafraichir(Object nouvelleDonnees,
                        boolean repandreRafraichissement) {
                // si l'on a reçu une liste d'images
                if (nouvelleDonnees instanceof ListeImageCarnet) {
                        ListeImageCarnet data = (ListeImageCarnet) nouvelleDonnees;
                        Object[][] photoData = new Object[data.size()][14];
                        int i = 0;

                        if (data.size() == 0) {
                                pageEncours = 0;
                        }

                        // on la parse et on récupère les informations qui nous interessent
                        for (Iterator<String> it = data.keySet().iterator(); it.hasNext();) {
                                ImageCarnet im = data.get(it.next());
                                photoData[i][0] = im.getOrdre();
                                photoData[i][1] = im.getNomOriginal();
                                photoData[i][2] = im.getDate();
                                photoData[i][3] = im.getIptcCity();
                                photoData[i][4] = im.getFabriquantAppareil() + " " + im.getModeleAppareil();
                                photoData[i][5] = im.getUrlFormatListe();
                                photoData[i][6] = im.getUrlFormatGalerie();
                                photoData[i][7] = im.getUrlFormatZoom();
                                photoData[i][8] = im.getNote();
                                photoData[i][9] = im.getId();
                                photoData[i][10] = im.getTailleImage()[1];
                                photoData[i][11] = im.getTailleImage()[0];
                                photoData[i][12] = im.getIdsObsAssociees();
                                photoData[i][13] = im.getIdsObsAssociees();

                                i++;
                        }


                        RecordDef rd = new RecordDef(ImageMediateur.getDefinitionsChampsGrilleImages());

                        final MemoryProxy dataProxy = new MemoryProxy(photoData);
                        final ArrayReader reader = new ArrayReader(rd);

                        final Store photoStore = new Store(dataProxy, reader);

                        rafraichirListeImage(nouvelleDonnees);

                        st = photoStore;
                        st.load();

                        // si on doit répandre les données, on notifie le médiateur qui les
                        // distribuera à son tour
                        if (repandreRafraichissement) {
                                getIMediateur().synchroniserDonneesZoomListeGalerie(st, this);
                        }
                }

                // si on reçoit un tableau JSON
                if (nouvelleDonnees instanceof JSONArray) {
                        // alors on a reçu les informations sur les mots clés                 
                        JSONArray donneesArbre = (JSONArray)nouvelleDonnees;
                        
                        Object[] arbreEtCorrespondancesIds = MotsClesUtilitaire.construireArbre("Tags", "racine", donneesArbre, false);
                        
                        arbreMotsCles = (Tree)arbreEtCorrespondancesIds[0];
                        motsCles = (HashMap<String, String>)arbreEtCorrespondancesIds[1];

                        // enfin on met à jour l'arbre des mots clés contenu dans le modèle
                        rafraichirArbreMotsCles(arbreMotsCles);
                        // la table de hachage
                        rafraichirMotsCles(motsCles);
                        // et on notifie le médiateur de la mise à jour en lui passant une
                        // copie des données
                        getIMediateur().rafraichirArbreMotsCles(arbreMotsCles);
                }

                // Si on reçoit un tableau d'entiers
                // c'est un tableau d'un seul entier qui est le nombre d'images
                // correspondant aux critères
                if (nouvelleDonnees instanceof int[]) {
                        int[] pages = (int[]) nouvelleDonnees;

                        // on calcule le nombre de pages nécessaires et on les met à jour
                        // dans le modèle
                        pageMax = calculerNbPages(pages[0]);
                        nbElements = pages[0];

                        // et on notifie de le mediateur du changement des valeurs
                        getIMediateur().changerPageMaxEtCourante(pageMax, pageEncours,
                                        taillePage, pages[0]);
                        
                        obtenirPhotoGalerie(this) ;
                }
                
                if(nouvelleDonnees instanceof ListeObservation) {
                        
                        getIMediateur().rafraichirMiniListeObservations((ListeObservation)nouvelleDonnees) ;
                }
                
                if(nouvelleDonnees instanceof Tree) {
                        rafraichirArbreMotsCles(nouvelleDonnees);
                        getIMediateur().rafraichirArbreMotsCles((Tree)nouvelleDonnees);
                }
        }

        /**
         * Met à jour les mots clés associés à une image et appelle le DAO pour
         * synchroniser la base de données
         * 
         * @param ids
         *            les identifiants des images selectionnées
         * @param motsClesEnCours
         *            les mots clés à appliquer aux images
         * @param arbreMC
         *            l'arbre de mots clés en cours
         */
        public void mettreAjourMotsCles(String[] ids, String motsClesEnCours,
                        com.gwtext.client.data.Tree arbreMC) {
                
                String idImgs = ""; 
                for (int i = 0; i < ids.length; i++) {
                        String idImageEnCours = "";
                        if (cacheImage.containsKey(ids[i])) {
                                ImageCarnet ic = cacheImage.get(ids[i]);
                                idImageEnCours = ic.getId();
                                ic.mettreAjourMotsCles(motsClesEnCours);
                        }
                        idImgs += idImageEnCours;
                        idImgs += (i < (ids.length - 1)) ? ",": ""; 
                }
                
                LiaisonMotsClesImageAsynchroneDAO liMcDao = new LiaisonMotsClesImageAsynchroneDAO(this);
                liMcDao.modifier(this, Utilisateur.getInstance().getIdentifiantUtilisateurConsulte(), idImgs, motsClesEnCours);

                rafraichirArbreMotsCles(arbreMC);
        }

        /**
         * Appelle le DAO des mots clés pour obtenir l'arbre complet stocké dans la
         * base de données
         */
        public void initialiserArbreMotsCles() {
                
                        MotsClesAsynchroneDAO MCDao = new MotsClesAsynchroneDAO("images");
                        MCDao.obtenirListeMotsCles(this);
        }

        /**
         * Envoie l'arbre des mots clés stocké localement à l'élément rafrachissable
         * donné, qui le demande
         * 
         * @param r
         *            le rafraichissable demandeur de l'arbre
         */
        public void obtenirArbreMotCle(Rafraichissable r) {
                        r.rafraichir(arbreMotsCles, false);
        }

        /**
         * Ajoute un mot clé à l'arbre des mots clés local et appelle le DAO qui
         * fait la mise à jour de l'arbre des mots clés dans la base
         * 
         * @param n
         *            le nouveau noeud contenant le mot clé
         * @param arbreMC
         *            l'arbre des mots cles en cours
         */
        public void ajouterMotCleDansArbre(TreeNode n,
                        com.gwtext.client.data.Tree arbreMC, Rafraichissable r) {
                MotsClesAsynchroneDAO MCDao = new MotsClesAsynchroneDAO("images");

                String[] usObj = (String[]) n.getUserObject();
                String motCle = usObj[0];
                String id = usObj[1];
                String parentId = "";

                if (!id.equals("racine")) {
                        String[] parentUsObj = (String[]) n.getParentNode().getUserObject();
                        if(!parentUsObj[1].equals("racine")) {
                                parentId = parentUsObj[1];
                        }
                }

                rafraichirArbreMotsCles(arbreMC);
                mettreAjourMotsClesId(motCle, id);

                String nouveauMotCle = "&identifiant=" + getIdentifiant() + "&motcle="
                                + motCle + "&id=" + id + "&parent=" + parentId;
                MCDao.ajouterBaseDeDonnees(nouveauMotCle, r);
        }

        /**
         * Supprime un noeud de l'arbre des mots clés et appelle le DAO qui va
         * supprimer les mots clés associés dans la base
         * 
         * @param n
         *            le noeud à supprimer
         * @param arbreMC
         *            l'arbre des mots clés en cours
         */
        public void supprimerMotCleDansArbre(TreeNode n, Tree arbreMC, Rafraichissable r) {

                MotsClesAsynchroneDAO MCDao = new MotsClesAsynchroneDAO("images");

                String[] usObj = (String[]) n.getUserObject();
                String id = usObj[1];

                MCDao.supprimerBaseDeDonnees(id, r);

        }

        /**
         * Modifie le noeud donné dans l'arbre des mots clés en cours et appelle le
         * DAO qui synchronise la modification dans la base de données
         * 
         * @param n
         *            le noeud modifié
         * @param arbreMC
         *            l'arbre des mots clés en cours
         */
        public void modifierMotCleDansArbre(TreeNode n, Tree arbreMC, Rafraichissable r) {

                MotsClesAsynchroneDAO MCDao = new MotsClesAsynchroneDAO("images");

                String[] usObj = (String[]) n.getUserObject();
                String motCle = usObj[0];
                String id = usObj[1];
                String parentId = "";

                if (!id.equals("racine")) {
                        String[] parentUsObj = (String[]) n.getParentNode().getUserObject();
                        if(!parentUsObj[1].equals("racine")) {
                                parentId = parentUsObj[1];
                        }
                }

                rafraichirArbreMotsCles(arbreMC);

                String motCleModifie = "&motcle=" + motCle + "&id=" + id + "&parent="
                                + parentId;
                MCDao.modifierBaseDeDonnees(motCleModifie, r);

        }

        /**
         * Deplace un noeud dans l'arbre des mots cles et appelle le DAO qui
         * reorganise l'arbre dans la base de donnees suivant le changement
         * 
         * @param n
         *            le noeud deplace (et son sous arbre associe)
         * @param arbreMC
         *            l'arbre des mots cles en cours
         */
        public void deplacerMotCleDansArbre(TreeNode n, Tree arbreMC, Rafraichissable r) {
                MotsClesAsynchroneDAO MCDao = new MotsClesAsynchroneDAO("images");

                String[] usObj = (String[]) n.getUserObject();
                String motCle = usObj[0];
                String id = usObj[1];
                String parentId = "";
                
                if (!id.equals("racine")) {
                        String[] parentUsObj = (String[]) n.getParentNode().getUserObject();
                        if(!parentUsObj[1].equals("racine")) {
                                parentId = parentUsObj[1];
                        }
                }

                rafraichirArbreMotsCles(arbreMC);

                String motCleModifie = "&motcle=" + motCle + "&id=" + id + "&parent="
                                + parentId;
                MCDao.deplacerBaseDeDonnees(motCleModifie, r);
        }

        /**
         * Change le numéro de la page en cours et envoie une demande de mise à jour
         * des données
         * 
         * @param nouvellePageCourante
         *            la nouvelle page à afficher
         */
        public void changerNumeroPage(int nouvellePageCourante) {
                pageEncours = nouvellePageCourante;
                obtenirNombrePhotoGalerie(this);
        }

        /**
         * Calcule le nombre de pages nécessaires pour afficher un nombre d'élements
         * donnés en fonction de la taille de page en cours
         * 
         * @param nbElements
         *            le nombre d'élements total
         * @return le nombre de pages
         */
        public int calculerNbPages(int nbElements) {
                // A cause de la betise de java pour les conversion implicite on fait
                // quelques conversions manuellement
                // pour eviter qu'il arrondisse mal la division
                // nombre de pages = (nombre d'element / taille de la page) arrondie à
                // l'entier superieur
                double nPage = (1.0 * nbElements) / (1.0 * taillePage);
                double nPageRound = Math.ceil(nPage);
                Double nPageInt = new Double(nPageRound);

                // on convertit en entier
                return nPageInt.intValue();
        }

        /**
         * Recalcule la page en cours lors du changement du nombre d'élements
         * 
         * @param nbElements
         *            le nombre d'élements total
         * @return la nouvelle page encours
         */
        public int calculerPageCourante(int nbElements) {
                // on calcule le nombre de page
                int nouvelNbPages = calculerNbPages(nbElements);
                // la nouvelle page en cours
                double nPageCourante = (1.0 * pageEncours) / (1.0 * pageMax)
                                * (1.0 * nouvelNbPages);

                // on arrondit au supérieur
                double nPageRound = Math.ceil(nPageCourante);
                Double nPageInt = new Double(nPageRound);

                // on convertit en entier
                return Math.abs(nPageInt.intValue());
        }

        /**
         * Change la taille de page et recalcule la page encours
         * 
         * @param nouvelleTaillePage
         *            la nouvelle taille de page à utiliser
         */
        public void changerTaillePage(int nouvelleTaillePage) {
                taillePage = nouvelleTaillePage;
                pageEncours = calculerPageCourante(nbElements);
                obtenirNombrePhotoGalerie(this);
        }
        
        /**
         * Met la valeur de la page en cours à la dernière 
         */
        public void setDernierePage() {
                changerNumeroPage(pageMax);
        }

        /**
         * Notifie le mediateur que l'upload ou le download est termine et qu'il
         * faut rafraichir les vues avec les nouvelles données
         */
        public void requeteTerminee() {
                getIMediateur().demasquerChargement();
                getIMediateur().rafraichirToutesVues();
        }

        /**
         * Obtient l'identifiant de l'utilisateur auprès du médiateur
         * 
         * @return id de l'utilisateur
         */
        public String getIdentifiant() {

                return getIMediateur().getIdentifiant();
        }

        /**
         * renvoie la taille d'une image grâce à son identifiant
         * 
         * @param id
         *            l'identifiant de l'image
         * @return un tableau contenant la longueur et la hauteur de l'image
         */
        public String[] obtenirTailleImage(String id) {

                return (cacheImage.get(id)).getTailleImage();

        }

        /**
         * Suivant l'id d'une image donnée, fais une demande au modèle pour qu'il
         * renvoie la note associée au rafrachissable qui la demande
         * 
         * @param r
         *            le rafraichissable demandeur de l'information
         * @param id
         *            l'identifiant del'image
         */
        public void obtenirNote(Rafraichissable r, String id) {

                r.rafraichir((cacheImage.get(id)).getNote(), true);

        }

        /**
         * Accesseur pour la configuration en cours d'utilisation
         * 
         * @return la configuration
         */
        public Configuration getConfig() {

                return config;
        }

        /**
         * Ajoute des images à la selection en cours
         * 
         * @param ids
         *            les identifiants des images à ajouter
         */
        public void ajouterImagesSelection(String[] ids) {

                for (int i = 0; i < ids.length; i++) {
                        
                        String idImg = cacheImage.get(ids[i]).getId();
                        selectionImages.add(idImg);
                }
        }

        public int getCompteSelection() {
                return selectionImages.size();
        }
        
        /**
         * Vide la selection en cours
         */
        public void viderSelection() {
                selectionImages.clear();
        }

        public String renvoyerSelection() {

                String selection = "";
                
                if(selectionImages.size() <= 0)
                {
                        selection += "-255" ;
                }
                else
                {
                        for (Iterator<String> it = selectionImages.iterator(); it.hasNext();) {
        
                                String idEncours = it.next();
                                selection += idEncours + ",";
                        }
                }

                return selection;
        }

        public void lierImagesObervations(String idsObs, String idsImg) {
                
                LienImageAsynchroneDAO lienDAO = new LienImageAsynchroneDAO(this) ;
                lienDAO.lierImageBaseDeDonnees(idsImg, idsObs) ;
                
        }

        public void obtenirLiaisonObservations(ImageMediateur imageMediateur,
                        String id) {
                
                String imgId = cacheImage.get(id).getId() ;
                
                LienImageAsynchroneDAO lienDao = new LienImageAsynchroneDAO(this) ;
                lienDao.obtenirLiaisonsImagesObservations(this, imgId) ;
                
        }

        public void supprimerLiaisonImages(String[] idsImg, String idObs) {
                
                String chaineIdImg = "";
                
                for(int i = 0; i < idsImg.length; i++) {
                        String idImg = cacheImage.get(idsImg[i]).getId() ;
                        chaineIdImg += ","+idImg;
                }
                
                chaineIdImg = chaineIdImg.replaceFirst(",", "");
                
                LienImageAsynchroneDAO lienDAO = new LienImageAsynchroneDAO(this) ;
                lienDAO.supprimerLienImageObservation(chaineIdImg, idObs) ;             
        }

        public void obtenirMiniListeObservations(Rafraichissable r, String[] critere, int taillePage, int numeroPage) {
                
                String[] tri = { "tri", "" + getIMediateur().getTriMiniListeObs() };
                String[] triDir = { "tri_dir", "" + getIMediateur().getDirectionTriMiniListeObs()};
                
                String[][] criteres = {{critere[0],critere[1]},{"limite",""+taillePage},{"numero_page",""+numeroPage}, tri, triDir} ;           
                
                // et on crée un DAO auquel on les transmet et qui envoie une requete pour recevoir les images
                ListeObservationAsynchroneDAO loaDAO = new ListeObservationAsynchroneDAO(this);
                loaDAO.obtenirListeObservation(r, iMediateur.getIdentifiant(), criteres);       
                
        }

        public void obtenirNombreMiniListeObservations(Rafraichissable r, String[] critere) {
                
                String[][] criteres = {{critere[0],critere[1]}} ;               
                
                // et on crée un DAO auquel on les transmet et qui envoie une requete pour recevoir les images
                NombreObservationAsynchroneDAO noaDAO = new NombreObservationAsynchroneDAO(this);
                noaDAO.obtenirNombreObservation(r, iMediateur.getIdentifiant(), criteres);      
                
        }

        public void obtenirDatesImages(Rafraichissable r) {
                ListeDateImageAsynchroneDAO lDateDao = new ListeDateImageAsynchroneDAO(this);
                lDateDao.obtenirListeDate(r, iMediateur.getIdentifiant());
        }
        
        public String obtenirIdPourOrdre(String ordreImage) {
                return cacheImage.get(ordreImage).getId();
        }

}