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