Salome HOME
07ca3d69dca7ca946c483248f36dc814ae668488
[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,re
24 import string,types
25 from copy import copy
26
27 # Objet re pour controler les identificateurs Python
28 concept_re=re.compile(r'[a-zA-Z_]\w*$')
29
30 # import rajoutés suite à l'ajout de Build_sd --> à résorber
31 import traceback
32 import Noyau
33 from Noyau import N_Exception
34 from Noyau.N_Exception import AsException
35 # fin import à résorber
36
37 # Modules EFICAS
38 import I_MCCOMPO
39
40 class ETAPE(I_MCCOMPO.MCCOMPO):
41
42    def ident(self):
43       return self.nom
44
45    def get_sdname(self):
46       if CONTEXT.debug : print "SDNAME ",self.reuse,self.sd,self.sd.get_name()
47       sdname=''
48       if self.reuse != None:
49         sdname= self.reuse.get_name()
50       else:
51         if self.sd:sdname=self.sd.get_name()
52       if string.find(sdname,'sansnom') != -1 or string.find(sdname,'SD_') != -1:
53         # dans le cas où la SD est 'sansnom' ou 'SD_' on retourne la chaîne vide
54         return ''
55       return sdname
56
57    def is_reentrant(self):
58       """ 
59           Indique si la commande est reentrante
60       """
61       return self.definition.reentrant == 'o' 
62
63    def init_modif(self):
64       """
65          Met l'état de l'étape à : modifié
66          Propage la modification au parent
67       """
68       # Une action
69       # doit etre realisée apres init_modif et la validite reevaluée
70       # apres cette action. L'état modified de tous les objets doit etre
71       # preservé.
72       self.state = 'modified'
73       if self.parent:
74         self.parent.init_modif()
75
76    def fin_modif(self):
77       """
78           Méthode appelée une fois qu'une modification a été faite afin de 
79           déclencher d'éventuels traitements post-modification
80           ex : INCLUDE et POURSUITE
81       """
82       if self.isvalid() :
83          d=self.parent.get_contexte_apres(self)
84       if self.parent:
85         self.parent.fin_modif()
86
87    def nomme_sd(self,nom) :
88       """
89           Cette méthode a pour fonction de donner un nom (nom) au concept 
90           produit par l'étape (self).
91             - si le concept n'existe pas, on essaye de le créer (à condition que l'étape soit valide ET non réentrante)
92             - si il existe déjà, on le renomme et on répercute les changements dans les autres étapes    
93           Les valeurs de retour sont :
94             - 0 si le nommage n'a pas pu etre mené à son terme,
95             - 1 dans le cas contraire
96       """
97       # Le nom d'un concept doit etre un identificateur Python (toujours vrai ?)
98       if not concept_re.match(nom):
99          return 0,"Un nom de concept doit etre un identificateur Python"
100
101       if len(nom) > 8 and self.jdc.definition.code == 'ASTER':
102         return 0,"Nom de concept trop long (maxi 8 caractères)"
103
104       self.init_modif()
105       #
106       # On verifie d'abord si les mots cles sont valides
107       #
108       if not self.isvalid(sd='non') : return 0,"Nommage du concept refusé : l'opérateur n'est pas valide"
109       #
110       # Cas particulier des opérateurs obligatoirement réentrants
111       #
112       if self.definition.reentrant == 'o':
113         self.sd = self.reuse = self.jdc.get_sd_avant_etape(nom,self)
114         if self.sd != None :
115           self.sdnom=self.sd.nom
116           return 1,"Concept existant"
117         else:
118           return 0,"Opérateur réentrant mais concept non existant"
119       #
120       # Cas particulier des opérateurs facultativement réentrants
121       #
122       old_reuse=None
123       if self.definition.reentrant == 'f' :
124         sd = self.jdc.get_sd_avant_etape(nom,self)
125         if sd != None :
126           # FR : il faut tester que la sd trouvée est du bon type !!!!!!!!!!!!!!!!!
127           if isinstance(sd,self.get_type_produit()) :
128              self.sd = self.reuse = sd
129              self.sdnom = sd.nom
130              return 1,"Opérateur facultativement réentrant et concept existant trouvé"
131           else:
132              return 0,"Concept déjà existant et de mauvais type"
133         else :
134           # il faut enlever le lien vers une SD existante car si on passe ici
135           # cela signifie que l'opérateur n'est pas utilisé en mode réentrant.
136           # Si on ne fait pas cela, on risque de modifier une SD produite par un autre opérateur
137           if self.reuse :
138              old_reuse=self.reuse
139              self.sd = self.reuse = self.sdnom = None
140       #
141       # On est dans le cas ou l'opérateur n'est pas réentrant ou est facultativement reentrant
142       # mais est utilisé en mode non réentrant
143       #
144       if self.sd == None :
145           if self.parent.get_sd_autour_etape(nom,self):
146             # Un concept de ce nom existe dans le voisinage de l'etape courante
147             # On retablit l'ancien concept reentrant s'il existait
148             if old_reuse:
149                self.sd=self.reuse=old_reuse
150                self.sdnom=old_reuse.nom
151             return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
152           else:
153             # Il n'existe pas de concept de ce nom dans le voisinage de l'etape courante
154             # On peut donc créer le concept retourné.
155             # Il est créé sans nom mais enregistré dans la liste des concepts existants
156             try:
157                self.get_sd_prod()
158                # Il suffit de changer son attribut nom pour le nommer
159                self.sd.nom = nom
160                self.sdnom=nom
161                return 1,"Nommage du concept effectué"
162             except:
163                return 0,"Nommage impossible"+str(sys.exc_info()[1])
164       else :
165           old_nom=self.sd.nom
166           if string.find(old_nom,'sansnom') :
167             # Dans le cas où old_nom == sansnom, isvalid retourne 0 alors que ...
168             # par contre si le concept existe et qu'il s'appelle sansnom c'est que l'étape est valide
169             # on peut donc le nommer sans test préalable
170             if self.parent.get_sd_autour_etape(nom,self):
171               return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
172             else:
173               self.sd.nom=nom
174               self.sdnom=nom
175               return 1,"Nommage du concept effectué"
176           if self.isvalid() :
177             # Normalement l appel de isvalid a mis a jour le concept produit (son type)
178             # Il suffit de spécifier l attribut nom de sd pour le nommer si le nom n est pas
179             # deja attribué
180             if self.parent.get_sd_autour_etape(nom,self):
181               return 0,"Nommage du concept refuse : un concept de meme nom existe deja"
182             else:
183               self.sd.nom=nom
184               self.sdnom=nom
185               return 1,"Nommage du concept effectué"
186           else:
187             # Normalement on ne devrait pas passer ici
188             return 0,'Normalement on ne devrait pas passer ici'
189
190    def get_sdprods(self,nom_sd):
191       """ 
192          Fonction : retourne le concept produit par l etape de nom nom_sd
193          s il existe sinon None
194       """
195       if self.sd:
196         if self.sd.nom == nom_sd:return self.sd
197
198    def active(self):
199       """
200           Rend l'etape courante active.
201           Il faut ajouter la sd si elle existe au contexte global du JDC
202           et à la liste des sd
203       """
204       if self.actif:return
205       self.actif = 1
206       if not self.sd : return
207       try:
208         self.jdc.append_sdprod(self.sd)
209       except:
210         pass
211
212    def inactive(self):
213       """
214           Rend l'etape courante inactive
215           Il faut supprimer la sd du contexte global du JDC
216           et de la liste des sd
217       """
218       self.actif = 0
219       if not self.sd : return
220       self.jdc.del_sdprod(self.sd)
221       self.jdc.delete_concept_after_etape(self,self.sd)
222
223    def control_sdprods(self,d):
224       """
225           Cette methode doit updater le contexte fournit par
226           l'appelant en argument (d) en fonction de sa definition
227           tout en verifiant que ses concepts produits ne sont pas 
228           deja definis dans le contexte
229       """
230       if type(self.definition.op_init) == types.FunctionType:
231         apply(self.definition.op_init,(self,d))
232       if self.sd:
233         if d.has_key(self.sd.nom):
234            # Le concept est deja defini
235            if self.reuse and self.reuse is d[self.sd.nom]:
236               # Le concept est reutilise : situation normale
237               pass
238            else:
239               # Redefinition du concept, on l'annule
240               #XXX on pourrait simplement annuler son nom pour conserver les objets
241               # l'utilisateur n'aurait alors qu'a renommer le concept (faisable??)
242               self.sd=self.reuse=self.sdnom=None
243               self.init_modif()
244         else:
245            # Le concept n'est pas defini, on peut updater d
246            d[self.sd.nom]=self.sd
247
248    def supprime_sdprods(self):
249       """ 
250             Fonction:
251             Lors d'une destruction d'etape, detruit tous les concepts produits
252             Un opérateur n a qu un concept produit 
253             Une procedure n'en a aucun
254             Une macro en a en général plus d'un
255       """
256       if not self.is_reentrant() :
257         # l'étape n'est pas réentrante
258         # le concept retourné par l'étape est à supprimer car il était 
259         # créé par l'étape
260         if self.sd != None :
261           self.parent.del_sdprod(self.sd)
262           self.parent.delete_concept(self.sd)
263
264    def delete_concept(self,sd):
265       """ 
266           Inputs :
267              - sd=concept detruit
268           Fonction :
269           Mettre a jour les mots cles de l etape et eventuellement 
270           le concept produit si reuse
271           suite à la disparition du concept sd
272           Seuls les mots cles simples MCSIMP font un traitement autre 
273           que de transmettre aux fils
274       """
275       if self.reuse and self.reuse == sd:
276         self.sd=self.reuse=None
277         self.init_modif()
278       for child in self.mc_liste :
279         child.delete_concept(sd)
280
281    def replace_concept(self,old_sd,sd):
282       """
283           Inputs :
284              - old_sd=concept remplace
285              - sd = nouveau concept 
286           Fonction :
287           Mettre a jour les mots cles de l etape et eventuellement
288           le concept produit si reuse
289           suite au remplacement  du concept old_sd
290       """
291       if self.reuse and self.reuse == old_sd:
292         self.sd=self.reuse=sd
293         self.init_modif()
294       for child in self.mc_liste :
295         child.replace_concept(old_sd,sd)
296
297    def get_noms_sd_oper_reentrant(self):
298       """ 
299           Retourne la liste des noms de concepts utilisés à l'intérieur de la commande
300           qui sont du type que peut retourner cette commande 
301       """
302       liste_sd = self.get_sd_utilisees()
303       l_noms = []
304       if type(self.definition.sd_prod) == types.FunctionType:
305         d=self.cree_dict_valeurs(self.mc_liste)
306         try:
307           classe_sd_prod = apply(self.definition.sd_prod,(),d)
308         except:
309           return []
310       else:
311         classe_sd_prod = self.definition.sd_prod
312       for sd in liste_sd :
313         if sd.__class__ is classe_sd_prod : l_noms.append(sd.nom)
314       l_noms.sort()
315       return l_noms
316
317    def get_genealogie(self):
318       """ 
319           Retourne la liste des noms des ascendants de l'objet self
320           en s'arretant à la première ETAPE rencontrée
321       """
322       return [self.nom]
323
324    def verif_existence_sd(self):
325      """
326         Vérifie que les structures de données utilisées dans self existent bien dans le contexte
327         avant étape, sinon enlève la référence à ces concepts
328      """
329      for motcle in self.mc_liste :
330          motcle.verif_existence_sd()
331      
332 #ATTENTION SURCHARGE: a garder en synchro ou a reintegrer dans le Noyau
333    def Build_sd(self,nom):
334       """
335            Methode de Noyau surchargee pour poursuivre malgre tout
336            si une erreur se produit pendant la creation du concept produit
337       """
338       try:
339          sd=Noyau.N_ETAPE.ETAPE.Build_sd(self,nom)
340          self.state="modified"
341       except AsException,e:
342          # Une erreur s'est produite lors de la construction du concept
343          # Comme on est dans EFICAS, on essaie de poursuivre quand meme
344          # Si on poursuit, on a le choix entre deux possibilités :
345          # 1. on annule la sd associée à self
346          # 2. on la conserve mais il faut la retourner
347          # En plus il faut rendre coherents sdnom et sd.nom
348          self.sd=None
349          self.sdnom=None
350          self.state="unchanged"
351          self.valid=0
352
353       return self.sd
354
355 #ATTENTION SURCHARGE: cette methode doit etre gardée en synchronisation avec Noyau
356    def make_register(self):
357       """
358          Initialise les attributs jdc, id, niveau et réalise les
359          enregistrements nécessaires
360          Pour EFICAS, on tient compte des niveaux
361          Surcharge la methode make_register du package Noyau
362       """
363       if self.parent :
364          self.jdc = self.parent.get_jdc_root()
365          self.id=   self.parent.register(self)
366          if self.definition.niveau :
367             # La définition est dans un niveau. En plus on
368             # l'enregistre dans le niveau
369             self.nom_niveau_definition = self.definition.niveau.nom
370             self.niveau = self.parent.dict_niveaux[self.nom_niveau_definition]
371             self.niveau.register(self)
372          else:
373             # La définition est au niveau global
374             self.nom_niveau_definition = 'JDC'
375             self.niveau=self.parent
376       else:
377          self.jdc = self.parent =None
378          self.id=None
379          self.niveau=None
380