Salome HOME
CCAR: ajout des fichiers macros
[tools/eficas.git] / Validation / V_MCSIMP.py
1 # -*- coding: utf-8 -*-
2 #@ MODIF V_MCSIMP Validation  DATE 17/08/2004   AUTEUR DURAND C.DURAND 
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    Ce module contient la classe mixin MCSIMP qui porte les méthodes
24    nécessaires pour réaliser la validation d'un objet de type MCSIMP
25    dérivé de OBJECT.
26
27    Une classe mixin porte principalement des traitements et est
28    utilisée par héritage multiple pour composer les traitements.
29 """
30 # Modules Python
31 import string,types
32 import traceback
33
34 # Modules EFICAS
35 from Noyau import N_CR
36 from Noyau.N_Exception import AsException
37
38 class MCSIMP:
39    """
40       COMMENTAIRE CCAR
41         Cette classe est quasiment identique à la classe originale d'EFICAS
42         a part quelques changements cosmétiques et des chagements pour la
43         faire fonctionner de facon plus autonome par rapport à l'environnement
44         EFICAS
45  
46         A mon avis, il faudrait aller plus loin et réduire les dépendances
47         amont au strict nécessaire.
48
49         - Est il indispensable de faire l'évaluation de la valeur dans le contexte
50           du jdc dans cette classe.
51
52         - Ne pourrait on pas doter les objets en présence des méthodes suffisantes
53           pour éviter les tests un peu particuliers sur GEOM, PARAMETRE et autres. J'ai
54           d'ailleurs modifié la classe pour éviter l'import de GEOM
55    """
56
57    CR=N_CR.CR
58    
59    def __init__(self):
60       self.state='undetermined'
61
62    def get_valid(self):
63        if hasattr(self,'valid'):
64           return self.valid
65        else:
66           self.valid=None
67           return None
68
69    def set_valid(self,valid):
70        old_valid=self.get_valid()
71        self.valid = valid
72        self.state = 'unchanged'
73        if not old_valid or old_valid != self.valid :
74            self.init_modif_up()
75
76    def isvalid(self,cr='non'):
77       """
78          Cette méthode retourne un indicateur de validité de l'objet de type MCSIMP
79
80            - 0 si l'objet est invalide
81            - 1 si l'objet est valide
82
83          Le paramètre cr permet de paramétrer le traitement. Si cr == 'oui'
84          la méthode construit également un comte-rendu de validation
85          dans self.cr qui doit avoir été créé préalablement.
86       """
87       if self.state == 'unchanged':
88         return self.valid
89       else:
90         valid = 1
91         v=self.valeur
92         #  verification presence
93         if self.isoblig() and v == None :
94           if cr == 'oui' :
95             self.cr.fatal(string.join(("Mot-clé : ",self.nom," obligatoire non valorisé")))
96           valid = 0
97
98         if v is None:
99            valid=0
100            if cr == 'oui' :
101               self.cr.fatal("None n'est pas une valeur autorisée")
102         else:
103            # type,into ...
104            valid = self.verif_type(val=v,cr=cr)*self.verif_into(cr=cr)*self.verif_card(cr=cr)
105            #
106            # On verifie les validateurs s'il y en a et si necessaire (valid == 1)
107            #
108            if valid and self.definition.validators and not self.definition.validators.verif(self.valeur):
109               if cr == 'oui' :
110                  self.cr.fatal(string.join(("Mot-clé : ",self.nom,"devrait avoir ",self.definition.validators.info())))
111               valid=0
112            # fin des validateurs
113            #
114
115         self.set_valid(valid)
116         return self.valid
117
118    def isoblig(self):
119       """ indique si le mot-clé est obligatoire
120       """
121       return self.definition.statut=='o'
122
123    def verif_card(self,cr='non'):
124       """ 
125          un mot-clé simple ne peut etre répété :
126            la cardinalité ici s'entend par la vérification que le nombre d'arguments de self.valeur
127            est bien compris entre self.min et self.max dans le cas où il s'agit d'une liste
128       """
129       card = 1
130       min=self.definition.min
131       max=self.definition.max
132
133       if type(self.valeur) == types.TupleType and not self.valeur[0] in ('RI','MP') or type(self.valeur) == types.ListType:
134         length=len(self.valeur)
135       else:
136         if self.valeur == None :
137            length=0
138         else:
139            length=1
140
141       if length < min or length >max:
142          if cr == 'oui':
143             self.cr.fatal("Nombre d'arguments de %s incorrect pour %s (min = %s, max = %s)" %(`self.valeur`,self.nom,min,max))
144          card = 0
145       return card
146
147    def verif_type(self,val=None,cr='non'):
148       """
149         FONCTION :
150          Cette methode verifie que le type de l'argument val est en conformite avec celui 
151          qui est declare dans la definition du mot cle simple.
152          Elle a plusieurs modes de fonctionnement liés à la valeur de cr.
153          Si cr vaut 'oui' : elle remplit le compte-rendu self.cr sinon elle ne le remplit pas.
154         PARAMETRE DE RETOUR :
155          Cette méthode retourne une valeur booléenne qui vaut 1 si le type de val est correct ou 0 sinon
156          
157       """
158       valeur = val
159       if valeur == None :
160         if cr == 'oui':
161           self.cr.fatal("None n'est pas une valeur autorisée")
162         return 0
163
164       if type(valeur) == types.TupleType and not valeur[0] in ('RI','MP') or type(valeur) == types.ListType:
165         # Ici on a identifié une liste de valeurs
166         for val in valeur:
167             if not self.verif_type(val=val,cr=cr) : return 0
168         return 1
169
170       # Ici, valeur est un scalaire ...il faut tester sur tous les types ou les valeurs possibles
171
172       for type_permis in self.definition.type:
173           if self.compare_type(valeur,type_permis) : return 1
174
175       # 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
176       if cr =='oui':
177           self.cr.fatal("%s n'est pas d'un type autorisé" %`valeur`)
178       return 0
179
180    def verif_into(self,cr='non'):
181       """
182       Vérifie si la valeur de self est bien dans l'ensemble discret de valeurs
183       donné dans le catalogue derrière l'attribut into ou vérifie que valeur est bien compris
184       entre val_min et val_max
185       """
186       if self.definition.into == None :
187         #on est dans le cas d'un ensemble continu de valeurs possibles (intervalle)
188         if self.definition.val_min == '**' and self.definition.val_max == '**':
189            # L'intervalle est infini, on ne fait pas de test
190            return 1
191         #if type(self.valeur) in (types.ListType,types.TupleType) :
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) in (types.ListType,types.TupleType) :
209         if type(self.valeur) == types.TupleType and not self.valeur[0] in ('RI','MP') or type(self.valeur) == types.ListType:
210           # Cas d'une liste de valeur
211           for e in self.valeur:
212             if e not in self.definition.into:
213               if cr=='oui':
214                 self.cr.fatal(string.join(("La valeur :",`e`," n'est pas permise pour le mot-clé :",self.nom)))
215               return 0
216         else:
217           if self.valeur not in self.definition.into:
218             if cr=='oui':
219               self.cr.fatal(string.join(("La valeur :",`self.valeur`," n'est pas permise pour le mot-clé :",self.nom)))
220             return 0
221         return 1
222
223    def is_complexe(self,valeur):
224       """ Retourne 1 si valeur est un complexe, 0 sinon """
225       if type(valeur) == types.InstanceType :
226         #XXX je n'y touche pas pour ne pas tout casser mais il serait
227         #XXX préférable d'appeler une méthode de valeur : return valeur.is_type('C'), par exemple
228         if valeur.__class__.__name__ in ('EVAL','complexe','PARAMETRE_EVAL'):
229           return 1
230         elif valeur.__class__.__name__ in ('PARAMETRE',):
231           # il faut tester si la valeur du parametre est un complexe
232           return self.is_complexe(valeur.valeur)
233         else:
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           return 0
267       elif type(valeur) not in (types.IntType,types.FloatType,types.LongType):
268         # ce n'est pas un réel
269         return 0
270       else:
271         return 1
272
273    def is_entier(self,valeur):
274       """ Retourne 1 si valeur est un entier, 0 sinon """
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('I'), par exemple
278         if valeur.__class__.__name__ in ('EVAL','entier','PARAMETRE_EVAL') :
279           return 1
280         elif valeur.__class__.__name__ in ('PARAMETRE',):
281           # il faut tester si la valeur du parametre est un entier
282           return self.is_entier(valeur.valeur)
283         else:
284           return 0
285       elif type(valeur) not in (types.IntType,types.LongType):
286         # ce n'est pas un entier
287         return 0
288       else:
289         return 1
290
291    def is_shell(self,valeur):
292       """ 
293           Retourne 1 si valeur est un shell, 0 sinon
294           Pour l'instant aucune vérification n'est faite
295           On impose juste que valeur soit une string
296       """
297       if type(valeur) != types.StringType:
298         return 0
299       else:
300         return 1
301
302    def is_object_from(self,objet,classe):
303       """
304            Retourne 1 si valeur est un objet de la classe classe ou d'une
305            sous-classe de classe, 0 sinon
306       """
307       if type(objet) != types.InstanceType :
308           return 0
309       if not objet.__class__ == classe and not issubclass(objet.__class__,classe):
310         return 0
311       else:
312         return 1
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