]> SALOME platform Git repositories - tools/eficas.git/blob - Validation/V_MCSIMP.py
Salome HOME
04f8e9e275ea4938546996154de22fe86830d783
[tools/eficas.git] / Validation / V_MCSIMP.py
1 #@ MODIF V_MCSIMP Validation  DATE 09/09/2003   AUTEUR DURAND C.DURAND 
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 isvalid(self,cr='non'):
62       """
63          Cette méthode retourne un indicateur de validité de l'objet
64          de type MCSIMP 
65          
66            - 0 si l'objet est invalide
67            - 1 si l'objet est valide
68
69          Le pramètre cr permet de paramétrer le traitement. Si cr == 'oui'
70          la méthode construit également un comte-rendu de validation
71          dans self.cr qui doit avoir été créé préalablement.
72       """
73       if self.state == 'unchanged':
74         return self.valid
75       else:
76         valid = 1
77         if hasattr(self,'valid'):
78           old_valid = self.valid
79         else:
80           old_valid = None
81         v=self.valeur
82         #  presence
83         if self.isoblig() and v == None :
84           if cr == 'oui' :
85             self.cr.fatal(string.join(("Mot-clé : ",self.nom," obligatoire non valorisé")))
86           valid = 0
87         if v is None:
88           valid=0
89           if cr == 'oui' :
90              self.cr.fatal("None n'est pas une valeur autorisée")
91         else:
92           # type,into ...
93           valid = self.verif_type(val=v,cr=cr)*self.verif_into(cr=cr)*self.verif_card(cr=cr)
94           #
95           # On verifie les validateurs s'il y en a
96           #
97           if self.definition.validators and not self.definition.validators.verif(self.valeur):
98             if cr == 'oui' :
99               self.cr.fatal(string.join(("Mot-clé : ",self.nom,"devrait avoir ",self.definition.validators.info())))
100             valid=0
101           # fin des validateurs
102           #
103         self.valid = valid
104         self.state = 'unchanged'
105         # Si la validité du mot clé a changé, on le signale à l'objet parent
106         if not old_valid or old_valid != self.valid : 
107            self.init_modif_up()
108         return self.valid
109
110    def isoblig(self):
111       """ indique si le mot-clé est obligatoire
112       """
113       return self.definition.statut=='o'
114
115    def verif_card(self,cr='non'):
116       """ 
117          un mot-clé simple ne peut etre répété :
118          la cardinalité ici s'entend par la vérification que le nombre d'arguments de self.valeur
119          est bien compris entre self.min et self.max dans le cas où il s'agit d'une liste
120       """
121       card = 1
122       min=self.definition.min
123       max=self.definition.max
124       if type(self.valeur) in (types.ListType,types.TupleType) and 'C' not in self.definition.type :
125         if len(self.valeur) < min or len(self.valeur)>max:
126           if cr == 'oui':
127             self.cr.fatal("Nombre d'arguments %s incorrects pour %s (min = %s, max = %s)" %(`self.valeur`,self.nom,min,max))
128           card = 0
129       else:
130         if self.valeur == None :
131           if min >= 1 :
132             # on n'a pas d'objet et on en attend au moins un
133             card=0
134         else :
135           if min > 1:
136             # on n'a qu'un objet et on en attend plus d'1
137             card = 0
138       return card
139
140    def verif_type(self,val=None,cr='non'):
141       """
142          FONCTION :
143          Cette methode verifie que le type de l'argument val est en conformite avec celui 
144          qui est declare dans la definition du mot cle simple.
145          Elle a plusieurs modes de fonctionnement liés à la valeur de cr.
146          Si cr vaut 'oui' : elle remplit le compte-rendu self.cr sinon elle ne le remplit pas.
147
148          PARAMETRE DE RETOUR :
149          Cette méthode retourne une valeur booléenne qui vaut 1 si le type de val est correct ou 0 sinon
150          
151       """
152       valeur = val
153       if valeur == None :
154         if cr == 'oui':
155           self.cr.fatal("None n'est pas une valeur autorisée")
156         return 0
157       if type(valeur) == types.TupleType:
158         # on peut avoir à faire à un complexe ou une liste de valeurs ...
159         if self.is_complexe(valeur) : return 1
160         else:
161           for val in valeur:
162             if not self.verif_type(val=val,cr=cr) : return 0
163           return 1
164       elif type(valeur) == types.ListType:
165         for val in valeur:
166             if not self.verif_type(val=val,cr=cr) : return 0
167         return 1
168       else:
169         # on n'a pas de tuple ...il faut tester sur tous les types ou les valeurs possibles
170         # XXX Pourquoi into est il traité ici et pas seulement dans verif_into ???
171         if self.definition.into != None :
172           try:
173             if valeur in self.definition.into :
174               return 1
175             else:
176               if cr == 'oui':
177                 self.cr.fatal("%s n'est pas une valeur autorisée" %valeur)
178               return 0
179           except:
180             print "problème avec :",self.nom
181             return 0
182         for type_permis in self.definition.type:
183           if self.compare_type(valeur,type_permis) : return 1
184         # si on sort de la boucle précédente par ici c'est que l'on n'a trouvé aucun type valable --> valeur refusée
185         if cr =='oui':
186           self.cr.fatal("%s n'est pas d'un type autorisé" %`valeur`)
187         return 0
188
189    def verif_into(self,cr='non'):
190       """
191       Vérifie si la valeur de self est bien dans l'ensemble discret de valeurs
192       donné dans le catalogue derrière l'attribut into ou vérifie que valeur est bien compris
193       entre val_min et val_max
194       """
195       if self.definition.into == None :
196         #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle)
197         if type(self.valeur)==types.TupleType :
198           test = 1
199           for val in self.valeur :
200             if type(val)!=types.StringType and type(val)!=types.InstanceType:
201               test = test*self.isinintervalle(val,cr=cr)
202           return test
203         else :
204           val = self.valeur
205           if type(val)!=types.StringType and type(val)!=types.InstanceType:
206             return self.isinintervalle(self.valeur,cr=cr)
207           else :
208             return 1
209       else :
210         # on est dans le cas d'un ensemble discret de valeurs possibles (into)
211         if type(self.valeur) == types.TupleType :
212           for e in self.valeur:
213             if e not in self.definition.into:
214               if cr=='oui':
215                 self.cr.fatal(string.join(("La valeur :",`e`," n'est pas permise pour le mot-clé :",self.nom)))
216               return 0
217         else:
218           if self.valeur == None or self.valeur not in self.definition.into:
219             if cr=='oui':
220               self.cr.fatal(string.join(("La valeur :",`self.valeur`," n'est pas permise pour le mot-clé :",self.nom)))
221             return 0
222         return 1
223
224    def is_complexe(self,valeur):
225       """ Retourne 1 si valeur est un complexe, 0 sinon """
226       if type(valeur) == types.StringType :
227         # on teste une valeur issue d'une entry (valeur saisie depuis EFICAS)
228         #XXX Il serait peut etre plus judicieux d'appeler une méthode de self.jdc
229         #XXX qui retournerait l'objet résultat de l'évaluation
230         #XXX ou meme de faire cette evaluation a l'exterieur de cette classe ??
231         if not self.jdc :return 0
232         try :
233           valeur = eval(valeur,self.jdc.g_context)
234         except:
235           return 0
236       if type(valeur) == types.InstanceType :
237         #XXX je n'y touche pas pour ne pas tout casser mais il serait
238         #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('C'), par exemple
239         if valeur.__class__.__name__ in ('EVAL','complexe'):
240           return 1
241         elif valeur.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
242           # il faut tester si la valeur du parametre est un entier
243           #XXX ne serait ce pas plutot complexe ???? sinon expliquer
244           return self.is_entier(valeur.valeur)
245         else:
246           print "Objet non reconnu dans is_complexe %s" %`valeur`
247           return 0
248       # Pour permettre l'utilisation de complexes Python
249       #elif type(valeur) == types.ComplexType:
250         #return 1
251       elif type(valeur) != types.TupleType :
252         return 0
253       else:
254         if len(valeur) != 3 :
255           return 0
256         else:
257           if type(valeur[0]) != types.StringType : return 0
258           if string.strip(valeur[0]) not in ('RI','MP'):
259             return 0
260           else:
261             if not self.is_reel(valeur[1]) or not self.is_reel(valeur[2]) : return 0
262             else: return 1
263
264    def is_reel(self,valeur):
265       """
266       Retourne 1 si valeur est un reel, 0 sinon
267       """
268       if type(valeur) == types.StringType :
269         # on teste une valeur issue d'une entry (valeur saisie depuis EFICAS)
270         if not self.jdc :return 0
271         try :
272           valeur = eval(valeur,self.jdc.g_context)
273         except:
274           return 0
275       if type(valeur) == types.InstanceType :
276         #XXX je n'y touche pas pour ne pas tout casser mais il serait
277         #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('R'), par exemple
278         #XXX ou valeur.is_reel()
279         #XXX ou encore valeur.compare(self.is_reel)
280         if valeur.__class__.__name__ in ('EVAL','reel') :
281           return 1
282         elif valeur.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
283           # il faut tester si la valeur du parametre est un réel
284           return self.is_reel(valeur.valeur)
285         else:
286           print "Objet non reconnu dans is_reel %s" %`valeur`
287           return 0
288       elif type(valeur) not in (types.IntType,types.FloatType,types.LongType):
289         # ce n'est pas un réel
290         return 0
291       else:
292         return 1
293
294    def is_entier(self,valeur):
295       """ Retourne 1 si valeur est un entier, 0 sinon """
296       if type(valeur) == types.StringType :
297         # on teste une valeur issue d'une entry (valeur saisie depuis EFICAS)
298         if not self.jdc :return 0
299         try :
300           valeur = eval(valeur,self.jdc.g_context)
301         except:
302           return 0
303       if type(valeur) == types.InstanceType :
304         #XXX je n'y touche pas pour ne pas tout casser mais il serait
305         #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('I'), par exemple
306         if valeur.__class__.__name__ in ('EVAL','entier') :
307           return 1
308         elif valeur.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
309           # il faut tester si la valeur du parametre est un entier
310           return self.is_entier(valeur.valeur)
311         else:
312           print "Objet non reconnu dans is_reel %s" %`valeur`
313           return 0
314       elif type(valeur) not in (types.IntType,types.LongType):
315         # ce n'est pas un entier
316         return 0
317       else:
318         return 1
319         
320    def is_shell(self,valeur):
321       """ 
322           Retourne 1 si valeur est un shell, 0 sinon
323           Pour l'instant aucune vérification n'est faite
324           On impose juste que valeur soit une string
325       """
326       if type(valeur) != types.StringType:
327         return 0
328       else:
329         return 1
330
331    def is_object_from(self,objet,classe):
332       """ 
333            Retourne 1 si valeur est un objet de la classe classe ou d'une sous-classe de classe,
334            0 sinon 
335       """
336       if type(objet) != types.InstanceType :
337         if type(objet) == types.StringType:
338           if not self.jdc :return 0
339           try :
340             objet = eval(objet,self.jdc.g_context)
341             if type(objet) != types.InstanceType : return 0
342           except:
343             return 0
344         else:
345           return 0
346       if not objet.__class__ == classe and not issubclass(objet.__class__,classe):
347         return 0
348       else:
349         return 1
350
351    def compare_type(self,valeur,type_permis):
352       """
353           Fonction booléenne qui retourne 1 si valeur est du type type_permis, 0 sinon
354       """
355       if type(valeur) == types.InstanceType and valeur.__class__.__name__ == 'PARAMETRE':
356         if type(valeur.valeur) == types.TupleType :
357           # on a à faire à un PARAMETRE qui définit une liste d'items
358           # --> on teste sur la première car on n'accepte que les liste homogènes
359           valeur = valeur.valeur[0]
360       if type_permis == 'R':
361         return self.is_reel(valeur)
362       elif type_permis == 'I':
363         return self.is_entier(valeur)
364       elif type_permis == 'C':
365         return self.is_complexe(valeur)
366       elif type_permis == 'shell':
367         return self.is_shell(valeur)
368       elif type_permis == 'TXM':
369         if type(valeur) != types.InstanceType:
370           return type(valeur)==types.StringType
371         else:
372           #XXX je n'y touche pas pour ne pas tout casser mais il serait
373           #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('TXM'), par exemple
374           if valeur.__class__.__name__ == 'chaine' :
375             return 1
376           elif valeur.__class__.__name__ == 'PARAMETRE':
377             # il faut tester si la valeur du parametre est une string
378             return type(valeur.valeur)==types.StringType
379           else:
380             return 0
381       elif type(type_permis) == types.ClassType:
382         # on ne teste pas certains objets de type GEOM , assd, ...
383         # On appelle la méthode de classe is_object de type_permis.
384         # Comme valeur peut etre de n'importe quel type on utilise la fonction (is_object.im_func)
385         # et non pas la methode (is_object) ce qui risquerait de provoquer des erreurs
386         if type_permis.is_object.im_func(valeur):
387           return 1
388         else :
389           return self.is_object_from(valeur,type_permis)
390       else:
391         print "Type non encore géré %s" %`type_permis`
392         print self.nom,self.parent.nom,self.jdc.fichier
393
394    def isinintervalle(self,valeur,cr='non'):
395       """
396       Booléenne qui retourne 1 si la valeur passée en argument est comprise dans
397       le domaine de définition donné dans le catalogue, 0 sinon.
398       """
399       if type(valeur) not in (types.IntType,types.FloatType,types.LongType) :
400         return 1
401       else :
402         min = self.definition.val_min
403         max = self.definition.val_max
404         if min == '**': min = valeur -1
405         if max == '**': max = valeur +1
406         if valeur < min or valeur > max :
407           if cr=='oui':
408             self.cr.fatal(string.join(("La valeur :",`valeur`," du mot-clé ",self.nom,\
409                                        " est en dehors du domaine de validité [",`min`,",",`max`,"]")))
410           return 0
411         else :
412           return 1
413
414    def init_modif_up(self):
415       """
416          Propage l'état modifié au parent s'il existe et n'est l'objet 
417          lui-meme
418       """
419       if self.parent and self.parent != self :
420         self.parent.state = 'modified'
421
422    def report(self):
423       """ génère le rapport de validation de self """
424       self.cr=self.CR()
425       self.cr.debut = "Mot-clé simple : "+self.nom
426       self.cr.fin = "Fin Mot-clé simple : "+self.nom
427       self.state = 'modified'
428       try:
429         self.isvalid(cr='oui')
430       except AsException,e:
431         if CONTEXT.debug : traceback.print_exc()
432         self.cr.fatal(string.join(("Mot-clé simple : ",self.nom,str(e))))
433       return self.cr
434
435
436
437
438
439