Salome HOME
a39c7ef31c48a09467136002334a6e74c32b0f3f
[tools/eficas.git] / Noyau / N_VALIDATOR.py
1 # -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2007-2013   EDF R&D
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 # Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 #
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #
20 """
21    Ce module contient toutes les classes necessaires pour
22    implanter le concept de validateur dans Accas
23 """
24 import types
25 import traceback
26 import re
27 from N_ASSD import ASSD
28 from N_types import is_int, is_float_or_int, is_complex, is_number, is_str, is_enum
29 from strfunc import convert 
30 from Extensions.i18n import tr
31
32 class ValError(Exception):pass
33
34 def cls_mro(cls):
35     if hasattr(cls,"__mro__"):return cls.__mro__
36     mro=[cls]
37     for base in cls.__bases__:
38         mro.extend(cls_mro(base))
39     return mro
40
41 class Protocol:
42     def __init__(self,name):
43         self.registry = {}
44         self.name = name
45         self.args={}
46
47     def register(self, T, A):
48         self.registry[T] = A
49
50     def adapt(self, obj):
51         # (a) verifier si l'objet peut s'adapter au protocole
52         adapt = getattr(obj, '__adapt__', None)
53         if adapt is not None:
54             # on demande à l'objet obj de réaliser lui-meme l'adaptation
55             return adapt(self)
56
57         # (b) verifier si un adapteur est enregistré (si oui l'utiliser)
58         if self.registry:
59             for T in cls_mro(obj.__class__):
60                 if T in self.registry:
61                     return self.registry[T](obj,self,**self.args)
62
63         # (c) utiliser l'adapteur par defaut
64         return self.default(obj,**self.args)
65
66     def default(self,obj,**args):
67         raise TypeError("Can't adapt %s to %s" %
68                         (obj.__class__.__name__, self.name))
69
70 class PProtocol(Protocol):
71     """Verificateur de protocole paramétré (classe de base)"""
72     #Protocole paramétré. Le registre est unique pour toutes les instances. La methode register est une methode de classe
73     registry={}
74     def __init__(self,name,**args):
75         self.name = name
76         self.args=args
77     def register(cls, T, A):
78         cls.registry[T] = A
79     register=classmethod(register)
80
81 class ListProtocol(Protocol):
82     """Verificateur de protocole liste : convertit un objet quelconque en liste pour validation ultérieure"""
83     def default(self,obj):
84         if type(obj) is tuple:
85             if len(obj) > 0 and obj[0] in ('RI','MP'):
86                 #il s'agit d'un complexe ancienne mode. La cardinalite vaut 1
87                 return (obj,)
88             else:
89                 return obj
90         elif type(obj) is list:
91             return obj
92         elif obj == None:
93             # pas de valeur affecte. La cardinalite vaut 0
94             return obj
95         elif is_str(obj):
96             #il s'agit d'une chaine. La cardinalite vaut 1
97             return (obj,)
98         else:
99             try:
100                 # si l'objet supporte len, on a la cardinalite
101                 length=len(obj)
102                 return obj
103             except:
104                 # sinon elle vaut 1
105                 return (obj,)
106
107 listProto=ListProtocol("list")
108
109
110 class TypeProtocol(PProtocol):
111     """Verificateur de type parmi une liste de types possibles"""
112     #pas de registre par instance. Registre unique pour toutes les instances de TypeProtocol
113     registry={}
114     def __init__(self,name,typ=None):
115         PProtocol.__init__(self,name,typ=typ)
116         self.typ=typ
117
118     def default(self,obj,typ):
119
120         err = ""
121         for type_permis in typ:
122             if type_permis == 'R':
123                 if is_float_or_int(obj): return obj
124             elif type_permis == 'I':
125                 if is_int(obj): return obj
126             elif type_permis == 'C':
127                 if self.is_complexe(obj): return obj
128             elif type_permis == 'TXM':
129                 if is_str(obj): return obj
130             elif type_permis == 'shell':
131                 if is_str(obj): return obj
132             elif type_permis == 'Fichier' :
133                  import os
134                  if (len(typ) > 2 and typ[2] == "Sauvegarde") or os.path.isfile(obj):
135                      return obj
136                  #else : raise ValError(ufmt(_(u"%s n'est pas un fichier valide"), repr(obj)))
137                  else : raise ValError(repr(obj)+tr(" n'est pas un fichier valide"))
138             elif type_permis == 'FichierNoAbs' :
139                  import os
140                  if (len(typ) > 2 and typ[2] == "Sauvegarde") or isinstance(obj, type("")):
141                      return obj
142                  #else : raise ValError(ufmt(_(u"%s n'est pas un fichier valide"), repr(obj)))
143                  else : raise ValError(repr(obj)+tr(" n'est pas un fichier valide"))
144             elif type_permis == 'Repertoire':
145                 import os
146                 if os.path.isdir(obj):
147                     return obj
148                 else:
149                     #raise ValError(ufmt(_(u"%s n'est pas un répertoire valide"), repr(obj)))
150                     raise ValError(repr(obj)+tr(" n'est pas un repertoire valide"))
151             elif type(type_permis) == types.ClassType or isinstance(type_permis,type):
152                 try:
153                     if self.is_object_from(obj,type_permis): return obj
154                 except Exception, err:
155                     pass
156             elif type(type_permis) == types.InstanceType or isinstance(type_permis,object):
157                 try:
158                     if type_permis.__convert__(obj): return obj
159                 except Exception, err:
160                     pass
161             else:
162                 #print convert(ufmt(_(u"Type non encore géré %s"), `type_permis`))
163                 print tr("Type non encore gere "), `type_permis`
164         #raise ValError(ufmt(_(u"%s (de type %s) n'est pas d'un type autorisé: %s %s"),
165                             #repr(obj), type(obj), typ, unicode(err)))
166         raise ValError(repr(obj) +tr("de type ") + repr(type(obj)) + tr (" n'est pas d'un type autorise: ")+ str(typ) + " " +  unicode(err)) 
167
168     def is_complexe(self,valeur):
169         """ Retourne 1 si valeur est un complexe, 0 sinon """
170         if is_number(valeur):
171             # Pour permettre l'utilisation de complexes Python (accepte les entiers et réels)
172             return 1
173         elif type(valeur) != tuple :
174             # On n'autorise pas les listes pour les complexes
175             return 0
176         elif len(valeur) != 3:
177             return 0
178         else:
179             # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
180             # valeur suivie de 2 reels.
181             if valeur[0].strip() in ('RI','MP'):
182                 try:
183                     v1=reelProto.adapt(valeur[1]),reelProto.adapt(valeur[2])
184                     return 1
185                 except:
186                     return 0
187             else:
188                 return 0
189
190     def is_object_from(self,objet,classe):
191         """
192            Retourne 1 si objet est une instance de la classe classe, 0 sinon
193         """
194         convert = getattr(classe, '__convert__', None)
195         if convert is not None:
196             # classe verifie les valeurs
197             try:
198                 v=  convert(objet)
199                 return v is not None
200             except ValueError, err:
201                 raise
202             except:
203                 return 0
204         # On accepte les instances de la classe et des classes derivees
205         return isinstance(objet,classe)
206
207 reelProto=TypeProtocol("reel",typ=('R',))
208
209 class CardProtocol(PProtocol):
210     """Verificateur de cardinalité """
211     #pas de registre par instance. Registre unique pour toutes les instances
212     registry={}
213     def __init__(self,name,min=1,max=1):
214         PProtocol.__init__(self,name,min=min,max=max)
215
216     def default(self,obj,min,max):
217         length=len(obj)
218         if length < min or length >max:
219             #raise ValError(ufmt(_(u"Nombre d'arguments de %s incorrect (min = %s, max = %s)"),
220             #               repr(obj), min, max))
221             raise ValError(tr("Nombre incorrect d'arguments de ")+repr(obj)+"min = "+repr(min)+" max ="+repr(max))
222         return obj
223
224 class IntoProtocol(PProtocol):
225     """Verificateur de choix possibles : liste discrète ou intervalle"""
226     #pas de registre par instance. Registre unique pour toutes les instances
227     registry={}
228     def __init__(self,name,into=None,val_min='**',val_max='**'):
229         PProtocol.__init__(self,name,into=into,val_min=val_min,val_max=val_max)
230         self.val_min=val_min
231         self.val_max=val_max
232
233     def default(self,obj,into,val_min,val_max):
234         if into:
235             if obj not in into:
236                 #raise ValError(ufmt(_(u"La valeur : %s  ne fait pas partie des choix possibles %s"),
237                 #               repr(obj), into))
238                 raise ValError(tr("La valeur :") +repr(obj)+ tr("  ne fait pas partie des choix possibles ") +  repr(into))
239         else:
240             #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle)
241             if is_float_or_int(obj):
242                 if val_min == '**': val_min = obj -1
243                 if val_max == '**': val_max = obj +1
244                 if obj < val_min or obj > val_max :
245                     #raise ValError(ufmt(_(u"La valeur : %s est en dehors du domaine de validité [ %s , %s ]"),
246                     #               repr(obj), self.val_min, self.val_max))
247                     raise ValError(tr("La valeur :") +repr(obj)+ tr(" est en dehors du domaine de validite [ ") +  repr(self.val_min) + "," + repr(self.val_max) + "]")
248         return obj
249
250 class MinStr:
251     #exemple de classe pour verificateur de type
252     #on utilise des instances de classe comme type (typ=MinStr(3,6), par exemple)
253     def __init__(self,min,max):
254         self.min=min
255         self.max=max
256
257     def __convert__(self,valeur):
258         if is_str(valeur) and self.min <= len(valeur) <= self.max:return valeur
259         raise ValError(ufmt(_(u"%s n'est pas une chaine de longueur comprise entre %s et %s"),
260                        valeur, self.min, self.max))
261         raise ValError(valeur + tr(" n'est pas une chaine de longueur comprise entre ") +  repr(self.min) + " et " + repr(self.max))
262
263     def __repr__(self):
264         #return ufmt(_(u"TXM de longueur entre %s et %s"), self.min, self.max)
265         return tr(" TXM de longueur entre ")+  repr(self.min) + " et " + repr(self.max)
266
267 class Valid(PProtocol):
268    """
269         Cette classe est la classe mere des validateurs Accas
270         Elle doit etre derivee
271         Elle presente la signature des methodes indispensables pour son bon
272         fonctionnement et dans certains cas leur comportement par défaut.
273
274         @ivar cata_info: raison de la validite ou de l'invalidite du validateur meme
275         @type cata_info: C{string}
276    """
277    registry={}
278    def __init__(self,**args):
279        PProtocol.__init__(self,"valid",**args)
280
281    def info(self):
282        """
283           Cette methode retourne une chaine de caractères informative sur
284           la validation demandée par le validateur. Elle est utilisée
285           pour produire le compte-rendu de validité du mot clé associé.
286        """
287        #return _(u"valeur valide")
288        return tr("valeur valide")
289
290    def aide(self):
291        """
292           Cette methode retourne une chaine de caractère qui permet
293           de construire un message d'aide en ligne.
294           En général, le message retourné est le meme que celui retourné par la
295           méthode info.
296        """
297        return self.info()
298
299    def info_erreur_item(self):
300        """
301           Cette méthode permet d'avoir un message d'erreur pour un item
302           dans une liste dans le cas ou le validateur fait des vérifications
303           sur les items d'une liste. Si le validateur fait seulement des
304           vérifications sur la liste elle meme et non sur ses items, la méthode
305           doit retourner une chaine vide.
306        """
307        return " "
308
309    def info_erreur_liste(self):
310        """
311           Cette méthode a un comportement complémentaire de celui de
312           info_erreur_item. Elle retourne un message d'erreur lié uniquement
313           aux vérifications sur la liste elle meme et pas sur ses items.
314           Dans le cas où le validateur ne fait pas de vérification sur des
315           listes, elle retourne une chaine vide
316        """
317        return " "
318
319    def verif(self,valeur):
320        """
321            Cette methode sert a verifier si la valeur passee en argument est consideree
322            comme valide ou non par le validateur. Dans le premier cas le validateur retourne 1
323            (valide) sinon 0 (invalide).
324
325            @type valeur: tout type python
326            @param valeur: valeur du mot cle a valider
327            @rtype: C{boolean}
328            @return: indicateur de validite 1 (valide) ou 0 (invalide)
329        """
330        raise NotImplementedError("Must be implemented")
331
332    def verif_item(self,valeur):
333        """
334           La methode verif du validateur effectue une validation complete de
335           la valeur. valeur peut etre un scalaire ou une liste. Le validateur
336           doit traiter les 2 aspects s'il accepte des listes (dans ce cas la
337           methode is_list doit retourner 1).
338           La methode valid_item sert pour effectuer des validations partielles
339           de liste. Elle doit uniquement verifier la validite d'un item de
340           liste mais pas les caracteristiques de la liste.
341        """
342        return 0
343
344    def valide_liste_partielle(self,liste_courante):
345        """
346           Cette methode retourne un entier qui indique si liste_courante est partiellement valide (valeur 1)
347           ou invalide (valeur 0). La validation partielle concerne les listes en cours de construction : on
348           veut savoir si la liste en construction peut etre complétée ou si elle peut déjà etre considérée
349           comme invalide.
350           En général un validateur effectue la meme validation pour les listes partielles et les
351           listes complètes.
352        """
353        return self.verif(liste_courante)
354
355    def verif_cata(self):
356        """
357            Cette methode sert a realiser des verifications du validateur lui meme.
358            Elle est facultative et retourne 1 (valide) par defaut.
359            Elle retourne 0 si le validateur est lui meme invalide si par exemple ses
360            parametres de definition ne sont pas corrects.
361            La raison de l'invalidite est stockee dans l'attribut cata_info.
362
363            @rtype: C{boolean}
364            @return: indicateur de validite 1 (valide) ou 0 (invalide)
365        """
366        return 1
367
368    def is_list(self):
369        """
370           Cette méthode retourne un entier qui indique si le validateur
371           permet les listes (valeur 1) ou ne les permet pas (valeur 0).
372           Par défaut, un validateur n'autorise que des scalaires.
373        """
374        return 0
375
376    def has_into(self):
377        """
378           Cette méthode retourne un entier qui indique si le validateur
379           propose une liste de choix (valeur 1) ou n'en propose pas.
380           Par défaut, un validateur n'en propose pas.
381        """
382        return 0
383
384    def get_into(self,liste_courante=None,into_courant=None):
385        """
386           Cette méthode retourne la liste de choix proposée par le validateur.
387           Si le validateur ne propose pas de liste de choix, la méthode
388           retourne None.
389           L'argument d'entrée liste_courante, s'il est différent de None, donne
390           la liste des choix déjà effectués par l'utilisateur. Dans ce cas, la
391           méthode get_into doit calculer la liste des choix en en tenant
392           compte. Par exemple, si le validateur n'autorise pas les répétitions,
393           la liste des choix retournée ne doit pas contenir les choix déjà
394           contenus dans liste_courante.
395           L'argument d'entrée into_courant, s'il est différent de None, donne
396           la liste des choix proposés par d'autres validateurs. Dans ce cas,
397           la méthode get_into doit calculer la liste des choix à retourner
398           en se limitant à cette liste initiale. Par exemple, si into_courant
399           vaut (1,2,3) et que le validateur propose la liste de choix (3,4,5),
400           la méthode ne doit retourner que (3,).
401
402           La méthode get_into peut retourner une liste vide [], ce qui veut
403           dire qu'il n'y a pas (ou plus) de choix possible. Cette situation
404           peut etre normale : l''utilisateur a utilisé tous les choix, ou
405           résulter d'une incohérence des validateurs :
406           choix parmi (1,2,3) ET choix parmi (4,5,6). Il est impossible de
407           faire la différence entre ces deux situations.
408        """
409        return into_courant
410
411 class ListVal(Valid):
412    """
413        Cette classe sert de classe mère pour tous les validateurs qui acceptent
414        des listes.
415    """
416    def is_list(self):
417        return 1
418
419    def get_into(self,liste_courante=None,into_courant=None):
420        """
421           Cette méthode get_into effectue un traitement général qui consiste
422           a filtrer la liste de choix into_courant, si elle existe, en ne
423           conservant que les valeurs valides (appel de la méthode valid).
424        """
425        if into_courant is None:
426           return None
427        else:
428           liste_choix=[]
429           for e in into_courant:
430               if self.verif(e):
431                  liste_choix.append(e)
432           return liste_choix
433
434    def convert(self,valeur):
435        """
436           Méthode convert pour les validateurs de listes. Cette méthode
437           fait appel à la méthode convert_item sur chaque élément de la
438           liste.
439        """
440        if is_enum(valeur):
441           for val in valeur:
442               self.convert_item(val)
443           return valeur
444        else:
445           return self.convert_item(valeur)
446
447    def verif(self,valeur):
448        """
449           Méthode verif pour les validateurs de listes. Cette méthode
450           fait appel à la méthode verif_item sur chaque élément de la
451           liste. Si valeur est un paramètre, on utilise sa valeur effective
452           valeur.valeur.
453        """
454        if is_enum(valeur):
455           for val in valeur:
456               if not self.verif_item(val):
457                  return 0
458           return 1
459        else:
460           return self.verif_item(valeur)
461
462 class Compulsory(ListVal):
463       """
464           Validateur operationnel
465           Verification de la présence obligatoire d'un élément dans une liste
466       """
467       registry={}
468       def __init__(self,elem=()):
469           if not is_enum(elem): elem=(elem,)
470           Valid.__init__(self,elem=elem)
471           self.elem=elem
472           self.cata_info=""
473
474       def info(self):
475           #return ufmt(_(u"valeur %s obligatoire"), `self.elem`)
476           return tr("valeur  obligatoire")
477
478       def default(self,valeur,elem):
479           return valeur
480
481       def verif_item(self,valeur):
482           return 1
483
484       def convert(self,valeur):
485           elem=list(self.elem)
486           for val in valeur:
487               v=self.adapt(val)
488               if v in elem:elem.remove(v)
489           if elem:
490               #raise ValError(ufmt(_(u"%s ne contient pas les elements obligatoires : %s "),
491               #               valeur, elem))
492               raise ValError(valeur + tr(" ne contient pas les elements obligatoires : ")+  elem)
493           return valeur
494
495       def has_into(self):
496           return 1
497
498       def verif(self,valeur):
499           if not is_enum(valeur):
500              liste=list(valeur)
501           else:
502              liste=valeur
503           for val in self.elem :
504              if val not in liste : return 0
505           return 1
506
507       def info_erreur_item(self):
508           #return _(u"La valeur n'est pas dans la liste des choix possibles")
509           return tr("La valeur n'est pas dans la liste des choix possibles")
510
511 class NoRepeat(ListVal):
512       """
513           Validateur operationnel
514           Verification d'absence de doublons dans la liste.
515       """
516       def __init__(self):
517           Valid.__init__(self)
518           self.cata_info=""
519
520       def info(self):
521           #return _(u": pas de présence de doublon dans la liste")
522           return tr(": pas de presence de doublon dans la liste")
523
524       def info_erreur_liste(self):
525           #return _(u"Les doublons ne sont pas permis")
526           return tr("Les doublons ne sont pas permis")
527
528       def default(self,valeur):
529           if valeur in self.liste :
530               #raise ValError(ufmt(_(u"%s est un doublon"), valeur))
531               raise ValError(repr(valeur) + tr(" est un doublon"))
532           return valeur
533
534       def convert(self,valeur):
535           self.liste=[]
536           for val in valeur:
537               v=self.adapt(val)
538               self.liste.append(v)
539           return valeur
540
541       def verif_item(self,valeur):
542           return 1
543
544       def verif(self,valeur):
545           if is_enum(valeur):
546              liste=list(valeur)
547              for val in liste:
548                 if liste.count(val)!=1 : return 0
549              return 1
550           else:
551              return 1
552
553       def get_into(self,liste_courante=None,into_courant=None):
554           """
555           Methode get_into spécifique pour validateur NoRepeat, on retourne
556           une liste de choix qui ne contient aucune valeur de into_courant
557           déjà contenue dans liste_courante
558           """
559           if into_courant is None:
560              liste_choix=None
561           else:
562              liste_choix=[]
563              for e in into_courant:
564                  if e in liste_choix: continue
565                  if liste_courante is not None and e in liste_courante: continue
566                  liste_choix.append(e)
567           return liste_choix
568
569 class LongStr(ListVal):
570       """
571           Validateur operationnel
572           Verification de la longueur d une chaine
573       """
574       def __init__(self,low,high):
575           ListVal.__init__(self,low=low,high=high)
576           self.low=low
577           self.high=high
578           self.cata_info=""
579
580       def info(self):
581           #return ufmt(_(u"longueur de la chaine entre %s et %s"), self.low, self.high)
582           return tr("longueur de la chaine entre")+ self.low + tr(" et ")+ self.high
583
584       def info_erreur_item(self):
585           #return _(u"Longueur de la chaine incorrecte")
586           return tr("Longueur de la chaine incorrecte")
587
588       def convert(self,valeur):
589           for val in valeur:
590               v=self.adapt(val)
591           return valeur
592
593       def verif_item(self,valeur):
594           try:
595              self.adapt(valeur)
596              return 1
597           except:
598              return 0
599
600       def default(self,valeur,low,high):
601           if not is_str(valeur):
602              #raise ValError(ufmt(_(u"%s n'est pas une chaine"), repr(valeur)))
603              raise ValError( repr(valeur) + tr(" n'est pas une chaine"))
604           if valeur[0]=="'" and valeur[-1]=="'" :
605              low=low+2
606              high=high+2
607           if len(valeur) < low or len(valeur) > high :
608              #raise ValError(ufmt(_(u"%s n'est pas de la bonne longueur"), repr(valeur)))
609              raise ValError( repr(valeur) + tr(" n'est pas de la bonne longueur"))
610           return valeur
611
612 class OnlyStr(ListVal):
613       """
614           Validateur operationnel
615           Valide que c'est une chaine
616       """
617       def __init__(self):
618           ListVal.__init__(self)
619           self.cata_info=""
620
621       def info(self):
622           #return _(u"regarde si c'est une chaine")
623           return tr("verifier que c'est une chaine")
624
625       def info_erreur_item(self):
626           #return _(u"Ce n'est pas une chaine")
627           return tr("Ce n'est pas une chaine")
628
629       def convert(self,valeur):
630           for val in valeur:
631               v=self.adapt(val)
632           return valeur
633
634       def verif_item(self,valeur):
635           try:
636              self.adapt(valeur)
637              return 1
638           except:
639              return 0
640
641       def default(self,valeur):
642           if not is_str(valeur):
643              #raise ValError(ufmt(_(u"%s n'est pas une chaine"), repr(valeur)))
644              raise ValError(repr(valeur) + tr(" n'est pas une chaine"))
645           return valeur
646
647 class OrdList(ListVal):
648       """
649           Validateur operationnel
650           Verification qu'une liste est croissante ou decroissante
651       """
652       def __init__(self,ord):
653           ListVal.__init__(self,ord=ord)
654           self.ord=ord
655           self.cata_info=""
656
657       def info(self):
658           #return ufmt(_(u"liste %s"), self.ord)
659           return tr("liste ") + self.ord
660
661       def info_erreur_liste(self) :
662           #return ufmt(_(u"La liste doit etre en ordre %s"), self.ord)
663           return tr("La liste doit etre en ordre ")+ self.ord
664
665       def convert(self,valeur):
666           self.val=None
667           self.liste=valeur
668           for v in valeur:
669               self.adapt(v)
670           return valeur
671
672       def default(self,valeur,ord):
673           if self.ord=='croissant':
674               if self.val is not None and valeur<self.val:
675                   #raise ValError(ufmt(_(u"%s n'est pas par valeurs croissantes"), repr(self.liste)))
676                   raise ValError(repr(self.liste) +tr(" n'est pas par valeurs croissantes"))
677           elif self.ord=='decroissant':
678               if self.val is not None and valeur > self.val:
679                   #raise ValError(ufmt(_(u"%s n'est pas par valeurs decroissantes"), repr(self.liste)))
680                   raise ValError(repr(self.liste) +tr(" n'est pas par valeurs decroissantes"))
681           self.val=valeur
682           return valeur
683
684       def verif_item(self,valeur):
685           return 1
686
687       def get_into(self,liste_courante=None,into_courant=None):
688           """
689           Methode get_into spécifique pour validateur OrdList, on retourne
690           une liste de choix qui ne contient aucune valeur de into_courant
691           dont la valeur est inférieure à la dernière valeur de
692           liste_courante, si elle est différente de None.
693           """
694           if into_courant is None:
695              return None
696           elif not liste_courante :
697              return into_courant
698           else:
699              liste_choix=[]
700              last_val=liste_choix[-1]
701              for e in into_courant:
702                  if self.ord=='croissant' and e <= last_val:continue
703                  if self.ord=='decroissant' and e >= last_val:continue
704                  liste_choix.append(e)
705              return liste_choix
706
707 class OrVal(Valid):
708       """
709           Validateur operationnel
710           Cette classe est un validateur qui controle une liste de validateurs
711           Elle verifie qu'au moins un des validateurs de la liste valide la valeur
712       """
713       def __init__(self,validators=()):
714           if not is_enum(validators):
715              validators=(validators,)
716           self.validators=[]
717           for validator in validators:
718               if type(validator) == types.FunctionType:
719                  self.validators.append(FunctionVal(validator))
720               else:
721                  self.validators.append(validator)
722           self.cata_info=""
723
724       def info(self):
725           return "\n ou ".join([v.info() for v in self.validators])
726
727       def convert(self,valeur):
728           for validator in self.validators:
729               try:
730                  return validator.convert(valeur)
731               except:
732                  pass
733           raise ValError(ufmt(_(u"%s n'est pas du bon type"), repr(valeur)))
734           raise ValError(repr(valeur) + tr(" n'est pas du bon type"))
735
736       def info_erreur_item(self):
737           l=[]
738           for v in self.validators:
739               err=v.info_erreur_item()
740               if err != " " : l.append(err)
741           chaine=" \n ou ".join(l)
742           return chaine
743
744       def info_erreur_liste(self):
745           l=[]
746           for v in self.validators:
747               err=v.info_erreur_liste()
748               if err != " " : l.append(err)
749           chaine=" \n ou ".join(l)
750           return chaine
751
752       def is_list(self):
753           """
754              Si plusieurs validateurs sont reliés par un OU
755              il suffit qu'un seul des validateurs attende une liste
756              pour qu'on considère que leur union attend une liste.
757           """
758           for validator in self.validators:
759               v=validator.is_list()
760               if v :
761                  return 1
762           return 0
763
764       def verif(self,valeur):
765           for validator in self.validators:
766               v=validator.verif(valeur)
767               if v :
768                  return 1
769           return 0
770
771       def verif_item(self,valeur):
772           for validator in self.validators:
773               v=validator.verif_item(valeur)
774               if v :
775                  return 1
776           return 0
777
778       def verif_cata(self):
779           infos=[]
780           for validator in self.validators:
781               v=validator.verif_cata()
782               if not v :infos.append(validator.cata_info)
783           if infos:
784              self.cata_info="\n".join(infos)
785              return 0
786           self.cata_info=""
787           return 1
788
789       def has_into(self):
790           """
791           Dans le cas ou plusieurs validateurs sont reliés par un OU
792           il faut que tous les validateurs proposent un choix pour
793           qu'on considère que leur union propose un choix.
794           Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
795           En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un choix (1,2,3,4,5,6)
796           """
797           for validator in self.validators:
798               v=validator.has_into()
799               if not v :
800                  return 0
801           return 1
802
803       def get_into(self,liste_courante=None,into_courant=None):
804           """
805           Dans le cas ou plusieurs validateurs sont reliés par un OU
806           tous les validateurs doivent proposer un choix pour
807           qu'on considère que leur union propose un choix. Tous les choix
808           proposés par les validateurs sont réunis (opérateur d'union).
809           Exemple : Enum(1,2,3) OU entier pair, ne propose pas de choix
810           En revanche, Enum(1,2,3) OU Enum(4,5,6) propose un
811           choix (1,2,3,4,5,6)
812           """
813           validator_into=[]
814           for validator in self.validators:
815               v_into=validator.get_into(liste_courante,into_courant)
816               if v_into is None:
817                  return v_into
818               validator_into.extend(v_into)
819           return validator_into
820
821       def valide_liste_partielle(self,liste_courante=None):
822           """
823            Méthode de validation de liste partielle pour le validateur Or.
824            Si un des validateurs gérés par le validateur Or considère la
825            liste comme valide, le validateur Or la considère comme valide.
826           """
827           for validator in self.validators:
828               v=validator.valide_liste_partielle(liste_courante)
829               if v :
830                  return 1
831           return 0
832
833 class AndVal(Valid):
834       """
835           Validateur operationnel
836           Cette classe est un validateur qui controle une liste de validateurs
837           Elle verifie que tous les validateurs de la liste valident la valeur
838       """
839       def __init__(self,validators=()):
840           if not is_enum(validators):
841              validators=(validators,)
842           self.validators=[]
843           for validator in validators:
844               if type(validator) == types.FunctionType:
845                  self.validators.append(FunctionVal(validator))
846               else:
847                  self.validators.append(validator)
848               if hasattr(validator,'fonctions'):
849                  for fonction in validator.fonctions :
850                     f=getattr(validator,fonction)
851                     setattr(self,fonction,f)
852           self.cata_info=""
853
854       def info(self):
855           return "\n et ".join([v.info() for v in self.validators])
856
857       def convert(self,valeur):
858           for validator in self.validators:
859               valeur=validator.convert(valeur)
860           return valeur
861
862       def info_erreur_item(self):
863           chaine=""
864           a=1
865           for v in self.validators:
866               if v.info_erreur_item() != " " :
867                  if a==1:
868                     chaine=v.info_erreur_item()
869                     a=0
870                  else:
871                     chaine=chaine+" \n et "+v.info_erreur_item()
872           return chaine
873
874       def info_erreur_liste(self):
875           a=1
876           for v in self.validators:
877               if v.info_erreur_liste() != " " :
878                  if a==1:
879                     chaine=v.info_erreur_liste()
880                     a=0
881                  else:
882                     chaine=chaine+" \n et "+v.info_erreur_liste()
883           return chaine
884
885       def verif(self,valeur):
886           for validator in self.validators:
887               v=validator.verif(valeur)
888               if not v :
889                  self.local_info=validator.info()
890                  return 0
891           return 1
892
893       def verif_item(self,valeur):
894           for validator in self.validators:
895               v=validator.verif_item(valeur)
896               if not v :
897                  # L'info n'est probablement pas la meme que pour verif ???
898                  self.local_info=validator.info()
899                  return 0
900           return 1
901
902       def verif_cata(self):
903           infos=[]
904           for validator in self.validators:
905               v=validator.verif_cata()
906               if not v :infos.append(validator.cata_info)
907           if infos:
908              self.cata_info="\n".join(infos)
909              return 0
910           self.cata_info=""
911           return 1
912
913       def valide_liste_partielle(self,liste_courante=None):
914           """
915            Méthode de validation de liste partielle pour le validateur And.
916            Tous les validateurs gérés par le validateur And doivent considérer
917            la liste comme valide, pour que le validateur And la considère
918            comme valide.
919           """
920           for validator in self.validators:
921               v=validator.valide_liste_partielle(liste_courante)
922               if not v :
923                  return 0
924           return 1
925
926       def is_list(self):
927           """
928           Si plusieurs validateurs sont reliés par un ET
929           il faut que tous les validateurs attendent une liste
930           pour qu'on considère que leur intersection attende une liste.
931           Exemple Range(2,5) ET Card(1) n'attend pas une liste
932           Range(2,5) ET Pair attend une liste
933           """
934           for validator in self.validators:
935               v=validator.is_list()
936               if v == 0 :
937                  return 0
938           return 1
939
940       def has_into(self):
941           """
942           Dans le cas ou plusieurs validateurs sont reliés par un ET
943           il suffit qu'un seul validateur propose un choix pour
944           qu'on considère que leur intersection propose un choix.
945           Exemple : Enum(1,2,3) ET entier pair, propose un choix
946           En revanche, entier pair ET superieur à 10 ne propose pas de choix
947           """
948           for validator in self.validators:
949               v=validator.has_into()
950               if v :
951                  return 1
952           return 0
953
954       def get_into(self,liste_courante=None,into_courant=None):
955           """
956           Dans le cas ou plusieurs validateurs sont reliés par un ET
957           il suffit qu'un seul validateur propose un choix pour
958           qu'on considère que leur intersection propose un choix. Tous les
959           choix proposés par les validateurs sont croisés (opérateur
960           d'intersection)
961           Exemple : Enum(1,2,3) ET entier pair, propose un choix (2,)
962           En revanche, Enum(1,2,3) ET Enum(4,5,6) ne propose pas de choix.
963           """
964           for validator in self.validators:
965               into_courant=validator.get_into(liste_courante,into_courant)
966               if into_courant in ([],None):break
967           return into_courant
968
969 def do_liste(validators):
970     """
971        Convertit une arborescence de validateurs en OrVal ou AndVal
972        validators est une liste de validateurs ou de listes ou de tuples
973     """
974     valids=[]
975     for validator in validators:
976         if type(validator) == types.FunctionType:
977            valids.append(FunctionVal(validator))
978         elif type(validator) is tuple:
979            valids.append(OrVal(do_liste(validator)))
980         elif type(validator) is list:
981            valids.append(AndVal(do_liste(validator)))
982         else:
983            valids.append(validator)
984     return valids
985
986 def validatorFactory(validator):
987     if type(validator) == types.FunctionType:
988        return FunctionVal(validator)
989     elif type(validator) is tuple:
990        return OrVal(do_liste(validator))
991     elif type(validator) is list:
992        return AndVal(do_liste(validator))
993     else:
994        return validator
995
996 # Ci-dessous : exemples de validateur (peu testés)
997
998 class RangeVal(ListVal):
999       """
1000           Exemple de classe validateur : verification qu'une valeur
1001           est dans un intervalle.
1002           Pour une liste on verifie que tous les elements sont
1003           dans l'intervalle
1004           Susceptible de remplacer les attributs "vale_min" "vale_max"
1005           dans les catalogues
1006       """
1007       def __init__(self,low,high):
1008           self.low=low
1009           self.high=high
1010           #self.cata_info=ufmt(_(u"%s doit être inférieur a %s"), low,high)
1011           self.cata_info=low + tr(" doit être inférieur a ")+ high
1012
1013       def info(self):
1014           #return ufmt(_(u"valeur dans l'intervalle %s , %s"), self.low, self.high)
1015           return tr(" valeur dans l 'intervalle ")+self.low+ self.high
1016
1017       def convert_item(self,valeur):
1018           if valeur > self.low and valeur < self.high:return valeur
1019           #raise ValError(ufmt(_(u"%s devrait être comprise entre %s et %s"),
1020           #                    valeur, self.low, self.high))
1021           raise ValError(valeur + tr(" devrait etre comprise entre ") +  self.low + tr(" et ")+ self.high)
1022
1023       def verif_item(self,valeur):
1024           return valeur > self.low and valeur < self.high
1025
1026       def info_erreur_item(self) :
1027           #return ufmt(_(u"La valeur doit etre comprise entre %s et %s"), self.low, self.high)
1028           return tr("La valeur doit etre comprise entre ") + self.low + tr(" et ") + self.high
1029
1030       def verif_cata(self):
1031           if self.low > self.high : return 0
1032           return 1
1033
1034 class CardVal(Valid):
1035       """
1036           Exemple de classe validateur : verification qu'une liste est
1037           d'une longueur superieur a un minimum (min) et inferieure
1038           a un maximum (max).
1039           Susceptible de remplacer les attributs "min" "max" dans les
1040           catalogues
1041       """
1042       def __init__(self,min='**',max='**'):
1043           self.min=min
1044           self.max=max
1045           self.cata_info=min + tr(" doit etre inferieur a ")+ max
1046           #self.cata_info= ufmt(_(u"%s doit etre inferieur a %s"), min,max)
1047
1048       def info(self):
1049           #return ufmt(_(u"longueur de liste comprise entre  %s et %s"), self.min, self.max)
1050           return tr("La longueur doit etre comprise entre ") + self.min + tr(" et ") + self.max
1051
1052       def info_erreur_liste(self):
1053           #return ufmt(_(u"Le cardinal de la liste doit etre compris entre %s et %s"),
1054           #            self.min, self.max)
1055           return tr("Le cardinal de la liste doit etre compris entre ") + self.min + tr(" et ") + self.max
1056
1057       def is_list(self):
1058           return self.max == '**' or self.max > 1
1059
1060       def get_into(self,liste_courante=None,into_courant=None):
1061           if into_courant is None:
1062              return None
1063           elif liste_courante is None:
1064              return into_courant
1065           elif self.max == '**':
1066              return into_courant
1067           elif len(liste_courante) < self.max:
1068              return into_courant
1069           else:
1070              return []
1071
1072       def convert(self,valeur):
1073           if is_enum(valeur):
1074              l=len(valeur)
1075           elif valeur is None:
1076              l=0
1077           else:
1078              l=1
1079           if self.max != '**' and l > self.max:
1080               #raise ValError(ufmt(_(u"%s devrait etre de longueur inferieure a %s"), valeur, self.max))
1081               raise ValError(valeur + tr(" devrait etre de longueur inferieure a ")+ self.min)
1082           if self.min != '**' and l < self.min:
1083               #raise ValError(ufmt(_(u"%s devrait etre de longueur superieure a %s"), valeur, self.min))
1084               raise ValError(valeur + tr(" devrait etre de longueur superieure a ")+ self.max)
1085           return valeur
1086
1087       def verif_item(self,valeur):
1088           return 1
1089
1090       def verif(self,valeur):
1091           if is_enum(valeur):
1092              if self.max != '**' and len(valeur) > self.max:return 0
1093              if self.min != '**' and len(valeur) < self.min:return 0
1094              return 1
1095           else:
1096              if self.max != '**' and 1 > self.max:return 0
1097              if self.min != '**' and 1 < self.min:return 0
1098              return 1
1099
1100       def verif_cata(self):
1101           if self.min != '**' and self.max != '**' and self.min > self.max : return 0
1102           return 1
1103
1104       def valide_liste_partielle(self,liste_courante=None):
1105           validite=1
1106           if liste_courante != None :
1107              if len(liste_courante) > self.max :
1108                 validite=0
1109           return validite
1110
1111 class PairVal(ListVal):
1112       """
1113           Exemple de classe validateur : verification qu'une valeur
1114           est paire.
1115           Pour une liste on verifie que tous les elements sont
1116           pairs
1117       """
1118       def __init__(self):
1119           ListVal.__init__(self)
1120           self.cata_info=""
1121
1122       def info(self):
1123           #return _(u"valeur paire")
1124           return tr("valeur paire")
1125
1126       def info_erreur_item(self):
1127           #return _(u"La valeur saisie doit etre paire")
1128           return tr("La valeur saisie doit etre paire")
1129
1130       def convert(self,valeur):
1131           for val in valeur:
1132              v=self.adapt(val)
1133              if v % 2 != 0:
1134                  #raise ValError(ufmt(_(u"%s contient des valeurs non paires"), repr(valeur)))
1135                  raise ValError(repr(valeur)+tr("contient des valeurs non paires"))
1136           return valeur
1137
1138       def default(self,valeur):
1139           return valeur
1140
1141       def verif_item(self,valeur):
1142           if type(valeur) not in (int,long):
1143              return 0
1144           return valeur % 2 == 0
1145
1146       def verif(self,valeur):
1147           if is_enum(valeur):
1148              for val in valeur:
1149                 if val % 2 != 0:return 0
1150              return 1
1151           else:
1152              if valeur % 2 != 0:return 0
1153              return 1
1154
1155 class EnumVal(ListVal):
1156       """
1157           Exemple de classe validateur : verification qu'une valeur
1158           est prise dans une liste de valeurs.
1159           Susceptible de remplacer l attribut "into" dans les catalogues
1160       """
1161       def __init__(self,into=()):
1162           if not is_enum(into): 
1163               into=(into,)
1164           self.into=into
1165           self.cata_info=""
1166
1167       def info(self):
1168           #return "valeur dans %s" % `self.into`
1169           return tr("valeur dans") +  self.into
1170
1171       def convert_item(self,valeur):
1172           if valeur in self.into:return valeur
1173           #raise ValError(ufmt(_(u"%s contient des valeurs hors des choix possibles: %s "),
1174           #                    valeur, self.into))
1175           raise ValError(valeur + tr(" contient des valeurs hors des choix possibles: ")+  self.into)
1176
1177       def verif_item(self,valeur):
1178           if valeur not in self.into:return 0
1179           return 1
1180
1181       def has_into(self):
1182           return 1
1183
1184       def get_into(self,liste_courante=None,into_courant=None):
1185           if into_courant is None:
1186              liste_choix= list(self.into)
1187           else:
1188              liste_choix=[]
1189              for e in into_courant:
1190                  if e in self.into:
1191                     liste_choix.append(e)
1192           return liste_choix
1193
1194       def info_erreur_item(self):
1195           #return _(u"La valeur n'est pas dans la liste des choix possibles")
1196           return tr("La valeur n'est pas dans la liste des choix possibles")
1197
1198 def ImpairVal(valeur):
1199     """
1200           Exemple de validateur
1201         Cette fonction est un validateur. Elle verifie que la valeur passee
1202         est bien un nombre impair.
1203     """
1204     if is_enum(valeur):
1205        for val in valeur:
1206            if val % 2 != 1:return 0
1207        return 1
1208     else:
1209        if valeur % 2 != 1:return 0
1210        return 1
1211
1212 ImpairVal.info="valeur impaire"
1213
1214 class F1Val(Valid):
1215       """
1216           Exemple de validateur
1217           Cette classe est un validateur de dictionnaire (mot cle facteur ?). Elle verifie
1218           que la somme des cles A et B vaut une valeur donnee
1219           en parametre du validateur
1220       """
1221       def __init__(self,somme=10):
1222           self.somme=somme
1223           self.cata_info=""
1224
1225       def info(self):
1226           #return ufmt(_(u"valeur %s pour la somme des cles A et B "), self.somme)
1227           return tr("valeur") + repr(self.somme) + tr(" pour la somme des cles A et B ")
1228
1229       def verif(self,valeur):
1230           if is_enum(valeur):
1231              for val in valeur:
1232                 if not val.has_key("A"):return 0
1233                 if not val.has_key("B"):return 0
1234                 if val["A"]+val["B"]  != self.somme:return 0
1235              return 1
1236           else:
1237              if not valeur.has_key("A"):return 0
1238              if not valeur.has_key("B"):return 0
1239              if valeur["A"]+valeur["B"]  != self.somme:return 0
1240              return 1
1241
1242 class FunctionVal(Valid):
1243       """
1244           Exemple de validateur
1245           Cette classe est un validateur qui est initialise avec une fonction
1246       """
1247       def __init__(self,function):
1248           self.function=function
1249
1250       def info(self):
1251           return self.function.info
1252
1253       def verif(self,valeur):
1254           return self.function(valeur)
1255
1256 #MC ca ne devrait plus servir !
1257 CoercableFuncs = { types.IntType:     int,
1258                    types.LongType:    long,
1259                    types.FloatType:   float,
1260                    types.ComplexType: complex,
1261                    types.UnicodeType: unicode }
1262
1263 class TypeVal(ListVal):
1264       """
1265           Exemple de validateur
1266           Cette classe est un validateur qui controle qu'une valeur
1267           est bien du type Python attendu.
1268           Pour une liste on verifie que tous les elements sont du bon type.
1269           Semblable a InstanceVal mais ici on fait le test par tentative de conversion
1270           alors qu'avec InstanceVal on ne teste que si isinstance est vrai.
1271       """
1272       def __init__(self, aType):
1273           #Si aType n'est pas un type, on le retrouve a l'aide de la fonction type
1274           #type(1) == int;type(0.2)==float;etc.
1275           if type(aType) != types.TypeType:
1276              aType=type(aType)
1277           self.aType=aType
1278           try:
1279              self.coerce=CoercableFuncs[ aType ]
1280           except:
1281              self.coerce = self.identity
1282
1283       def info(self):
1284           #return ufmt(_(u"valeur de %s"), self.aType)
1285           return tr("valeur de ")+ self.aType
1286
1287       def identity ( self, value ):
1288           if type( value ) == self.aType:
1289              return value
1290           raise ValError
1291
1292       def convert_item(self,valeur):
1293           return   self.coerce(valeur)
1294
1295       def verif_item(self,valeur):
1296           try:
1297              self.coerce(valeur)
1298           except:
1299              return 0
1300           return 1
1301
1302 class InstanceVal(ListVal):
1303       """
1304           Exemple de validateur
1305           Cette classe est un validateur qui controle qu'une valeur est
1306           bien une instance (au sens Python) d'une classe
1307           Pour une liste on verifie chaque element de la liste
1308       """
1309       def __init__(self,aClass):
1310           #Si aClass est une classe on la memorise dans self.aClass
1311           #sinon c'est une instance dont on memorise la classe
1312           if type(aClass) == types.InstanceType:
1313              #instance ancienne mode
1314              aClass=aClass.__class__
1315           elif type(aClass) == types.ClassType:
1316              #classe ancienne mode
1317              aClass=aClass
1318           elif type(aClass) == type:
1319              #classe nouvelle mode
1320              aClass=aClass
1321           elif isinstance(aClass,object):
1322              #instance nouvelle mode
1323              aClass=type(aClass)
1324           else:
1325              raise ValError(_(u"type non supporté"))
1326
1327           self.aClass=aClass
1328
1329       def info(self):
1330           #return ufmt(_(u"valeur d'instance de %s"), self.aClass.__name__)
1331           return tr("valeur d'instance de ")+ self.aClass.__name__
1332
1333       def verif_item(self,valeur):
1334           if not isinstance(valeur,self.aClass): return 0
1335           return 1
1336
1337 class VerifTypeTuple(Valid,ListVal) :
1338       def __init__(self,typeDesTuples):
1339           self.typeDesTuples=typeDesTuples
1340           Valid.__init__(self)
1341           self.cata_info=""
1342
1343       def info(self):
1344           return _(u": vérifie les types dans un tuple")
1345
1346       def info_erreur_liste(self):
1347           return _(u"Les types entrés ne sont pas permis")
1348
1349       def default(self,valeur):
1350           #if valeur in self.liste : raise ValError("%s est un doublon" % valeur)
1351           return valeur
1352
1353       def is_list(self) :
1354           return 1
1355
1356       def convert_item(self,valeur):
1357           if len(valeur) != len(self.typeDesTuples):
1358              #raise ValError(ufmt(_(u"%s devrait etre de type  %s "), valeur, repr(self.typeDesTuples)))
1359              raise ValError(repr(valeur)+tr(" devrait etre de type  ")+ self.typeDesTuples)
1360           for i in range(len(valeur)) :
1361               ok=self.verifType(valeur[i],self.typeDesTuples[i])
1362               if ok!=1 : 
1363                  #raise ValError(ufmt(_(u"%s devrait etre de type  %s "), valeur, self.typeDesTuples))
1364                  raise ValError(repr(valeur)+tr(" devrait etre de type  ")+ self.typeDesTuples)
1365           return valeur
1366
1367       def verif_item(self,valeur):
1368           try :
1369              if len(valeur) != len(self.typeDesTuples):
1370                 return 0
1371              for i in range(len(valeur)) :
1372                 ok=self.verifType(valeur[i],self.typeDesTuples[i])
1373                 if ok!=1:
1374                    return 0
1375           except :
1376              return 0
1377           return 1
1378
1379       def verifType(self,valeur,type_permis):
1380           if type_permis == 'R':
1381              if type(valeur) in (types.IntType,types.FloatType,types.LongType):return 1
1382           elif type_permis == 'I':
1383              if type(valeur) in (types.IntType,types.LongType):return 1
1384           elif type_permis == 'C':
1385              if self.is_complexe(valeur):return 1
1386           elif type_permis == 'TXM':
1387              if type(valeur)==types.StringType:return 1
1388           return 0
1389
1390       def verif(self,valeur):
1391           if type(valeur) in (types.ListType,types.TupleType):
1392              liste=list(valeur)
1393              for val in liste:
1394                 if self.verif_item(val)!=1 : return 0
1395              return 1
1396  
1397 class VerifExiste(ListVal) :
1398       """
1399          fonctionne avec into
1400          Met une liste à jour selon les mot clefs existant
1401          exemple si into = ("A","B","C")
1402          si au niveau N du JDC les objets "A" et "C" existe
1403          alors la liste des into deviendra ( "A","C")
1404
1405          niveauVerif est le niveau du JDC dans lequel va s effectuer la verification
1406          niveauVerif est defini par rapport au Noeud :
1407          exemple niveauVerif = 1 : on verifie les freres
1408                  niveauVerif = 2 : on verifie les oncles..
1409       """
1410       def __init__(self,niveauVerif):
1411           ListVal.__init__(self)
1412           self.niveauVerif=niveauVerif
1413           self.MCSimp=None
1414           self.listeDesFreres=()
1415           self.fonctions=('verifie_liste','set_MCSimp')
1416
1417       def is_list(self):
1418           return 1
1419
1420       def verifie_liste(self,liste):
1421           self.set_MCSimp(self.MCSimp)
1422           for item in liste :
1423             if not( item in self.listeDesFreres) : return 0
1424           return 1
1425
1426       def verif_item(self,valeur):
1427           self.set_MCSimp(self.MCSimp)
1428           if valeur in self.listeDesFreres : return 1
1429           return 0
1430
1431       def set_MCSimp(self, MCSimp) :
1432           self.MCSimp=MCSimp
1433           k=self.niveauVerif
1434           mc=MCSimp
1435           while (k != 0) :
1436              parent=mc.parent
1437              mc=parent
1438              k=k-1
1439          #on met la liste à jour
1440           parent.forceRecalcul=self.niveauVerif
1441           self.listeDesFreres=parent.liste_mc_presents()
1442
1443       def convert_item(self,valeur):
1444           if valeur in self.listeDesFreres : return valeur
1445           raise ValError(ufmt(_(u"%s n'est pas dans %s"), valeur, self.listeDesFreres))
1446
1447 class RegExpVal(ListVal):
1448     """
1449     Vérifie qu'une chaîne de caractère corresponde à l'expression régulière 'pattern'
1450     """
1451
1452     errormsg = u'La chaîne "%(value)s" ne correspond pas au motif "%(pattern)s"'
1453
1454     def __init__(self, pattern):
1455         self.pattern = pattern
1456         self.compiled_regexp = re.compile(pattern)
1457     
1458     def info(self):
1459         return u'Une chaîne correspondant au motif "%s" est attendue.' % self.pattern
1460
1461     def verif_item(self, valeur):
1462         if self.compiled_regexp.match(valeur):
1463             return 1
1464         else:
1465             return (0, self.errormsg % {"value": valeur, "pattern": self.pattern})
1466
1467     def convert_item(self, valeur):
1468         if self.compiled_regexp.match(valeur):
1469             return valeur
1470         else:
1471             raise ValError(self.errormsg % {"value": valeur, "pattern": self.pattern})
1472
1473 class FileExtVal(RegExpVal):
1474     """
1475     Vérifie qu'une chaîne de caractère soit un nom de fichier valide avec l'extension 'ext'
1476     """
1477
1478     def __init__(self, ext):
1479         self.ext = ext
1480         self.errormsg = u'"%%(value)s" n\'est pas un nom de fichier %(ext)s valide' % {"ext": ext}
1481         RegExpVal.__init__(self, "^[\w\-]+\.%s$" % self.ext)
1482     
1483     def info(self):
1484         #return u'Un nom de fichier se terminant par ".%s" est attendu.' % self.ext
1485         return tr('Un nom de fichier se terminant par') + self.ext +tr(" est attendu.")