]> SALOME platform Git repositories - tools/eficas.git/blob - Validation/V_MCSIMP.py
Salome HOME
PN résolution de la fiche AO2004-191
[tools/eficas.git] / Validation / V_MCSIMP.py
1 #@ MODIF V_MCSIMP Validation  DATE 04/02/2004   AUTEUR CAMBIER S.CAMBIER 
2 #            CONFIGURATION MANAGEMENT OF EDF VERSION
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR   
8 # (AT YOUR OPTION) ANY LATER VERSION.                                 
9 #
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT 
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF          
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU    
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.                            
14 #
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE   
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,       
17 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.      
18 #                                                                       
19 #                                                                       
20 # ======================================================================
21 """
22    Ce module contient la classe mixin MCSIMP qui porte les méthodes
23    nécessaires pour réaliser la validation d'un objet de type MCSIMP
24    dérivé de OBJECT.
25
26    Une classe mixin porte principalement des traitements et est
27    utilisée par héritage multiple pour composer les traitements.
28 """
29 # Modules Python
30 import string,types
31 import traceback
32
33 # Modules EFICAS
34 from Noyau import N_CR
35 from Noyau.N_Exception import AsException
36
37 class MCSIMP:
38    """
39       COMMENTAIRE CCAR
40         Cette classe est quasiment identique à la classe originale d'EFICAS
41         a part quelques changements cosmétiques et des chagements pour la
42         faire fonctionner de facon plus autonome par rapport à l'environnement
43         EFICAS
44  
45         A mon avis, il faudrait aller plus loin et réduire les dépendances
46         amont au strict nécessaire.
47
48         - Est il indispensable de faire l'évaluation de la valeur dans le contexte
49           du jdc dans cette classe.
50
51         - Ne pourrait on pas doter les objets en présence des méthodes suffisantes
52           pour éviter les tests un peu particuliers sur GEOM, PARAMETRE et autres. J'ai
53           d'ailleurs modifié la classe pour éviter l'import de GEOM
54    """
55
56    CR=N_CR.CR
57    
58    def __init__(self):
59       self.state='undetermined'
60
61    def get_valid(self):
62        if hasattr(self,'valid'):
63           return self.valid
64        else:
65           self.valid=None
66           return None
67
68    def set_valid(self,valid):
69        old_valid=self.get_valid()
70        self.valid = valid
71        self.state = 'unchanged'
72        if not old_valid or old_valid != self.valid :
73            self.init_modif_up()
74
75    def isvalid(self,cr='non'):
76       """
77          Cette méthode retourne un indicateur de validité de l'objet de type MCSIMP
78
79            - 0 si l'objet est invalide
80            - 1 si l'objet est valide
81
82          Le paramètre cr permet de paramétrer le traitement. Si cr == 'oui'
83          la méthode construit également un comte-rendu de validation
84          dans self.cr qui doit avoir été créé préalablement.
85       """
86       if self.state == 'unchanged':
87         return self.valid
88       else:
89         valid = 1
90         v=self.valeur
91         #  verification presence
92         if self.isoblig() and v == None :
93           if cr == 'oui' :
94             self.cr.fatal(string.join(("Mot-clé : ",self.nom," obligatoire non valorisé")))
95           valid = 0
96
97         if v is None:
98            valid=0
99            if cr == 'oui' :
100               self.cr.fatal("None n'est pas une valeur autorisée")
101         else:
102            # type,into ...
103            valid = self.verif_type(val=v,cr=cr)*self.verif_into(cr=cr)*self.verif_card(cr=cr)
104            #
105            # On verifie les validateurs s'il y en a et si necessaire (valid == 1)
106            #
107            if valid and self.definition.validators and not self.definition.validators.verif(self.valeur):
108               if cr == 'oui' :
109                  self.cr.fatal(string.join(("Mot-clé : ",self.nom,"devrait avoir ",self.definition.validators.info())))
110               valid=0
111            # fin des validateurs
112            #
113
114         self.set_valid(valid)
115         return self.valid
116
117    def isoblig(self):
118       """ indique si le mot-clé est obligatoire
119       """
120       return self.definition.statut=='o'
121
122    def verif_card(self,cr='non'):
123       """ 
124          un mot-clé simple ne peut etre répété :
125            la cardinalité ici s'entend par la vérification que le nombre d'arguments de self.valeur
126            est bien compris entre self.min et self.max dans le cas où il s'agit d'une liste
127       """
128       card = 1
129       min=self.definition.min
130       max=self.definition.max
131
132       if type(self.valeur) == types.TupleType and not self.valeur[0] in ('RI','MP') or type(self.valeur) == types.ListType:
133         length=len(self.valeur)
134       else:
135         if self.valeur == None :
136            length=0
137         else:
138            length=1
139
140       if length < min or length >max:
141          if cr == 'oui':
142             self.cr.fatal("Nombre d'arguments de %s incorrect pour %s (min = %s, max = %s)" %(`self.valeur`,self.nom,min,max))
143          card = 0
144       return card
145
146    def verif_type(self,val=None,cr='non'):
147       """
148         FONCTION :
149          Cette methode verifie que le type de l'argument val est en conformite avec celui 
150          qui est declare dans la definition du mot cle simple.
151          Elle a plusieurs modes de fonctionnement liés à la valeur de cr.
152          Si cr vaut 'oui' : elle remplit le compte-rendu self.cr sinon elle ne le remplit pas.
153         PARAMETRE DE RETOUR :
154          Cette méthode retourne une valeur booléenne qui vaut 1 si le type de val est correct ou 0 sinon
155          
156       """
157       valeur = val
158       if valeur == None :
159         if cr == 'oui':
160           self.cr.fatal("None n'est pas une valeur autorisée")
161         return 0
162
163       if type(valeur) == types.TupleType and not valeur[0] in ('RI','MP') or type(valeur) == types.ListType:
164         # Ici on a identifié une liste de valeurs
165         for val in valeur:
166             if not self.verif_type(val=val,cr=cr) : return 0
167         return 1
168
169       # Ici, valeur est un scalaire ...il faut tester sur tous les types ou les valeurs possibles
170
171       for type_permis in self.definition.type:
172           if self.compare_type(valeur,type_permis) : return 1
173
174       # si on sort de la boucle précédente par ici c'est qu'on n'a trouvé aucun type valable --> valeur refusée
175       # on essaie d evaluer si c est un parametre tordu : exemple a*b ou a et b sont definis
176       if valeur.__class__.__name__ in ('PARAMETRE_EVAL','PARAMETRE'):
177           try :
178
179             # On crée un dictionnaire qui servira de contexte aux evaluations
180             # Ce dictionnaire sera initialisé avec les paramètres du JDC
181             d={}
182             for param in self.jdc.params :
183                 expression = param.nom+'='+repr(param.valeur)
184                 # ici on enrichit le dictionnaire d
185                 exec expression in d
186
187             obj=eval( valeur.valeur,d) 
188
189             for type_permis in self.definition.type:
190                 if self.compare_type(obj,type_permis) : 
191                     return 1
192           except Exception,e :
193             print "AAAAAAAAAAAAA"
194             print "e = ",str(e)
195             pass
196
197       if cr =='oui':
198           self.cr.fatal("%s n'est pas d'un type autorisé" %`valeur`)
199       return 0
200
201    def verif_into(self,cr='non'):
202       """
203       Vérifie si la valeur de self est bien dans l'ensemble discret de valeurs
204       donné dans le catalogue derrière l'attribut into ou vérifie que valeur est bien compris
205       entre val_min et val_max
206       """
207       if self.definition.into == None :
208         #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle)
209         if self.definition.val_min == '**' and self.definition.val_max == '**':
210            # L'intervalle est infini, on ne fait pas de test
211            return 1
212         #if type(self.valeur) in (types.ListType,types.TupleType) :
213         if type(self.valeur) == types.TupleType and not self.valeur[0] in ('RI','MP') or type(self.valeur) == types.ListType:
214           # Cas d'une liste de valeurs
215           test = 1
216           for val in self.valeur :
217             if type(val) != types.StringType and type(val) != types.InstanceType:
218               test = test*self.isinintervalle(val,cr=cr)
219           return test
220         else :
221           # Cas d'un scalaire
222           val = self.valeur
223           if type(val)!=types.StringType and type(val)!=types.InstanceType:
224             return self.isinintervalle(self.valeur,cr=cr)
225           else :
226             return 1
227       else :
228         # on est dans le cas d'un ensemble discret de valeurs possibles (into)
229         #if type(self.valeur) in (types.ListType,types.TupleType) :
230         if type(self.valeur) == types.TupleType and not self.valeur[0] in ('RI','MP') or type(self.valeur) == types.ListType:
231           # Cas d'une liste de valeur
232           for e in self.valeur:
233             if e not in self.definition.into:
234               if cr=='oui':
235                 self.cr.fatal(string.join(("La valeur :",`e`," n'est pas permise pour le mot-clé :",self.nom)))
236               return 0
237         else:
238           if self.valeur not in self.definition.into:
239             if cr=='oui':
240               self.cr.fatal(string.join(("La valeur :",`self.valeur`," n'est pas permise pour le mot-clé :",self.nom)))
241             return 0
242         return 1
243
244    def is_complexe(self,valeur):
245       """ Retourne 1 si valeur est un complexe, 0 sinon """
246       if type(valeur) == types.InstanceType :
247         #XXX je n'y touche pas pour ne pas tout casser mais il serait
248         #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('C'), par exemple
249         if valeur.__class__.__name__ in ('EVAL','complexe','PARAMETRE_EVAL'):
250           return 1
251         elif valeur.__class__.__name__ in ('PARAMETRE',):
252           # il faut tester si la valeur du parametre est un complexe
253           return self.is_complexe(valeur.valeur)
254         else:
255           print "Objet non reconnu dans is_complexe %s" %`valeur`
256           return 0
257       # Pour permettre l'utilisation de complexes Python
258       #elif type(valeur) == types.ComplexType:
259         #return 1
260       elif type(valeur) != types.TupleType :
261         # On n'autorise pas les listes pour les complexes
262         return 0
263       elif len(valeur) != 3:return 0
264       else:
265           # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
266           # valeur suivie de 2 reels.
267           try:
268              if string.strip(valeur[0]) in ('RI','MP') and self.is_reel(valeur[1]) and self.is_reel(valeur[2]):
269                 return 1
270           except:
271              return 0
272
273    def is_reel(self,valeur):
274       """
275       Retourne 1 si valeur est un reel, 0 sinon
276       """
277       if type(valeur) == types.InstanceType :
278         #XXX je n'y touche pas pour ne pas tout casser mais il serait
279         #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('R'), par exemple
280         #XXX ou valeur.is_reel()
281         #XXX ou encore valeur.compare(self.is_reel)
282         if valeur.__class__.__name__ in ('EVAL','reel','PARAMETRE_EVAL') :
283           return 1
284         elif valeur.__class__.__name__ in ('PARAMETRE',):
285           # il faut tester si la valeur du parametre est un réel
286           return self.is_reel(valeur.valeur)
287         else:
288           print "Objet non reconnu dans is_reel %s" %`valeur`
289           return 0
290       elif type(valeur) not in (types.IntType,types.FloatType,types.LongType):
291         # ce n'est pas un réel
292         return 0
293       else:
294         return 1
295
296    def is_entier(self,valeur):
297       """ Retourne 1 si valeur est un entier, 0 sinon """
298       if type(valeur) == types.InstanceType :
299         #XXX je n'y touche pas pour ne pas tout casser mais il serait
300         #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('I'), par exemple
301         if valeur.__class__.__name__ in ('EVAL','entier','PARAMETRE_EVAL') :
302           return 1
303         elif valeur.__class__.__name__ in ('PARAMETRE',):
304           # il faut tester si la valeur du parametre est un entier
305           return self.is_entier(valeur.valeur)
306         else:
307           print "Objet non reconnu dans is_reel %s" %`valeur`
308           return 0
309       elif type(valeur) not in (types.IntType,types.LongType):
310         # ce n'est pas un entier
311         return 0
312       else:
313         return 1
314
315    def is_shell(self,valeur):
316       """ 
317           Retourne 1 si valeur est un shell, 0 sinon
318           Pour l'instant aucune vérification n'est faite
319           On impose juste que valeur soit une string
320       """
321       if type(valeur) != types.StringType:
322         return 0
323       else:
324         return 1
325
326    def is_object_from(self,objet,classe):
327       """
328            Retourne 1 si valeur est un objet de la classe classe ou d'une
329            sous-classe de classe, 0 sinon
330       """
331       if type(objet) != types.InstanceType :
332           return 0
333       if not objet.__class__ == classe and not issubclass(objet.__class__,classe):
334         return 0
335       else:
336         return 1
337
338    def compare_type(self,valeur,type_permis):
339       """
340           Fonction booléenne qui retourne 1 si valeur est du type type_permis, 0 sinon
341       """
342       if type(valeur) == types.InstanceType and valeur.__class__.__name__ == 'PARAMETRE':
343         if type(valeur.valeur) == types.TupleType :
344           # on a à faire à un PARAMETRE qui définit une liste d'items
345           # --> on teste sur la première car on n'accepte que les liste homogènes
346           valeur = valeur.valeur[0]
347       if type_permis == 'R':
348         return self.is_reel(valeur)
349       elif type_permis == 'I':
350         return self.is_entier(valeur)
351       elif type_permis == 'C':
352         return self.is_complexe(valeur)
353       elif type_permis == 'shell':
354         return self.is_shell(valeur)
355       elif type_permis == 'TXM':
356         if type(valeur) != types.InstanceType:
357           return type(valeur)==types.StringType
358         else:
359           #XXX je n'y touche pas pour ne pas tout casser mais il serait
360           #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('TXM'), par exemple
361           if valeur.__class__.__name__ == 'chaine' :
362             return 1
363           elif valeur.__class__.__name__ == 'PARAMETRE':
364             # il faut tester si la valeur du parametre est une string
365             return type(valeur.valeur)==types.StringType
366           else:
367             return 0
368       elif type(type_permis) == types.ClassType:
369         # on ne teste pas certains objets de type GEOM , assd, ...
370         # On appelle la méthode de classe is_object de type_permis.
371         # Comme valeur peut etre de n'importe quel type on utilise la fonction (is_object.im_func)
372         # et non pas la methode (is_object) ce qui risquerait de provoquer des erreurs
373         if type_permis.is_object.im_func(valeur):
374           return 1
375         else :
376           return self.is_object_from(valeur,type_permis)
377       else:
378         print "Type non encore géré %s" %`type_permis`
379         print self.nom,self.parent.nom,self.jdc.fichier
380
381    def isinintervalle(self,valeur,cr='non'):
382       """
383       Booléenne qui retourne 1 si la valeur passée en argument est comprise dans
384       le domaine de définition donné dans le catalogue, 0 sinon.
385       """
386       if type(valeur) not in (types.IntType,types.FloatType,types.LongType) :
387         return 1
388       else :
389         min = self.definition.val_min
390         max = self.definition.val_max
391         if min == '**': min = valeur -1
392         if max == '**': max = valeur +1
393         if valeur < min or valeur > max :
394           if cr=='oui':
395             self.cr.fatal(string.join(("La valeur :",`valeur`," du mot-clé ",self.nom,\
396                                        " est en dehors du domaine de validité [",`min`,",",`max`,"]")))
397           return 0
398         else :
399           return 1
400
401    def init_modif_up(self):
402       """
403          Propage l'état modifié au parent s'il existe et n'est l'objet 
404          lui-meme
405       """
406       if self.parent and self.parent != self :
407         self.parent.state = 'modified'
408
409    def report(self):
410       """ génère le rapport de validation de self """
411       self.cr=self.CR()
412       self.cr.debut = "Mot-clé simple : "+self.nom
413       self.cr.fin = "Fin Mot-clé simple : "+self.nom
414       self.state = 'modified'
415       try:
416         self.isvalid(cr='oui')
417       except AsException,e:
418         if CONTEXT.debug : traceback.print_exc()
419         self.cr.fatal(string.join(("Mot-clé simple : ",self.nom,str(e))))
420       return self.cr
421
422
423
424
425
426