Salome HOME
This commit was generated by cvs2git to track changes on a CVS vendor
[tools/eficas.git] / Ihm / I_ETAPE.py
1 #            CONFIGURATION MANAGEMENT OF EDF VERSION
2 # ======================================================================
3 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
4 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
5 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
6 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
7 # (AT YOUR OPTION) ANY LATER VERSION.
8 #
9 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
10 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
11 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
12 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
13 #
14 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
15 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
16 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
17 #
18 #
19 # ======================================================================
20 """
21 """
22 # Modules Python
23 import sys
24 import string,types
25 from copy import copy
26
27 # import rajoutés suite à l'ajout de Build_sd --> à résorber
28 import traceback
29 import Noyau
30 from Noyau import N_Exception
31 from Noyau.N_Exception import AsException
32 # fin import à résorber
33
34 # Modules EFICAS
35 import I_MCCOMPO
36
37 class ETAPE(I_MCCOMPO.MCCOMPO):
38
39    def ident(self):
40       return self.nom
41
42    def get_sdname(self):
43       if CONTEXT.debug : print "SDNAME ",self.reuse,self.sd,self.sd.get_name()
44       sdname=''
45       if self.reuse != None:
46         sdname= self.reuse.get_name()
47       else:
48         if self.sd:sdname=self.sd.get_name()
49       if string.find(sdname,'sansnom') != -1 or string.find(sdname,'SD_') != -1:
50         # dans le cas où la SD est 'sansnom' ou 'SD_' on retourne la chaîne vide
51         return ''
52       return sdname
53
54    def is_reentrant(self):
55       """ 
56           Indique si la commande est reentrante
57       """
58       return self.definition.reentrant == 'o' 
59
60    def init_modif(self):
61       """
62          Met l'état de l'étape à : modifié
63          Propage la modification au parent
64       """
65       # Une action
66       # doit etre realisée apres init_modif et la validite reevaluée
67       # apres cette action. L'état modified de tous les objets doit etre
68       # preservé.
69       self.state = 'modified'
70       if self.parent:
71         self.parent.init_modif()
72
73    def fin_modif(self):
74       """
75           Méthode appelée une fois qu'une modification a été faite afin de 
76           déclencher d'éventuels traitements post-modification
77           ex : INCLUDE et POURSUITE
78       """
79       if self.isvalid() :
80          d=self.parent.get_contexte_apres(self)
81       if self.parent:
82         self.parent.fin_modif()
83
84    def nomme_sd(self,nom) :
85       """
86           Cette méthode a pour fonction de donner un nom (nom) au concept 
87           produit par l'étape (self).
88           - si le concept n'existe pas, on essaye de le créer (à condition que l'étape soit valide ET non réentrante)
89           - si il existe déjà, on le renomme et on répercute les changements dans les autres étapes    
90           Les valeurs de retour sont :
91            0 si le nommage n'a pas pu etre mené à son terme,
92            1 dans le cas contraire
93       """
94       if len(nom) > 8 and self.jdc.definition.code == 'ASTER':
95         return 0,"Nom de concept trop long (maxi 8 caractères)"
96       self.init_modif()
97       #
98       # On verifie d'abord si les mots cles sont valides
99       #
100       if not self.isvalid(sd='non') : return 0,"Nommage du concept refusé : l'opérateur n'est pas valide"
101       #
102       # Cas particulier des opérateurs obligatoirement réentrants
103       #
104       if self.definition.reentrant == 'o':
105         self.sd = self.reuse = self.jdc.get_sd_avant_etape(nom,self)
106         if self.sd != None :
107           self.sdnom=self.sd.nom
108           return 1,"Concept existant"
109         else:
110           return 0,"Opérateur réentrant mais concept non existant"
111       #
112       # Cas particulier des opérateurs facultativement réentrants
113       #
114       old_reuse=None
115       if self.definition.reentrant == 'f' :
116         sd = self.jdc.get_sd_avant_etape(nom,self)
117         if sd != None :
118           # FR : il faut tester que la sd trouvée est du bon type !!!!!!!!!!!!!!!!!
119           if isinstance(sd,self.get_type_produit()) :
120              self.sd = self.reuse = sd
121              self.sdnom = sd.nom
122              return 1,"Opérateur facultativement réentrant et concept existant trouvé"
123           else:
124              return 0,"Concept déjà existant et de mauvais type"
125         else :
126           # il faut enlever le lien vers une SD existante car si on passe ici
127           # cela signifie que l'opérateur n'est pas utilisé en mode réentrant.
128           # Si on ne fait pas cela, on risque de modifier une SD produite par un autre opérateur
129           if self.reuse :
130              old_reuse=self.reuse
131              self.sd = self.reuse = self.sdnom = None
132       #
133       # On est dans le cas ou l'opérateur n'est pas réentrant ou est facultativement reentrant
134       # mais est utilisé en mode non réentrant
135       #
136       if self.sd == None :
137           if self.parent.get_sd_autour_etape(nom,self):
138             # Un concept de ce nom existe dans le voisinage de l'etape courante
139             # On retablit l'ancien concept reentrant s'il existait
140             if old_reuse:
141                self.sd=self.reuse=old_reuse
142                self.sdnom=old_reuse.nom
143             return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
144           else:
145             # Il n'existe pas de concept de ce nom dans le voisinage de l'etape courante
146             # On peut donc créer le concept retourné.
147             # Il est créé sans nom mais enregistré dans la liste des concepts existants
148             self.get_sd_prod()
149             # Il suffit de changer son attribut nom pour le nommer
150             self.sd.nom = nom
151             self.sdnom=nom
152             return 1,"Nommage du concept effectué"
153       else :
154           old_nom=self.sd.nom
155           if string.find(old_nom,'sansnom') :
156             # Dans le cas où old_nom == sansnom, isvalid retourne 0 alors que ...
157             # par contre si le concept existe et qu'il s'appelle sansnom c'est que l'étape est valide
158             # on peut donc le nommer sans test préalable
159             if self.parent.get_sd_autour_etape(nom,self):
160               return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
161             else:
162               self.sd.nom=nom
163               self.sdnom=nom
164               return 1,"Nommage du concept effectué"
165           if self.isvalid() :
166             # Normalement l appel de isvalid a mis a jour le concept produit (son type)
167             # Il suffit de spécifier l attribut nom de sd pour le nommer si le nom n est pas
168             # deja attribué
169             if self.parent.get_sd_autour_etape(nom,self):
170               return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
171             else:
172               self.sd.nom=nom
173               self.sdnom=nom
174               return 1,"Nommage du concept effectué"
175           else:
176             # Normalement on ne devrait pas passer ici
177             return 0,'Normalement on ne devrait pas passer ici'
178
179    def get_sdprods(self,nom_sd):
180       """ 
181          Fonction : retourne le concept produit par l etape de nom nom_sd
182                     s il existe sinon None
183       """
184       if self.sd:
185         if self.sd.nom == nom_sd:return self.sd
186
187    def active(self):
188       """
189           Rend l'etape courante active.
190           Il faut ajouter la sd si elle existe au contexte global du JDC
191           et à la liste des sd
192       """
193       if self.actif:return
194       self.actif = 1
195       if not self.sd : return
196       try:
197         self.jdc.append_sdprod(self.sd)
198       except:
199         pass
200
201    def inactive(self):
202       """
203           Rend l'etape courante inactive
204           Il faut supprimer la sd du contexte global du JDC
205           et de la liste des sd
206       """
207       self.actif = 0
208       if not self.sd : return
209       self.jdc.del_sdprod(self.sd)
210       self.jdc.delete_concept_after_etape(self,self.sd)
211
212    def control_sdprods(self,d):
213       """
214           Cette methode doit updater le contexte fournit par
215           l'appelant en argument (d) en fonction de sa definition
216           tout en verifiant que ses concepts produits ne sont pas 
217           deja definis dans le contexte
218       """
219       if type(self.definition.op_init) == types.FunctionType:
220         apply(self.definition.op_init,(self,d))
221       if self.sd:
222         if d.has_key(self.sd.nom):
223            # Le concept est deja defini
224            if self.reuse and self.reuse is d[self.sd.nom]:
225               # Le concept est reutilise : situation normale
226               pass
227            else:
228               # Redefinition du concept, on l'annule
229               #XXX on pourrait simplement annuler son nom pour conserver les objets
230               # l'utilisateur n'aurait alors qu'a renommer le concept (faisable??)
231               self.sd=self.reuse=self.sdnom=None
232               self.init_modif()
233         else:
234            # Le concept n'est pas defini, on peut updater d
235            d[self.sd.nom]=self.sd
236
237    def supprime_sdprods(self):
238       """ 
239           Fonction:
240             Lors d'une destruction d'etape, detruit tous les concepts produits
241             Un opérateur n a qu un concept produit 
242             Une procedure n'en a aucun
243             Une macro en a en général plus d'un
244       """
245       if not self.is_reentrant() :
246         # l'étape n'est pas réentrante
247         # le concept retourné par l'étape est à supprimer car il était 
248         # créé par l'étape
249         if self.sd != None :
250           self.parent.del_sdprod(self.sd)
251           self.parent.delete_concept(self.sd)
252
253    def delete_concept(self,sd):
254       """ 
255           Inputs :
256              sd=concept detruit
257           Fonction :
258              Mettre a jour les mots cles de l etape et eventuellement 
259              le concept produit si reuse
260              suite à la disparition du concept sd
261              Seuls les mots cles simples MCSIMP font un traitement autre 
262              que de transmettre aux fils
263       """
264       if self.reuse and self.reuse == sd:
265         self.sd=self.reuse=None
266         self.init_modif()
267       for child in self.mc_liste :
268         child.delete_concept(sd)
269
270    def replace_concept(self,old_sd,sd):
271       """
272           Inputs :
273              old_sd=concept remplace
274              sd = nouveau concept 
275           Fonction :
276              Mettre a jour les mots cles de l etape et eventuellement
277              le concept produit si reuse
278              suite au remplacement  du concept old_sd
279       """
280       if self.reuse and self.reuse == old_sd:
281         self.sd=self.reuse=sd
282         self.init_modif()
283       for child in self.mc_liste :
284         child.replace_concept(old_sd,sd)
285
286    def make_register(self):
287       """
288          Initialise les attributs jdc, id, niveau et réalise les
289          enregistrements nécessaires
290          Pour EFICAS, on tient compte des niveaux
291          Surcharge la methode make_register du package Noyau
292       """
293       if self.parent :
294          self.jdc = self.parent.get_jdc_root()
295          self.id=   self.parent.register(self)
296          if self.definition.niveau :
297             # La définition est dans un niveau. En plus on
298             # l'enregistre dans le niveau
299             self.nom_niveau_definition = self.definition.niveau.nom
300             self.niveau = self.parent.dict_niveaux[self.nom_niveau_definition]
301             self.niveau.register(self)
302          else:
303             # La définition est au niveau global
304             self.nom_niveau_definition = 'JDC'
305             self.niveau=self.parent
306       else:
307          self.jdc = self.parent =None
308          self.id=None
309          self.niveau=None
310
311    def copy(self):
312       """ Méthode qui retourne une copie de self non enregistrée auprès du JDC
313           et sans sd 
314       """
315       etape = copy(self)
316       etape.sd = None
317       etape.state = 'modified'
318       etape.reuse = None
319       etape.sdnom = None
320       etape.etape=etape
321       etape.mc_liste=[]
322       for objet in self.mc_liste:
323         new_obj = objet.copy()
324         new_obj.reparent(etape)
325         etape.mc_liste.append(new_obj)
326       return etape
327
328    def get_noms_sd_oper_reentrant(self):
329       """ 
330           Retourne la liste des noms de concepts utilisés à l'intérieur de la commande
331           qui sont du type que peut retourner cette commande 
332       """
333       liste_sd = self.get_sd_utilisees()
334       l_noms = []
335       if type(self.definition.sd_prod) == types.FunctionType:
336         d=self.cree_dict_valeurs(self.mc_liste)
337         try:
338           classe_sd_prod = apply(self.definition.sd_prod,(),d)
339         except:
340           return []
341       else:
342         classe_sd_prod = self.definition.sd_prod
343       for sd in liste_sd :
344         if sd.__class__ is classe_sd_prod : l_noms.append(sd.nom)
345       l_noms.sort()
346       return l_noms
347
348    def get_sd_utilisees(self):
349       """ 
350           Retourne la liste des concepts qui sont utilisés à l'intérieur d'une commande
351           ( comme valorisation d'un MCS) 
352       """
353       l=[]
354       for child in self.mc_liste:
355         l.extend(child.get_sd_utilisees())
356       return l
357
358    def get_genealogie(self):
359       """ 
360           Retourne la liste des noms des ascendants de l'objet self
361           en s'arretant à la première ETAPE rencontrée
362       """
363       return [self.nom]
364
365    def reparent(self,parent):
366      """
367          Cette methode sert a reinitialiser la parente de l'objet
368      """
369      self.parent=parent
370      self.jdc=parent.get_jdc_root()
371      self.etape=self
372      for mocle in self.mc_liste:
373         mocle.reparent(self)
374
375    def verif_existence_sd(self):
376      """
377         Vérifie que les structures de données utilisées dans self existent bien dans le contexte
378         avant étape, sinon enlève la référence à ces concepts
379      """
380      for motcle in self.mc_liste :
381          motcle.verif_existence_sd()
382      
383    def Build_sd(self,nom):
384       """
385          Construit le concept produit de l'opérateur. Deux cas 
386          peuvent se présenter :
387         
388          - le parent n'est pas défini. Dans ce cas, l'étape prend en charge la création 
389            et le nommage du concept.
390
391          - le parent est défini. Dans ce cas, l'étape demande au parent la création et 
392            le nommage du concept.
393
394       """
395       if not self.isactif():return
396       # FR : attention cette méthode ne devrait pas se trouver là car elle surcharge celle qui 
397       # se trouve dans N_ETAPE.py et elle est partie intégrante du noyau, mais, suite à l'absence de 
398       # test de validité de l'opérateur avant d'essayer de déterminer la sd produite, on n'arrivait
399       # pas à relire avec EFICAS un fichier contenant une étape encore incomplète du style :
400       #  sansnom = AFFE_CHAR_CINE(MODELE=None)
401       # Suite à la stabilisation du noyau d'Aster, je n'ai pas eu d'autre solution que de surcharger
402       # cette méthode ici en rajoutant le test manquant ...
403       # CCAR : cette modification ne corrige le probleme qu'en partie. Il faudrait probablement
404       # supprimer les erreurs fatales (exception ) et retourner systematiquement un objet produit
405       # meme en cas d'erreur et reporter l'emission du message d'erreur a la phase de validation
406       #
407       if not self.isvalid(sd='non') : return
408       self.sdnom=nom
409       try:
410          if self.parent:
411             sd= self.parent.create_sdprod(self,nom)
412             if type(self.definition.op_init) == types.FunctionType: 
413                apply(self.definition.op_init,(self,self.parent.g_context))
414          else:
415             sd=self.get_sd_prod()
416             # On n'utilise pas self.definition.op_init car self.parent 
417             # n'existe pas
418             if sd != None and self.reuse == None:
419                # On ne nomme le concept que dans le cas de non reutilisation 
420                # d un concept
421                sd.nom=nom
422          if self.jdc and self.jdc.par_lot == "NON" :
423             self.Execute()
424          return sd
425       except AsException,e:
426          # Une erreur s'est produite lors de la construction du concept
427          # Comme on est dans EFICAS, on essaie de poursuivre quand meme
428          # Si on poursuit, on a le choix entre deux possibilités :
429          # 1. on annule la sd associée à self
430          # 2. on la conserve mais il faut la retourner
431          # En plus il faut rendre coherents sdnom et sd.nom
432          self.sd=None
433          self.sdnom=None
434          self.state="unchanged"
435          self.valid=0
436          return self.sd
437
438          #raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
439          #                     'fichier : ',self.appel[1],e)
440       except EOFError:
441          # XXX Normalement le contexte courant doit etre le parent.
442          # Il n'y a pas de raison de remettre le contexte au parent
443          #self.reset_current_step()
444          raise
445       except :
446          l=traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2])
447          raise AsException("Etape ",self.nom,'ligne : ',self.appel[0],
448                            'fichier : ',self.appel[1]+'\n',
449                             string.join(l))
450      
451      
452      
453      
454      
455      
456      
457      
458      
459      
460      
461      
462      
463      
464      
465      
466      
467      
468      
469         
470