Subversion Repositories eFlore/Applications.cel

Rev

Rev 2757 | Blame | Compare with Previous | Last modification | View Log | RSS feed

package org.tela_botanica.client.vues.observation.filtres;

import java.util.Comparator;
import java.util.Iterator;

import org.tela_botanica.client.i18n.Msg;
import org.tela_botanica.client.interfaces.Filtrable;
import org.tela_botanica.client.interfaces.Rafraichissable;
import org.tela_botanica.client.modeles.objets.EntiteGeographiqueObservation;
import org.tela_botanica.client.modeles.objets.ListeEntiteGeographiqueObservation;
import org.tela_botanica.client.modeles.objets.Observation;
import org.tela_botanica.client.observation.ObservationMediateur;
import org.tela_botanica.client.util.Util;

import com.gwtext.client.data.Node;
import com.gwtext.client.data.NodeTraversalCallback;
import com.gwtext.client.data.Tree;
import com.gwtext.client.widgets.Component;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.event.PanelListenerAdapter;
import com.gwtext.client.widgets.tree.TreeNode;
import com.gwtext.client.widgets.tree.TreePanel;
import com.gwtext.client.widgets.tree.event.TreeNodeListenerAdapter;
import com.gwtext.client.widgets.tree.event.TreePanelListenerAdapter;
import com.gwtext.client.core.EventObject;

/**
 * Arbre Filtrant sur les entites geographiques 
 *
 * 
 * @author aurelien + david
 * 
 */


