]> SALOME platform Git repositories - tools/eficas.git/blob - Validation/V_MCSIMP.py
Salome HOME
PN : pour les clefs documentaires
[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 que l'on n'a trouvé aucun type valable --> valeur refusée
175       if cr =='oui':
176           self.cr.fatal("%s n'est pas d'un type autorisé" %`valeur`)
177       return 0
178
179    def verif_into(self,cr='non'):
180       """
181       Vérifie si la valeur de self est bien dans l'ensemble discret de valeurs
182       donné dans le catalogue derrière l'attribut into ou vérifie que valeur est bien compris
183       entre val_min et val_max
184       """
185       if self.definition.into == None :
186         #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle)
187         if self.definition.val_min == '**' and self.definition.val_max == '**':
188            # L'intervalle est infini, on ne fait pas de test
189            return 1
190         #if type(self.valeur) in (types.ListType,types.TupleType) :
191         if type(self.valeur) == types.TupleType and not self.valeur[0] in ('RI','MP') or type(self.valeur) == types.ListType:
192           # Cas d'une liste de valeurs
193           test = 1
194           for val in self.valeur :
195             if type(val) != types.StringType and type(val) != types.InstanceType:
196               test = test*self.isinintervalle(val,cr=cr)
197           return test
198         else :
199           # Cas d'un scalaire
200           val = self.valeur
201           if type(val)!=types.StringType and type(val)!=types.InstanceType:
202             return self.isinintervalle(self.valeur,cr=cr)
203           else :
204             return 1
205       else :
206         # on est dans le cas d'un ensemble discret de valeurs possibles (into)
207         #if type(self.valeur) in (types.ListType,types.TupleType) :
208         if type(self.valeur) == types.TupleType and not self.valeur[0] in ('RI','MP') or type(self.valeur) == types.ListType:
209           # Cas d'une liste de valeur
210           for e in self.valeur:
211             if e not in self.definition.into:
212               if cr=='oui':
213                 self.cr.fatal(string.join(("La valeur :",`e`," n'est pas permise pour le mot-clé :",self.nom)))
214               return 0
215         else:
216           if self.valeur not in self.definition.into:
217             if cr=='oui':
218               self.cr.fatal(string.join(("La valeur :",`self.valeur`," n'est pas permise pour le mot-clé :",self.nom)))
219             return 0
220         return 1
221
222    def is_complexe(self,valeur):
223       """ Retourne 1 si valeur est un complexe, 0 sinon """
224       if type(valeur) == types.InstanceType :
225         #XXX je n'y touche pas pour ne pas tout casser mais il serait
226         #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('C'), par exemple
227         if valeur.__class__.__name__ in ('EVAL','complexe','PARAMETRE_EVAL'):
228           return 1
229         elif valeur.__class__.__name__ in ('PARAMETRE',):
230           # il faut tester si la valeur du parametre est un complexe
231           return self.is_complexe(valeur.valeur)
232         else:
233           print "Objet non reconnu dans is_complexe %s" %`valeur`
234           return 0
235       # Pour permettre l'utilisation de complexes Python
236       #elif type(valeur) == types.ComplexType:
237         #return 1
238       elif type(valeur) != types.TupleType :
239         # On n'autorise pas les listes pour les complexes
240         return 0
241       elif len(valeur) != 3:return 0
242       else:
243           # Un complexe doit etre un tuple de longueur 3 avec 'RI' ou 'MP' comme premiere
244           # valeur suivie de 2 reels.
245           try:
246              if string.strip(valeur[0]) in ('RI','MP') and self.is_reel(valeur[1]) and self.is_reel(valeur[2]):
247                 return 1
248           except:
249              return 0
250
251    def is_reel(self,valeur):
252       """
253       Retourne 1 si valeur est un reel, 0 sinon
254       """
255       if type(valeur) == types.InstanceType :
256         #XXX je n'y touche pas pour ne pas tout casser mais il serait
257         #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('R'), par exemple
258         #XXX ou valeur.is_reel()
259         #XXX ou encore valeur.compare(self.is_reel)
260         if valeur.__class__.__name__ in ('EVAL','reel','PARAMETRE_EVAL') :
261           return 1
262         elif valeur.__class__.__name__ in ('PARAMETRE',):
263           # il faut tester si la valeur du parametre est un réel
264           return self.is_reel(valeur.valeur)
265         else:
266           print "Objet non reconnu dans is_reel %s" %`valeur`
267           return 0
268       elif type(valeur) not in (types.IntType,types.FloatType,types.LongType):
269         # ce n'est pas un réel
270         return 0
271       else:
272         return 1
273
274    def is_entier(self,valeur):
275       """ Retourne 1 si valeur est un entier, 0 sinon """
276       if type(valeur) == types.InstanceType :
277         #XXX je n'y touche pas pour ne pas tout casser mais il serait
278         #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('I'), par exemple
279         if valeur.__class__.__name__ in ('EVAL','entier','PARAMETRE_EVAL') :
280           return 1
281         elif valeur.__class__.__name__ in ('PARAMETRE',):
282           # il faut tester si la valeur du parametre est un entier
283           return self.is_entier(valeur.valeur)
284         else:
285           print "Objet non reconnu dans is_reel %s" %`valeur`
286           return 0
287       elif type(valeur) not in (types.IntType,types.LongType):
288         # ce n'est pas un entier
289         return 0
290       else:
291         return 1
292
293    def is_shell(self,valeur):
294       """ 
295           Retourne 1 si valeur est un shell, 0 sinon
296           Pour l'instant aucune vérification n'est faite
297           On impose juste que valeur soit une string
298       """
299       if type(valeur) != types.StringType:
300         return 0
301       else:
302         return 1
303
304    def is_object_from(self,objet,classe):
305       """
306            Retourne 1 si valeur est un objet de la classe classe ou d'une
307            sous-classe de classe, 0 sinon
308       """
309       if type(objet) != types.InstanceType :
310           return 0
311       if not objet.__class__ == classe and not issubclass(objet.__class__,classe):
312         return 0
313       else:
314         return 1
315
316    def compare_type(self,valeur,type_permis):
317       """
318           Fonction booléenne qui retourne 1 si valeur est du type type_permis, 0 sinon
319       """
320       if type(valeur) == types.InstanceType and valeur.__class__.__name__ == 'PARAMETRE':
321         if type(valeur.valeur) == types.TupleType :
322           # on a à faire à un PARAMETRE qui définit une liste d'items
323           # --> on teste sur la première car on n'accepte que les liste homogènes
324           valeur = valeur.valeur[0]
325       if type_permis == 'R':
326         return self.is_reel(valeur)
327       elif type_permis == 'I':
328         return self.is_entier(valeur)
329       elif type_permis == 'C':
330         return self.is_complexe(valeur)
331       elif type_permis == 'shell':
332         return self.is_shell(valeur)
333       elif type_permis == 'TXM':
334         if type(valeur) != types.InstanceType:
335           return type(valeur)==types.StringType
336         else:
337           #XXX je n'y touche pas pour ne pas tout casser mais il serait
338           #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('TXM'), par exemple
339           if valeur.__class__.__name__ == 'chaine' :
340             return 1
341           elif valeur.__class__.__name__ == 'PARAMETRE':
342             # il faut tester si la valeur du parametre est une string
343             return type(valeur.valeur)==types.StringType
344           else:
345             return 0
346       elif type(type_permis) == types.ClassType:
347         # on ne teste pas certains objets de type GEOM , assd, ...
348         # On appelle la méthode de classe is_object de type_permis.
349         # Comme valeur peut etre de n'importe quel type on utilise la fonction (is_object.im_func)
350         # et non pas la methode (is_object) ce qui risquerait de provoquer des erreurs
351         if type_permis.is_object.im_func(valeur):
352           return 1
353         else :
354           return self.is_object_from(valeur,type_permis)
355       else:
356         print "Type non encore géré %s" %`type_permis`
357         print self.nom,self.parent.nom,self.jdc.fichier
358
359    def isinintervalle(self,valeur,cr='non'):
360       """
361       Booléenne qui retourne 1 si la valeur passée en argument est comprise dans
362       le domaine de définition donné dans le catalogue, 0 sinon.
363       """
364       if type(valeur) not in (types.IntType,types.FloatType,types.LongType) :
365         return 1
366       else :
367         min = self.definition.val_min
368         max = self.definition.val_max
369         if min == '**': min = valeur -1
370         if max == '**': max = valeur +1
371         if valeur < min or valeur > max :
372           if cr=='oui':
373             self.cr.fatal(string.join(("La valeur :",`valeur`," du mot-clé ",self.nom,\
374                                        " est en dehors du domaine de validité [",`min`,",",`max`,"]")))
375           return 0
376         else :
377           return 1
378
379    def init_modif_up(self):
380       """
381          Propage l'état modifié au parent s'il existe et n'est l'objet 
382          lui-meme
383       """
384       if self.parent and self.parent != self :
385         self.parent.state = 'modified'
386
387    def report(self):
388       """ génère le rapport de validation de self """
389       self.cr=self.CR()
390       self.cr.debut = "Mot-clé simple : "+self.nom
391       self.cr.fin = "Fin Mot-clé simple : "+self.nom
392       self.state = 'modified'
393       try:
394         self.isvalid(cr='oui')
395       except AsException,e:
396         if CONTEXT.debug : traceback.print_exc()
397         self.cr.fatal(string.join(("Mot-clé simple : ",self.nom,str(e))))
398       return self.cr
399
400
401
402
403
404