Salome HOME
modif pour MT
[tools/eficas.git] / Validation / V_ETAPE.py
1 # coding=utf-8
2 # ======================================================================
3 # COPYRIGHT (C) 1991 - 2017  EDF R&D                  WWW.CODE-ASTER.ORG
4 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
5 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
6 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
7 # (AT YOUR OPTION) ANY LATER VERSION.
8 #
9 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
10 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
11 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
12 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
13 #
14 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
15 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
16 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
17 #
18 #
19 # ======================================================================
20
21
22 """
23    Ce module contient la classe mixin ETAPE qui porte les methodes
24    necessaires pour realiser la validation d'un objet de type ETAPE
25    derive de OBJECT.
26
27    Une classe mixin porte principalement des traitements et est
28    utilisee par heritage multiple pour composer les traitements.
29 """
30 from __future__ import print_function
31 from __future__ import absolute_import
32
33 # Modules Python
34 import types
35 import sys
36 import traceback
37 import re
38
39 # Modules EFICAS
40 from . import V_MCCOMPO
41 from Noyau import MAXSIZE, MAXSIZE_MSGCHK
42 from Noyau.N_Exception import AsException
43 from Noyau.N_utils import AsType
44 from Extensions.i18n import tr
45
46
47
48 class ETAPE(V_MCCOMPO.MCCOMPO):
49
50     """
51     """
52
53     def validChild(self):
54         """ Cette methode teste la validite des mots cles de l'etape """
55         for child in self.mcListe:
56             if not child.isValid():
57                 return 0
58         return 1
59
60     def validRegles(self, cr):
61         """ Cette methode teste la validite des regles de l'etape """
62         text_erreurs, test_regles = self.verifRegles()
63         if not test_regles:
64             if cr == 'oui':
65                 self.cr.fatal( "Regle(s) non respectee(s) : %s" % text_erreurs)
66             return 0
67         return 1
68
69     def validSdnom(self, cr):
70         """ Cette methode teste la validite du nom du concept produit par l'etape """
71         valid = 1
72         if self.sd.nom != None:
73             if self.sd.nom.find('sansnom') != -1:
74                 # la SD est 'sansnom' : --> erreur
75                 if cr == 'oui':
76                     self.cr.fatal(("object must have a name"))
77                 valid = 0
78             elif re.search('^SD_[0-9]*$', self.sd.nom):
79                 # la SD est 'SD_' cad son nom = son id donc pas de nom donne
80                 # par utilisateur : --> erreur
81                 if cr == 'oui':
82                     self.cr.fatal( ("invalid name ('SD_' is a reserved keyword)"))
83                 valid = 0
84         return valid
85
86     def getValid(self):
87         if hasattr(self, 'valid'):
88             return self.valid
89         else:
90             self.valid = None
91             return None
92
93     def setValid(self, valid):
94         old_valid = self.getValid()
95         self.valid = valid
96         self.state = 'unchanged'
97         if not old_valid or old_valid != self.valid:
98             self.initModifUp()
99
100     def isValid(self, sd='oui', cr='non'):
101         """
102            Methode pour verifier la validite de l'objet ETAPE. Cette methode
103            peut etre appelee selon plusieurs modes en fonction de la valeur
104            de sd et de cr.
105
106            Si cr vaut oui elle cree en plus un compte-rendu.
107
108            Cette methode a plusieurs fonctions :
109
110             - mettre a jour l'etat de self (update)
111
112             - retourner un indicateur de validite 0=non, 1=oui
113
114             - produire un compte-rendu : self.cr
115
116         """
117         if CONTEXT.debug:
118             print(("ETAPE.isValid ", self.nom))
119         if self.state == 'unchanged':
120             return self.valid
121         else:
122             valid = self.validChild()
123             valid = valid * self.validRegles(cr)
124
125             if self.reste_val != {}:
126                 if cr == 'oui':
127                     self.cr.fatal(
128                         "unknown keywords : %s" % ','.join(list(self.reste_val.keys())))
129                 valid = 0
130
131             if sd == "non":
132                 # Dans ce cas, on ne teste qu'une validite partielle (sans tests sur le concept produit)
133                 # Consequence : on ne change pas l'etat ni l'attribut valid, on retourne simplement
134                 # l'indicateur de validite valid
135                 return valid
136
137             if self.definition.reentrant == 'n' and self.reuse:
138                 # Il ne peut y avoir de concept reutilise avec un OPER non
139                 # reentrant
140                 if cr == 'oui':
141                     self.cr.fatal(
142                         'Operateur non reentrant : ne pas utiliser reuse')
143                 valid = 0
144
145             if self.sd == None:
146                 # Le concept produit n'existe pas => erreur
147                 if cr == 'oui':
148                     self.cr.fatal(("Concept is not defined"))
149                 valid = 0
150             else:
151                 valid = valid * self.validSdnom(cr)
152
153             if valid:
154                 valid = self.updateSdprod(cr)
155
156             self.setValid(valid)
157
158             return self.valid
159
160     def updateSdprod(self, cr='non'):
161         """
162              Cette methode met a jour le concept produit en fonction des conditions initiales :
163
164               1. Il n'y a pas de concept retourne (self.definition.sd_prod == None)
165
166               2. Le concept retourne n existait pas (self.sd == None)
167
168               3. Le concept retourne existait. On change alors son type ou on le supprime
169
170              En cas d'erreur (exception) on retourne un indicateur de validite de 0 sinon de 1
171         """
172         sd_prod = self.definition.sd_prod
173         if type(sd_prod) == types.FunctionType:  # Type de concept retourne calcule
174             d = self.creeDictValeurs(self.mcListe)
175             try:
176                 sd_prod = sd_prod(*(), **d)
177             except:
178                 # Erreur pendant le calcul du type retourne
179                 if CONTEXT.debug:
180                     traceback.print_exc()
181                 self.sd = None
182                 if cr == 'oui':
183                     l = traceback.format_exception(sys.exc_info()[0],
184                                                    sys.exc_info()[1],
185                                                    sys.exc_info()[2])
186                     self.cr.fatal(
187                         'unable to affect type to concept\n %s' % ' '.join(l[2:]))
188                 return 0
189         # on teste maintenant si la SD est reutilisee ou s'il faut la
190         # creer
191         valid = 1
192         if self.reuse:
193             if AsType(self.reuse) != sd_prod:
194                 if cr == 'oui':
195                     self.cr.fatal(
196                         ('Type de concept reutilise incompatible avec type produit'))
197                 valid = 0
198             if self.sdnom != '':
199                 if self.sdnom[0] != '_' and self.reuse.nom != self.sdnom:
200                     # Le nom de la variable de retour (self.sdnom) doit etre le
201                     # meme que celui du concept reutilise (self.reuse.nom)
202                     if cr == 'oui':
203                         self.cr.fatal('Concept reutilise : le nom de la variable de retour devrait etre %s et non %s' % ( self.reuse.nom, self.sdnom))
204                     valid = 0
205             if valid:
206                 self.sd = self.reuse
207         else:
208             if sd_prod == None:  # Pas de concept retourne
209                 # Que faut il faire de l eventuel ancien sd ?
210                 self.sd = None
211             else:
212                 if self.sd:
213                     # Un sd existe deja, on change son type
214                     if CONTEXT.debug:
215                         print(("changement de type:", self.sd, sd_prod))
216                     if self.sd.__class__ != sd_prod:
217                         self.sd.changeType(sd_prod)
218                 else:
219                     # Le sd n existait pas , on ne le cree pas
220                     if cr == 'oui':
221                         self.cr.fatal("Concept retourne non defini")
222                     valid = 0
223             if self.definition.reentrant == 'o':
224                 if cr == 'oui':
225                     self.cr.fatal(
226                         ('Commande obligatoirement reentrante : specifier reuse=concept'))
227                 valid = 0
228         return valid
229
230     def report(self):
231         """
232             Methode pour generation d un rapport de validite
233         """
234         self.cr = self.CR(debut='Command : ' + tr(self.nom)
235                           + '    line : ' + repr(self.appel[0])
236                           + '    file : ' + repr(self.appel[1]),
237                           fin='End Command : ' + tr(self.nom))
238         self.state = 'modified'
239         try:
240             self.isValid(cr='oui')
241         except AsException as e:
242             if CONTEXT.debug:
243                 traceback.print_exc()
244             self.cr.fatal('Command : %s line : %r file : %r %s' % (tr(self.nom), self.appel[0], self.appel[1], e))
245         i = 0
246         for child in self.mcListe:
247             i += 1
248             if i > MAXSIZE:
249                 print (MAXSIZE_MSGCHK.format(MAXSIZE, len(self.mcListe)))
250                 break
251             self.cr.add(child.report())
252         return self.cr