Rev 2624 | 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;
}
}