Salome HOME
gestion des listes et label sur 2
[tools/eficas.git] / Validation / V_ETAPE.py
1 # coding=utf-8
2 # person_in_charge: mathieu.courtois at edf.fr
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2015  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
23 """
24    Ce module contient la classe mixin ETAPE qui porte les méthodes
25    nécessaires pour réaliser la validation d'un objet de type ETAPE
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 types
33 import sys
34 import traceback
35 import re
36
37 # Modules EFICAS
38 import V_MCCOMPO
39 from Noyau import MAXSIZE, MAXSIZE_MSGCHK
40 from Noyau.N_Exception import AsException
41 from Noyau.N_utils import AsType
42 from Noyau.strfunc import ufmt
43
44
45 class ETAPE(V_MCCOMPO.MCCOMPO):
46
47     """
48     """
49
50     def valid_child(self):
51         """ Cette methode teste la validite des mots cles de l'etape """
52         for child in self.mc_liste:
53             if not child.isvalid():
54                 return 0
55         return 1
56
57     def valid_regles(self, cr):
58         """ Cette methode teste la validite des regles de l'etape """
59         text_erreurs, test_regles = self.verif_regles()
60         if not test_regles:
61             if cr == 'oui':
62                 self.cr.fatal(
63                     _(u"Règle(s) non respectée(s) : %s"), text_erreurs)
64             return 0
65         return 1
66
67     def valid_sdnom(self, cr):
68         """ Cette methode teste la validite du nom du concept produit par l'etape """
69         valid = 1
70         if self.sd.nom != None:
71             if self.jdc and self.jdc.definition.code == 'ASTER' and len(self.sd.nom) > 8:
72                 # le nom de la sd doit avoir une longueur <= 8 caractères pour
73                 # ASTER
74                 if cr == 'oui':
75                     self.cr.fatal(
76                         _(u"Le nom de concept %s est trop long (8 caractères maxi)"),
77                         self.sd.nom)
78                 valid = 0
79             if self.sd.nom.find('sansnom') != -1:
80                 # la SD est 'sansnom' : --> erreur
81                 if cr == 'oui':
82                     self.cr.fatal(_(u"Pas de nom pour le concept retourné"))
83                 valid = 0
84             elif re.search('^SD_[0-9]*$', self.sd.nom):
85                 # la SD est 'SD_' cad son nom = son id donc pas de nom donné
86                 # par utilisateur : --> erreur
87                 if cr == 'oui':
88                     self.cr.fatal(
89                         _(u"Nom de concept invalide ('SD_' est réservé)"))
90                 valid = 0
91         return valid
92
93     def get_valid(self):
94         if hasattr(self, 'valid'):
95             return self.valid
96         else:
97             self.valid = None
98             return None
99
100     def set_valid(self, valid):
101         old_valid = self.get_valid()
102         self.valid = valid
103         self.state = 'unchanged'
104         if not old_valid or old_valid != self.valid:
105             self.init_modif_up()
106
107     def isvalid(self, sd='oui', cr='non'):
108         """
109            Methode pour verifier la validité de l'objet ETAPE. Cette méthode
110            peut etre appelée selon plusieurs modes en fonction de la valeur
111            de sd et de cr.
112
113            Si cr vaut oui elle crée en plus un compte-rendu.
114
115            Cette méthode a plusieurs fonctions :
116
117             - mettre à jour l'état de self (update)
118
119             - retourner un indicateur de validité 0=non, 1=oui
120
121             - produire un compte-rendu : self.cr
122
123         """
124         if CONTEXT.debug:
125             print "ETAPE.isvalid ", self.nom
126         if self.state == 'unchanged':
127             return self.valid
128         else:
129             valid = self.valid_child()
130             valid = valid * self.valid_regles(cr)
131
132             if self.reste_val != {}:
133                 if cr == 'oui':
134                     self.cr.fatal(
135                         _(u"Mots clés inconnus : %s"), ','.join(self.reste_val.keys()))
136                 valid = 0
137
138             if sd == "non":
139                 # Dans ce cas, on ne teste qu'une validité partielle (sans tests sur le concept produit)
140                 # Conséquence : on ne change pas l'état ni l'attribut valid, on retourne simplement
141                 # l'indicateur de validité valid
142                 return valid
143
144             if self.definition.reentrant == 'n' and self.reuse:
145                 # Il ne peut y avoir de concept reutilise avec un OPER non
146                 # reentrant
147                 if cr == 'oui':
148                     self.cr.fatal(
149                         _(u'Opérateur non réentrant : ne pas utiliser reuse'))
150                 valid = 0
151
152             if self.sd == None:
153                 # Le concept produit n'existe pas => erreur
154                 if cr == 'oui':
155                     self.cr.fatal(_(u"Concept retourné non défini"))
156                 valid = 0
157             else:
158                 valid = valid * self.valid_sdnom(cr)
159
160             if valid:
161                 valid = self.update_sdprod(cr)
162
163             self.set_valid(valid)
164
165             return self.valid
166
167     def update_sdprod(self, cr='non'):
168         """
169              Cette méthode met à jour le concept produit en fonction des conditions initiales :
170
171               1. Il n'y a pas de concept retourné (self.definition.sd_prod == None)
172
173               2. Le concept retourné n existait pas (self.sd == None)
174
175               3. Le concept retourné existait. On change alors son type ou on le supprime
176
177              En cas d'erreur (exception) on retourne un indicateur de validité de 0 sinon de 1
178         """
179         sd_prod = self.definition.sd_prod
180         if type(sd_prod) == types.FunctionType:  # Type de concept retourné calculé
181             d = self.cree_dict_valeurs(self.mc_liste)
182             try:
183                 sd_prod = apply(sd_prod, (), d)
184             except:
185                 # Erreur pendant le calcul du type retourné
186                 if CONTEXT.debug:
187                     traceback.print_exc()
188                 self.sd = None
189                 if cr == 'oui':
190                     l = traceback.format_exception(sys.exc_info()[0],
191                                                    sys.exc_info()[1],
192                                                    sys.exc_info()[2])
193                     self.cr.fatal(
194                         _(u'Impossible d affecter un type au résultat\n %s'), ' '.join(l[2:]))
195                 return 0
196         # on teste maintenant si la SD est r\351utilis\351e ou s'il faut la
197         # cr\351er
198         valid = 1
199         if self.reuse:
200             if AsType(self.reuse) != sd_prod:
201                 if cr == 'oui':
202                     self.cr.fatal(
203                         _(u'Type de concept réutilisé incompatible avec type produit'))
204                 valid = 0
205             if self.sdnom != '':
206                 if self.sdnom[0] != '_' and self.reuse.nom != self.sdnom:
207                     # Le nom de la variable de retour (self.sdnom) doit etre le
208                     # meme que celui du concept reutilise (self.reuse.nom)
209                     if cr == 'oui':
210                         self.cr.fatal(_(u'Concept réutilisé : le nom de la variable de '
211                                         u'retour devrait être %s et non %s'),
212                                       self.reuse.nom, self.sdnom)
213                     valid = 0
214             if valid:
215                 self.sd = self.reuse
216         else:
217             if sd_prod == None:  # Pas de concept retourné
218                 # Que faut il faire de l eventuel ancien sd ?
219                 self.sd = None
220             else:
221                 if self.sd:
222                     # Un sd existe deja, on change son type
223                     if CONTEXT.debug:
224                         print "changement de type:", self.sd, sd_prod
225                     if self.sd.__class__ != sd_prod:
226                         self.sd.change_type(sd_prod)
227                 else:
228                     # Le sd n existait pas , on ne le crée pas
229                     if cr == 'oui':
230                         self.cr.fatal(_(u"Concept retourné non défini"))
231                     valid = 0
232             if self.definition.reentrant == 'o':
233                 if cr == 'oui':
234                     self.cr.fatal(
235                         _(u'Commande obligatoirement réentrante : spécifier reuse=concept'))
236                 valid = 0
237         return valid
238
239     def report(self):
240         """
241             Methode pour generation d un rapport de validite
242         """
243         self.cr = self.CR(debut=u'Etape : ' + self.nom
244                           + u'    ligne : ' + `self.appel[0]`
245                           + u'    fichier : ' + `self.appel[1]`,
246                           fin=u'Fin Etape : ' + self.nom)
247         self.state = 'modified'
248         try:
249             self.isvalid(cr='oui')
250         except AsException, e:
251             if CONTEXT.debug:
252                 traceback.print_exc()
253             self.cr.fatal(_(u'Etape : %s ligne : %r fichier : %r %s'),
254                           self.nom, self.appel[0], self.appel[1], e)
255         i = 0
256         for child in self.mc_liste:
257             i += 1
258             if i > MAXSIZE:
259                 print(MAXSIZE_MSGCHK.format(MAXSIZE, len(self.mc_liste)))
260                 break
261             self.cr.add(child.report())
262         return self.cr