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