Salome HOME
version 19 mars
[tools/eficas.git] / Validation / V_ETAPE.py
1 # -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2007-2013   EDF R&D
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 # Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 #
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #
20
21
22 """
23    Ce module contient la classe mixin ETAPE qui porte les méthodes
24    nécessaires pour réaliser la validation d'un objet de type ETAPE
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 types
32 import sys
33 import traceback
34 import re
35
36 # Modules EFICAS
37 import V_MCCOMPO
38 from Noyau.N_Exception import AsException
39 from Noyau.N_utils import AsType
40 from Noyau.strfunc import ufmt
41
42 try :
43   from Extensions.i18n import tr
44 except :
45   def tr(txt):
46     return txt
47
48
49 class ETAPE(V_MCCOMPO.MCCOMPO):
50    """
51    """
52
53    def valid_child(self):
54        """ Cette methode teste la validite des mots cles de l'etape """
55        for child in self.mc_liste :
56            if not child.isvalid():
57               return 0
58        return 1
59
60    def valid_regles(self,cr):
61        """ Cette methode teste la validite des regles de l'etape """
62        text_erreurs,test_regles = self.verif_regles()
63        if not test_regles :
64           if cr == 'oui' :
65               self.cr.fatal(_(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 ASTER
75           #   if cr == 'oui' :
76           #      self.cr.fatal(_(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é par utilisateur : --> erreur
86              if cr == 'oui' :
87                 self.cr.fatal(_(u"Nom de concept invalide ('SD_' est réservé)"))
88              valid = 0
89        return valid
90
91    def get_valid(self):
92        if hasattr(self,'valid'):
93           return self.valid
94        else:
95           self.valid=None
96           return None
97
98    def set_valid(self,valid):
99        old_valid=self.get_valid()
100        self.valid = valid
101        self.state = 'unchanged'
102        if not old_valid or old_valid != self.valid :
103            self.init_modif_up()
104
105    def isvalid(self,sd='oui',cr='non'):
106       """
107          Methode pour verifier la validité de l'objet ETAPE. Cette méthode
108          peut etre appelée selon plusieurs modes en fonction de la valeur
109          de sd et de cr.
110
111          Si cr vaut oui elle crée en plus un compte-rendu.
112
113          Cette méthode a plusieurs fonctions :
114
115           - mettre à jour l'état de self (update)
116
117           - retourner un indicateur de validité 0=non, 1=oui
118
119           - produire un compte-rendu : self.cr
120
121       """
122       if CONTEXT.debug : print "ETAPE.isvalid ",self.nom
123       if self.state == 'unchanged' :
124         return self.valid
125       else:
126         valid=self.valid_child()
127         valid=valid * self.valid_regles(cr)
128
129         if self.reste_val != {}:
130           if cr == 'oui' :
131             self.cr.fatal(_(u"Mots clés inconnus : %s"), ','.join(self.reste_val.keys()))
132           valid=0
133
134         if sd == "non":
135           # Dans ce cas, on ne teste qu'une validité partielle (sans tests sur le concept produit)
136           # Conséquence : on ne change pas l'état ni l'attribut valid, on retourne simplement
137           # l'indicateur de validité valid
138           return valid
139
140         if self.definition.reentrant == 'n' and self.reuse:
141           # Il ne peut y avoir de concept reutilise avec un OPER non reentrant
142           if cr == 'oui' :
143               self.cr.fatal(_(u'Opérateur non réentrant : ne pas utiliser reuse'))
144           valid=0
145
146         if self.sd == None:
147           # Le concept produit n'existe pas => erreur
148           if cr == 'oui' :
149               self.cr.fatal(_(u"Concept retourné non défini"))
150           valid = 0
151         else:
152           valid = valid * self.valid_sdnom(cr)
153
154         if valid:
155           valid = self.update_sdprod(cr)
156
157         self.set_valid(valid)
158
159         return self.valid
160
161    def update_sdprod(self,cr='non'):
162       """
163            Cette méthode met à jour le concept produit en fonction des conditions initiales :
164
165             1. Il n'y a pas de concept retourné (self.definition.sd_prod == None)
166
167             2. Le concept retourné n existait pas (self.sd == None)
168
169             3. Le concept retourné existait. On change alors son type ou on le supprime
170
171            En cas d'erreur (exception) on retourne un indicateur de validité de 0 sinon de 1
172       """
173       sd_prod=self.definition.sd_prod
174       if type(sd_prod) == types.FunctionType: # Type de concept retourné calculé
175         d=self.cree_dict_valeurs(self.mc_liste)
176         try:
177           sd_prod= apply(sd_prod,(),d)
178         except:
179           # Erreur pendant le calcul du type retourné
180           if CONTEXT.debug: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(_(u'Impossible d affecter un type au résultat\n %s'), ' '.join(l[2:]))
187           return 0
188       # on teste maintenant si la SD est r\351utilis\351e ou s'il faut la cr\351er
189       valid=1
190       if self.reuse:
191         if AsType(self.reuse) != sd_prod:
192           if cr == 'oui' :
193               self.cr.fatal(_(u'Type de concept réutilisé incompatible avec type produit'))
194           valid= 0
195         if self.sdnom!='':
196            if self.sdnom[0] != '_' and self.reuse.nom != self.sdnom:
197              # Le nom de la variable de retour (self.sdnom) doit etre le meme que celui du concept reutilise (self.reuse.nom)
198              if cr == 'oui' :
199                 self.cr.fatal(_(u'Concept réutilisé : le nom de la variable de '
200                                      u'retour devrait être %s et non %s'),
201                                    self.reuse.nom, self.sdnom)
202              valid= 0
203         if valid:self.sd=self.reuse
204       else:
205         if sd_prod == None:# Pas de concept retourné
206           # Que faut il faire de l eventuel ancien sd ?
207           self.sd = None
208         else:
209           if self.sd:
210              # Un sd existe deja, on change son type
211              if CONTEXT.debug:print "changement de type:",self.sd,sd_prod
212              if self.sd.__class__ != sd_prod:
213                self.sd.change_type(sd_prod)
214           else:
215              # Le sd n existait pas , on ne le crée pas
216              if cr == 'oui' :
217                  self.cr.fatal(_(u"Concept retourné non défini"))
218              valid=0
219         if self.definition.reentrant == 'o':
220            if cr == 'oui' :
221                self.cr.fatal(_(u'Commande obligatoirement réentrante : spécifier reuse=concept'))
222            valid=0
223       return valid
224
225
226    def report(self):
227       """
228           Methode pour generation d un rapport de validite
229       """
230       self.cr=self.CR(debut=tr('Etape : ')+tr(self.nom) +' ' \
231                 + tr('    ligne : ')+`self.appel[0]`\
232                 + tr('    fichier :')+`self.appel[1]`,
233                  fin = tr('Fin Etape : ')+tr(self.nom))
234       self.state = 'modified'
235       try:
236         self.isvalid(cr='oui')
237       except AsException,e:
238         if CONTEXT.debug : traceback.print_exc()
239         self.cr.fatal(tr('Etape : ')+tr(self.nom) \
240                 + tr('    ligne : ')+`self.appel[0]`\
241                 + tr('    fichier :')+`self.appel[1]`, +e)
242       for child in self.mc_liste:
243         self.cr.add(child.report())
244       return self.cr
245