Salome HOME
F.R: composimp.py : dans méthode select_in_file, ajout d'un paramètre manquant dans le
[tools/eficas.git] / Ihm / I_ETAPE.py
1 """
2 """
3 # Modules Python
4 import string,types
5 from copy import copy
6
7 # Modules EFICAS
8 import I_MCCOMPO
9
10 class ETAPE(I_MCCOMPO.MCCOMPO):
11
12    def __init__(self):
13       self.niveau=self.jdc
14
15    def ident(self):
16       return self.nom
17
18    def get_fr(self):
19       """ 
20          Retourne l'attribut fr de self.definition 
21       """
22       try:
23          return self.definition.fr
24       except:
25          return ''
26
27    def get_sdname(self):
28       if CONTEXT.debug : print "SDNAME ",self.reuse,self.sd,self.sd.get_name()
29       if self.reuse != None:
30         sdname= self.reuse.get_name()
31       else:
32         sdname=self.sd.get_name()
33       if string.find(sdname,'sansnom') != -1 or string.find(sdname,'SD_') != -1:
34         # dans le cas où la SD est 'sansnom' ou 'SD_' on retourne la chaîne vide
35         return ''
36       return sdname
37
38    def is_reentrant(self):
39       """ 
40           Indique si la commande est reentrante
41       """
42       return self.definition.reentrant == 'o' 
43
44    def init_modif(self):
45       """
46          Met l'état de l'étape à : modifié
47          Propage la modification au parent
48          Si la fonction op_init existe, l'active
49       """
50       # Une action
51       # doit etre realisée apres init_modif et la validite reevaluée
52       # apres cette action. L'état modified de tous les objets doit etre
53       # preservé.
54       self.state = 'modified'
55       if self.parent:
56         self.parent.init_modif()
57
58    def fin_modif(self):
59       """
60           Méthode appelée une fois qu'une modification a été faite afin de 
61           déclencher d'éventuels traitements post-modification
62           ex : INCLUDE et POURSUITE
63       """
64       if self.isvalid() :
65          if type(self.definition.op_init) == types.FunctionType :
66             # XXX Normalement en mode editeur g_context ne peut pas etre utilisé
67             apply(self.definition.op_init,(self,self.parent.g_context))   
68       self.state = 'modified'
69     
70    def nomme_sd(self,nom) :
71       """
72           Cette méthode a pour fonction de donner un nom (nom) au concept 
73           produit par l'étape (self).
74           - si le concept n'existe pas, on essaye de le créer (à condition que l'étape soit valide ET non réentrante)
75           - si il existe déjà, on le renomme et on répercute les changements dans les autres étapes    
76           Les valeurs de retour sont :
77            0 si le nommage n'a pas pu etre mené à son terme,
78            1 dans le cas contraire
79       """
80       if len(nom) > 8 and self.jdc.definition.code == 'ASTER':
81         return 0,"Nom de concept trop long (maxi 8 caractères)"
82       self.init_modif()
83       # Cas particulier des opérateurs réentrants
84       if not self.isvalid(sd='non') : return 0,"Nommage du concept refusé : l'opérateur n'est pas valide"
85       if self.definition.reentrant == 'o':
86         # FR : appel à get_sdprod incorrect : il faut appeler get_sd_avant_etape
87         #self.sd = self.reuse = self.jdc.get_sdprod(nom)
88         self.sd = self.reuse = self.jdc.get_sd_avant_etape(nom,self)
89         if self.sd != None :
90           return 1,"Concept existant"
91         else:
92           return 0,"Opérateur réentrant mais concept non existant"
93       if self.definition.reentrant == 'f' :
94         sd = self.jdc.get_sd_avant_etape(nom,self)
95         if sd != None :
96           # FR : il faut tester que la sd trouvée est du bon type !!!!!!!!!!!!!!!!!
97           if isinstance(sd,self.get_type_produit()) :
98              self.sd = self.reuse = sd
99              return 1,"Opérateur facultativement réentrant et concept existant trouvé"
100           else:
101              return 0,"Concept déjà existant et de mauvais type"
102         else :
103           # il faut éventuellement enlever le lien vers une SD existante car si on passe ici
104           # cela signifie que l'opérateur n'est pas utilisé en mode réentrant.
105           # Si on ne fait pas cela, le nom de l'opérateur réutilisé est aussi modifié
106           # et on ne peut plus modifier la SD de l'opérateur
107           if self.reuse :
108              self.sd = self.reuse = None
109       # l'opérateur n'est pas réentrant ou facultativement reentrant mais pas dans ce cas
110       if self.sd == None :
111           if self.parent.get_sd_autour_etape(nom,self):
112             # On force self.valid a 0 car l appel a isvalid precedent l a mis a 1
113             # mais ceci indique seulement une validité partielle
114             # isvalid ne devrait peut etre pas mettre l attribut valid à 1 si sd == 'non'
115             self.valid=0
116             return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
117           # Il n'existe pas de sd de nom sdnom. On peut donc créer le concept retourné.
118           # Il est créé sans nom mais enregistré dans la liste des concepts existants
119           self.get_sd_prod()
120           self.sd.nom = nom
121           return 1,"Nommage du concept effectué"
122       else :
123         old_nom=self.sd.nom
124         if string.find(old_nom,'sansnom') :
125            # Dans le cas où old_nom == sansnom, isvalid retourne 0 alors que ...
126            # par contre si le concept existe et qu'il s'appelle sansnom c'est que l'étape est valide
127            # on peut donc le nommer sans test préalable
128            self.sd.nom=nom
129            return 1,"Nommage du concept effectué"
130         if self.isvalid() :
131           # Normalement l appel de isvalid a mis a jour le concept produit (son type)
132           # Il suffit de spécifier l attribut nom de sd pour le nommer si le nom n est pas
133           # deja attribué
134           if self.parent.get_sd_autour_etape(nom,self):
135             return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
136           else:
137             self.sd.nom=nom
138             return 1,"Nommage du concept effectué"
139         else:
140           # Normalement on ne devrait pas passer ici
141           return 0,'Normalement on ne devrait pas passer ici'
142
143    def get_sdprods(self,nom_sd):
144       """ 
145          Fonction : retourne le concept produit par l etape de nom nom_sd
146                     s il existe sinon None
147       """
148       if self.sd:
149         if self.sd.nom == nom_sd:return self.sd
150
151    def active(self):
152       """
153           Rend l'etape courante active.
154           Il faut ajouter la sd si elle existe au contexte global du JDC
155           et à la liste des sd
156       """
157       self.actif = 1
158       if not self.sd : return
159       # XXX Pourquoi faut-il faire ce qui suit ??? par defaut les etapes sont actives
160       try:
161         self.jdc.append_sdprod(self.sd)
162       except:
163         pass
164
165    def inactive(self):
166       """
167           Rend l'etape courante inactive
168           Il faut supprimer la sd du contexte global du JDC
169           et de la liste des sd
170       """
171       self.actif = 0
172       if not self.sd : return
173       self.jdc.del_sdprod(self.sd)
174       self.jdc.delete_concept_after_etape(self,self.sd)
175
176    def supprime_sdprods(self):
177       """ 
178           Fonction:
179             Lors d'une destruction d'etape, detruit tous les concepts produits
180             Un opérateur n a qu un concept produit 
181             Une procedure n'en a aucun
182             Une macro en a en général plus d'un
183       """
184       # XXX pour les macros il faudrait peut etre aussi 
185       #     supprimer les concepts a droite du = ???
186       if not self.is_reentrant() :
187         # l'étape n'est pas réentrante
188         # le concept retourné par l'étape est à supprimer car il était 
189         # créé par l'étape
190         if self.sd != None :
191           self.parent.del_sdprod(self.sd)
192           self.parent.delete_concept(self.sd)
193
194    def delete_concept(self,sd):
195       """ 
196           Inputs :
197              sd=concept detruit
198           Fonction :
199              Mettre a jour les mots cles de l etape et eventuellement 
200              le concept produit si reuse
201              suite à la disparition du concept sd
202              Seuls les mots cles simples MCSIMP font un traitement autre 
203              que de transmettre aux fils
204       """
205       if self.reuse and self.reuse == sd:
206         self.sd=self.reuse=None
207         self.init_modif()
208       for child in self.mc_liste :
209         child.delete_concept(sd)
210
211    def make_register(self):
212       """
213          Initialise les attributs jdc, id, niveau et réalise les
214          enregistrements nécessaires
215          Pour EFICAS, on tient compte des niveaux
216       """
217       if self.parent :
218          self.jdc = self.parent.get_jdc_root()
219          self.id=   self.parent.register(self)
220          if self.definition.niveau :
221             # La définition est dans un niveau. En plus on
222             # l'enregistre dans le niveau
223             self.nom_niveau_definition = self.definition.niveau.nom
224             self.niveau = self.parent.dict_niveaux[self.nom_niveau_definition]
225             self.niveau.register(self)
226          else:
227             # La définition est au niveau global
228             self.nom_niveau_definition = 'JDC'
229             self.niveau=self.parent
230       else:
231          self.jdc = self.parent =None
232          self.id=None
233          self.niveau=None
234
235    def copy(self):
236       """ Méthode qui retourne une copie de self non enregistrée auprès du JDC
237           et sans sd 
238       """
239       etape = copy(self)
240       etape.sd = None
241       etape.state = 'modified'
242       etape.reuse = None
243       etape.sdnom = None
244       etape.etape=etape
245       etape.mc_liste=[]
246       for objet in self.mc_liste:
247         new_obj = objet.copy()
248         new_obj.reparent(etape)
249         etape.mc_liste.append(new_obj)
250       return etape
251
252    def get_noms_sd_oper_reentrant(self):
253       """ 
254           Retourne la liste des noms de concepts utilisés à l'intérieur de la commande
255           qui sont du type que peut retourner cette commande 
256       """
257       liste_sd = self.get_sd_utilisees()
258       l_noms = []
259       if type(self.definition.sd_prod) == types.FunctionType:
260         d=self.cree_dict_valeurs(self.mc_liste)
261         try:
262           classe_sd_prod = apply(self.definition.sd_prod,(),d)
263         except:
264           return []
265       else:
266         classe_sd_prod = self.definition.sd_prod
267       for sd in liste_sd :
268         if sd.__class__ is classe_sd_prod : l_noms.append(sd.nom)
269       l_noms.sort()
270       return l_noms
271
272    def get_sd_utilisees(self):
273       """ 
274           Retourne la liste des concepts qui sont utilisés à l'intérieur d'une commande
275           ( comme valorisation d'un MCS) 
276       """
277       l=[]
278       for child in self.mc_liste:
279         l.extend(child.get_sd_utilisees())
280       return l
281
282    def get_genealogie(self):
283       """ 
284           Retourne la liste des noms des ascendants de l'objet self
285           en s'arretant à la première ETAPE rencontrée
286       """
287       return [self.nom]
288
289    def reparent(self,parent):
290      """
291          Cette methode sert a reinitialiser la parente de l'objet
292      """
293      self.parent=parent
294      self.jdc=parent.get_jdc_root()
295      self.etape=self
296      for mocle in self.mc_liste:
297         mocle.reparent(self)
298
299    def verif_existence_sd(self):
300      """
301         Vérifie que les structures de données utilisées dans self existent bien dans le contexte
302         avant étape, sinon enlève la référence à ces concepts
303      """
304      for motcle in self.mc_liste :
305          motcle.verif_existence_sd()
306      
307    def Build_sd(self,nom):
308       """
309          Construit le concept produit de l'opérateur. Deux cas 
310          peuvent se présenter :
311         
312          - le parent n'est pas défini. Dans ce cas, l'étape prend en charge la création 
313            et le nommage du concept.
314
315          - le parent est défini. Dans ce cas, l'étape demande au parent la création et 
316            le nommage du concept.
317
318       """
319       if not self.isactif():return
320       # FR : attention cette méthode ne devrait pas se trouver là car elle surcharge celle qui 
321       # se trouve dans N_ETAPE.py et elle est partie intégrante du noyau, mais, suite à l'absence de 
322       # test de validité de l'opérateur avant d'essayer de déterminer la sd produite, on n'arrivait
323       # pas à relire avec EFICAS un fichier contenant une étape encore incomplète du style :
324       #  sansnom = AFFE_CHAR_CINE(MODELE=None)
325       # Suite à la stabilisation du noyau d'Aster, je n'ai pas eu d'autre solution que de surcharger
326       # cette méthode ici en rajoutant le test manquant ...
327       if not self.isvalid(sd='non') : return
328       try:
329          if self.parent:
330             sd= self.parent.create_sdprod(self,nom)
331             if type(self.definition.op_init) == types.FunctionType: 
332                apply(self.definition.op_init,(self,self.parent.g_context))
333          else:
334             sd=self.get_sd_prod()
335             # On n'utilise pas self.definition.op_init car self.parent 
336             # n'existe pas
337             if sd != None and self.reuse == None:
338                # On ne nomme le concept que dans le cas de non reutilisation 
339                # d un concept
340                sd.nom=nom
341          if self.jdc and self.jdc.par_lot == "NON" :
342             self.Execute()
343          return sd
344       except AsException,e:
345          raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
346                               'fichier : ',self.appel[1],e)
347       except EOFError:
348          # XXX Normalement le contexte courant doit etre le parent.
349          # Il n'y a pas de raison de remettre le contexte au parent
350          #self.reset_current_step()
351          raise
352       except :
353          l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2])
354          raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
355                            'fichier : ',self.appel[1]+'\n',
356                             string.join(l))
357      
358      
359      
360      
361      
362      
363      
364      
365      
366      
367      
368      
369      
370      
371      
372      
373      
374      
375      
376         
377