Subversion Repositories eFlore/Applications.cel

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
199 david 1
package org.tela_botanica.client.vues.observation.filtres;
54 david 2
 
90 jpm 3
import java.util.Comparator;
68 david 4
import java.util.Iterator;
5
 
54 david 6
import org.tela_botanica.client.interfaces.Filtrable;
7
import org.tela_botanica.client.interfaces.Rafraichissable;
989 aurelien 8
import org.tela_botanica.client.modeles.objets.EntiteGeographiqueObservation;
9
import org.tela_botanica.client.modeles.objets.ListeEntiteGeographiqueObservation;
10
import org.tela_botanica.client.modeles.objets.Observation;
54 david 11
import org.tela_botanica.client.observation.ObservationMediateur;
965 aurelien 12
import org.tela_botanica.client.util.Util;
54 david 13
 
14
import com.gwtext.client.data.Node;
15
import com.gwtext.client.data.NodeTraversalCallback;
16
import com.gwtext.client.data.Tree;
17
import com.gwtext.client.widgets.Component;
18
import com.gwtext.client.widgets.Panel;
19
import com.gwtext.client.widgets.event.PanelListenerAdapter;
20
import com.gwtext.client.widgets.tree.TreeNode;
21
import com.gwtext.client.widgets.tree.TreePanel;
87 jpm 22
import com.gwtext.client.widgets.tree.event.TreeNodeListenerAdapter;
85 jpm 23
import com.gwtext.client.widgets.tree.event.TreePanelListenerAdapter;
24
import com.gwtext.client.core.EventObject;
54 david 25
 
26
/**
199 david 27
 * Arbre Filtrant sur les entites geographiques
28
 *
54 david 29
 *
199 david 30
 * @author aurelien + david
54 david 31
 *
32
 */
199 david 33
 
34
 
