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