]> SALOME platform Git repositories - tools/eficas.git/blob - Validation/V_MCSIMP.py
Salome HOME
CCAR: Mise a niveau ASter 7.2.11 + correction diverses validation mots cles
[tools/eficas.git] / Validation / V_MCSIMP.py
1 #@ MODIF V_MCSIMP Validation  DATE 06/10/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 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            valid = self.verif_type(val=v,cr=cr)
105            valid=valid*self.verif_into(cr=cr)
106            valid=valid*self.verif_card(cr=cr)
107            #
108            # On verifie les validateurs s'il y en a et si necessaire (valid == 1)
109            #
110            if valid and self.definition.validators and not self.definition.validators.verif(self.valeur):
111               if cr == 'oui' :
112                  self.cr.fatal(string.join(("Mot-clé : ",self.nom,"devrait avoir ",self.definition.validators.info())))
113               valid=0
114            # fin des validateurs
115            #
116
117         self.set_valid(valid)
118         return self.valid
119
120    def isoblig(self):
121       """ indique si le mot-clé est obligatoire
122       """
123       return self.definition.statut=='o'
124
125    def verif_card(self,cr='non'):
126       """ 
127          un mot-clé simple ne peut etre répété :
128            la cardinalité ici s'entend par la vérification que le nombre d'arguments de self.valeur
129            est bien compris entre self.min et self.max dans le cas où il s'agit d'une liste
130       """
131       card = 1
132       min=self.definition.min
133       max=self.definition.max
134
135       if type(self.valeur) == types.TupleType and not self.valeur[0] in ('RI','MP') or type(self.valeur) == types.ListType:
136         length=len(self.valeur)
137       else:
138         if self.valeur == None :
139            length=0
140         else:
141            length=1
142
143       if length < min or length >max:
144          if cr == 'oui':
145             self.cr.fatal("Nombre d'arguments de %s incorrect pour %s (min = %s, max = %s)" %(`self.valeur`,self.nom,min,max))
146          card = 0
147       return card
148
149    def verif_type(self,val=None,cr='non'):
150       """
151         FONCTION :
152          Cette methode verifie que le type de l'argument val est en conformite avec celui 
153          qui est declare dans la definition du mot cle simple.
154          Elle a plusieurs modes de fonctionnement liés à la valeur de cr.
155          Si cr vaut 'oui' : elle remplit le compte-rendu self.cr sinon elle ne le remplit pas.
156         PARAMETRE DE RETOUR :
157          Cette méthode retourne une valeur booléenne qui vaut 1 si le type de val est correct ou 0 sinon
158          
159       """
160       valeur = val
161       if valeur == None :
162         if cr == 'oui':
163           self.cr.fatal("None n'est pas une valeur autorisée")
164         return 0
165
166       if type(valeur) == types.TupleType and not valeur[0] in ('RI','MP') or type(valeur) == types.ListType:
167         # Ici on a identifié une liste de valeurs
168         for val in valeur:
169             if not self.verif_type(val=val,cr=cr) : return 0
170         return 1
171
172       # Ici, valeur est un scalaire ...il faut tester sur tous les types ou les valeurs possibles
173
174       for type_permis in self.definition.type:
175           if self.compare_type(valeur,type_permis) : return 1
176
177       # 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
178       if cr =='oui':
179           self.cr.fatal("%s n'est pas d'un type autorisé" %`valeur`)
180       return 0
181
182    def verif_into(self,cr='non'):
183       """
184       Vérifie si la valeur de self est bien dans l'ensemble discret de valeurs
185       donné dans le catalogue derrière l'attribut into ou vérifie que valeur est bien compris
186       entre val_min et val_max
187       """
188       if self.definition.into == None :
189         #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle)
190         if self.definition.val_min == '**' and self.definition.val_max == '**':
191            # L'intervalle est infini, on ne fait pas de test
192            return 1
193         #if type(self.valeur) in (types.ListType,types.TupleType) :
194         if type(self.valeur) == types.TupleType and not self.valeur[0] in ('RI','MP') or type(self.valeur) == types.ListType:
195           # Cas d'une liste de valeurs
196           test = 1
197           for val in self.valeur :
198             if type(val) != types.StringType and type(val) != types.InstanceType:
199               test = test*self.isinintervalle(val,cr=cr)
200           return test
201         else :
202           # Cas d'un scalaire
203           val = self.valeur
204           if type(val)!=types.StringType and type(val)!=types.InstanceType:
205             return self.isinintervalle(self.valeur,cr=cr)
206           else :
207             return 1
208       else :
209         # on est dans le cas d'un ensemble discret de valeurs possibles (into)
210         #if type(self.valeur) in (types.ListType,types.TupleType) :
211         if type(self.valeur) == types.TupleType and not self.valeur[0] in ('RI','MP') or type(self.valeur) == types.ListType:
212           # Cas d'une liste de valeur
213           for e in self.valeur:
214             if e not in self.definition.into:
215               if cr=='oui':
216                 self.cr.fatal(string.join(("La valeur :",`e`," n'est pas permise pour le mot-clé :",self.nom)))
217               return 0
218         else:
219           if self.valeur not in self.definition.into:
220             if cr=='oui':
221               self.cr.fatal(string.join(("La valeur :",`self.valeur`," n'est pas permise pour le mot-clé :",self.nom)))
222             return 0
223         return 1
224
225    def is_complexe(self,valeur):
226       """ Retourne 1 si valeur est un complexe, 0 sinon """
227       if type(valeur) == types.InstanceType :
228         #XXX je n'y touche pas pour ne pas tout casser mais il serait
229         #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('C'), par exemple
230         if valeur.__class__.__name__ in ('EVAL','complexe','PARAMETRE_EVAL'):
231           return 1
232         elif valeur.__class__.__name__ in ('PARAMETRE',):
233           # il faut tester si la valeur du parametre est un complexe
234           return self.is_complexe(valeur.valeur)
235         else:
236           print "Objet non reconnu dans is_complexe %s" %`valeur`
237           return 0
238       # Pour permettre l'utilisation de complexes Python
239       #elif type(valeur) == types.ComplexType:
240         #return 1
241       elif type(valeur) != types.TupleType :
242         # On n'autorise pas les listes pour les complexes
243         return 0
244       elif len(valeur) != 3:return 0
245       else:
246           # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
247           # valeur suivie de 2 reels.
248           try:
249              if string.strip(valeur[0]) in ('RI','MP') and self.is_reel(valeur[1]) and self.is_reel(valeur[2]):
250                 return 1
251           except:
252              return 0
253
254    def is_reel(self,valeur):
255       """
256       Retourne 1 si valeur est un reel, 0 sinon
257       """
258       if type(valeur) == types.InstanceType :
259         #XXX je n'y touche pas pour ne pas tout casser mais il serait
260         #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('R'), par exemple
261         #XXX ou valeur.is_reel()
262         #XXX ou encore valeur.compare(self.is_reel)
263         if valeur.__class__.__name__ in ('EVAL','reel','PARAMETRE_EVAL') :
264           return 1
265         elif valeur.__class__.__name__ in ('PARAMETRE',):
266           # il faut tester si la valeur du parametre est un réel
267           return self.is_reel(valeur.valeur)
268         else:
269           print "Objet non reconnu dans is_reel %s" %`valeur`
270           return 0
271       elif type(valeur) not in (types.IntType,types.FloatType,types.LongType):
272         # ce n'est pas un réel
273         return 0
274       else:
275         return 1
276
277    def is_entier(self,valeur):
278       """ Retourne 1 si valeur est un entier, 0 sinon """
279       if type(valeur) == types.InstanceType :
280         #XXX je n'y touche pas pour ne pas tout casser mais il serait
281         #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('I'), par exemple
282         if valeur.__class__.__name__ in ('EVAL','entier','PARAMETRE_EVAL') :
283           return 1
284         elif valeur.__class__.__name__ in ('PARAMETRE',):
285           # il faut tester si la valeur du parametre est un entier
286           return self.is_entier(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.LongType):
291         # ce n'est pas un entier
292         return 0
293       else:
294         return 1
295
296    def is_shell(self,valeur):
297       """ 
298           Retourne 1 si valeur est un shell, 0 sinon
299           Pour l'instant aucune vérification n'est faite
300           On impose juste que valeur soit une string
301       """
302       if type(valeur) != types.StringType:
303         return 0
304       else:
305         return 1
306
307    def is_object_from(self,objet,classe):
308       """
309            Retourne 1 si valeur est un objet de la classe classe ou d'une
310            sous-classe de classe, 0 sinon
311       """
312       if type(objet) != types.InstanceType :
313           return 0
314       if not objet.__class__ == classe and not issubclass(objet.__class__,classe):
315         return 0
316       else:
317         return 1
318
319    def compare_type(self,valeur,type_permis):
320       """
321           Fonction booléenne qui retourne 1 si valeur est du type type_permis, 0 sinon
322       """
323       if type(valeur) == types.InstanceType and valeur.__class__.__name__ == 'PARAMETRE':
324         if type(valeur.valeur) == types.TupleType :
325           # on a à faire à un PARAMETRE qui définit une liste d'items
326           # --> on teste sur la première car on n'accepte que les liste homogènes
327           valeur = valeur.valeur[0]
328       if type_permis == 'R':
329         return self.is_reel(valeur)
330       elif type_permis == 'I':
331         return self.is_entier(valeur)
332       elif type_permis == 'C':
333         return self.is_complexe(valeur)
334       elif type_permis == 'shell':
335         return self.is_shell(valeur)
336       elif type_permis == 'TXM':
337         if type(valeur) != types.InstanceType:
338           return type(valeur)==types.StringType
339         else:
340           #XXX je n'y touche pas pour ne pas tout casser mais il serait
341           #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('TXM'), par exemple
342           if valeur.__class__.__name__ == 'chaine' :
343             return 1
344           elif valeur.__class__.__name__ == 'PARAMETRE':
345             # il faut tester si la valeur du parametre est une string
346             return type(valeur.valeur)==types.StringType
347           else:
348             return 0
349       elif type(type_permis) == types.ClassType:
350         # on ne teste pas certains objets de type GEOM , assd, ...
351         # On appelle la méthode de classe is_object de type_permis.
352         # Comme valeur peut etre de n'importe quel type on utilise la fonction (is_object.im_func)
353         # et non pas la methode (is_object) ce qui risquerait de provoquer des erreurs
354         if type_permis.is_object.im_func(valeur):
355           return 1
356         else :
357           return self.is_object_from(valeur,type_permis)
358       else:
359         print "Type non encore géré %s" %`type_permis`
360         print self.nom,self.parent.nom,self.jdc.fichier
361
362    def isinintervalle(self,valeur,cr='non'):
363       """
364       Booléenne qui retourne 1 si la valeur passée en argument est comprise dans
365       le domaine de définition donné dans le catalogue, 0 sinon.
366       """
367       if type(valeur) not in (types.IntType,types.FloatType,types.LongType) :
368         return 1
369       else :
370         min = self.definition.val_min
371         max = self.definition.val_max
372         if min == '**': min = valeur -1
373         if max == '**': max = valeur +1
374         if valeur < min or valeur > max :
375           if cr=='oui':
376             self.cr.fatal(string.join(("La valeur :",`valeur`," du mot-clé ",self.nom,\
377                                        " est en dehors du domaine de validité [",`min`,",",`max`,"]")))
378           return 0
379         else :
380           return 1
381
382    def init_modif_up(self):
383       """
384          Propage l'état modifié au parent s'il existe et n'est l'objet 
385          lui-meme
386       """
387       if self.parent and self.parent != self :
388         self.parent.state = 'modified'
389
390    def report(self):
391       """ génère le rapport de validation de self """
392       self.cr=self.CR()
393       self.cr.debut = "Mot-clé simple : "+self.nom
394       self.cr.fin = "Fin Mot-clé simple : "+self.nom
395       self.state = 'modified'
396       try:
397         self.isvalid(cr='oui')
398       except AsException,e:
399         if CONTEXT.debug : traceback.print_exc()
400         self.cr.fatal(string.join(("Mot-clé simple : ",self.nom,str(e))))
401       return self.cr
402
403
404
405
406
407