68 david 35
public class ArbreEntiteGeographiqueObservationFiltreVue extends Panel implements Rafraichissable,
54 david 36
		Filtrable {
37
 
38
	/**
39
	 * Le médiateur associé à la vue
40
	 */
41
	private ObservationMediateur	observationMediateur		= null;
42
 
43
	/**
44
	 * Les localites en cours
45
	 */
68 david 46
	private String entitesGeographiquesEncours = "";
54 david 47
 
48
	/**
49
	 * Le treepanel qui affiche l'arbre
50
	 */
68 david 51
	private TreePanel arbreEntitesGeographiques = null;
54 david 52
 
68 david 53
 
54 david 54
	/**
55
	 * booléen d'initialisation
56
	 */
57
	private boolean estInstancie = false;
58
 
59
	/**
60
	 * booléen d'etat
61
	 */
62
	private boolean filtreModifie = false;
85 jpm 63
	private boolean arbreCharge = false ;
64
 
86 jpm 65
	private String nomFiltre = "" ;
66
 
54 david 67
	/**
68
	 * Constructeur sans argument (privé car ne doit pas être utilisé)
69
	 */
70
	@SuppressWarnings("unused")
68 david 71
	private ArbreEntiteGeographiqueObservationFiltreVue() {
54 david 72
		super();
73
	}
74
 
75
	/**
76
	 * Constructeur avec paramètres
77
	 *
78
	 * @param im
79
	 *            le médiateur à associer
80
	 */
68 david 81
	public ArbreEntiteGeographiqueObservationFiltreVue(ObservationMediateur obs) {
54 david 82
 
83
		// on crée le panel
168 aurelien 84
		super("Localités");
54 david 85
 
86
		this.observationMediateur = obs;
87
 
68 david 88
		arbreEntitesGeographiques = new TreePanel();
54 david 89
 
90
		this.setPaddings(5);
91
 
92
		this.setCollapsible(true);
202 david 93
 
94
		this.setAutoScroll(true);
128 aurelien 95
 
54 david 96
 
97
		// on ajoute les listeners
98
		ajouterListenersPanel();
99
		estInstancie = false;
100
	}
101
 
102
	/**
103
	 * Ajoute les listeners pour le rendu du panel
104
	 */
105
	private void ajouterListenersPanel() {
68 david 106
		  this.addListener(new PanelListenerAdapter() {
54 david 107
 
108
			// on instancie réellement les composants au moment du rendu pour
109
			// accélérer l'affichage
110
			// et éviter des bugs
1292 aurelien 111
			@Override
54 david 112
			public void onRender(Component component) {
113
 
114
				// on interdit le drag and drop dans l'arbre
68 david 115
				arbreEntitesGeographiques.setEnableDD(false);
73 david 116
				arbreEntitesGeographiques.setId("x-view-tree-filter-entity");
54 david 117
 
118
				// on crée une racine pour l'arbre
72 david 119
				TreeNode root = new TreeNode("Localités");
70 david 120
				root.setId("racine_entite");
72 david 121
				String[] usObject = { "Localités" };
54 david 122
				root.setUserObject(usObject);
123
 
68 david 124
				arbreEntitesGeographiques.setRootNode(root);
125
				arbreEntitesGeographiques.setRootVisible(true);
126
				arbreEntitesGeographiques.setBorder(false);
85 jpm 127
				root.setExpandable(true) ;
54 david 128
 
68 david 129
				add(arbreEntitesGeographiques);
54 david 130
 
131
				// on ajoute les listeners d'évenements
132
				ajouterListeners();
133
 
134
 
135
				// enfin on considère le composant comme instancié
136
				estInstancie = true;
137
			}
138
		});
139
	}
68 david 140
 
54 david 141
	/**
70 david 142
	 * ajoute les listeners pour les boutons et le cochage des entites
54 david 143
	 */
144
	private void ajouterListeners() {
85 jpm 145
 
146
		arbreEntitesGeographiques.addListener(new TreePanelListenerAdapter() {
147
 
1292 aurelien 148
			@Override
85 jpm 149
			public void onClick(TreeNode node, EventObject e) {
683 aurelien 150
				gererClicNoeud(node);
85 jpm 151
			}
152
 
153
		}) ;
87 jpm 154
 
155
		arbreEntitesGeographiques.getRootNode().addListener(new TreeNodeListenerAdapter() {
156
 
1292 aurelien 157
			@Override
87 jpm 158
			public void onExpand(Node node) {
159
				if(!arbreCharge)
160
				{
161
					observationMediateur.obtenirListeEntiteGeographique() ;
162
					arbreCharge = true ;
163
				}
164
			}
165
 
166
		}) ;
54 david 167
	}
140 aurelien 168
 
683 aurelien 169
	private void gererClicNoeud(TreeNode node) {
170
 
171
		mettreAJourValeurEnCours(node);
172
		observationMediateur.obtenirNombreObservation() ;
173
	}
174
 
175
	private void mettreAJourValeurEnCours(TreeNode node) {
176
 
177
		nomFiltre = "" ;
178
		entitesGeographiquesEncours = "" ;
179
 
2568 aurelien 180
		String[] filtresStr = {"pays","departement","localite","lieudit","station"};
181
 
182
		int profNoeud = node.getDepth();
183
		if(profNoeud == 0) {
683 aurelien 184
				if(!arbreCharge)
185
				{
186
					arbreEntitesGeographiques.getRootNode().expand();
187
				}
188
				else
189
				{
190
					observationMediateur.obtenirNombreObservation() ;
191
				}
2568 aurelien 192
		} else {
193
			Node noeud = (Node)node;
194
			for(int i = profNoeud - 1; i >= 0; i--) {
195
				nomFiltre += filtresStr[i]+",";
196
				entitesGeographiquesEncours += ((String[])noeud.getUserObject())[0]+",";
197
				noeud = noeud.getParentNode();
198
			}
199
			nomFiltre.replaceAll(",$", "");
200
			entitesGeographiquesEncours.replaceAll(",$", "");
683 aurelien 201
		}
202
 
203
		filtreModifie = true ;
204
	}
205
 
140 aurelien 206
	public void initialiser() {
207
 
208
		arbreCharge = false ;
263 aurelien 209
		entitesGeographiquesEncours = "";
140 aurelien 210
		arbreEntitesGeographiques.collapseAll();
211
		// on vide l'ancien arbre
212
		Node[] rootChild = arbreEntitesGeographiques.getRootNode().getChildNodes();
213
		for (int i = 0; i < rootChild.length; i++) {
214
 
215
			rootChild[i].remove();
216
		}
217
 
218
		arbreEntitesGeographiques.getRootNode().addListener(new TreeNodeListenerAdapter() {
219
 
1292 aurelien 220
			@Override
140 aurelien 221
			public void onExpand(Node node) {
222
				if(!arbreCharge)
223
				{
224
					observationMediateur.obtenirListeEntiteGeographique() ;
225
					arbreCharge = true ;
226
				}
227
			}
228
 
229
		}) ;
230
	}
54 david 231
 
232
	/**
233
	 * Méthode héritée de l'interface rafraichissable
234
	 */
1292 aurelien 235
	@Override
54 david 236
	public void rafraichir(Object nouvelleDonnees,
237
			boolean repandreRaffraichissement) {
238
 
128 aurelien 239
 
68 david 240
		if (nouvelleDonnees instanceof ListeEntiteGeographiqueObservation) {
241
 
242
			ListeEntiteGeographiqueObservation data = (ListeEntiteGeographiqueObservation) nouvelleDonnees ;
243
 
244
				// on crée un arbre vide
166 aurelien 245
				Tree nouvelArbre = new Tree() ;
68 david 246
				TreeNode root = new TreeNode();
72 david 247
				root.setId("racine_entite");
248
				root.setText("Localités");
89 jpm 249
				String[] usObjRoot = { "Localités"};
250
				root.setUserObject(usObjRoot);
166 aurelien 251
				nouvelArbre.setRootNode(root);
68 david 252
 
89 jpm 253
				// on vide tous les noeuds
254
				arbreEntitesGeographiques.getRootNode().eachChild(new NodeTraversalCallback() {
255
 
1292 aurelien 256
					@Override
89 jpm 257
					public boolean execute(Node node) {
258
						node.remove();
259
						return true;
260
					}
261
				});
263 aurelien 262
 
263
			// on la parse et on récupère les informations qui nous interessent
264
			for (Iterator<String> it= data.keySet().iterator(); it.hasNext();) {
199 david 265
 
1292 aurelien 266
					EntiteGeographiqueObservation ent=data.get(it.next());
263 aurelien 267
					creerHierarchieNoeud(nouvelArbre ,root, ent);
268
					doLayout();
269
				}
270
 
166 aurelien 271
				copierFilsNoeud(root, arbreEntitesGeographiques.getRootNode());
263 aurelien 272
				arbreEntitesGeographiques.getRootNode().sort(comparerNoeuds()) ;
54 david 273
 
89 jpm 274
				// si l'arbre n'était pas encore considéré comme instancié
199 david 275
 
89 jpm 276
				if (!estInstancie) {
277
					// on signale que oui
278
					estInstancie = true;
54 david 279
				}
89 jpm 280
 
281
				// l'état du filtre est réinitialisé
282
				filtreModifie = false;
109 aurelien 283
 
89 jpm 284
				//show() ;
166 aurelien 285
				arbreEntitesGeographiques.doLayout();
54 david 286
 
287
			}
89 jpm 288
 
289
		if(nouvelleDonnees instanceof Observation)
128 aurelien 290
		{
199 david 291
			// Cas d'ajout unitaire d'une observation
292
 
128 aurelien 293
			// si l'arbre n'est pas encore chargé, on ne tient pas compte de l'ajout
294
			// l'arbre complet sera de toute façon renvoyé plus tard lors du premier chargement
295
			// de l'arbre
296
			if(!arbreCharge) {
297
				return;
298
			}
299
 
89 jpm 300
			Observation obs = (Observation)nouvelleDonnees ;
263 aurelien 301
			EntiteGeographiqueObservation ent = new EntiteGeographiqueObservation(obs.getIdentifiantLocalite(),obs.getLocalite(),obs.getLieudit(),obs.getStation());
2568 aurelien 302
			ent.setPays(obs.getPays());
89 jpm 303
 
263 aurelien 304
			creerHierarchieNoeud(arbreEntitesGeographiques.getTree(), arbreEntitesGeographiques.getRootNode(), ent);
89 jpm 305
 
263 aurelien 306
			doLayout();
307
			arbreEntitesGeographiques.doLayout() ;
89 jpm 308
		}
68 david 309
	}
54 david 310
 
311
 
312
	/**
313
	 * Accesseur pour le panneau contenant l'arbre
314
	 *
315
	 * @return le panneau de l'arbre des mots clés
316
	 */
317
	public TreePanel getArbreMotsCles() {
68 david 318
		return arbreEntitesGeographiques;
54 david 319
	}
320
 
321
	/**
322
	 * Méthode héritée de Filtrable renvoie le nom du filtre
323
	 */
1292 aurelien 324
	@Override
54 david 325
	public String renvoyerNomFiltre() {
326
 
327
		return "Localités";
328
	}
329
 
330
	/**
331
	 * Renvoie un tableau contenant le nom du champ à filtrer et la valeur
332
	 *
333
	 * @return un tableau contenant le nom du champ à filtrer et sa valeur
334
	 */
1292 aurelien 335
	@Override
54 david 336
	public String[] renvoyerValeursAFiltrer() {
337
 
338
		valider();
85 jpm 339
 
86 jpm 340
		String valeursFiltrees[] = {nomFiltre, entitesGeographiquesEncours } ;
54 david 341
 
342
		return valeursFiltrees;
343
	}
344
 
345
	/**
346
	 * Fonction récursive qui prend deux noeuds d'arbre en paramètre et crée un
347
	 * copie du sous arbre du premier noeud, qu'elle concatène au deuxième
348
	 *
349
	 * @param ndPereOriginal
350
	 *            le père des noeuds de l'arbre original
351
	 * @param ndPereCopie
352
	 *            le père qui va recevoir les copies
353
	 */
354
	private void copierFilsNoeud(Node ndPereOriginal, TreeNode ndPereCopie) {
355
		if (ndPereCopie != null && ndPereOriginal != null) {
356
			Node[] ndNodeFils = ndPereOriginal.getChildNodes();
357
 
358
			for (int i = 0; i < ndNodeFils.length; i++) {
359
 
360
				String[] usObj = (String[]) ndNodeFils[i].getUserObject();
361
				TreeNode child = new TreeNode(usObj[0]);
362
				child.setUserObject(usObj);
166 aurelien 363
				child.setId(""+usObj[1]);
54 david 364
				ndPereCopie.appendChild(child);
365
 
366
				if (!ndNodeFils[i].isLeaf()) {
367
					copierFilsNoeud(ndNodeFils[i], child);
368
				}
369
 
370
			}
371
		}
372
	}
373
 
374
	/**
375
	 * Méthode héritée de Filtrable Renvoie l'état du filtre (modifié ou non)
376
	 */
1292 aurelien 377
	@Override
54 david 378
	public boolean renvoyerEtatFiltre() {
379
 
380
		return filtreModifie;
381
	}
382
 
1292 aurelien 383
	@Override
54 david 384
	public void valider() {
86 jpm 385
 
54 david 386
		if (estInstancie) {
86 jpm 387
 
54 david 388
		}
389
	}
90 jpm 390
 
391
	public Comparator<TreeNode> comparerNoeuds()
392
	{
393
		return new Comparator<TreeNode>() {
54 david 394
 
1292 aurelien 395
			@Override
90 jpm 396
			public int compare(TreeNode o1, TreeNode o2) {
397
 
109 aurelien 398
				if(o1.getText().equals("Inconnue")) {
399
					return -1 ;
400
				}
401
 
402
				if(o2.getText().equals("Inconnue")) {
403
					return 1 ;
404
				}
405
 
406
				if(o1.getDepth() == 1 && o2.getDepth() == 1)
91 jpm 407
				{
109 aurelien 408
					String l1 = o1.getText() ;
409
					String l2 = o2.getText() ;
410
					if(l1.length() == 1) {
411
						l1 = "0"+l1;
412
					}
91 jpm 413
 
109 aurelien 414
					if(l2.length() == 1) {
415
						l2 = "0"+l2;
416
					}
417
 
128 aurelien 418
					Integer n1 = 0;
419
					Integer n2 = 0;
109 aurelien 420
 
128 aurelien 421
					try{
422
						n1 = Integer.parseInt(l1) ;
423
						n2 = Integer.parseInt(l2) ;
424
					} catch(NumberFormatException ne)  {
425
						n1 = 0;
426
						n2 = 0;
427
					}
428
 
91 jpm 429
					return n1.compareTo(n2) ;
430
				}
431
				else
263 aurelien 432
				{
433
					String n1 = o1.getId() ;
434
					String n2 = o2.getId() ;
435
 
90 jpm 436
 
263 aurelien 437
					return  n1.compareToIgnoreCase(n2);
91 jpm 438
				}
90 jpm 439
			}
440
		} ;
441
	}
104 jpm 442
 
443
	public void raz() {
263 aurelien 444
 
104 jpm 445
		arbreCharge = false ;
140 aurelien 446
		arbreEntitesGeographiques.collapseAll();
104 jpm 447
		arbreEntitesGeographiques.clear() ;
448
 
449
		// on crée une racine pour l'arbre
450
		TreeNode root = new TreeNode("Localités");
451
		root.setId("racine_entite");
452
		String[] usObject = { "Localités" };
453
		root.setUserObject(usObject);
454
 
455
		arbreEntitesGeographiques.setRootNode(root);
456
 
457
		arbreEntitesGeographiques.getRootNode().addListener(new TreeNodeListenerAdapter() {
458
 
1292 aurelien 459
			@Override
104 jpm 460
			public void onExpand(Node node) {
461
				if(!arbreCharge)
462
				{
463
					observationMediateur.obtenirDatesObservation() ;
464
					arbreCharge = true ;
465
				}
466
			}
467
 
468
		}) ;
469
 
263 aurelien 470
		entitesGeographiquesEncours  = "";
104 jpm 471
 
263 aurelien 472
	}
473
 
474
	private TreeNode creerNoeud(String id, String texte) {
104 jpm 475
 
263 aurelien 476
		TreeNode nouveauNoeud = new TreeNode();
477
		nouveauNoeud.setId(""+(id));
478
		nouveauNoeud.setText(texte);
479
		String[] usObj = {texte,id+""};
480
		nouveauNoeud.setUserObject(usObj);
481
 
482
		return nouveauNoeud;
104 jpm 483
	}
91 jpm 484
 
263 aurelien 485
	/**
486
	 *
487
	 * @param arbre l'arbre dans lequel on recherche s'il faut créer les noeuds
488
	 * @param root le noeud racine auquel on concatène la hierarchie crée
489
	 * @param ent l'entité géographique qui doit être décomposée en arborescence
490
	 * @return
491
	 */
492
	private void creerHierarchieNoeud(Tree arbre, TreeNode root, EntiteGeographiqueObservation ent) {
493
 
965 aurelien 494
		String id_zone_geo=null;
495
		String zone_geo=null;
263 aurelien 496
		String lieuDit=null;
497
		String station=null;
498
 
2568 aurelien 499
		String id_pays = ent.getPays();
500
 
965 aurelien 501
		// TODO creer une fonction plus efficace lors du passage au multi reférentiel
502
		id_zone_geo = Util.convertirChaineZoneGeoVersDepartement(ent.getIdZoneGeo());
263 aurelien 503
 
965 aurelien 504
		id_zone_geo = id_zone_geo.replaceAll("\"", "");
505
		id_zone_geo = id_zone_geo.replace('\\',' ');
506
		id_zone_geo = id_zone_geo.trim();
507
		zone_geo = ent.getZoneGeo();
508
		lieuDit = ent.getLieuDit();
509
		station = ent.getStation();
263 aurelien 510
 
2568 aurelien 511
		if(id_pays.equals(null) || (id_pays.trim()).isEmpty()) {
512
			id_pays="Inconnue" ;
513
		}
514
 
965 aurelien 515
		if(id_zone_geo.contains("000null") || id_zone_geo.equals(null) || (id_zone_geo.trim()).equals("")) {
516
			id_zone_geo="Inconnue" ;
2568 aurelien 517
		} else {
518
			if(ent.getIdZoneGeo().contains("INSEE-C:") && ent.getIdZoneGeo().length() > 10) {
519
				id_pays = "FR";
520
			}
263 aurelien 521
		}
522
 
965 aurelien 523
		if(zone_geo.contains("000null") || zone_geo.equals(null) || (zone_geo.trim().equals(""))) {
524
			zone_geo="Inconnue" ;
263 aurelien 525
		}
526
 
527
		if(lieuDit.contains("000null") || lieuDit.equals(null) || (lieuDit.trim().equals(""))) {
528
			lieuDit="Inconnue" ;
529
		}
530
 
531
		if(station.contains("000null") || station.equals(null) || (station.trim().equals(""))) {
532
			station="Inconnue" ;
533
		}
534
 
2568 aurelien 535
		String[] idLocalites = {id_pays, id_zone_geo, zone_geo, lieuDit, station};
263 aurelien 536
 
2568 aurelien 537
		Node noeudMemeId = null;
538
		String idNoeud = "";
539
		String locNiveau = "";
263 aurelien 540
 
2568 aurelien 541
		Node noeudParent = root;
263 aurelien 542
 
2568 aurelien 543
		for(int i = 0; i < idLocalites.length; i++) {
544
			// Recherche des noeuds correspondant à chacun des niveaux de la hierarchie
545
			locNiveau = idLocalites[i];
546
			idNoeud += idLocalites[i];
547
 
548
			noeudMemeId = arbre.getNodeById(idNoeud);
549
 
550
			// Si le noeud n'existe pas on le crée
551
			if(noeudMemeId == null) {
552
				noeudMemeId = creerNoeud(idNoeud, locNiveau);
553
				noeudParent.appendChild(noeudMemeId) ;
554
			}
555
 
556
			noeudParent = noeudMemeId;
263 aurelien 557
		}
558
 
559
		root.sort(comparerNoeuds()) ;
560
	}
683 aurelien 561
 
562
	@Override
563
	public void viderFiltre() {
564
		arbreEntitesGeographiques.getSelectionModel().clearSelections();
565
		entitesGeographiquesEncours ="";
566
	}
567
 
568
	public void viderFiltre(String nom) {
569
 
570
		final int profondeur = calculerProfondeurPourNomFiltre(nom);
571
 
572
		// on vide tous les noeuds
573
		arbreEntitesGeographiques.getRootNode().cascade(new NodeTraversalCallback() {
574
 
1292 aurelien 575
			@Override
683 aurelien 576
			public boolean execute(Node node) {
577
 
578
				boolean continuer = true;
579
 
580
				TreeNode noeudArbreEncours = (TreeNode)node;
581
 
582
				if(arbreEntitesGeographiques.getSelectionModel().isSelected(noeudArbreEncours)) {
583
 
584
					int profondeurDepart = noeudArbreEncours.getDepth();
585
 
586
					for(int profondeurNoeudArbreEncours = profondeurDepart; profondeurNoeudArbreEncours >= profondeur; profondeurNoeudArbreEncours--) {
587
						noeudArbreEncours = (TreeNode)noeudArbreEncours.getParentNode();
588
					}
589
 
590
					arbreEntitesGeographiques.getSelectionModel().select(noeudArbreEncours);
591
					mettreAJourValeurEnCours(noeudArbreEncours);
592
 
593
					continuer = false;
594
				}
595
 
596
				return continuer;
597
			}
598
 
599
		});
600
	}
263 aurelien 601
 
683 aurelien 602
	private int calculerProfondeurPourNomFiltre(String nom) {
603
 
604
		int profondeur = 0;
605
 
2568 aurelien 606
		if(nom.equals("pays")) {
683 aurelien 607
			profondeur = 1;
608
		}
609
 
2568 aurelien 610
		if(nom.equals("departement")) {
683 aurelien 611
			profondeur = 2;
612
		}
613
 
2568 aurelien 614
		if(nom.equals("localite")) {
683 aurelien 615
			profondeur = 3;
616
		}
617
 
2568 aurelien 618
		if(nom.equals("lieudit")) {
683 aurelien 619
			profondeur = 4;
620
		}
621
 
2568 aurelien 622
		if(nom.equals("station")) {
623
			profondeur = 5;
624
		}
625
 
683 aurelien 626
		return profondeur;
627
	}
628
 
54 david 629
}