Salome HOME
premiere version
[tools/eficas.git] / Validation / V_MACRO_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 MACRO_ETAPE qui porte les méthodes
24    nécessaires pour réaliser la validation d'un objet de type MACRO_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
35 # Modules EFICAS
36 import V_MCCOMPO
37 import V_ETAPE
38 from Noyau.N_Exception import AsException
39 from Noyau.N_utils import AsType
40 from Noyau.strfunc import ufmt
41
42 class MACRO_ETAPE(V_ETAPE.ETAPE):
43    """
44    """
45
46    def isvalid(self,sd='oui',cr='non'):
47       """
48          Methode pour verifier la validité de l'objet ETAPE. Cette méthode
49          peut etre appelée selon plusieurs modes en fonction de la valeur
50          de sd et de cr.
51
52          Si cr vaut oui elle crée en plus un compte-rendu.
53
54          Cette méthode a plusieurs fonctions :
55
56           - mettre à jour l'état de self (update)
57
58           - retourner un indicateur de validité 0=non, 1=oui
59
60           - produire un compte-rendu : self.cr
61
62       """
63       if CONTEXT.debug : print "ETAPE.isvalid ",self.nom
64       if self.state == 'unchanged' :
65         return self.valid
66       else:
67         valid=1
68         # On marque les concepts CO pour verification ulterieure de leur bonne utilisation
69         l = self.get_all_co()
70         # On verifie que les concepts CO sont bien passes par type_sdprod
71         for c in l:
72            #if c.etape is self.parent:
73            if c.is_typco() != 2:
74              # le concept est propriete de l'etape parent
75              # Il n'a pas ete transforme par type_sdprod
76              # Cette situation est interdite
77              # Pb: La macro-commande a passe le concept a une commande (macro ?) mal definie
78              if cr =='oui':
79                self.cr.fatal(_(u"Macro-commande mal définie : le concept n'a pas été typé par "
80                                u"un appel à type_sdprod pour %s"), c.nom)
81              valid=0
82
83         valid=valid * self.valid_child()
84         valid=valid * self.valid_regles(cr)
85
86         if self.reste_val != {}:
87           if cr == 'oui' :
88             self.cr.fatal(_(u"Mots clés inconnus : %s"), ','.join(self.reste_val.keys()))
89           valid=0
90
91         if sd == "non":
92            # Dans ce cas, on ne calcule qu'une validite partielle, on ne modifie pas l'état de self
93            # on retourne simplement l'indicateur valid
94            return valid
95
96         if self.sd != None :
97            valid = valid * self.valid_sdnom(cr)
98
99         if self.definition.reentrant == 'n' and self.reuse:
100            # Il ne peut y avoir de concept reutilise avec une MACRO  non reentrante
101            if cr == 'oui' :
102                self.cr.fatal(_(u'Macro-commande non réentrante : ne pas utiliser reuse'))
103            valid=0
104
105         if valid:
106           valid = self.update_sdprod(cr)
107
108         # Si la macro comprend des etapes internes, on teste leur validite
109         for e in self.etapes:
110           if not e.isvalid():
111             valid=0
112             break
113
114         self.set_valid(valid)
115
116         return self.valid
117
118    def update_sdprod(self,cr='non'):
119       """
120            Cette méthode met à jour le concept produit en fonction des conditions initiales :
121
122             1. Il n'y a pas de concept retourné (self.definition.sd_prod == None)
123
124             2. Le concept retourné n existait pas (self.sd == None)
125
126             3. Le concept retourné existait. On change alors son type ou on le supprime
127
128            En cas d'erreur (exception) on retourne un indicateur de validité de 0 sinon de 1
129       """
130       sd_prod=self.definition.sd_prod
131       # On memorise le type retourné dans l attribut typret
132       self.typret=None
133       if type(sd_prod) == types.FunctionType:
134         # Type de concept retourné calculé
135         d=self.cree_dict_valeurs(self.mc_liste)
136         try:
137           # la sd_prod d'une macro a l'objet lui meme en premier argument
138           # contrairement à une ETAPE ou PROC_ETAPE
139           # Comme sd_prod peut invoquer la méthode type_sdprod qui ajoute
140           # les concepts produits dans self.sdprods, il faut le mettre à zéro
141           self.sdprods=[]
142           sd_prod= apply(sd_prod,(self,),d)
143         except:
144           # Erreur pendant le calcul du type retourné
145           if CONTEXT.debug:traceback.print_exc()
146           self.sd=None
147           if cr == 'oui' :
148              l=traceback.format_exception(sys.exc_info()[0],
149                                           sys.exc_info()[1],
150                                           sys.exc_info()[2])
151              self.cr.fatal(_(u'Impossible d affecter un type au résultat\n%s'), ' '.join(l[2:]))
152           return 0
153       # on teste maintenant si la SD est r\351utilis\351e ou s'il faut la cr\351er
154       valid=1
155       if self.reuse:
156         # Un concept reutilise a ete specifie
157         if AsType(self.reuse) != sd_prod:
158           if cr == 'oui' :
159               self.cr.fatal(_(u'Type de concept réutilisé incompatible avec type produit'))
160           valid=0
161         if self.sdnom!='':
162            if self.sdnom[0] != '_' and self.reuse.nom != self.sdnom:
163              # Le nom de la variable de retour (self.sdnom) doit etre le meme que celui du concept reutilise (self.reuse.nom)
164              if cr == 'oui' :
165                 self.cr.fatal(_(u'Concept réutilisé : le nom de la variable de '
166                                      u'retour devrait être %s et non %s'),
167                                    self.reuse.nom, self.sdnom)
168              valid= 0
169         if valid:self.sd=self.reuse
170       else:
171         #Cas d'un concept non reutilise
172         if sd_prod == None:# Pas de concept retourné
173           # Que faut il faire de l eventuel ancien sd ?
174           self.sd = None
175         else:
176           if self.sd:
177             # Un sd existe deja, on change son type
178             if CONTEXT.debug:print "changement de type:",self.sd,sd_prod
179             if self.sd.__class__ != sd_prod:
180               self.sd.change_type(sd_prod)
181             self.typret=sd_prod
182           else:
183             # Le sd n existait pas , on ne le crée pas
184             self.typret=sd_prod
185             if cr == 'oui' :
186                 self.cr.fatal(_(u"Concept retourné non défini"))
187             valid=0
188         if self.definition.reentrant == 'o':
189            if cr == 'oui' :
190                self.cr.fatal(_(u'Commande obligatoirement réentrante : spécifier reuse=concept'))
191            valid=0
192       return valid
193
194    def report(self):
195       """
196           Methode pour la generation d un rapport de validation
197       """
198       V_ETAPE.ETAPE.report(self)
199       for e in self.etapes :
200         self.cr.add(e.report())
201       return self.cr
202