public class ArbreEntiteGeographiqueObservationFiltreVue extends Panel implements Rafraichissable,
                Filtrable {

        /**
         * Le médiateur associé à la vue
         */
        private ObservationMediateur    observationMediateur            = null;

        /**
         * Les localites en cours
         */
        private String entitesGeographiquesEncours = "";

        /**
         * Le treepanel qui affiche l'arbre
         */
        private TreePanel arbreEntitesGeographiques = null;


        /**
         * booléen d'initialisation
         */
        private boolean estInstancie = false;

        /**
         * booléen d'etat
         */
        private boolean filtreModifie = false;
        private boolean arbreCharge = false ;

        private String nomFiltre = "" ;
        
        /**
         * Constructeur sans argument (privé car ne doit pas être utilisé)
         */
        @SuppressWarnings("unused")
        private ArbreEntiteGeographiqueObservationFiltreVue() {
                super();
        }

        /**
         * Constructeur avec paramètres
         * 
         * @param im
         *            le médiateur à associer
         */
        public ArbreEntiteGeographiqueObservationFiltreVue(ObservationMediateur obs) {

                // on crée le panel
                super(Msg.get("localites"));
                
                this.observationMediateur = obs;

                arbreEntitesGeographiques = new TreePanel();

                this.setPaddings(5);

                this.setCollapsible(true);
        
                this.setAutoScroll(true);
                

                // on ajoute les listeners
                ajouterListenersPanel();
                estInstancie = false;
        }

        /**
         * Ajoute les listeners pour le rendu du panel
         */
        private void ajouterListenersPanel() {
                  this.addListener(new PanelListenerAdapter() {

                        // on instancie réellement les composants au moment du rendu pour
                        // accélérer l'affichage
                        // et éviter des bugs
                        @Override
                        public void onRender(Component component) {

                                // on interdit le drag and drop dans l'arbre
                                arbreEntitesGeographiques.setEnableDD(false);
                                arbreEntitesGeographiques.setId("x-view-tree-filter-entity");

                                // on crée une racine pour l'arbre
                                TreeNode root = new TreeNode(Msg.get("localites"));
                                root.setId("racine_entite");
                                String[] usObject = { Msg.get("localites") };
                                root.setUserObject(usObject);

                                arbreEntitesGeographiques.setRootNode(root);
                                arbreEntitesGeographiques.setRootVisible(true);
                                arbreEntitesGeographiques.setBorder(false);
                                root.setExpandable(true) ;

                                add(arbreEntitesGeographiques);

                                // on ajoute les listeners d'évenements
                                ajouterListeners();

                                
                                // enfin on considère le composant comme instancié
                                estInstancie = true;
                        }
                });
        }
        
        /**
         * ajoute les listeners pour les boutons et le cochage des entites
         */
        private void ajouterListeners() {
                
                arbreEntitesGeographiques.addListener(new TreePanelListenerAdapter() {
                        
                        @Override
                        public void onClick(TreeNode node, EventObject e) {
                                gererClicNoeud(node);
                        }
                        
                }) ;
                
                arbreEntitesGeographiques.getRootNode().addListener(new TreeNodeListenerAdapter() {
                        
                        @Override
                        public void onExpand(Node node) {
                                if(!arbreCharge)
                                {
                                        observationMediateur.obtenirListeEntiteGeographique() ;
                                        arbreCharge = true ;
                                }
                        }
                        
                }) ;
        }
        
        private void gererClicNoeud(TreeNode node) {
                
                mettreAJourValeurEnCours(node);
                observationMediateur.obtenirNombreObservation() ;
        }
        
        private void mettreAJourValeurEnCours(TreeNode node) {
                
                nomFiltre = "" ;
                entitesGeographiquesEncours = "" ;
                
                String[] filtresStr = {"pays","departement","localite","lieudit","station"};
                
                int profNoeud = node.getDepth();
                if(profNoeud == 0) {
                                if(!arbreCharge)
                                {
                                        arbreEntitesGeographiques.getRootNode().expand();
                                }
                                else 
                                {
                                        observationMediateur.obtenirNombreObservation() ;
                                }
                } else {
                        Node noeud = (Node)node;
                        for(int i = profNoeud - 1; i >= 0; i--) {
                                nomFiltre += filtresStr[i]+",";
                                entitesGeographiquesEncours += ((String[])noeud.getUserObject())[0]+",";
                                noeud = noeud.getParentNode();
                        }
                        nomFiltre.replaceAll(",$", "");
                        entitesGeographiquesEncours.replaceAll(",$", "");
                }
                
                filtreModifie = true ;
        }
        
        public void initialiser() {
                
                arbreCharge = false ;
                entitesGeographiquesEncours = "";
                arbreEntitesGeographiques.collapseAll();
                // on vide l'ancien arbre
                Node[] rootChild = arbreEntitesGeographiques.getRootNode().getChildNodes();
                for (int i = 0; i < rootChild.length; i++) {
                        
                        rootChild[i].remove();
                }
                
                arbreEntitesGeographiques.getRootNode().addListener(new TreeNodeListenerAdapter() {
                        
                        @Override
                        public void onExpand(Node node) {
                                if(!arbreCharge)
                                {
                                        observationMediateur.obtenirListeEntiteGeographique() ;
                                        arbreCharge = true ;
                                }
                        }
                        
                }) ;
        }

        /**
         * Méthode héritée de l'interface rafraichissable
         */
        @Override
        public void rafraichir(Object nouvelleDonnees,
                        boolean repandreRaffraichissement) {

                
                if (nouvelleDonnees instanceof ListeEntiteGeographiqueObservation) {
                
                        ListeEntiteGeographiqueObservation data = (ListeEntiteGeographiqueObservation) nouvelleDonnees ;
                
                                // on crée un arbre vide
                                Tree nouvelArbre = new Tree() ;
                                TreeNode root = new TreeNode();
                                root.setId("racine_entite");
                                root.setText(Msg.get("localites"));
                                String[] usObjRoot = { Msg.get("localites") };
                                root.setUserObject(usObjRoot);
                                nouvelArbre.setRootNode(root);
                                
                                // on vide tous les noeuds
                                arbreEntitesGeographiques.getRootNode().eachChild(new NodeTraversalCallback() {
        
                                        @Override
                                        public boolean execute(Node node) {
                                                node.remove();
                                                return true;
                                        }
                                });
                        
                        // on la parse et on récupère les informations qui nous interessent
                        for (Iterator<String> it= data.keySet().iterator(); it.hasNext();) {
                                
                                        EntiteGeographiqueObservation ent=data.get(it.next());
                                        creerHierarchieNoeud(nouvelArbre ,root, ent);
                                        doLayout();
                                }
                        
                                copierFilsNoeud(root, arbreEntitesGeographiques.getRootNode());
                                arbreEntitesGeographiques.getRootNode().sort(comparerNoeuds()) ;

                                // si l'arbre n'était pas encore considéré comme instancié
                                
                                if (!estInstancie) {
                                        // on signale que oui
                                        estInstancie = true;
                                }
        
                                // l'état du filtre est réinitialisé
                                filtreModifie = false;
                                
                                //show() ;
                                arbreEntitesGeographiques.doLayout();

                        }

                if(nouvelleDonnees instanceof Observation)
                {       
                        // Cas d'ajout unitaire d'une observation
                        
                        // si l'arbre n'est pas encore chargé, on ne tient pas compte de l'ajout
                        // l'arbre complet sera de toute façon renvoyé plus tard lors du premier chargement
                        // de l'arbre
                        if(!arbreCharge) {
                                return;
                        }

                        Observation obs = (Observation)nouvelleDonnees ;
                        EntiteGeographiqueObservation ent = new EntiteGeographiqueObservation(obs.getIdentifiantLocalite(),obs.getLocalite(),obs.getLieudit(),obs.getStation());
                        ent.setPays(obs.getPays());

                        creerHierarchieNoeud(arbreEntitesGeographiques.getTree(), arbreEntitesGeographiques.getRootNode(), ent);

                        doLayout();
                        arbreEntitesGeographiques.doLayout() ;
                }
        }


        /**
         * Accesseur pour le panneau contenant l'arbre
         * 
         * @return le panneau de l'arbre des mots clés
         */
        public TreePanel getArbreMotsCles() {
                return arbreEntitesGeographiques;
        }

        /**
         * Méthode héritée de Filtrable renvoie le nom du filtre
         */
        @Override
        public String renvoyerNomFiltre() {

                return Msg.get("localites");
        }

        /**
         * Renvoie un tableau contenant le nom du champ à filtrer et la valeur
         * 
         * @return un tableau contenant le nom du champ à filtrer et sa valeur
         */
        @Override
        public String[] renvoyerValeursAFiltrer() {

                valider();
                
                String valeursFiltrees[] = {nomFiltre, entitesGeographiquesEncours } ;

                return valeursFiltrees;
        }

        /**
         * Fonction récursive qui prend deux noeuds d'arbre en paramètre et crée un
         * copie du sous arbre du premier noeud, qu'elle concatène au deuxième
         * 
         * @param ndPereOriginal
         *            le père des noeuds de l'arbre original
         * @param ndPereCopie
         *            le père qui va recevoir les copies
         */
        private void copierFilsNoeud(Node ndPereOriginal, TreeNode ndPereCopie) {
                if (ndPereCopie != null && ndPereOriginal != null) {
                        Node[] ndNodeFils = ndPereOriginal.getChildNodes();

                        for (int i = 0; i < ndNodeFils.length; i++) {

                                String[] usObj = (String[]) ndNodeFils[i].getUserObject();
                                TreeNode child = new TreeNode(usObj[0]);
                                child.setUserObject(usObj);
                                child.setId(""+usObj[1]);
                                ndPereCopie.appendChild(child);

                                if (!ndNodeFils[i].isLeaf()) {
                                        copierFilsNoeud(ndNodeFils[i], child);
                                }

                        }
                }
        }

        /**
         * Méthode héritée de Filtrable Renvoie l'état du filtre (modifié ou non)
         */
        @Override
        public boolean renvoyerEtatFiltre() {

                return filtreModifie;
        }

        @Override
        public void valider() {
                
                if (estInstancie) {
                        
                }
        }

        public Comparator<TreeNode> comparerNoeuds()
        {
                return new Comparator<TreeNode>() {

                        @Override
                        public int compare(TreeNode o1, TreeNode o2) {
                                
                                if(o1.getText().equals(Msg.get("inconnue"))) {
                                        return -1 ;
                                }
                                
                                if(o2.getText().equals(Msg.get("inconnue"))) {
                                        return 1 ;
                                }
                                
                                if(o1.getDepth() == 1 && o2.getDepth() == 1)
                                {
                                        String l1 = o1.getText() ;
                                        String l2 = o2.getText() ;
                                        if(l1.length() == 1) {
                                                l1 = "0"+l1;
                                        }
                                        
                                        if(l2.length() == 1) {
                                                l2 = "0"+l2;
                                        }
                                        
                                        Integer n1 = 0;
                                        Integer n2 = 0;
                                        
                                        try{
                                                n1 = Integer.parseInt(l1) ;
                                                n2 = Integer.parseInt(l2) ;
                                        } catch(NumberFormatException ne)  {
                                                n1 = 0;
                                                n2 = 0;
                                        }
                                        
                                        return n1.compareTo(n2) ;
                                }
                                else
                                {
                                        String n1 = o1.getId() ;
                                        String n2 = o2.getId() ;
                                                                        
                                
                                        return  n1.compareToIgnoreCase(n2);
                                }
                        }
                } ;
        }

        public void raz() {
                
                arbreCharge = false ;
                arbreEntitesGeographiques.collapseAll();
                arbreEntitesGeographiques.clear() ;
                
                // on crée une racine pour l'arbre
                TreeNode root = new TreeNode(Msg.get("localites"));
                root.setId("racine_entite");
                String[] usObject = { Msg.get("localites") };
                root.setUserObject(usObject);

                arbreEntitesGeographiques.setRootNode(root);
                
                arbreEntitesGeographiques.getRootNode().addListener(new TreeNodeListenerAdapter() {
                        
                        @Override
                        public void onExpand(Node node) {
                                if(!arbreCharge)
                                {
                                        observationMediateur.obtenirDatesObservation() ;
                                        arbreCharge = true ;
                                }
                        }
                        
                }) ;
                
                entitesGeographiquesEncours  = "";
                
        }
        
        private TreeNode creerNoeud(String id, String texte) {
                
                TreeNode nouveauNoeud = new TreeNode();
                nouveauNoeud.setId(""+(id));
                nouveauNoeud.setText(texte);
                String[] usObj = {texte,id+""};
                nouveauNoeud.setUserObject(usObj);
                
                return nouveauNoeud;
        }
        
        /**
         * 
         * @param arbre l'arbre dans lequel on recherche s'il faut créer les noeuds
         * @param root le noeud racine auquel on concatène la hierarchie crée
         * @param ent l'entité géographique qui doit être décomposée en arborescence
         * @return
         */
        private void creerHierarchieNoeud(Tree arbre, TreeNode root, EntiteGeographiqueObservation ent) {
                
                String id_zone_geo=null;
                String zone_geo=null;
                String lieuDit=null;
                String station=null;
                
                String id_pays = ent.getPays();
                
                // TODO creer une fonction plus efficace lors du passage au multi reférentiel
                id_zone_geo = Util.convertirChaineZoneGeoVersDepartement(ent.getIdZoneGeo());
                
                id_zone_geo = id_zone_geo.replaceAll("\"", "");
                id_zone_geo = id_zone_geo.replace('\\',' ');
                id_zone_geo = id_zone_geo.trim();
                zone_geo = ent.getZoneGeo();
                lieuDit = ent.getLieuDit();
                station = ent.getStation();
                
                if(id_pays.equals(null) || (id_pays.trim()).isEmpty()) {
                        id_pays=Msg.get("inconnue") ;
                }
                
                if(id_zone_geo.contains("000null") || id_zone_geo.equals(null) || (id_zone_geo.trim()).equals("")) {
                        id_zone_geo=Msg.get("inconnue") ;
                } else {
                        if(ent.getIdZoneGeo().contains("INSEE-C:") && ent.getIdZoneGeo().length() > 10) {
                                id_pays = "FR";
                        }
                }
                
                if(zone_geo.contains("000null") || zone_geo.equals(null) || (zone_geo.trim().equals(""))) {
                        zone_geo=Msg.get("inconnue") ;
                }
                
                if(lieuDit.contains("000null") || lieuDit.equals(null) || (lieuDit.trim().equals(""))) {
                        lieuDit=Msg.get("inconnue") ;
                }
                
                if(station.contains("000null") || station.equals(null) || (station.trim().equals(""))) {
                        station=Msg.get("inconnue") ;
                }
                
                String[] idLocalites = {id_pays, id_zone_geo, zone_geo, lieuDit, station};
                
                Node noeudMemeId = null;
                String idNoeud = "";
                String locNiveau = "";

                Node noeudParent = root;

                for(int i = 0; i < idLocalites.length; i++) {
                        // Recherche des noeuds correspondant à chacun des niveaux de la hierarchie
                        locNiveau = idLocalites[i];
                        idNoeud += idLocalites[i];

                        noeudMemeId = arbre.getNodeById(idNoeud);       

                        // Si le noeud n'existe pas on le crée
                        if(noeudMemeId == null) {
                                noeudMemeId = creerNoeud(idNoeud, locNiveau);
                                noeudParent.appendChild(noeudMemeId) ;
                        }

                        noeudParent = noeudMemeId;
                }

                root.sort(comparerNoeuds()) ;
        }

        @Override
        public void viderFiltre() {
                arbreEntitesGeographiques.getSelectionModel().clearSelections();
                entitesGeographiquesEncours ="";
        }

        public void viderFiltre(String nom) {
                
                final int profondeur = calculerProfondeurPourNomFiltre(nom);
                
                // on vide tous les noeuds
                arbreEntitesGeographiques.getRootNode().cascade(new NodeTraversalCallback() {

                        @Override
                        public boolean execute(Node node) {
                                
                                boolean continuer = true;
                                
                                TreeNode noeudArbreEncours = (TreeNode)node;
                                
                                if(arbreEntitesGeographiques.getSelectionModel().isSelected(noeudArbreEncours)) {
                                        
                                        int profondeurDepart = noeudArbreEncours.getDepth();
                                        
                                        for(int profondeurNoeudArbreEncours = profondeurDepart; profondeurNoeudArbreEncours >= profondeur; profondeurNoeudArbreEncours--) {
                                                noeudArbreEncours = (TreeNode)noeudArbreEncours.getParentNode();
                                        }
                                        
                                        arbreEntitesGeographiques.getSelectionModel().select(noeudArbreEncours); 
                                        mettreAJourValeurEnCours(noeudArbreEncours);

                                        continuer = false;
                                }

                                return continuer;
                        }

                });
        }

        private int calculerProfondeurPourNomFiltre(String nom) {

                int profondeur = 0;

                if(nom.equals("pays")) {
                        profondeur = 1;
                }

                if(nom.equals("departement")) {
                        profondeur = 2;
                }

                if(nom.equals("localite")) {
                        profondeur = 3;
                }

                if(nom.equals("lieudit")) {
                        profondeur = 4;
                }

                if(nom.equals("station")) {
                        profondeur = 5;
                }

                return profondeur;
        }

}