]> SALOME platform Git repositories - tools/eficas.git/blob - Ihm/I_JDC.py
Salome HOME
8768ec591bc1bcc546326ff5a751c05e9bec0ea7
[tools/eficas.git] / Ihm / I_JDC.py
1 #            CONFIGURATION MANAGEMENT OF EDF VERSION
2 # ======================================================================
3 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
4 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
5 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
6 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
7 # (AT YOUR OPTION) ANY LATER VERSION.
8 #
9 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
10 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
11 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
12 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
13 #
14 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
15 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
16 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
17 #
18 #
19 # ======================================================================
20 """
21 """
22 # Modules Python
23 import types,traceback
24 import string,linecache
25
26 # Modules Eficas
27 import I_OBJECT
28 from Noyau.N_ASSD import ASSD
29 from Noyau.N_ETAPE import ETAPE
30 from Noyau.N_Exception import AsException
31 from Extensions import commentaire,parametre,parametre_eval
32
33 class JDC(I_OBJECT.OBJECT):
34    """
35    """
36    def __init__(self):
37       self.editmode=0
38       self.etapes_niveaux=[]
39       self.niveau=self
40       self.params=[]
41       self.fonctions=[]
42       self._etape_context=None
43       self.recorded_units={}
44       self.old_recorded_units={}
45
46    def get_cmd(self,nomcmd):
47       """
48           Retourne l'objet de type COMMANDE de nom nomcmd
49       """
50       for cata in self.cata:
51          if hasattr(cata,nomcmd):
52             return getattr(cata,nomcmd)
53
54    def get_sd_avant_du_bon_type(self,etape,types_permis):
55       """
56           Retourne la liste des concepts avant etape d'un type acceptable
57       """
58       d=self.get_contexte_avant(etape)
59       l=[]
60       for k,v in d.items():
61         if type(v) != types.InstanceType : continue
62         # On considère que seul assd indique un type quelconque pas CO
63         elif self.assd in types_permis :
64            l.append(k)
65         elif self.est_permis(v,types_permis):
66            l.append(k)
67       l.sort()
68       return l
69
70    def est_permis(self,v,types_permis):
71       for type_ok in types_permis:
72           if type_ok in ('R','I','C','TXM') and v in self.params : 
73              return 1
74           elif type_ok == 'R' and v.__class__.__name__ == 'reel' : 
75              return 1
76           elif type_ok == 'I' and v.__class__.__name__ == 'entier' : 
77              return 1
78           elif type_ok == 'C' and v.__class__.__name__ == 'complexe' : 
79              return 1
80           elif type_ok == 'TXM' and v.__class__.__name__ == 'chaine' : 
81              return 1
82           elif type(type_ok) != types.ClassType : 
83              continue
84           elif v.__class__ == type_ok or issubclass(v.__class__,type_ok):
85              return 1
86       return 0
87
88    def addentite(self,name,pos):
89       """
90           Ajoute une entite :
91           Si name est le nom d une commande ou un commentaire ajoute 
92           une etape au JDC
93           Sinon remonte une erreur
94       """
95       self.init_modif()
96       self.editmode=1
97       if name == "COMMENTAIRE" :
98         # ajout d'un commentaire
99         self.set_current_step()
100         ind = 1
101         for child in self.etapes :
102           if isinstance(child,commentaire.COMMENTAIRE):
103             ind = ind+1
104         objet = commentaire.COMMENTAIRE('',parent=self)
105         objet.nom = "_comm_"+`ind`
106         if pos == None : pos = 0
107         self.etapes.insert(pos,objet)
108         self.editmode=0
109         self.active_etapes()
110         return objet
111       elif name == "PARAMETRE":
112         # ajout d'un parametre
113         self.set_current_step()
114         nom_param = '_param_'+str(len(self.params)+1)
115         objet = parametre.PARAMETRE(nom=nom_param)
116         if pos == None : pos = 0
117         self.etapes.insert(pos,objet)
118         self.editmode=0
119         self.reset_context()
120         self.active_etapes()
121         return objet
122       elif name == "PARAMETRE_EVAL":
123         # ajout d'un parametre EVAL
124         self.set_current_step()
125         nom_param = '_param_'+str(len(self.params)+1)
126         objet = parametre_eval.PARAMETRE_EVAL(nom=nom_param)
127         if pos == None : pos = 0
128         self.etapes.insert(pos,objet)
129         self.editmode=0
130         self.reset_context()
131         self.active_etapes()
132         return objet
133       elif type(name)==types.InstanceType:
134         # on est dans le cas où on veut ajouter une commande déjà 
135         # existante (par copie donc)
136         # on est donc nécessairement en mode editeur ...
137         objet = name
138         # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
139         objet.reparent(self)
140         self.set_current_step()
141         if isinstance(objet,ETAPE):
142           if objet.nom_niveau_definition == 'JDC':
143             # l'objet dépend directement du JDC
144             objet.niveau = self
145           else:
146             # l'étape dépend d'un niveau et non directement du JDC :
147             # il faut l'enregistrer dans le niveau de parent
148             objet.parent.dict_niveaux[objet.nom_niveau_definition].register(objet)
149             objet.niveau = objet.parent.dict_niveaux[objet.nom_niveau_definition]
150         self.etapes.insert(pos,objet)
151         # il faut vérifier que les concepts utilisés par objet existent bien
152         # à ce niveau d'arborescence
153         objet.verif_existence_sd()
154         self.active_etapes()
155         self.editmode=0
156         self.reset_context()
157         return objet
158       else :
159         # On veut ajouter une nouvelle commande
160         try:
161           self.set_current_step()
162           cmd=self.get_cmd(name)
163           # L'appel a make_objet n'a pas pour effet d'enregistrer l'étape
164           # auprès du step courant car editmode vaut 1
165           # Par contre elle a le bon parent grace a set_current_step
166           e=cmd.make_objet()
167           if pos == None : pos = 0
168           self.etapes.insert(pos,e)
169           self.reset_current_step()
170           self.editmode=0
171           self.reset_context()
172           self.active_etapes()
173           return e
174         except AsException,e:
175           self.reset_current_step()
176           self.editmode=0
177           raise AsException("Impossible d ajouter la commande "+name + '\n' +str(e))
178         except:
179           traceback.print_exc()
180           self.reset_current_step()
181           self.editmode=0
182           raise AsException("Impossible d ajouter la commande "+name)
183
184    def set_current_step(self):
185       CONTEXT.unset_current_step()
186       CONTEXT.set_current_step(self)
187
188    def reset_current_step(self):
189       CONTEXT.unset_current_step()
190
191    def liste_mc_presents(self):
192       return []
193
194    def get_sd_avant_etape(self,nom_sd,etape):
195       return self.get_contexte_avant(etape).get(nom_sd,None)
196
197    def get_sd_apres_etape_avec_detruire(self,nom_sd,sd,etape,avec='non'):
198       """ 
199            Cette méthode retourne la SD sd de nom nom_sd qui est éventuellement
200            définie apres etape en tenant compte des concepts detruits
201            Si avec vaut 'non' exclut etape de la recherche
202       """
203       ietap=self.etapes.index(etape)
204       if avec == 'non':ietap=ietap+1
205       d={nom_sd:sd}
206       for e in self.etapes[ietap:]:
207          if e.isactif():
208             e.update_context(d)
209             autre_sd=d.get(nom_sd,None)
210             if autre_sd is None:
211               # Le concept a ete detruit
212               return None
213             if autre_sd is not sd :
214               # L'etape produit un concept de meme nom
215               if hasattr(e,'reuse') and e.reuse == autre_sd:
216                  # Le concept est reutilise, ce n'est pas un produit de l'etape
217                  continue
218               else:
219                  # Le concept est produit par l'etape
220                  return autre_sd
221       # On n'a rien trouve. Pas de concept de nom nom_sd
222       return None
223
224    def get_sd_apres_etape(self,nom_sd,etape,avec='non'):
225       """ 
226            Cette méthode retourne la SD de nom nom_sd qui est éventuellement
227            définie apres etape 
228            Si avec vaut 'non' exclut etape de la recherche
229       """
230       ietap=self.etapes.index(etape)
231       if avec == 'non':ietap=ietap+1
232       for e in self.etapes[ietap:]:
233         sd=e.get_sdprods(nom_sd)
234         if sd:
235           if hasattr(e,'reuse'):
236             if e.reuse != sd:
237               return sd
238       return None
239
240    def get_sd_autour_etape(self,nom_sd,etape,avec='non'):
241       """
242            Fonction: retourne la SD de nom nom_sd qui est éventuellement
243            définie avant ou apres etape
244            Permet de vérifier si un concept de meme nom existe dans le périmètre 
245            d'une étape
246            Si avec vaut 'non' exclut etape de la recherche
247       """
248       sd=self.get_sd_avant_etape(nom_sd,etape)
249       if sd:return sd
250       return self.get_sd_apres_etape(nom_sd,etape,avec)
251
252    def get_contexte_avant(self,etape):
253       """
254          Retourne le dictionnaire des concepts connus avant etape
255          On tient compte des commandes qui modifient le contexte
256          comme DETRUIRE ou les macros
257          Si etape == None, on retourne le contexte en fin de JDC
258       """
259       # L'étape courante pour laquelle le contexte a été calculé est
260       # mémorisée dans self.index_etape_courante
261       # XXX on pourrait faire mieux dans le cas PAR_LOT="NON" : en
262       # mémorisant l'étape
263       # courante pendant le processus de construction des étapes.
264       # Si on insère des commandes (par ex, dans EFICAS), il faut préalablement
265       # remettre ce pointeur à 0
266       if etape:
267          index_etape=self.etapes.index(etape)
268       else:
269          index_etape=len(self.etapes)
270       if index_etape >= self.index_etape_courante:
271          # On calcule le contexte en partant du contexte existant
272          d=self.current_context
273          if self.index_etape_courante==0 and self.context_ini:
274             d.update(self.context_ini)
275          liste_etapes=self.etapes[self.index_etape_courante:index_etape]
276       else:
277          d=self.current_context={}
278          if self.context_ini:d.update(self.context_ini)
279          liste_etapes=self.etapes
280
281       for e in liste_etapes:
282          if e is etape:
283             break
284          if e.isactif():
285             e.update_context(d)
286       self.index_etape_courante=index_etape
287       return d
288
289    def get_contexte_apres(self,etape):
290       """
291          Retourne le dictionnaire des concepts connus apres etape
292          On tient compte des commandes qui modifient le contexte
293          comme DETRUIRE ou les macros
294          Si etape == None, on retourne le contexte en fin de JDC
295       """
296       if not etape: return self.get_contexte_avant(etape)
297
298       d=self.get_contexte_avant(etape)
299       if etape.isactif():etape.update_context(d)
300       self.index_etape_courante=self.index_etape_courante+1
301       return d
302
303    def active_etapes(self):
304       """
305           Cette méthode a pour fonction de désactiver les étapes qui doivent
306           l'être cad, dans le cas d'ASTER, les étapes qui ne sont pas 
307           comprises entre le premier DEBUT/POURSUITE et le premier FIN 
308           et rendre actives les autres
309       """
310       if self.definition.code == 'ASTER' :
311          # Seulement pour ASTER :
312          # Avant DEBUT actif vaut 0
313          # Apres DEBUT et avant le 1er FIN actif vaut 1
314          # Apres le 1er FIN actif vaut -1
315          actif=0
316       else:
317          actif=1
318       for etape in self.etapes:
319         if actif == 0 and etape.nom in ['DEBUT','POURSUITE']:actif=1
320         if actif == 1:
321            etape.active()
322         else:
323            etape.inactive()
324         if etape.nom == 'FIN':actif=-1
325
326    def suppentite(self,etape) :
327       """  
328           Cette methode a pour fonction de supprimer une étape dans 
329           un jeu de commandes
330       """
331       self.init_modif()
332       # On memorise le contexte avant l'etape a supprimer
333       d=self.get_contexte_avant(etape)
334       index_etape=self.etapes.index(etape)
335
336       self.etapes.remove(etape)
337       if etape.niveau is not self:
338         # Dans ce cas l'étape est enregistrée dans un niveau
339         # Il faut la désenregistrer
340         etape.niveau.unregister(etape)
341       etape.supprime_sdprods()
342       self.active_etapes()
343
344       # Apres suppression de l'etape il faut controler que les etapes
345       # suivantes ne produisent pas des concepts DETRUITS dans op_init de etape
346       for e in self.etapes[index_etape:]:
347          e.control_sdprods(d)
348       
349       self.reset_context()
350       self.fin_modif()
351
352    def analyse(self):
353       self.compile()
354       if not self.cr.estvide():return
355       self.exec_compile()
356       self.active_etapes()
357
358    def register(self,etape):
359       """ 
360            Cette méthode ajoute  etape dans la liste
361            des etapes self.etapes et retourne l identificateur d'étape
362            fourni par l appel a g_register
363
364            A quoi sert editmode ?
365               - Si editmode vaut 1, on est en mode edition de JDC. On cherche 
366                 à enregistrer une étape que l'on a créée avec eficas (en passant 
367                 par addentite) auquel cas on ne veut récupérer que son numéro 
368                 d'enregistrement et c'est addentité qui l'enregistre dans 
369                 self.etapes à la bonne place...
370               - Si editmode vaut 0, on est en mode relecture d'un fichier de 
371                 commandes et on doit enregistrer l'étape à la fin de self.etapes 
372                 (dans ce cas l'ordre des étapes est bien l'ordre chronologique 
373                 de leur création   )
374       """
375       if not self.editmode:
376          self.etapes.append(etape)
377       else:
378          pass
379       return self.g_register(etape)
380
381    def register_parametre(self,param):
382       """
383           Cette méthode sert à ajouter un paramètre dans la liste des paramètres
384       """
385       self.params.append(param)
386
387    def register_fonction(self,fonction):
388       """
389           Cette méthode sert à ajouter une fonction dans la liste des fonctions
390       """
391       self.fonctions.append(fonction)
392
393    def delete_param(self,param):
394       """
395           Supprime le paramètre param de la liste des paramètres
396           et du contexte gobal
397       """
398       if param in self.params : self.params.remove(param)
399       if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
400
401    def get_parametres_fonctions_avant_etape(self,etape):
402       """
403           Retourne deux éléments :
404           - une liste contenant les noms des paramètres (constantes ou EVAL) 
405             définis avant etape
406           - une liste contenant les formules définies avant etape
407       """
408       l_constantes = []
409       l_fonctions = []
410       # on récupère le contexte avant etape
411       # on ne peut mettre dans les deux listes que des éléments de ce contexte
412       d=self.get_contexte_avant(etape)
413       # construction de l_constantes
414       for param in self.params:
415         nom = param.nom
416         if not nom : continue
417         if d.has_key(nom): l_constantes.append(nom)
418       # construction de l_fonctions
419       for form in self.fonctions:
420         nom = form.nom
421         if not nom : continue
422         if d.has_key(nom): l_fonctions.append(form.get_formule())
423
424       # on ajoute les concepts produits par DEFI_VALEUR
425       # XXX On pourrait peut etre faire plutot le test sur le type
426       # de concept : entier, reel, complexe, etc.
427       for k,v in d.items():
428          if hasattr(v,'etape') and v.etape.nom in ('DEFI_VALEUR',):
429             l_constantes.append(k)
430
431       # on retourne les deux listes
432       return l_constantes,l_fonctions
433
434    def get_nb_etapes_avant(self,niveau):
435       """ 
436           Retourne le nombre d etapes avant le debut de niveau
437       """
438       nb=0
439       for niv in self.etapes_niveaux:
440         if niv == niveau:break
441         nb=nb+len(niv.etapes)
442       return nb
443
444    def send_message(self,message):
445       if self.appli:
446          self.appli.send_message(message)
447
448    def init_modif(self):
449       """
450       Méthode appelée au moment où une modification va être faite afin de 
451       déclencher d'éventuels traitements pré-modification
452       """
453       self.state = 'modified'
454
455    def fin_modif(self):
456       self.isvalid()
457       pass
458
459    def get_liste_mc_inconnus(self):
460      """
461      Retourne une liste contenant les mots-clés inconnus à la relecture du JDC
462      """
463      # cette liste a le format suivant : [etape,(bloc,mcfact,...),nom_mc,valeur_mc]
464      l_mc = []
465      for etape in self.etapes :
466          if etape.isactif() :
467             if not etape.isvalid() :
468                l = etape.get_liste_mc_inconnus()
469                if l : l_mc.extend(l)
470      return l_mc    
471
472    def get_file(self,unite=None,fic_origine=''):
473       """
474           Retourne le nom du fichier correspondant à un numero d'unité
475           logique (entier) ainsi que le source contenu dans le fichier
476       """
477       if self.appli :
478          # Si le JDC est relié à une application maitre, on délègue la recherche
479          file,text = self.appli.get_file(unite,fic_origine)
480       else:
481          file = None
482          if unite != None:
483             if os.path.exists("fort."+str(unite)):
484                file= "fort."+str(unite)
485          if file == None :
486             raise AsException("Impossible de trouver le fichier correspondant \
487                                a l unite %s" % unite)
488          if not os.path.exists(file):
489             raise AsException("%s n'est pas un fichier existant" % unite)
490          fproc=open(file,'r')
491          text=fproc.read()
492          fproc.close()
493       if file == None : return None,None
494       text=string.replace(text,'\r\n','\n')
495       linecache.cache[file]=0,0,string.split(text,'\n'),file
496       return file,text
497
498
499    def get_genealogie(self):
500       """
501           Retourne la liste des noms des ascendants de l'objet self
502           jusqu'à la première ETAPE parent.
503       """
504       return []
505
506    def NommerSdprod(self,sd,sdnom,restrict='non'):
507       """
508           Nomme la SD apres avoir verifie que le nommage est possible : 
509           nom non utilise
510           Si le nom est deja utilise, leve une exception
511           Met le concept créé dans le concept global g_context
512       """
513       # XXX En mode editeur dans EFICAS, le nommage doit etre géré différemment
514       # Le dictionnaire g_context ne représente pas le contexte
515       # effectif avant une étape.
516       # Il faut utiliser get_contexte_avant avec indication de l'étape
517       # traitée. 
518       # Cette etape est indiquee par l'attribut _etape_context qui a ete 
519       # positionné préalablement par un appel à set_etape_context
520
521       if CONTEXT.debug : print "JDC.NommerSdprod ",sd,sdnom
522
523       if self._etape_context:
524          o=self.get_contexte_avant(self._etape_context).get(sdnom,None)
525       else:
526          o=self.sds_dict.get(sdnom,None)
527
528       if isinstance(o,ASSD):
529          raise AsException("Nom de concept deja defini : %s" % sdnom)
530
531       # ATTENTION : Il ne faut pas ajouter sd dans sds car il s y trouve deja.
532       # Ajoute a la creation (appel de reg_sd).
533       self.sds_dict[sdnom]=sd
534       sd.nom=sdnom
535
536       # En plus si restrict vaut 'non', on insere le concept dans le contexte du JDC
537       if restrict == 'non':
538          self.g_context[sdnom]=sd
539
540
541    def set_etape_context(self,etape):
542       """
543           Positionne l'etape qui sera utilisee dans NommerSdProd pour
544           decider si le concept passé pourra etre  nommé
545       """
546       self._etape_context=etape
547
548    def reset_context(self):
549       """ 
550           Cette methode reinitialise le contexte glissant pour pouvoir
551           tenir compte des modifications de l'utilisateur : création
552           de commandes, nommage de concepts, etc.
553       """
554       self.current_context={}
555       self.index_etape_courante=0
556
557    def del_sdprod(self,sd):
558       """
559           Supprime la SD sd de la liste des sd et des dictionnaires de contexte
560       """
561       if sd in self.sds : self.sds.remove(sd)
562       if self.g_context.has_key(sd.nom) : del self.g_context[sd.nom]
563       if self.sds_dict.has_key(sd.nom) : del self.sds_dict[sd.nom]
564
565    def del_param(self,param):
566       """
567           Supprime le paramètre param de la liste des paramètres
568           et du contexte gobal
569       """
570       if param in self.params : self.params.remove(param)
571       if self.g_context.has_key(param.nom) : del self.g_context[param.nom]
572
573    def del_fonction(self,fonction):
574       """
575           Supprime la fonction fonction de la liste des fonctions
576           et du contexte gobal
577       """
578       if fonction in self.fonctions : self.fonctions.remove(fonction)
579       if self.g_context.has_key(fonction.nom) : del self.g_context[fonction.nom]
580
581    def append_sdprod(self,sd):
582       """
583           Ajoute la SD sd à la liste des sd en vérifiant au préalable qu'une SD de
584           même nom n'existe pas déjà
585       """
586       if sd == None or sd.nom == None:return
587
588       o=self.sds_dict.get(sd.nom,None)
589       if isinstance(o,ASSD):
590          raise AsException("Nom de concept deja defini : %s" % sd.nom)
591       self.sds_dict[sd.nom]=sd
592       self.g_context[sd.nom] = sd
593       if sd not in self.sds : self.sds.append(sd)
594
595    def append_param(self,param):
596       """
597           Ajoute le paramètre param à la liste des params
598           et au contexte global
599       """
600       # il faudrait vérifier qu'un paramètre de même nom n'existe pas déjà !!!
601       if param not in self.params : self.params.append(param)
602       self.g_context[param.nom]=param
603
604    def append_fonction(self,fonction):
605       """
606           Ajoute la fonction fonction à la liste des fonctions
607           et au contexte global
608       """
609       # il faudrait vérifier qu'une fonction de même nom n'existe pas déjà !!!
610       if fonction not in self.fonctions : self.fonctions.append(fonction)
611       self.g_context[fonction.nom]=fonction
612
613    def delete_concept_after_etape(self,etape,sd):
614       """
615           Met à jour les étapes du JDC qui sont après etape en fonction
616           de la disparition du concept sd
617       """
618       index = self.etapes.index(etape)+1
619       if index == len(self.etapes) : 
620          return # etape est la dernière étape du jdc ...on ne fait rien !
621       for child in self.etapes[index:]:
622         child.delete_concept(sd)
623
624    def delete_concept(self,sd):
625       """
626           Inputs :
627              - sd=concept detruit
628           Fonction :
629           Mettre a jour les etapes du JDC suite à la disparition du
630           concept sd
631           Seuls les mots cles simples MCSIMP font un traitement autre
632           que de transmettre aux fils
633       """
634       for etape in self.etapes :
635         etape.delete_concept(sd)
636
637    def replace_concept_after_etape(self,etape,old_sd,sd):
638       """
639           Met à jour les étapes du JDC qui sont après etape en fonction
640           du remplacement du concept sd
641       """
642       index = self.etapes.index(etape)+1
643       if index == len(self.etapes) :
644          return # etape est la dernière étape du jdc ...on ne fait rien !
645       for child in self.etapes[index:]:
646         child.replace_concept(old_sd,sd)
647
648    def dump_state(self):
649       print "dump_state"
650       print "JDC.state: ",self.state
651       for etape in self.etapes :
652          print etape.nom+".state: ",etape.state
653       
654    def change_unit(self,unit,etape,old_unit):
655       if self.recorded_units.has_key(old_unit):del self.recorded_units[old_unit]
656       self.record_unit(unit,etape)
657
658    def record_unit(self,unit,etape):
659       """Enregistre les unites logiques incluses et les infos relatives a l'etape"""
660       if unit is None:
661          # Cas de POURSUITE
662          self.recorded_units[None]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
663       else:
664          self.recorded_units[unit]=(etape.fichier_ini ,etape.fichier_text,etape.recorded_units)
665
666 #ATTENTION SURCHARGE : cette methode surcharge la methode du package Validation : a reintegrer