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